13

I have the following setup :

  • A CentOS host running the docker service
  • A user defined docker bridge network
  • 2 Docker containers connected to that user defined bridge network
  • An OpenVPN installation (currently running on the host. Can also run in a docker container)
  • Some clients connected to the OpenVPN

How can I allow for docker containers on the docker bridge network to communicate with the openvpn clients on the tun0 network ?

I would like to be able to have tcp based communication between docker1 (10.10.0.3) and clients connected to the vpn (172.19.0.x range) in a transparent way.

What do I need to setup on docker (networking / iptables / ...) side and on the host (iptables ?)

  • 1
    Maybe late, but in your case I believe you need tap, nut tun, I have been working on that for more 12 hours with no success till now. – Mohammed Noureldin Jul 15 '17 at 12:31
  • @MohammedNoureldin did you guys found a solution? I’m also considering now going to tap device. What’s frustrating is that from within the ovpn container I can access the vpn clients. And from vpn clients I can access the other containers on the same Docker network. But the forwarding between “eth0” and tun0 inside the ovpn container isn’t working. I guess it’s due to tun0 nature vs. tap. – Huygens Oct 19 '17 at 16:32
  • @Huygens, yes I solved it, please ask a separate question and give a reference to me and I will do my best to help you. – Mohammed Noureldin Oct 20 '17 at 0:45
  • 1
    Hi @MohammedNoureldin I’ve found the 2 missing instructions for it to work. They were in openvpn man pages 👍. I’ll post an answer soon to this question for others. – Huygens Oct 21 '17 at 7:21
  • 1
    @Huygens, good to know, actually I have not had yet time to post the answer, but I am interested to see what worked for your case. – Mohammed Noureldin Oct 21 '17 at 11:12
8

Context

I have been using the very good Docker container from Kyle Manna (https://github.com/kylemanna/docker-openvpn). I'm using the so-called "paranoid" documentation to set-up my OpenVPN server, but in my view this should be the standard way and not the paranoid way.

Configuration

In order to allow bi-directional connection between selected Docker containers and the VPN clients, you need to create a Docker network on which you are going to attach container which should be allowed to be accessed by the VPN clients. The VPN server is going to be one of those containers.

The VPN server should have the client-to-client, topology subnet, dev tun0 (or other tun device) and push "route <docker net IP> <docker net mask>" configured.

The host of the VPN server should be configured to support forwarding of IP packets from one subnet to another. This means setting the sysctl ip_forward to 1 (it should be the case if you have Docker install), allowing packets from the tun device to go through the iptables FORWARD chain and setting proper routing. This can be summarise with these commands:

$ sudo sysctl -w net.ipv4.ip_forward=1
$ sudo iptables -A FORWARD -i tun+ -j ACCEPT
$ sudo ip route add 192.168.255.0/24 via <IP address of OpenVPN server container>

Anyway, here are the options I've used to set-up the server:

$ docker run --rm --net=none -it -v $PWD/files/openvpn:/etc/openvpn kylemanna/openvpn:2.4 ovpn_genconfig -u udp://<FQDN> -N -d -c -p "route <docker net IP> <docker net range>" -e "topology subnet"

This should generate a server config file similar to:

server 192.168.255.0 255.255.255.0
verb 3
key /etc/openvpn/pki/private/vpn.example.com.key
ca /etc/openvpn/pki/ca.crt
cert /etc/openvpn/pki/issued/vpn.example.com.crt
dh /etc/openvpn/pki/dh.pem
tls-auth /etc/openvpn/pki/ta.key
key-direction 0
keepalive 10 60
persist-key
persist-tun

proto udp
# Rely on Docker to do port mapping, internally always 1194
port 1194
dev tun0
status /tmp/openvpn-status.log

user nobody
group nogroup
client-to-client

### Push Configurations Below
push "dhcp-option DNS 8.8.8.8"
push "route 172.20.20.0 255.255.255.0"

### Extra Configurations Below
topology subnet

Concrete example

I will now take a concrete example. In this example, I will run the above mention OpenVPN server inside Docker on host vpn.example.com. This container is attached to the Docker network docker-net-vpn. Here are the commands (in this example I generate the server configuration directly on the server and I skip the CA generation, please follow the paranoid documentation of the above mention project instead):

$ docker network create --attachable=true --driver=bridge --subnet=172.20.20.0/24 --gateway=172.20.20.1 docker-net-vpn
$ docker run --rm --net=none -it -v $PWD/files/openvpn:/etc/openvpn kylemanna/openvpn:2.4 ovpn_genconfig -u udp://vpn.example.com -N -d -c -p "route 172.20.20.0 255.255.255.0" -e "topology subnet"
$ docker run --detach --name openvpn -v $PWD/files/openvpn:/etc/openvpn --net=docker-net-vpn --ip=172.20.20.2 -p 1194:1194/udp --cap-add=NET_ADMIN kylemanna/openvpn:2.4
$ sudo sysctl -w net.ipv4.ip_forward=1
$ sudo iptables -A FORWARD -i tun+ -j ACCEPT
$ sudo ip route add 192.168.255.0/24 via 172.20.20.2

The first command creates a dedicated new Docker network which define a new subnet. We will attach the OpenVPN server to this network.

The second one creates the OpenVPN configuration using the same subnet as defined in the 1st command.

The third one creates the OpenVPN server. It is attached to the newly created Docker network and uses a fix IP.

The fourth and fifth commands configure IP forwarding.

The last command adds a new route towards the VPN client configuration via the OpenVPN container fixed IP.

Note

I haven't tried it, but it should be possible to restrict the FORWARD rule for iptables. The Docker network creation created a new bridge device. This bridge is named br-<ID> with ID being the first 12 characters of the Docker network ID. This ID can be obtained with docker network inspect -f '{{.Id}}' docker-net-vpn | cut -b-12. Therefore the following command is maybe more restrictive (so better security-wise) but should still allow our traffic to be routed:

$ NET_VPN_BRIDGE="br-$(docker network inspect -f '{{.Id}}' docker-net-vpn | cut -b-12)"
$ sudo iptables -A FORWARD -i tun+ -o ${NET_VPN_BRIDGE} -j ACCEPT
  • Hey, can't get this to work, I can tracerote to 192.168.255.6 and I get: 1 gnet (172.20.20.1) 1966.269 ms !H 1966.248 ms !H 1966.239 ms !H, but I can't ping or reach open ports. – GuySoft Dec 29 '18 at 23:27
  • Hi @GuySoft what traceroute is reporting is that your last hop (172.20.20.1) cannot reach the host 192.168.255.6. So it means your routing table is probably incorrect. Can we chat to see where is the problem? – Huygens Dec 30 '18 at 22:26
  • It started working, I think what happend is that both machines had docker installed, and both had a subnet 172.20.20.1, that made things clash, I need to find a way to make docker not create a subnet that would clash on the client machine. – GuySoft Jan 1 '19 at 14:04
  • If you use Docker Compose, you can specify the IP address range that the network should use. See the Compose documentation. It’s also possible to do it from the command line with docker network…. – Huygens Jan 1 '19 at 14:13
  • I think im not getting the part where a connection to the host (host ip + openvpn port) is being routed to the openvpn container (172.20.20.2) – jtomasrl Aug 6 '19 at 0:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.