aboutsummaryrefslogtreecommitdiffgithub
diff options
context:
space:
mode:
authorAustin Adams <git@austinjadams.com>2015-08-09 22:55:31 -0400
committerAustin Adams <git@austinjadams.com>2015-08-09 22:55:31 -0400
commitf1f56a7ae647fa12784504a2c6bdcc96e276b970 (patch)
tree15aa272631bc72f0c8b8d323ebef780d8ff9bbe1
parent5cda9dfa4bc94ab06e0da8186104119ac0006349 (diff)
downloadnsdo-f1f56a7ae647fa12784504a2c6bdcc96e276b970.tar.gz
nsdo-f1f56a7ae647fa12784504a2c6bdcc96e276b970.tar.xz
add page on using nsdo with openvpn
I've been wanting to write a blog post about my use of Linux network namespaces with openvpn for a while, but I still haven't bothered to create a blog in the first place (...yep), so I thought this repository might be a good place for a quick guide. I hope it helps someone someday.
-rw-r--r--README.md16
-rw-r--r--nsdo.12
-rw-r--r--openvpn-example.md110
-rw-r--r--readme.head14
4 files changed, 136 insertions, 6 deletions
diff --git a/README.md b/README.md
index 99e3b98..2f045f9 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,8 @@
nsdo
====
-This is a simple C program that runs a command inside a given [Linux
-network namespace][1].
+`nsdo` (network namespace do) is a simple C program that runs a command
+inside a given [Linux network namespace][1].
Effectively, it simplifies:
@@ -30,6 +30,15 @@ Otherwise:
To change the default installation directory of `/usr/local`, set
`PREFIX` to something else when you call `make install`.
+openvpn example
+---------------
+
+I wrote this program because I run some applications under a VPN (e.g.,
+clients for peer-to-peer protocols) and leave others untouched (like a
+game client).
+
+For more details, see [openvpn-example.md][5].
+
license
-------
[MIT/X11][3].
@@ -38,6 +47,7 @@ license
[2]: https://en.wikipedia.org/wiki/Setuid
[3]: https://github.com/ausbin/nsdo/blob/master/LICENSE
[4]: https://aur.archlinux.org/packages/nsdo-git/
+[5]: https://github.com/ausbin/nsdo/blob/master/openvpn-example.md
manpage
-------
@@ -54,7 +64,7 @@ manpage
DESCRIPTION
Execute command as the current user/group in namespace, a
- Linux network namespace setup with iproute2 (see ip-netns
+ Linux network namespace set up with iproute2 (see ip-netns
(8)).
By default, iproute2 places network namespaces in
diff --git a/nsdo.1 b/nsdo.1
index c4e2960..a2a3753 100644
--- a/nsdo.1
+++ b/nsdo.1
@@ -6,7 +6,7 @@ nsdo \- run a command in a network namespace
.I namespace command
[\fIargs\fR ...]
.SH DESCRIPTION
-Execute \fIcommand\fR as the current user/group in \fInamespace\fR, a Linux network namespace setup with \fBiproute2\fR (see \fBip-netns (8)\fR).
+Execute \fIcommand\fR as the current user/group in \fInamespace\fR, a Linux network namespace set up with \fBiproute2\fR (see \fBip-netns (8)\fR).
.PP
By default, \fBiproute2\fR places network namespaces in /var/run/netns/, so \fBnsdo\fR searces for namespaces there (including \fInamespace\fR).
To prevent \fIcommand\fR from easily escaping the namespace 'jail,' \fBnsdo\fR will exit if the current namespace exists in that directory.
diff --git a/openvpn-example.md b/openvpn-example.md
new file mode 100644
index 0000000..9972784
--- /dev/null
+++ b/openvpn-example.md
@@ -0,0 +1,110 @@
+*Note: I base this method heavily on [a great article by Sebastian
+Thorarensen][1].*
+
+To isolate VPN applications from applications running 'bare,' I use the
+following method, which involves nsdo. It has the handy effect of
+putting each instance of the openvpn client in its own network
+namespace, allowing you to run a bunch of VPNs at the same time, each
+available only to programs you choose.
+
+First, I leverage the [Arch `openvpn` package's `openvpn@.service`][2]
+systemd [service][3], which I'll paste here for posterity:
+
+ [Unit]
+ Description=OpenVPN connection to %i
+
+ [Service]
+ Type=forking
+ ExecStart=/usr/bin/openvpn --cd /etc/openvpn --config /etc/openvpn/%i.conf --daemon openvpn@%i --writepid /run/openvpn@%i.pid
+ PIDFile=/run/openvpn@%i.pid
+
+ [Install]
+ WantedBy=multi-user.target
+
+(For instance, you'd start an openvpn instance configured in
+`/etc/openvpn/foo.conf` with `systemctl start openvpn@foo`.)
+
+By default, openvpn manually runs `ifconfig` or `ip` to set up its tun
+device. Luckily for us, you can configure openvpn to run a custom script
+instead. (though you have to set `script-security` >= 2. :( )
+
+I named my script `/usr/local/bin/vpn-ns`, so here's the relevant snippet
+from my [openvpn configuration file][4]:
+
+ # ...
+ # (my other configuration)
+ # ...
+
+ # script should run `ip`, not openvpn
+ route-noexec
+ ifconfig-noexec
+ up "/usr/local/bin/vpn-ns"
+ down "/usr/local/bin/vpn-ns"
+ route-up "/usr/local/bin/vpn-ns"
+ script-security 2
+
+Using [Sebastian's script][1] as a basis, I hacked together the
+following. Notice that it uses iproute2 to create a network namespace
+with the name of the instance's configuration file (`foo` in the earlier
+example).
+
+ #!/bin/bash
+ # based heavily on http://naju.se/articles/openvpn-netns
+
+ [[ $EUID -ne 0 ]] && {
+ echo "$0: this program requires root privileges. try again with 'sudo'?" >&2
+ exit 1
+ }
+
+ # convert a dot-decimal mask (e.g., 255.255.255.0) to a bit-count mask
+ # (like /24) for iproute2. this probably isn't the most beautiful way.
+ tobitmask() {
+ bits=0
+ while read -rd . octet; do
+ (( col = 2**7 ))
+ while (( col > 0 )); do
+ (( octet & col )) || break 2
+ (( bits++ ))
+ (( col >>= 1 ))
+ done
+ done <<<"$1"
+ echo $bits
+ }
+
+ # guess name of network namespace from name of config file
+ basename="$(basename "$config")"
+ ns="${basename%.conf}"
+ netmask="$(tobitmask "$route_netmask_1")"
+
+ case $script_type in
+ up)
+ ip netns add "$ns"
+ ip -netns "$ns" link set dev lo up
+ ip link set dev $dev up netns "$ns" mtu "$tun_mtu"
+ ip -netns "$ns" addr add "$ifconfig_local/$netmask" dev "$dev"
+ ;;
+ route-up)
+ ip -netns "$ns" route add default via "$route_vpn_gateway"
+ ;;
+ down)
+ ip netns del "$ns"
+ ;;
+ *)
+ echo "$0: unknown \$script_type: '$script_type'" >&2
+ exit 2;
+ ;;
+ esac
+
+Now, once you've told systemd to start `openvpn@foo`, you can run any
+application you'd like under the new namespace:
+
+ $ nsdo foo firefox
+
+Alternatively, if you don't want to bother with nsdo:
+
+ $ sudo ip netns foo sudo -u $USER firefox
+
+[1]: http://naju.se/articles/openvpn-netns
+[2]: https://projects.archlinux.org/svntogit/packages.git/tree/trunk/openvpn@.service?h=packages/openvpn
+[3]: http://www.freedesktop.org/software/systemd/man/systemd.service.html
+[4]: https://community.openvpn.net/openvpn/wiki/Openvpn23ManPage
diff --git a/readme.head b/readme.head
index 06d959f..72545f8 100644
--- a/readme.head
+++ b/readme.head
@@ -1,8 +1,8 @@
nsdo
====
-This is a simple C program that runs a command inside a given [Linux
-network namespace][1].
+`nsdo` (network namespace do) is a simple C program that runs a command
+inside a given [Linux network namespace][1].
Effectively, it simplifies:
@@ -30,6 +30,15 @@ Otherwise:
To change the default installation directory of `/usr/local`, set
`PREFIX` to something else when you call `make install`.
+openvpn example
+---------------
+
+I wrote this program because I run some applications under a VPN (e.g.,
+clients for peer-to-peer protocols) and leave others untouched (like a
+game client).
+
+For more details, see [openvpn-example.md][5].
+
license
-------
[MIT/X11][3].
@@ -38,6 +47,7 @@ license
[2]: https://en.wikipedia.org/wiki/Setuid
[3]: https://github.com/ausbin/nsdo/blob/master/LICENSE
[4]: https://aur.archlinux.org/packages/nsdo-git/
+[5]: https://github.com/ausbin/nsdo/blob/master/openvpn-example.md
manpage
-------