Lightweight swiss-knife-like VPN client to tunnel to Private Internet Access, Mullvad, Windscribe, Surfshark Cyberghost, VyprVPN and NordVPN VPN servers, using Go, OpenVPN, iptables, DNS over TLS, ShadowSocks and Tinyproxy
ANNOUNCEMENT: Video of the Git history of Gluetun
Click to show base components
- Alpine 3.12 for a tiny image (37MB of packages, 6.7MB of Go binary and 5.6MB for Alpine)
- OpenVPN 2.4.9 to tunnel to your VPN provider servers
- IPtables 1.8.4 enforces the container to communicate only through the VPN or with other containers in its virtual network (acts as a killswitch)
- Unbound 1.10.1 configured with Cloudflare's 1.1.1.1 DNS over TLS (configurable with 5 different providers)
- Files and blocking lists built periodically used with Unbound (see
BLOCK_MALICIOUS
,BLOCK_SURVEILLANCE
andBLOCK_ADS
environment variables) - TinyProxy 1.10.0
- Shadowsocks 3.3.4
- Based on Alpine 3.12 for a small Docker image of 52MB
- Supports Private Internet Access, Mullvad, Windscribe, Surfshark, Cyberghost, Vyprvpn and NordVPN servers
- DNS over TLS baked in with service provider(s) of your choice
- DNS fine blocking of malicious/ads/surveillance hostnames and IP addresses, with live update every 24 hours
- Choose the vpn network protocol,
udp
ortcp
- Built in firewall kill switch to allow traffic only with needed the VPN servers and LAN devices
- Built in SOCKS5 proxy (Shadowsocks, tunnels TCP+UDP)
- Built in HTTP proxy (Tinyproxy, tunnels TCP)
- Connect other containers to it
- Connect LAN devices to it
- Compatible with amd64, i686 (32 bit), ARM 64 bit, ARM 32 bit v6 and v7 π
- Private Internet Access: pick the region, the level of encryption and enable port forwarding
- Mullvad: Pick the country, city and ISP and optionally a custom port to use (i.e.
53
(udp) or80
(tcp)) - Windscribe: Pick the region, and optionally a custom port to use
- Surfshark: Pick the region or a multi hop region name
- Cyberghost: Pick the region and server group.
- VyprVPN: Pick the region, port forwarding works by default
- NordVPN: Pick the region and optionally the server number
- Possibility of split horizon DNS by selecting multiple DNS over TLS providers
- Subprograms all drop root privileges once launched
- Subprograms output streams are all merged together
- Can work as a Kubernetes sidecar container, thanks @rorph
-
Requirements
- A VPN account with one of the service providers:
-
Private Internet Access: username and password (sign up)
-
Mullvad: user ID (sign up)
-
Windscribe: username and password | Signup up using my affiliate link below
-
Surfshark: username and password (sign up)
-
Cyberghost: username, password and device client key file (sign up)
-
Vyprvpn: username and password
-
NordVPN: username and password
-
- If you have a host or router firewall, please refer to the firewall documentation
- A VPN account with one of the service providers:
-
On some devices you may need to setup your tunnel kernel module on your host with
insmod /lib/modules/tun.ko
ormodprobe tun
- Synology users: please read this part of the Wiki
-
Launch the container with:
docker run -d --name gluetun --cap-add=NET_ADMIN \ -e REGION="CA Montreal" -e USER=js89ds7 -e PASSWORD=8fd9s239G \ qmcgaw/private-internet-access
or use docker-compose.yml with:
docker-compose up -d
Note that you can:
- Change the many environment variables available
- Use
-p 8888:8888/tcp
to access the HTTP web proxy (and put your LAN inEXTRA_SUBNETS
environment variable, in example192.168.1.0/24
) - Use
-p 8388:8388/tcp -p 8388:8388/udp
to access the SOCKS5 proxy (and put your LAN inEXTRA_SUBNETS
environment variable, in example192.168.1.0/24
) - Use
-p 8000:8000/tcp
to access the HTTP control server built-in
If you encounter an issue with the tun device not being available, see the FAQ
-
You can update the image with
docker pull qmcgaw/private-internet-access:latest
. See the wiki for more information on other tags available.
Check the VPN IP address matches your expectations
docker run --rm --network=container:gluetun alpine:3.12 wget -qO- https://ipinfo.io
Want more testing? βΆ see the Wiki
TLDR; only set the π marked environment variables to get started.
Variable | Default | Choices | Description |
---|---|---|---|
π VPNSP |
private internet access |
private internet access , mullvad , windscribe , surfshark , vyprvpn , nordvpn |
VPN Service Provider |
IP_STATUS_FILE |
/ip |
Any filepath | Filepath to store the public IP address assigned |
PROTOCOL |
udp |
udp or tcp |
Network protocol to use |
OPENVPN_VERBOSITY |
1 |
0 to 6 |
Openvpn verbosity level |
OPENVPN_ROOT |
no |
yes or no |
Run OpenVPN as root |
OPENVPN_TARGET_IP |
Valid IP address | Specify a target VPN server (or gateway) IP address to use | |
OPENVPN_CIPHER |
i.e. aes-256-gcm |
Specify a custom cipher to use. It will also set ncp-disable if using AES GCM for PIA |
|
OPENVPN_AUTH |
i.e. sha256 |
Specify a custom auth algorithm to use |
-
Private Internet Access
Variable Default Choices Description π USER
Your username π PASSWORD
Your password REGION
Austria
One of the PIA regions VPN server region PIA_ENCRYPTION
strong
normal
,strong
Encryption preset PORT_FORWARDING
off
on
,off
Enable port forwarding on the VPN server PORT_FORWARDING_STATUS_FILE
/forwarded_port
Any filepath Filepath to store the forwarded port number -
Mullvad
Variable Default Choices Description π USER
Your user ID COUNTRY
Sweden
One of the Mullvad countries VPN server country CITY
One of the Mullvad cities VPN server city ISP
One of the Mullvad ISP VPN server ISP PORT
80
or443
for TCP; or53
for UDP. Leave blank for default Mullvad server portCustom VPN port to use -
Windscribe
Variable Default Choices Description π USER
Your username π PASSWORD
Your password REGION
Austria
One of the Windscribe regions VPN server region PORT
One from the this list of ports Custom VPN port to use -
Surfshark
Variable Default Choices Description π USER
Your service username, found at the bottom of the manual setup page π PASSWORD
Your service password REGION
Austria
One of the Surfshark regions (subdomains) VPN server region -
Cyberghost
Variable Default Choices Description π USER
Your username π PASSWORD
Your password π CLIENT_KEY
Your device client key content, see below REGION
Austria
One of the Cyberghost countries VPN server country CYBERGHOST_GROUP
Premium UDP Europe
One of the server groups Server group To specify your client key, you can either:
-
Bind mount it at
/files/client.key
, for example with-v /yourpath/client.key:/files/client.key:ro
-
Convert it to a single line value using:
docker run -it --rm -v /yourpath/client.key:/files/client.key:ro qmcgaw/private-internet-access clientkey
And use the line produced as the value for the environment variable
CLIENT_KEY
.
-
-
Vyprvpn
Variable Default Choices Description π USER
Your username π PASSWORD
Your password REGION
Austria
One of the VyprVPN regions VPN server region -
NordVPN
Variable Default Choices Description π USER
Your username π PASSWORD
Your password π REGION
Austria
(wrong)One of the NordVPN server country, i.e. Switzerland
VPN server country SERVER_NUMBER
Server integer number Optional server number. For example 251
forItaly #251
None of the following values are required.
Variable | Default | Choices | Description |
---|---|---|---|
DOT |
on |
on , off |
Activate DNS over TLS with Unbound |
DOT_PROVIDERS |
cloudflare |
cloudflare , google , quad9 , quadrant , cleanbrowsing , securedns , libredns |
Comma delimited list of DNS over TLS providers |
DOT_CACHING |
on |
on , off |
Unbound caching |
DOT_IPV6 |
off |
on , off |
DNS IPv6 resolution |
DOT_PRIVATE_ADDRESS |
All private CIDRs ranges | Comma separated list of CIDRs or single IP addresses Unbound won't resolve to. Note that the default setting prevents DNS rebinding | |
DOT_VERBOSITY |
1 |
0 to 5 |
Unbound verbosity level |
DOT_VERBOSITY_DETAILS |
0 |
0 to 4 |
Unbound details verbosity level |
DOT_VALIDATION_LOGLEVEL |
0 |
0 to 2 |
Unbound validation log level |
DNS_UPDATE_PERIOD |
24h |
i.e. 0 , 30s , 5m , 24h |
Period to update block lists and cryptographic files and restart Unbound. Set to 0 to deactivate updates |
BLOCK_MALICIOUS |
on |
on , off |
Block malicious hostnames and IPs with Unbound |
BLOCK_SURVEILLANCE |
off |
on , off |
Block surveillance hostnames and IPs with Unbound |
BLOCK_ADS |
off |
on , off |
Block ads hostnames and IPs with Unbound |
UNBLOCK |
i.e. domain1.com,x.domain2.co.uk |
Comma separated list of domain names to leave unblocked with Unbound | |
DNS_PLAINTEXT_ADDRESS |
1.1.1.1 |
Any IP address | IP address to use as DNS resolver if DOT is off |
DNS_KEEP_NAMESERVER |
off |
on or off |
Keep the nameservers in /etc/resolv.conf untouched, but disabled DNS blocking features |
That one is important if you want to connect to the container from your LAN for example, using Shadowsocks or Tinyproxy.
Variable | Default | Choices | Description |
---|---|---|---|
FIREWALL |
on |
on or off |
Turn on or off the container built-in firewall. You should use it for debugging purposes only. |
EXTRA_SUBNETS |
i.e. 192.168.1.0/24,192.168.10.121,10.0.0.5/28 |
Comma separated subnets allowed in the container firewall | |
FIREWALL_DEBUG |
off |
on or off |
Prints every firewall related command. You should use it for debugging purposes only. |
Variable | Default | Choices | Description |
---|---|---|---|
SHADOWSOCKS |
off |
on , off |
Enable the internal SOCKS5 proxy Shadowsocks |
SHADOWSOCKS_LOG |
off |
on , off |
Enable logging |
SHADOWSOCKS_PORT |
8388 |
1024 to 65535 |
Internal port number for Shadowsocks to listen on |
SHADOWSOCKS_PASSWORD |
Password to use to connect to Shadowsocks | ||
SHADOWSOCKS_METHOD |
chacha20-ietf-poly1305 |
One of these ciphers | Method to use for Shadowsocks |
Variable | Default | Choices | Description |
---|---|---|---|
TINYPROXY |
off |
on , off |
Enable the internal HTTP proxy tinyproxy |
TINYPROXY_LOG |
Info |
Info , Connect , Notice , Warning , Error , Critical |
Tinyproxy log level |
TINYPROXY_PORT |
8888 |
1024 to 65535 |
Internal port number for Tinyproxy to listen on |
TINYPROXY_USER |
Username to use to connect to Tinyproxy | ||
TINYPROXY_PASSWORD |
Password to use to connect to Tinyproxy |
Variable | Default | Choices | Description |
---|---|---|---|
TZ |
i.e. Europe/London |
Specify a timezone to use to have correct log times | |
UID |
1000 |
User ID to run as non root and for ownership of files written | |
GID |
1000 |
Group ID to run as non root and for ownership of files written |
Variable | Default | Choices | Description |
---|---|---|---|
PUBLICIP_PERIOD |
12h |
Valid duration | Period to check for public IP address. Set to 0 to disable. |
There are various ways to achieve this, depending on your use case.
-
Connect containers in the same docker-compose.yml as Gluetun
Add
network_mode: "service:gluetun"
to your docker-compose.yml (no need fordepends_on
) -
Connect other containers to Gluetun
Add
--network=container:gluetun
when launching the container, provided Gluetun is already running -
Connect containers from another docker-compose.yml
Add
network_mode: "container:gluetun"
to your docker-compose.yml, provided Gluetun is already running -
Connect LAN devices through the built-in HTTP proxy *Tinyproxy* (i.e. with Chrome, Kodi, etc.)
You might want to use Shadowsocks instead which tunnels UDP as well as TCP, whereas Tinyproxy only tunnels TCP.
- Setup a HTTP proxy client, such as SwitchyOmega for Chrome
- Ensure the Gluetun container is launched with:
- port
8888
published-p 8888:8888/tcp
- your LAN subnet, i.e.
192.168.1.0/24
, set as-e EXTRA_SUBNETS=192.168.1.0/24
- port
- With your HTTP proxy client, connect to the Docker host (i.e.
192.168.1.10
) on port8888
. You need to enter your credentials if you set them withTINYPROXY_USER
andTINYPROXY_PASSWORD
. - If you set
TINYPROXY_LOG
toInfo
, more information will be logged in the Docker logs
-
Connect LAN devices through the built-in SOCKS5 proxy *Shadowsocks* (per app, system wide, etc.)
- Setup a SOCKS5 proxy client, there is a list of ShadowSocks clients for all platforms
- note some clients do not tunnel UDP so your DNS queries will be done locally and not through Gluetun and its built in DNS over TLS
- Clients that support such UDP tunneling are, as far as I know:
- iOS: Potatso Lite
- OSX: ShadowsocksX
- Android: Shadowsocks by Max Lv
- Ensure the Gluetun container is launched with:
- port
8388
published-p 8388:8388/tcp -p 8388:8388/udp
- your LAN subnet, i.e.
192.168.1.0/24
, set as-e EXTRA_SUBNETS=192.168.1.0/24
- port
- With your SOCKS5 proxy client
- Enter the Docker host (i.e.
192.168.1.10
) as the server IP - Enter port TCP (and UDP, if available)
8388
as the server port - Use the password you have set with
SHADOWSOCKS_PASSWORD
- Choose the encryption method/algorithm to the method you specified in
SHADOWSOCKS_METHOD
- Enter the Docker host (i.e.
- If you set
SHADOWSOCKS_LOG
toon
, (a lot) more information will be logged in the Docker logs
- Setup a SOCKS5 proxy client, there is a list of ShadowSocks clients for all platforms
-
Access ports of containers connected to Gluetun
In example, to access port
8000
of containerxyz
and9000
of containerabc
connected to Gluetun, publish ports8000
and9000
for the Gluetun container and access them as you would with any other container -
Access ports of containers connected to Gluetun, all in the same docker-compose.yml
In example, to access port
8000
of containerxyz
and9000
of containerabc
connected to Gluetun, publish port8000
and9000
for the Gluetun container. The docker-compose.yml file would look like:version: '3.7' services: gluetun: image: qmcgaw/private-internet-access container_name: gluetun cap_add: - NET_ADMIN environment: - USER=js89ds7 - PASSWORD=8fd9s239G ports: - 8000:8000/tcp - 9000:9000/tcp abc: image: abc container_name: abc network_mode: "service:gluetun" xyz: image: xyz container_name: xyz network_mode: "service:gluetun"
Note that not all regions support port forwarding.
When PORT_FORWARDING=on
, a port will be forwarded on the VPN server side and written to the file specified by PORT_FORWARDING_STATUS_FILE=/forwarded_port
.
It can be useful to mount this file as a volume to read it from other containers, for example to configure a torrenting client.
A built-in HTTP server listens on port 8000
to modify the state of the container. You have the following routes available:
http://<your-docker-host-ip>:8000/openvpn/actions/restart
restarts the openvpn processhttp://<your-docker-host-ip>:8000/unbound/actions/restart
re-downloads the DNS files (crypto and block lists) and restarts the unbound process
- Contribute with code: see the Wiki.
- The list of existing contributors π
- Github workflows to know what's building
- List of issues and feature requests
This repository is under an MIT license
Sponsor me on Github, donate to paypal.me/qmcgaw or subscribe to a VPN provider through one of my affiliate links:
Feel also free to have a look at the Kanban board and contribute to the code or the issues discussion.
Many thanks to @Frepke, @Ralph521, G. Mendez, M. Otmar Weber, J. Perez and A. Cooper for supporting me financially π₯π