diff --git a/Dockerfile b/Dockerfile index ac2841dc..5dff7789 100644 --- a/Dockerfile +++ b/Dockerfile @@ -29,11 +29,22 @@ LABEL \ org.opencontainers.image.source="https://github.com/qdm12/private-internet-access-docker" \ org.opencontainers.image.title="PIA client" \ org.opencontainers.image.description="VPN client to tunnel to private internet access servers using OpenVPN, IPtables, DNS over TLS and Alpine Linux" -ENV USER= \ - PASSWORD= \ - ENCRYPTION=strong \ +ENV VPNSP=pia \ + USER= \ PROTOCOL=udp \ + TZ= \ + # PIA only + PASSWORD= \ REGION="CA Montreal" \ + ENCRYPTION=strong \ + PORT_FORWARDING=off \ + PORT_FORWARDING_STATUS_FILE="/forwarded_port" \ + # Mullvad only + COUNTRY=Sweden \ + CITY= \ + ISP= \ + PORT= \ + # DNS over TLS DOT=on \ DOT_PROVIDERS=cloudflare \ DOT_PRIVATE_ADDRESS=127.0.0.1/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,169.254.0.0/16,::1/128,fc00::/7,fe80::/10,::ffff:0:0/96 \ @@ -45,19 +56,19 @@ ENV USER= \ BLOCK_SURVEILLANCE=off \ BLOCK_ADS=off \ UNBLOCK= \ + # Firewall EXTRA_SUBNETS= \ - PORT_FORWARDING=off \ - PORT_FORWARDING_STATUS_FILE="/forwarded_port" \ + # Tinyproxy TINYPROXY=off \ TINYPROXY_LOG=Info \ TINYPROXY_PORT=8888 \ TINYPROXY_USER= \ TINYPROXY_PASSWORD= \ + # Shadowsocks SHADOWSOCKS=off \ SHADOWSOCKS_LOG=on \ SHADOWSOCKS_PORT=8388 \ - SHADOWSOCKS_PASSWORD= \ - TZ= + SHADOWSOCKS_PASSWORD= ENTRYPOINT /entrypoint EXPOSE 8888/tcp 8388/tcp 8388/udp HEALTHCHECK --interval=3m --timeout=3s --start-period=20s --retries=1 CMD /entrypoint healthcheck diff --git a/README.md b/README.md index e0e68b9f..7c6dc543 100644 --- a/README.md +++ b/README.md @@ -121,10 +121,14 @@ docker run --rm --network=container:pia alpine:3.10 wget -qO- https://ipinfo.io | Environment variable | Default | Description | | --- | --- | --- | -| `REGION` | `CA Montreal` | One of the [PIA regions](https://www.privateinternetaccess.com/pages/network/) | +| `REGION` | `CA Montreal` | (PIA only) one of the [PIA regions](https://www.privateinternetaccess.com/pages/network/) | +| `COUNTRY` | `Sweden` | (Mullvad only) one of the [Mullvad countries](https://mullvad.net/en/servers/#openvpn) | +| `CITY` | | (Mullvad only, *optional*) one of the [Mullvad cities](https://mullvad.net/en/servers/#openvpn) | +| `ISP` | | (Mullvad only, *optional*) one of the [Mullvad ISP](https://mullvad.net/en/servers/#openvpn) | +| `PORT` | | (Mullvad only, *optional*) For TCP, `80` or `443`, or `53` for UDP. Leave blank for default Mullvad server port | | `PROTOCOL` | `udp` | `tcp` or `udp` | -| `ENCRYPTION` | `strong` | `normal` or `strong` | -| `USER` | | Your PIA username | +| `ENCRYPTION` | `strong` | (PIA only) `normal` or `strong` | +| `USER` | | PIA username **or** Mullvad user ID | | `PASSWORD` | | Your PIA password | | `DOT` | `on` | `on` or `off`, to activate DNS over TLS to 1.1.1.1 | | `DOT_PROVIDERS` | `cloudflare` | Comma delimited list of DNS over TLS providers from `cloudflare`, `google`, `quad9`, `quadrant`, `cleanbrowsing`, `securedns`, `libredns` | @@ -138,8 +142,8 @@ docker run --rm --network=container:pia alpine:3.10 wget -qO- https://ipinfo.io | `BLOCK_ADS` | `off` | `on` or `off`, blocks ads hostnames and IPs | | `UNBLOCK` | | comma separated string (i.e. `web.com,web2.ca`) to unblock hostnames | | `EXTRA_SUBNETS` | | comma separated subnets allowed in the container firewall (i.e. `192.168.1.0/24,192.168.10.121,10.0.0.5/28`) | -| `PORT_FORWARDING` | `off` | Set to `on` to forward a port on PIA server | -| `PORT_FORWARDING_STATUS_FILE` | `/forwarded_port` | File path to store the forwarded port number | +| `PORT_FORWARDING` | `off` | (PIA only) Set to `on` to forward a port on PIA server | +| `PORT_FORWARDING_STATUS_FILE` | `/forwarded_port` | (PIA only) File path to store the forwarded port number | | `TINYPROXY` | `off` | `on` or `off`, to enable the internal HTTP proxy tinyproxy | | `TINYPROXY_LOG` | `Info` | `Info`, `Connect`, `Notice`, `Warning`, `Error` or `Critical` | | `TINYPROXY_PORT` | `8888` | `1024` to `65535` internal port for HTTP proxy | @@ -311,8 +315,9 @@ Note that not all regions support port forwarding. ## TODOs +- Case insensitive for env variables values - Support other VPN providers - - Mullvad + - ~Mullvad~ - Windscribe - Gotify support for notificactions - Periodic update of malicious block lists with Unbound restart diff --git a/docker-compose.yml b/docker-compose.yml index ed2a816b..08a5b496 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -14,24 +14,39 @@ services: - 8388:8388/udp # command: environment: + # More variables are available, see the readme table + - VPNSP=pia - USER=js89ds7 + - PROTOCOL=udp + - TZ= + + # PIA only + - REGION=CA Montreal - PASSWORD=8fd9s239G - ENCRYPTION=strong - - PROTOCOL=udp - - REGION=CA Montreal + - PORT_FORWARDING=off + + # Mullvad only + - COUNTRY=Sweden + - CITY= + - ISP= + - PORT= + + # DNS over TLS - DOT=on - DOT_PROVIDERS=cloudflare + - DOT_VERBOSITY=1 - BLOCK_MALICIOUS=on - BLOCK_SURVEILLANCE=off - BLOCK_ADS=off - UNBLOCK= + # Firewall - EXTRA_SUBNETS= + # Shadowsocks + - SHADOWSOCKS=off + - SHADOWSOCKS_PASSWORD= + # Tinyproxy - TINYPROXY=off - - TINYPROXY_LOG=Info - TINYPROXY_USER= - TINYPROXY_PASSWORD= - - SHADOWSOCKS=off - - SHADOWSOCKS_LOG=on - - SHADOWSOCKS_PORT=8388 - - SHADOWSOCKS_PASSWORD= restart: always diff --git a/internal/params/mullvad.go b/internal/params/mullvad.go new file mode 100644 index 00000000..318bdb04 --- /dev/null +++ b/internal/params/mullvad.go @@ -0,0 +1,40 @@ +package params + +import ( + "strings" + + libparams "github.com/qdm12/golibs/params" + "github.com/qdm12/private-internet-access-docker/internal/constants" + "github.com/qdm12/private-internet-access-docker/internal/models" +) + +// GetMullvadCountry obtains the country for the Mullvad server from the +// environment variable COUNTRY +func (p *paramsReader) GetMullvadCountry() (country models.MullvadCountry, err error) { + choices := append(constants.MullvadCityChoices(), "") + s, err := p.envParams.GetValueIfInside("COUNTRY", choices) + return models.MullvadCountry(strings.ToLower(s)), err +} + +// GetMullvadCity obtains the city for the Mullvad server from the +// environment variable CITY +func (p *paramsReader) GetMullvadCity() (country models.MullvadCity, err error) { + choices := append(constants.MullvadCityChoices(), "") + s, err := p.envParams.GetValueIfInside("CITY", choices) + return models.MullvadCity(strings.ToLower(s)), err +} + +// GetMullvadISP obtains the ISP for the Mullvad server from the +// environment variable ISP +func (p *paramsReader) GetMullvadISP() (country models.MullvadProvider, err error) { + choices := append(constants.MullvadProviderChoices(), "") + s, err := p.envParams.GetValueIfInside("ISP", choices) + return models.MullvadProvider(strings.ToLower(s)), err +} + +// GetMullvadPort obtains the port to reach the Mullvad server on from the +// environment variable PORT +func (p *paramsReader) GetMullvadPort() (port uint16, err error) { + n, err := p.envParams.GetEnvIntRange("PORT", 0, 65535, libparams.Default("0")) + return uint16(n), err +} diff --git a/internal/params/params.go b/internal/params/params.go index f18148da..489f563b 100644 --- a/internal/params/params.go +++ b/internal/params/params.go @@ -12,6 +12,8 @@ import ( // ParamsReader contains methods to obtain parameters type ParamsReader interface { + GetVPNSP() (country models.MullvadCountry, err error) + // DNS over TLS getters GetDNSOverTLS() (DNSOverTLS bool, err error) GetDNSOverTLSProviders() (providers []models.DNSProvider, err error) @@ -39,6 +41,12 @@ type ParamsReader interface { GetPIAEncryption() (models.PIAEncryption, error) GetPIARegion() (models.PIARegion, error) + // Mullvad getters + GetMullvadCountry() (country models.MullvadCountry, err error) + GetMullvadCity() (country models.MullvadCity, err error) + GetMullvadISP() (country models.MullvadProvider, err error) + GetMullvadPort() (port uint16, err error) + // Shadowsocks getters GetShadowSocks() (activated bool, err error) GetShadowSocksLog() (activated bool, err error) @@ -75,3 +83,9 @@ func NewParamsReader(logger logging.Logger) ParamsReader { unsetEnv: os.Unsetenv, } } + +// GetVPNSP obtains the VPN service provider to use from the environment variable VPNSP +func (p *paramsReader) GetVPNSP() (country models.MullvadCountry, err error) { + s, err := p.envParams.GetValueIfInside("VPNSP", []string{"pia", "mullvad"}) + return models.MullvadCountry(s), err +}