Routing Docker traffic through a VPN connection
I've recently taken to using Docker to install and run various software on my home server. Something that so far, it excels at - the people at linuxserver.io are doing great work! I've had a rocky time with Docker in the past after having had it foisted upon me for development work, which I did not enjoy, but I can see the benefits for certain situations.
I found myself needing to run the traffic from one particular container
(Jackett) over a VPN connection so that it could by-pass country-specific
restrictions. As a noob Docker user, this caused some confusion, but I eventually
stumbled upon the --net
parameter to docker create
and run
.
Using this parameter it's possible to tell a container to use the network of
another. You can run an OpenVPN client container, which will initiate a secure
connection, and configure other containers to use its network. The beauty of
this setup is that you don't need to learn or manage any complicated ip_tables
rules or any other network configuration, you can just point one container at
another and have the traffic secured.
All I needed now was a suitable Docker image. Eventually, I got lucky and found an image that supported my exact VPN provider, NordVPN.
This is how I created and started the OpenVPN container. Once this was running, a secure VPN connection was established to NordVPN.
1
2
3
4
5
6
7
8
9
docker run \
--name vpn \
--cap-add=NET_ADMIN \
--device /dev/net/tun \
-p 9117:9117 \
-e NETWORK=192.168.1.0/24 \
-e USER=username \
-e PASS='password' \
bubuntux/nordvpn
Most of these options are standard, but the -p 9117:9117
parameter on line 5
needs explanation. This is the port mapping that Jackett uses by default. When
we use another container's network it's necessary to expose the port(s) that our
other containers use on the VPN container.
And here is how I setup Jackett to use the VPN container. The relevant line is
--net=container:vpn
. Note that I don't have a -p 9117:9117
line here like I
would if I was not using --net=container:vpn
.
1
2
3
4
5
6
7
8
9
10
docker run \
--name=jackett \
--restart unless-stopped \
-e PUID=1000 \
-e PGID=1000 \
-e TZ=Europe/London \
--net=container:vpn \
-v /opt/appdata/jackett:/config \
-v /opt/appdata/jackett/downloads:/downloads \
linuxserver/jackett
Now I can access Jackett at http://<host-ip>:9117
and all traffic will be sent
through the VPN container's network!