Docker-openvpn: Access VPN clients from host of container

Created on 4 Jul 2018  路  14Comments  路  Source: kylemanna/docker-openvpn

Hi,

I was already searching if someone has posted anything about similar use case to my, but couldn't find anything to get me on the right track. Basically my intent is to route packets from public network to the VPN node's port. So here's what I've done already and what I want to do to reach my goal:

I created new Docker network (named dockernet0) 17.18.0.0 for VPN container. After that I created new VPN container in the mentioned network with ovpn_genconfig to which I added additional parameters (along the -u):

  • -s 192.168.123.0/24
  • -d
  • -c

I assigned static IP of 17.18.0.19 to the VPN container. Once config was completed I successfully connected one client to the network. The client got assigned address 192.168.123.6. After that I tried to access to it from the host (Debian 9 running Docker 18.03) where I did all previous steps. The command I used is ping 192.168.123.6. Since there was no any routing rules on the host to the way of Docker network where VPN container resides, connection failed as expected. After that I also tried to ping VPN host (otherwise accessible via 17.18.0.19) with VPN IP of 192.168.123.1 and also failed. The next thing was to add route on the host level with command ip route add 192.168.123.0/24 via 17.18.0.19 dev dockernet0. After that I tried to ping client again and that unfortunately failed. So I tried to ping the VPN host (192.168.123.1) and this succeed.

I've done this one time before (like one month ago) and as far as I remember I got it working after I injected some MASQUERADE rule which included host's address to iptables of VPN container. I checked if command is stored in history but there was no any preserved (or I already restarted that container in the meanwhile and got removed).

I presume that what I've done is not a proper way of handling such case. Any help would be greatly appreciated and this can also serve for the future visitors then.

Thanks in advance!

Most helpful comment

It works for me if I add this iptables rule in the container:

iptables -t nat -A POSTROUTING -o tun+ -j MASQUERADE

I made it permanent by overriding the setupIptablesAndRouting in ovpn_env.sh:

function setupIptablesAndRouting {
    iptables -t nat -C POSTROUTING -s $OVPN_SERVER -o $OVPN_NATDEVICE -j MASQUERADE || {
      iptables -t nat -A POSTROUTING -s $OVPN_SERVER -o $OVPN_NATDEVICE -j MASQUERADE
    }
    for i in "${OVPN_ROUTES[@]}"; do
        iptables -t nat -C POSTROUTING -s "$i" -o $OVPN_NATDEVICE -j MASQUERADE || {
          iptables -t nat -A POSTROUTING -s "$i" -o $OVPN_NATDEVICE -j MASQUERADE
        }
    done

    iptables -t nat -A POSTROUTING -o tun+ -j MASQUERADE
}

All 14 comments

It works for me if I add this iptables rule in the container:

iptables -t nat -A POSTROUTING -o tun+ -j MASQUERADE

I made it permanent by overriding the setupIptablesAndRouting in ovpn_env.sh:

function setupIptablesAndRouting {
    iptables -t nat -C POSTROUTING -s $OVPN_SERVER -o $OVPN_NATDEVICE -j MASQUERADE || {
      iptables -t nat -A POSTROUTING -s $OVPN_SERVER -o $OVPN_NATDEVICE -j MASQUERADE
    }
    for i in "${OVPN_ROUTES[@]}"; do
        iptables -t nat -C POSTROUTING -s "$i" -o $OVPN_NATDEVICE -j MASQUERADE || {
          iptables -t nat -A POSTROUTING -s "$i" -o $OVPN_NATDEVICE -j MASQUERADE
        }
    done

    iptables -t nat -A POSTROUTING -o tun+ -j MASQUERADE
}

could you please describe steps to implement this?
i do:
"docker-compose exec openvpn sh"
"# iptables -t nat -A POSTROUTING -o tun+ -j MASQUERADE"

but it doest not help, i cant ping clients ips from host

Thank you!

The iptables command has to run inside the container .. not on the host.
As I wrote, you can automate it by providing your own version of setupIptablesAndRouting in ovpn_env.sh.

