Currently there’s two things I want to do with my PC at the same time, one is watching streaming services like ABC iView (which won’t run from non-Australian IP addresses) and another is torrenting over a VPN. I had considered doing something ugly with iptables to try and get routing done on a per-UID basis but that seemed to difficult. At the time I wasn’t aware of the ip rule add uidrange  option. So setting up a private networking namespace with a systemd-nspawn container seemed like a good idea.
For the chroot (which I use as a slang term for a copy of a Linux installation in a subdirectory) I used a btrfs subvol that’s a snapshot of the root subvol. The idea is that when I upgrade the root system I can just recreate the chroot with a new snapshot.
To get this working I created files in the root subvol which are used for the container.
I created a script like the following named /usr/local/sbin/container-sshd to launch the container. It sets up the networking and executes sshd. The systemd-nspawn program is designed to launch init but that’s not required, I prefer to just launch sshd so there’s only one running process in a container that’s not being actively used.
#!/bin/bash # restorecon commands only needed for SE Linux /sbin/restorecon -R /dev /bin/mount none -t tmpfs /run /bin/mkdir -p /run/sshd /sbin/restorecon -R /run /tmp /sbin/ifconfig host0 10.3.0.2 netmask 255.255.0.0 /sbin/route add default gw 10.2.0.1 exec /usr/sbin/sshd -D -f /etc/ssh/sshd_torrent_config
How to Launch It
To setup the container I used a command like “/usr/bin/systemd-nspawn -D /subvols/torrent -M torrent –bind=/home -n /usr/local/sbin/container-sshd“.
First I had tried the --network-ipvlan option which creates a new IP address on the same MAC address. That gave me an interface iv-br0 on the container that I could use normally (br0 being the bridge used in my workstation as it’s primary network interface). The IP address I assigned to that was in the same subnet as br0, but for some reason that’s unknown to me (maybe an interaction between bridging and network namespaces) I couldn’t access it from the host, I could only access it from other hosts on the network. I then tried the --network-macvlan option (to create a new MAC address for virtual networking), but that had the same problem with accessing the IP address from the local host outside the container as well as problems with MAC redirection to the primary MAC of the host (again maybe an interaction with bridging).
Then I tried just the “-n” option which gave it a private network interface. That created an interface named ve-torrent on the host side and one named host0 in the container. Using ifconfig and route to configure the interface in the container before launching sshd is easy. I haven’t yet determined a good way of configuring the host side of the private network interface automatically.
I had to use a bind for /home because /home is a subvol and therefore doesn’t get included in the container by default.
How it Works
Now when it’s running I can just “ssh -X” to the container and then run graphical programs that use the VPN while at the same time running graphical programs on the main host that don’t use the VPN.
Things To Do
Find out why --network-ipvlan and --network-macvlan don’t work with communication from the same host.
Find out why --network-macvlan gives errors about MAC redirection when pinging.
Determine a good way of setting up the host side after the systemd-nspawn program has run.
Find out if there are better ways of solving this problem, this way works but might not be ideal. Comments welcome.