Ever wanted to route your local traffic through a VPN and expose a SOCKS5 proxy for even more flexibility? By combining OpenVPN and Dante in Docker, you can create a powerful, portable VPN solution that’s easy to deploy and manage—especially when paired with a local DNS setup, as described in the previous post in this series.
Why Combine OpenVPN and Dante?
OpenVPN is a popular open-source VPN solution that encrypts your traffic and routes it through a remote server. Dante is a lightweight SOCKS5 proxy server. By running both together, you can:
- Expose a SOCKS5 proxy (via Dante) so any device or app that supports SOCKS5 can use your VPN connection—without installing OpenVPN clients everywhere.
- Run multiple VPNs at the same time.
- Use friendly DNS names (like
gateway.docker
orus-east.docker
).
The Architecture
Here’s what we’re building:
- OpenVPN container: Connects to your VPN provider and creates a tunnel interface.
- Dante container: Runs a SOCKS5 proxy, forwarding all traffic through the OpenVPN tunnel.
- dnsmasq is configured so
gateway.docker
resolves to the Dante container.
docker-compose.yaml
Here’s a sample docker-compose.yml
that brings it all together:
services:
ovpn:
build:
context: ./ovpn
dockerfile: Dockerfile.ovpn
container_name: ovpn
sysctls:
net.ipv6.conf.all.disable_ipv6: 0
cap_add:
- NET_ADMIN
devices:
- /dev/net/tun
volumes:
- ./ovpn/config:/ovpn:z
environment:
- VPN_CONFIG_FILE=/ovpn/config.ovpn
restart: unless-stopped # no, always, unless-stopped, on-failure,
on-failure:3
healthcheck:
# because Dante interpreting `tun0` as a hostname is _really_ hard to debug
test: ["CMD", "ping", "-c", "1", "1.1.1.1"]
interval: 10s
timeout: 5s
retries: 5
networks:
vpn-network:
dns: # DNS configured in previous post in this series
aliases:
- gateway.docker
dante:
build:
context: ./dante
dockerfile: Dockerfile.dante
container_name: dante
volumes:
- ./dante/config:/dante:z
environment:
- DANTE_CONFIG_FILE=/dante/danted.conf
depends_on:
ovpn:
# because Dante interpreting `tun0` as a hostname is _really_ hard to debug
condition: service_healthy
restart: unless-stopped # no, always, unless-stopped, on-failure, on-failure:3
network_mode: "service:ovpn"
networks:
vpn-network:
driver: bridge
dns:
external: true
Key points:
network_mode: "service:ovpn"
makes Dante share the OpenVPN container’s network namespace, so all proxy traffic goes through the VPN tunnel.- The Dante container is named
dante
, but with your dnsmasq setup and the alias,gateway.docker
will resolve to it.
With this configuration you should now be able to run
HTTPS_PROXY=socks5h://gateway.docker curl https://ifconfig.me
. Since there
isn’t any port mapping you can run as many instances as you want for example
us-east.docker
, us-west.docker
, and applications running in Docker and your
k8s cluster can use the VPN as well.
Check out this repo for a no-guarantees example of this configuration.