diff --git a/Dockerfile b/Dockerfile index b29cbc3f6..120f0e7d8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -43,6 +43,7 @@ ENV VPNSP=pia \ OPENVPN_VERBOSITY=1 \ OPENVPN_ROOT=no \ OPENVPN_TARGET_IP= \ + OPENVPN_IPV6=off \ TZ= \ UID=1000 \ GID=1000 \ diff --git a/README.md b/README.md index 9ad6783a3..42d69e66e 100644 --- a/README.md +++ b/README.md @@ -103,6 +103,7 @@ docker run --rm --network=container:gluetun alpine:3.12 wget -qO- https://ipinfo | `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 | +| `OPENVPN_IPV6` | `off` | `on`, `off` | Enable tunneling of IPv6 (only for Mullvad) | *For all providers below, server location parameters are all optional. By default a random server is picked using the filter settings provided.* @@ -127,6 +128,8 @@ docker run --rm --network=container:gluetun alpine:3.12 wget -qO- https://ipinfo | `ISP` | | One of the [Mullvad ISP](https://mullvad.net/en/servers/#openvpn) | VPN server ISP | | `PORT` | | `80`, `443` or `1401` for TCP; `53`, `1194`, `1195`, `1196`, `1197`, `1300`, `1301`, `1302`, `1303` or `1400` for UDP. Defaults to TCP `443` and UDP `1194` | Custom VPN port to use | + 💡 [Mullvad IPv6 Wiki page](https://github.com/qdm12/gluetun/wiki/Mullvad-IPv6) + - Windscribe | Variable | Default | Choices | Description | diff --git a/internal/models/selection.go b/internal/models/selection.go index b4443dd5b..d0b36e653 100644 --- a/internal/models/selection.go +++ b/internal/models/selection.go @@ -46,6 +46,7 @@ type ServerSelection struct { //nolint:maligned type ExtraConfigOptions struct { ClientKey string `json:"-"` // Cyberghost EncryptionPreset string `json:"encryptionPreset"` // PIA + OpenVPNIPv6 bool `json:"openvpnIPv6"` // Mullvad } // PortForwarding contains settings for port forwarding @@ -74,6 +75,10 @@ func (p *ProviderSettings) String() string { if p.ServerSelection.Number > 0 { number = fmt.Sprintf("%d", p.ServerSelection.Number) } + ipv6 := "off" + if p.ExtraConfigOptions.OpenVPNIPv6 { + ipv6 = "on" + } switch strings.ToLower(string(p.Name)) { case "private internet access old": settingsList = append(settingsList, @@ -92,6 +97,7 @@ func (p *ProviderSettings) String() string { "City: "+p.ServerSelection.City, "ISP: "+p.ServerSelection.ISP, "Custom port: "+customPort, + "IPv6: "+ipv6, ) case "windscribe": settingsList = append(settingsList, diff --git a/internal/params/openvpn.go b/internal/params/openvpn.go index 552f741b8..61e5403aa 100644 --- a/internal/params/openvpn.go +++ b/internal/params/openvpn.go @@ -81,3 +81,9 @@ func (r *reader) GetOpenVPNCipher() (cipher string, err error) { func (r *reader) GetOpenVPNAuth() (auth string, err error) { return r.envParams.GetEnv("OPENVPN_AUTH") } + +// GetOpenVPNIPv6 obtains if ipv6 should be tunneled through the +// openvpn tunnel from the environment variable OPENVPN_IPV6 +func (r *reader) GetOpenVPNIPv6() (ipv6 bool, err error) { + return r.envParams.GetOnOff("OPENVPN_IPV6", libparams.Default("off")) +} diff --git a/internal/params/params.go b/internal/params/params.go index 959cf2eb1..4a5f9643d 100644 --- a/internal/params/params.go +++ b/internal/params/params.go @@ -54,6 +54,7 @@ type Reader interface { GetTargetIP() (ip net.IP, err error) GetOpenVPNCipher() (cipher string, err error) GetOpenVPNAuth() (auth string, err error) + GetOpenVPNIPv6() (tunnel bool, err error) // PIA getters GetPortForwarding() (activated bool, err error) diff --git a/internal/provider/mullvad.go b/internal/provider/mullvad.go index abde1ac47..8f0a8fc42 100644 --- a/internal/provider/mullvad.go +++ b/internal/provider/mullvad.go @@ -94,7 +94,6 @@ func (m *mullvad) BuildConf(connections []models.OpenVPNConnection, verbosity, u "sndbuf 524288", "rcvbuf 524288", "tls-cipher TLS-DHE-RSA-WITH-AES-256-GCM-SHA384:TLS-DHE-RSA-WITH-AES-256-CBC-SHA", - "tun-ipv6", "fast-io", "script-security 2", @@ -112,6 +111,12 @@ func (m *mullvad) BuildConf(connections []models.OpenVPNConnection, verbosity, u fmt.Sprintf("proto %s", connections[0].Protocol), fmt.Sprintf("cipher %s", cipher), } + if extras.OpenVPNIPv6 { + lines = append(lines, "tun-ipv6") + } else { + lines = append(lines, `pull-filter ignore "route-ipv6"`) + lines = append(lines, `pull-filter ignore "ifconfig-ipv6"`) + } if !root { lines = append(lines, "user nonrootuser") } diff --git a/internal/settings/openvpn_test.go b/internal/settings/openvpn_test.go index 8ff6e3eeb..3339f8220 100644 --- a/internal/settings/openvpn_test.go +++ b/internal/settings/openvpn_test.go @@ -19,7 +19,7 @@ func Test_OpenVPN_JSON(t *testing.T) { } data, err := json.Marshal(in) require.NoError(t, err) - assert.Equal(t, `{"user":"","verbosity":0,"runAsRoot":true,"cipher":"","auth":"","provider":{"name":"name","serverSelection":{"networkProtocol":"","region":"","group":"","country":"","city":"","isp":"","owned":false,"customPort":0,"number":0,"encryptionPreset":""},"extraConfig":{"encryptionPreset":""},"portForwarding":{"enabled":false,"filepath":""}}}`, string(data)) + assert.Equal(t, `{"user":"","verbosity":0,"runAsRoot":true,"cipher":"","auth":"","provider":{"name":"name","serverSelection":{"networkProtocol":"","region":"","group":"","country":"","city":"","isp":"","owned":false,"customPort":0,"number":0,"encryptionPreset":""},"extraConfig":{"encryptionPreset":"","openvpnIPv6":false},"portForwarding":{"enabled":false,"filepath":""}}}`, string(data)) var out OpenVPN err = json.Unmarshal(data, &out) require.NoError(t, err) diff --git a/internal/settings/providers.go b/internal/settings/providers.go index 0aa956686..94240d8dc 100644 --- a/internal/settings/providers.go +++ b/internal/settings/providers.go @@ -106,6 +106,10 @@ func GetMullvadSettings(paramsReader params.Reader) (settings models.ProviderSet return settings, fmt.Errorf("port %d is not valid for UDP protocol", settings.ServerSelection.CustomPort) } } + settings.ExtraConfigOptions.OpenVPNIPv6, err = paramsReader.GetOpenVPNIPv6() + if err != nil { + return settings, err + } return settings, nil }