titidnh/openvpn_client_proxy

By titidnh

β€’Updated 3 months ago

Lightweight Docker: OpenVPN + Privoxy + AdGuard DNS for ad/adult content blocking via VPN.

Image
Networking
0

3.1K

titidnh/openvpn_client_proxy repository overview

⁠OpenVPN Client Proxy

Lightweight Docker container that connects to any OpenVPN server and exposes the tunnel as a plain HTTP proxy on port 3128 β€” no VPN client needed on the host, no root config, just point your app at the proxy.

docker run \
  --cap-add=NET_ADMIN \
  --device /dev/net/tun \
  -v ./vpn-config:/vpn:ro \
  -p 127.0.0.1:3128:3128 \
  titidnh/openvpn_client_proxy:latest
curl --proxy http://127.0.0.1:3128 https://api.ipify.org
# β†’ your VPN exit IP

⁠What's inside

πŸ”’ VPN Kill Switchiptables DROP by default β€” nothing leaks if the tunnel drops
πŸ›‘οΈ DNS Leak ProtectionAll DNS forced through local dnsmasq, upstream only via the tunnel
πŸ” Auto-ReconnectBuilt-in supervisor restarts any failed service with exponential backoff
🌐 HTTP ProxyPrivoxy on :3128 β€” works with any app that supports HTTP_PROXY
πŸ”‘ Optional Proxy AuthSet PROXY_USER + PROXY_PASS to require Basic Auth (nginx fronts Privoxy)
🧹 DNS FilteringConfigurable upstream DNS β€” AdGuard, Cloudflare, Quad9, or any resolver
πŸ”— Tailscale Exit NodeOptional β€” route your entire Tailscale network through the VPN
🐳 Multi-archlinux/amd64 and linux/arm64
πŸ“¦ ~120 MB imageAlpine base + multi-stage build (Tailscale binaries only)

⁠Quick setup

⁠1. Prepare your config directory
./vpn-config/
β”œβ”€β”€ vpn.conf    ← your provider's .ovpn file, renamed
└── vpn.auth    ← optional: username on line 1, password on line 2

Most VPN providers (Mullvad, ProtonVPN, NordVPN…) let you export an .ovpn file β€” just rename it vpn.conf.

⁠2. Run
docker run \
  --cap-add=NET_ADMIN \
  --device /dev/net/tun \
  --rm \
  -v ./vpn-config:/vpn:ro \
  -p 127.0.0.1:3128:3128 \
  titidnh/openvpn_client_proxy:latest
⁠3. Use the proxy
# curl
curl --proxy http://127.0.0.1:3128 https://api.ipify.org

# environment variable (works for most CLI tools)
export HTTP_PROXY="http://127.0.0.1:3128"
export HTTPS_PROXY="http://127.0.0.1:3128"

# Python
proxies = {"http": "http://127.0.0.1:3128", "https": "http://127.0.0.1:3128"}
requests.get("https://api.ipify.org", proxies=proxies)

⁠Environment variables

VariableDefaultDescription
DNS_SERVER_194.140.14.14Primary upstream DNS (AdGuard Default β€” ads blocked, no adult filter)
DNS_SERVER_294.140.15.15Secondary upstream DNS
PROXY_USER(empty)Enable Basic Auth β€” set together with PROXY_PASS
PROXY_PASS(empty)Proxy password (bcrypt-hashed at startup via htpasswd)
ENABLE_TAILSCALEfalseStart Tailscale inside the container
TAILSCALE_AUTHKEY(empty)Tailscale pre-auth key
TAILSCALE_ADVERTISE_EXIT_NODEfalseAdvertise as a Tailscale exit node
TAILSCALE_HOSTNAMEopenvpn-client-proxyHostname shown in Tailscale admin
TAILSCALE_ACCEPT_ROUTESfalseAccept routes from the tailnet
TAILSCALE_FLAGS(empty)Extra flags passed verbatim to tailscale up
⁠DNS presets
-e DNS_SERVER_1=1.1.1.1        -e DNS_SERVER_2=1.0.0.1          # Cloudflare β€” no filter
-e DNS_SERVER_1=9.9.9.9        -e DNS_SERVER_2=149.112.112.112   # Quad9 β€” malware/phishing
-e DNS_SERVER_1=94.140.14.15   -e DNS_SERVER_2=94.140.15.16      # AdGuard Family β€” ads + adult
-e DNS_SERVER_1=8.8.8.8        -e DNS_SERVER_2=8.8.4.4           # Google β€” no filter