ovpn_env.sh is created when you generate the initial config for the data volume. You have to add the function in my comment above to this file ..

ok, after i append this function in ovpn_env.sh should i run this script or restart/rebuild container?

Restarting the container should be enough.

thank you, but i just cant get it)
on my host i have this devices:

br-e397836da6d5: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.18.0.1  netmask 255.255.0.0  broadcast 0.0.0.0
        inet6 fe80::42:91ff:fe44:b970  prefixlen 64  scopeid 0x20<link>
        ether 02:42:91:44:b9:70  txqueuelen 0  (Ethernet)

veth8d46887: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 fe80::242e:43ff:fe1d:444f  prefixlen 64  scopeid 0x20<link>
        ether 26:2e:43:1d:44:4f  txqueuelen 0  (Ethernet)

related to openvpn container

so adding rule you provide all traffic from host to 172.18.0.1 should pass to clients?

My question is how to pass traffic from 172.18.0.1 to one of the clients (192.168.255.4) ?

Thank your for your answers!

go into your running docker openvpn container:

docker exec -it openvpn /bin/bash
(if your container is not named openvpn adjust the command)

run the iptables command in the container:
iptables -t nat -A POSTROUTING -o tun+ -j MASQUERADE

and check if it works. If not, show me the routes by running this in the container as well:

ip route

# ping 192.168.255.4
PING 192.168.255.4 (192.168.255.4) 56(84) bytes of data.
27 packets transmitted, 0 received, 100% packet loss, time 25999ms
# ip route
default via 172.18.0.1 dev eth0
172.18.0.0/16 dev eth0 proto kernel scope link src 172.18.0.2
192.168.254.0/24 via 192.168.255.2 dev tun0
192.168.255.0/24 dev tun0 proto kernel scope link src 192.168.255.1

hmm .. did you set OVPN_CLIENT_TO_CLIENT to 1 in ovpn_env.sh. Don't know if thats needed to access the client from the server. I enabled it and it works for me ..

Heres my whole config:

declare -x OVPN_AUTH=
declare -x OVPN_CIPHER=
declare -x OVPN_CLIENT_TO_CLIENT=1
declare -x OVPN_CN=vpn.EXAMPLE.COM
declare -x OVPN_COMP_LZO=0
declare -x OVPN_DEFROUTE=1
declare -x OVPN_DEVICE=tun
declare -x OVPN_DEVICEN=0
declare -x OVPN_DISABLE_PUSH_BLOCK_DNS=0
declare -x OVPN_DNS=1
declare -x OVPN_DNS_SERVERS=([0]="1.1.1.1" [1]="8.8.8.8" [2]="8.8.4.4")
declare -x OVPN_ENV=/etc/openvpn/ovpn_env.sh
declare -x OVPN_EXTRA_CLIENT_CONFIG=()
declare -x OVPN_EXTRA_SERVER_CONFIG=()
declare -x OVPN_FRAGMENT=
declare -x OVPN_KEEPALIVE='10 60'
declare -x OVPN_MTU=
declare -x OVPN_NAT=1
declare -x OVPN_PORT=1194
declare -x OVPN_PROTO=tcp
declare -x OVPN_PUSH=()
declare -x OVPN_ROUTES=([0]="10.0.0.0/16" [1]="172.17.0.0/16")
declare -x OVPN_SERVER=10.0.10.0/24
declare -x OVPN_SERVER_URL=tcp://vpn.EXAMPLE.COM
declare -x OVPN_TLS_CIPHER=

Caution, I use 10.0.10.0/24 as vpn subnet!

yes, it is set to 1,
I think the problem might be because of host machine OS, i am using CentOS 7
Thank you for your help

Was problem solved? @truewt @ivakinpavel

@djbios yes, closing.

I follow your instructions and i'm able to ping any vpn client from the host of container. What about if i would like to ping the same vpn client from any LAN devices in the same network of host container?

Was this page helpful?
0 / 5 - 0 ratings