aboutsummaryrefslogtreecommitdiffgithub
diff options
context:
space:
mode:
authorAustin Adams <git@austinjadams.com>2015-09-12 11:27:28 -0400
committerAustin Adams <git@austinjadams.com>2015-09-12 11:27:28 -0400
commitdf5335060d2623ec1e54bdc42bfe4f36f1071d0a (patch)
treeacd3c5b34760bff7f721ef21270a30fe43c97051
parentf1f56a7ae647fa12784504a2c6bdcc96e276b970 (diff)
downloadnsdo-df5335060d2623ec1e54bdc42bfe4f36f1071d0a.tar.gz
nsdo-df5335060d2623ec1e54bdc42bfe4f36f1071d0a.tar.xz
improve error messages and update vpn suggestions
nsdo now returns better error messages. For instance, if a stat() fails, it gives the filename in the error message. I've also tweaked my vpn suggestions to re-use the same network namespaces across openvpn client restarts. Before, the network namespace was added and removed in the vpn-ns script, but because that ran for every start/stop of the openvpn client, sometimes the network namespace in which an application was running would get 'stale.' Specifically, if Firefox was running in my VPN's network namespace, but I suspended my laptop, the vpn-ns script would create a new network namespace when the computer came out of suspend and the openvpn client started up again. So, /run/netns/vpn (for example) would point to namespace 12345679, where openvpn was running, while firefox would be running in namespace 12345678. The fix -- to use a separate systemd service to create the namespaces -- just makes sense, and I should've done it this way in the first place.
-rw-r--r--README.md2
-rw-r--r--nsdo.c15
-rw-r--r--openvpn-example.md24
-rw-r--r--readme.head2
4 files changed, 32 insertions, 11 deletions
diff --git a/README.md b/README.md
index 2f045f9..5a26649 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@ inside a given [Linux network namespace][1].
Effectively, it simplifies:
- $ sudo ip netns exec myns sudo -u "$USER" myprogram
+ $ sudo ip netns exec myns sudo -u $USER myprogram
to
diff --git a/nsdo.c b/nsdo.c
index 8643c19..7fed018 100644
--- a/nsdo.c
+++ b/nsdo.c
@@ -61,7 +61,7 @@ int current_ns_inode(ino_t *inode) {
struct stat nsstat;
if (stat("/proc/self/ns/net", &nsstat) == -1) {
- perror(PROGRAM ": stat(\"/proc/sys/ns/net\")");
+ perror(PROGRAM ": stat(\"/proc/self/ns/net\")");
return 0;
}
@@ -95,7 +95,9 @@ int inode_in_nspath(ino_t inode) {
}
if (stat(nspath, &nsstat) == -1) {
- perror(PROGRAM ": stat");
+ /* i hate to break consistency and use fprintf() rather than
+ perror(), but it's necessary here. */
+ fprintf(stderr, PROGRAM ": stat(\"%s\"): %s\n", nspath, strerror(errno));
return -1;
}
@@ -106,7 +108,7 @@ int inode_in_nspath(ino_t inode) {
}
if (errno != 0) {
- perror(PROGRAM ": readdir");
+ perror(PROGRAM ": readdir(\"" NS_PATH "\")");
return -1;
}
@@ -137,7 +139,7 @@ int bad_nsname(char *ns) {
}
int set_netns(char *ns) {
- int nsfd;
+ int nsfd, perm_issue;
char *nspath;
if (bad_nsname(ns)) {
@@ -158,7 +160,12 @@ int set_netns(char *ns) {
free(nspath);
if (setns(nsfd, CLONE_NEWNET) == -1) {
+ perm_issue = errno == EPERM;
perror(PROGRAM ": setns");
+
+ if (perm_issue)
+ fprintf(stderr, "\nis the " PROGRAM " binary missing the setuid bit?\n");
+
return 0;
} else {
return 1;
diff --git a/openvpn-example.md b/openvpn-example.md
index 9972784..9879ed8 100644
--- a/openvpn-example.md
+++ b/openvpn-example.md
@@ -24,6 +24,25 @@ systemd [service][3], which I'll paste here for posterity:
(For instance, you'd start an openvpn instance configured in
`/etc/openvpn/foo.conf` with `systemctl start openvpn@foo`.)
+To make OpenVPN keep the same network namespace across VPN reconnections
+or daemon restarts (e.g., after a suspend), I put the following in
+`/etc/systemd/system/openvpn@.service.d/netns.conf`:
+
+ [Unit]
+ Requires=netns@%i.service
+ After=netns@%i.service
+
+And then create a `netns@.service` in `/etc/systemd/system`:
+
+ [Unit]
+ Description=network namespace %I
+
+ [Service]
+ Type=oneshot
+ ExecStart=/bin/ip netns add %I
+ ExecStop=/bin/ip netns del %I
+ RemainAfterExit=yes
+
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. :( )
@@ -39,7 +58,6 @@ from my [openvpn configuration file][4]:
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
@@ -78,7 +96,6 @@ example).
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"
@@ -86,9 +103,6 @@ example).
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;
diff --git a/readme.head b/readme.head
index 72545f8..a2bac30 100644
--- a/readme.head
+++ b/readme.head
@@ -6,7 +6,7 @@ inside a given [Linux network namespace][1].
Effectively, it simplifies:
- $ sudo ip netns exec myns sudo -u "$USER" myprogram
+ $ sudo ip netns exec myns sudo -u $USER myprogram
to