kylemanna / docker-openvpn

🔒 OpenVPN server in a Docker container complete with an EasyRSA PKI CA
https://hub.docker.com/r/kylemanna/openvpn/
MIT License
8.62k stars 2.37k forks source link

Unable to connect to VPN server in docker network #745

Open kaybinwang opened 1 year ago

kaybinwang commented 1 year ago

I have a bunch of containers running on a docker bridge network called dev. I want to be able to run a VPN server there so that my host machine can connect to the network and access all the running containers on that network. This is all on the same device, so traffic never needs to use the public internet.

Assume there is a docker network called dev already created on subnet 172.28.0.0/16.

I created the VPN server using the instructions with slight modifications. The main differences are that I:

  1. used 127.0.0.1 as the VPN server name
  2. pushed route 172.28.0.0 255.255.255.0 to the VPN config
  3. connected the VPN server to the docker dev network (172.28.0.0/16)
    
    OVPN_DATA="ovpn-data-example"

Initialize the $OVPN_DATA container that will hold the configuration files and

certificates. The container will prompt for a passphrase to protect the

private key used by the newly generated certificate authority.

docker volume create --name $OVPN_DATA docker run -v $OVPN_DATA:/etc/openvpn --log-driver=none --rm kylemanna/openvpn ovpn_genconfig \ -u "udp://127.0.0.1" \ # 1. the VPN client is running on the same device -p "route 172.28.0.0 255.255.255.0" # 2. added so that the UDP packets route to docker subnetwork docker run -v $OVPN_DATA:/etc/openvpn --log-driver=none --rm -it kylemanna/openvpn ovpn_initpki

Start OpenVPN server process

docker run -v $OVPN_DATA:/etc/openvpn -d \ --network dev \ # 3. connect VPN server to the dev network -p 1194:1194/udp \ --cap-add=NET_ADMIN \ kylemanna/openvpn

Generate a client certificate without a passphrase

docker run -v $OVPN_DATA:/etc/openvpn --log-driver=none --rm -it kylemanna/openvpn easyrsa build-client-full CLIENTNAME nopass

Retrieve the client configuration with embedded certificates

docker run -v $OVPN_DATA:/etc/openvpn --log-driver=none --rm kylemanna/openvpn ovpn_getclient CLIENTNAME > CLIENTNAME.ovpn


After this, I use Tunnelblick to connect to the server using the `CLIENTNAME.ovpn` but it hangs on waiting for a server response.

2023-03-11 15:48:03.795632 TCP/UDP: Preserving recently used remote address: [AF_INET]127.0.0.1:1194 2023-03-11 15:48:03.795856 Socket Buffers: R=[786896->786896] S=[9216->9216] 2023-03-11 15:48:03.795888 UDP link local: (not bound) 2023-03-11 15:48:03.795911 UDP link remote: [AF_INET]127.0.0.1:1194 2023-03-11 15:48:03.795948 MANAGEMENT: >STATE:1678567683,WAIT,,,,,, 2023-03-11 15:49:03.350385 TLS Error: TLS key negotiation failed to occur within 60 seconds (check your network connectivity) 2023-03-11 15:49:03.351442 TLS Error: TLS handshake failed

kaybinwang commented 1 year ago

These comments from other threads suggest that this is possible:

However, I haven't had any luck and feel like I might be missing something obvious.

markNZed commented 1 year ago

This is painful to learn about but it may not be as hard as it seems.

Add the openvpn container to a Docker network

Make sure that your route for the VPN is not using an overlapping IP range with the Docker network e.g. in ./openvpn-data/conf/openvpn.conf I have route 192.169.255.0 255.255.255.0 push the openvpn container's IP on the vpn as the DNS for VPN clients e.g. push "dhcp-option DNS 192.169.255.1" Now you need to forward DNS requests from the openvpn container to the Docker network DNS, the address 127.0.0.11 points to this DNS in the openvpn container. A simple way to forward the DNS is to use dnsmasq e.g. inside the openvpn container run:

apk --no-cache upgrade
apk add dnsmasq
echo "server=127.0.0.11" >> /etc/dnsmasq.conf
dnsmasq -d -q

You should see the requests coming from the VPN clients. To make this permanent you could build a docker container that wraps around the kylemanna/openvpn image e.g. Dockerfile:

FROM kylemanna/openvpn

RUN apk --no-cache upgrade
RUN apk add dnsmasq
RUN echo "server=127.0.0.11" >> /etc/dnsmasq.conf
RUN sed -i '$!b; i\dnsmasq' /usr/local/bin/ovpn_run

One VERY painful lesson is understanding how Windows machines build DNS requests by adding suffixes to simple names. This can mean the Docker network DNS cannot resolve the DNS request, to get around this you can add a . to turn the container name into a FQN e.g. the IP of the container openvpn can be found with: nslookup openvpn. and if you had a webservice running in a docker container on the host where the openvpn is running at myweb:8080 then in a browser on a Windows machine connected to the VPN you would need to point to http://myweb.:8080