⁠Docker Compose examples

⁠Minimal
services:
  vpnproxy:
    image: titidnh/openvpn_client_proxy:latest
    container_name: vpn_proxy
    restart: always
    cap_add: [ NET_ADMIN ]
    devices: [ "/dev/net/tun" ]
    volumes:
      - ./vpn-config:/vpn:ro
    ports:
      - "127.0.0.1:3128:3128"
⁠With proxy authentication
services:
  vpnproxy:
    image: titidnh/openvpn_client_proxy:latest
    container_name: vpn_proxy
    restart: always
    cap_add: [ NET_ADMIN ]
    devices: [ "/dev/net/tun" ]
    volumes:
      - ./vpn-config:/vpn:ro
    ports:
      - "3128:3128"    # safe to expose β€” auth required
    environment:
      PROXY_USER: "alice"
      PROXY_PASS: "s3cr3t!"
curl --proxy http://alice:[email protected]:3128 https://api.ipify.org
⁠Route another container through the VPN
services:
  vpnproxy:
    image: titidnh/openvpn_client_proxy:latest
    restart: always
    cap_add: [ NET_ADMIN ]
    devices: [ "/dev/net/tun" ]
    volumes:
      - ./vpn-config:/vpn:ro

  myapp:
    image: myapp:latest
    depends_on:
      vpnproxy:
        condition: service_healthy
    environment:
      HTTP_PROXY:  "http://vpn_proxy:3128"
      HTTPS_PROXY: "http://vpn_proxy:3128"
⁠With Tailscale exit node
services:
  vpnproxy:
    image: titidnh/openvpn_client_proxy:latest
    restart: always
    cap_add: [ NET_ADMIN ]
    devices: [ "/dev/net/tun" ]
    sysctls:
      net.ipv4.ip_forward: "1"
      net.ipv6.conf.all.forwarding: "1"
    volumes:
      - ./vpn-config:/vpn:ro
      - tailscale-state:/var/lib/tailscale
    ports:
      - "3128:3128"
    environment:
      PROXY_USER:                    "alice"
      PROXY_PASS:                    "s3cr3t!"
      ENABLE_TAILSCALE:              "true"
      TAILSCALE_AUTHKEY:             "tskey-auth-xxxx"
      TAILSCALE_ADVERTISE_EXIT_NODE: "true"
      TAILSCALE_HOSTNAME:            "my-vpn-exit-node"

volumes:
  tailscale-state:

⁠Security

The proxy listens on 0.0.0.0:3128 with no authentication by default. Pick at least one mitigation:

OptionHow
Enable authSet PROXY_USER + PROXY_PASS β€” nginx enforces Basic Auth, bcrypt-hashed
Localhost only-p 127.0.0.1:3128:3128
Internal networkDon't publish the port β€” use a named Docker bridge between containers

Basic Auth sends credentials in base64. For exposure beyond localhost, combine with auth + a trusted network boundary.


⁠Requirements

  • Docker Engine β‰₯ 20.10
  • NET_ADMIN capability + /dev/net/tun device
  • Host kernel with tun module loaded (modprobe tun)
  • A valid .ovpn config file from your VPN provider

⁠Source & docs

Full documentation, all configuration options, and troubleshooting guide on GitHub: github.com/titidnh/openvpn_client_proxy⁠

Tag summary

Content type

Image

Digest

sha256:10751d640…

Size

60.5 MB

Last updated

3 months ago

docker pull titidnh/openvpn_client_proxy