15

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 ?)

ddewaele
  • 333
  • 1
  • 4
  • 12
  • 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 00:45
  • Hi @MohammedNoureldin. Thanks for your proposal, but I'm afraid creating a separate question would be against the Q&A rules as it would create a duplicate. Could you answer this question if you have the time? I can for sure +1 you then. – Huygens Oct 20 '17 at 08:03
  • 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 07: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
  • @MohammedNoureldin answer posted :-) I'm waiting for your feedback. – Huygens Oct 23 '17 at 11:43

1 Answers1

9

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
Huygens
  • 1,708
  • 3
  • 20
  • 36
  • 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 01 '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 01 '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 06 '19 at 00:32
  • Hi @jtomasrl could you be more specific where you have a difficulties? Especially referring the step and what kind of support you would need to better understand it. – Huygens Sep 04 '19 at 12:53
  • Hey @Huygens, I tried running your exact commands above in the concrete example, and when I run `ip route add 192.168.255.0/24 via 172.20.20.2`, I get: `Error: Nexthop has invalid gateway.`. Is this even still possible any more? – James Apr 14 '20 at 09:03
  • 1
    I realised that it's because I was trying to use an `overlay network instead of a `bridge` network. Is there any way to make this work with an overlay network, because the VPN can be running on one host and a container can be on another one connected by the overlay! – James Apr 14 '20 at 09:10
  • Hi @James I would need to create an overlay network to see how to configure it. I cannot answer your question sadly. It’s a good one. I would suggest to open a new question for it so it can get some visibility. I won’t have the time to try to find out at the moment. Cheers – Huygens Apr 14 '20 at 11:36
  • @James have you figured out how to do it with overlay network? – Mohammed Noureldin Jan 15 '22 at 03:11