You can start the OpenVPN link inside a namespace and then run every command you want to use that OpenVPN link inside the namespace. Details on how to do it are presented in Running an OpenVPN tunnel inside a network namespace,
by Sebastian Thorarensen.
I tried it and it does work.
The idea is to provide a custom script to carry out the up and route-up phases of the OpenVPN connection inside a specific namespace instead of the global one.
Here is an answer based on the above source,
but modified to add Google DNS to resolv.conf
.
First create an --up script for OpenVPN.
This script will create the VPN tunnel interface inside a network namespace called vpn, instead of the default namespace.
$ cat > netns-up << 'EOF'
#!/bin/sh
case $script_type in
up)
ip netns add vpn
ip netns exec vpn ip link set dev lo up
mkdir -p /etc/netns/vpn
echo "nameserver 8.8.8.8" > /etc/netns/vpn/resolv.conf
ip link set dev "$1" up netns vpn mtu "$2"
ip netns exec vpn ip addr add dev "$1" \
"$4/${ifconfig_netmask:-30}" \
${ifconfig_broadcast:+broadcast "$ifconfig_broadcast"}
test -n "$ifconfig_ipv6_local" && \
ip netns exec vpn ip addr add dev "$1" \
"$ifconfig_ipv6_local"/112
;;
route-up)
ip netns exec vpn ip route add default via "$route_vpn_gateway"
test -n "$ifconfig_ipv6_remote" && \
ip netns exec vpn ip route add default via \
"$ifconfig_ipv6_remote"
;;
down)
ip netns delete vpn
;;
esac
EOF
Then start OpenVPN and tell it to use our --up script instead of executing ifconfig and route.
openvpn --ifconfig-noexec --route-noexec --up netns-up --route-up netns-up --down netns-up
Now you can start programs to be tunneled like this:
ip netns exec vpn command
The only catch is that you need to be root to invoke ip netns exec ...
and maybe you do not want your application to run as root.
The solution is simple:
sudo ip netns exec vpn sudo -u $(whoami) command
You're confusing two things here.
A socket is a file descriptor - a handle - given to a program so that it can use a network connection in almost the same way it uses files. The socket API is protocol-independent; sockets can be created for IPv4 connections or IPv6 ones, but (given kernel support) also for things like DECnet, AppleTalk, or read Ethernet.
Since the socket API is fairly easy to use but since talking to a process on the same machine using an actual network protocol is rather inefficient, at some point the UNIX domain socket was created to allow use of the socket API without that inefficiency. It also adds some extra features; e.g., it is possible to pass file descriptors to another process over a UNIX domain socket.
When one uses UNIX domain sockets, both processes still hold a socket, one for each side of the connection. The use of the socket is no different from, say, IPv4 sockets, apart from the initial connection setup.
One thing the socket API cannot do without is an address; it is not possible to create a socket without passing it an address to talk to, and this is no different for the UNIX domain socket. Since it's UNIX, where everything is a file anyway, it was decided to make these addresses look like filenames. And since we're already doing that, it makes sense to make these addresses appear in the file system, since that makes it easy to spot them.
Unfortunately, the name given to these things in the file system was also 'UNIX domain socket' (or at least, that's what people started calling them). They're not the actual sockets in the sense of the socket API, however; they couldn't be, since those are just a number. As such, their counterpart in an IPv4 socket is not that number, but instead the IP address and port number of the peer you're talking to.
Occasionally, I'll add that since the socket API doesn't deal with files directly, these filesystem representations aren't strictly necessary. Indeed, Linux has a concept of 'anonymous UNIX domain sockets', which are just that: UNIX domain sockets without any link in the filesystem...
Best Answer
Connecting to a DBus daemon listening on an abstract Unix socket in a different network namespace is not possible. Such addresses can be identified in
ss -x
via an address that contains a@
:As a workaround, you can create a non-abstract Unix or IP socket which proxies to the abstract Unix socket. This is to be done outside the network namespace. From within the network namespace, you can then connect to that address. E.g. assuming the above abstract socket address, run this outside the namespace:
Then from within the namespace you can connect by setting this environment variable: