diff --git a/Dockerfile b/Dockerfile index 4c2b6b5d..ef1bbf7b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -200,10 +200,6 @@ EXPOSE 8000/tcp 8888/tcp 8388/tcp 8388/udp HEALTHCHECK --interval=5s --timeout=5s --start-period=10s --retries=1 CMD /gluetun-entrypoint healthcheck ARG TARGETPLATFORM RUN apk add --no-cache --update -l wget && \ - apk add --no-cache --update -X "https://dl-cdn.alpinelinux.org/alpine/v3.12/main" openvpn==2.4.12-r0 && \ - apk add --no-cache --update -X "https://dl-cdn.alpinelinux.org/alpine/v3.16/main" openssl\~1.1 && \ - mv /usr/sbin/openvpn /usr/sbin/openvpn2.4 && \ - apk del openvpn && \ apk add --no-cache --update openvpn ca-certificates iptables ip6tables unbound tzdata && \ mv /usr/sbin/openvpn /usr/sbin/openvpn2.5 && \ # Fix vulnerability issue diff --git a/README.md b/README.md index d35b6423..e7faa7f0 100644 --- a/README.md +++ b/README.md @@ -35,8 +35,8 @@ Lightweight swiss-knife-like VPN client to multiple VPN service providers ## Quick links -- [Setup](#Setup) -- [Features](#Features) +- [Setup](#setup) +- [Features](#features) - Problem? - [Check the Wiki](https://github.com/qdm12/gluetun/wiki) - [Start a discussion](https://github.com/qdm12/gluetun/discussions) @@ -57,7 +57,7 @@ Lightweight swiss-knife-like VPN client to multiple VPN service providers ## Features -- Based on Alpine 3.17 for a small Docker image of 42MB +- Based on Alpine 3.17 for a small Docker image of 39.1MB - Supports: **AirVPN**, **Cyberghost**, **ExpressVPN**, **FastestVPN**, **HideMyAss**, **IPVanish**, **IVPN**, **Mullvad**, **NordVPN**, **Perfect Privacy**, **Privado**, **Private Internet Access**, **PrivateVPN**, **ProtonVPN**, **PureVPN**, **SlickVPN**, **Surfshark**, **TorGuard**, **VPNSecure.me**, **VPNUnlimited**, **Vyprvpn**, **WeVPN**, **Windscribe** servers - Supports OpenVPN for all providers listed - Supports Wireguard both kernelspace and userspace diff --git a/cmd/gluetun/main.go b/cmd/gluetun/main.go index dc36f06b..5b63194e 100644 --- a/cmd/gluetun/main.go +++ b/cmd/gluetun/main.go @@ -264,7 +264,6 @@ func _main(ctx context.Context, buildInfo models.BuildInformation, err = printVersions(ctx, logger, []printVersionElement{ {name: "Alpine", getVersion: alpineConf.Version}, - {name: "OpenVPN 2.4", getVersion: ovpnConf.Version24}, {name: "OpenVPN 2.5", getVersion: ovpnConf.Version25}, {name: "Unbound", getVersion: dnsConf.Version}, {name: "IPtables", getVersion: func(ctx context.Context) (version string, err error) { diff --git a/internal/configuration/settings/openvpn.go b/internal/configuration/settings/openvpn.go index 68980eb5..b4a3dad4 100644 --- a/internal/configuration/settings/openvpn.go +++ b/internal/configuration/settings/openvpn.go @@ -17,7 +17,7 @@ import ( // OpenVPN contains settings to configure the OpenVPN client. type OpenVPN struct { // Version is the OpenVPN version to run. - // It can only be "2.4" or "2.5". + // It can only be "2.5". Version string // User is the OpenVPN authentication username. // It cannot be nil in the internal state if OpenVPN is used. @@ -88,7 +88,7 @@ var ivpnAccountID = regexp.MustCompile(`^(i|ivpn)\-[a-zA-Z0-9]{4}\-[a-zA-Z0-9]{4 func (o OpenVPN) validate(vpnProvider string) (err error) { // Validate version - validVersions := []string{openvpn.Openvpn24, openvpn.Openvpn25} + validVersions := []string{openvpn.Openvpn25} if !helpers.IsOneOf(o.Version, validVersions...) { return fmt.Errorf("%w: %q can only be one of %s", ErrOpenVPNVersionIsNotValid, o.Version, strings.Join(validVersions, ", ")) diff --git a/internal/configuration/settings/settings.go b/internal/configuration/settings/settings.go index c3471a67..1745a14d 100644 --- a/internal/configuration/settings/settings.go +++ b/internal/configuration/settings/settings.go @@ -4,7 +4,6 @@ import ( "fmt" "github.com/qdm12/gluetun/internal/configuration/settings/helpers" - "github.com/qdm12/gluetun/internal/constants/openvpn" "github.com/qdm12/gluetun/internal/constants/providers" "github.com/qdm12/gluetun/internal/constants/vpn" "github.com/qdm12/gluetun/internal/models" @@ -170,27 +169,14 @@ func (s Settings) Warnings() (warnings []string) { if helpers.IsOneOf(*s.VPN.Provider.Name, providers.SlickVPN) && s.VPN.Type == vpn.OpenVPN { - if s.VPN.OpenVPN.Version == openvpn.Openvpn24 { - warnings = append(warnings, "OpenVPN 2.4 uses OpenSSL 1.1.1 "+ - "which allows the usage of weak security in today's standards. "+ - "This can be ok if good security is enforced by the VPN provider. "+ - "However, "+*s.VPN.Provider.Name+" uses weak security so you should use "+ - "OpenVPN 2.5 to enforce good security practices.") - } else { - warnings = append(warnings, "OpenVPN 2.5 uses OpenSSL 3 "+ - "which prohibits the usage of weak security in today's standards. "+ - *s.VPN.Provider.Name+" uses weak security which is out "+ - "of Gluetun's control so the only workaround is to allow such weaknesses "+ - `using the OpenVPN option tls-cipher "DEFAULT:@SECLEVEL=0". `+ - "You might want to reach to your provider so they upgrade their certificates. "+ - "Once this is done, you will have to let the Gluetun maintainers know "+ - "by creating an issue, attaching the new certificate and we will update Gluetun.") - } - } - - if s.VPN.OpenVPN.Version == openvpn.Openvpn24 { - warnings = append(warnings, "OpenVPN 2.4 will be removed in release v3.34.0 (around June 2023). "+ - "Please create an issue if you have a compelling reason to keep it.") + warnings = append(warnings, "OpenVPN 2.5 uses OpenSSL 3 "+ + "which prohibits the usage of weak security in today's standards. "+ + *s.VPN.Provider.Name+" uses weak security which is out "+ + "of Gluetun's control so the only workaround is to allow such weaknesses "+ + `using the OpenVPN option tls-cipher "DEFAULT:@SECLEVEL=0". `+ + "You might want to reach to your provider so they upgrade their certificates. "+ + "Once this is done, you will have to let the Gluetun maintainers know "+ + "by creating an issue, attaching the new certificate and we will update Gluetun.") } return warnings diff --git a/internal/constants/openvpn/versions.go b/internal/constants/openvpn/versions.go index 19b578d3..93789f5e 100644 --- a/internal/constants/openvpn/versions.go +++ b/internal/constants/openvpn/versions.go @@ -1,6 +1,5 @@ package openvpn const ( - Openvpn24 = "2.4" Openvpn25 = "2.5" ) diff --git a/internal/openvpn/start.go b/internal/openvpn/start.go index f8cfc244..a4b1a210 100644 --- a/internal/openvpn/start.go +++ b/internal/openvpn/start.go @@ -14,7 +14,6 @@ import ( var ErrVersionUnknown = errors.New("OpenVPN version is unknown") const ( - binOpenvpn24 = "openvpn2.4" binOpenvpn25 = "openvpn2.5" ) @@ -22,8 +21,6 @@ func start(ctx context.Context, starter command.Starter, version string, flags [ stdoutLines, stderrLines chan string, waitError chan error, err error) { var bin string switch version { - case openvpn.Openvpn24: - bin = binOpenvpn24 case openvpn.Openvpn25: bin = binOpenvpn25 default: diff --git a/internal/openvpn/version.go b/internal/openvpn/version.go index 19df6605..7631cb9f 100644 --- a/internal/openvpn/version.go +++ b/internal/openvpn/version.go @@ -8,10 +8,6 @@ import ( "strings" ) -func (c *Configurator) Version24(ctx context.Context) (version string, err error) { - return c.version(ctx, binOpenvpn24) -} - func (c *Configurator) Version25(ctx context.Context) (version string, err error) { return c.version(ctx, binOpenvpn25) } diff --git a/internal/provider/airvpn/openvpnconf.go b/internal/provider/airvpn/openvpnconf.go index 9e22e084..e1f04f86 100644 --- a/internal/provider/airvpn/openvpnconf.go +++ b/internal/provider/airvpn/openvpnconf.go @@ -24,8 +24,6 @@ func (p *Provider) OpenVPNConfig(connection models.Connection, } switch settings.Version { - case openvpn.Openvpn24: - providerSettings.Ciphers = []string{openvpn.AES256cbc} case openvpn.Openvpn25: providerSettings.Ciphers = []string{ openvpn.AES256gcm, openvpn.AES256cbc, openvpn.AES192gcm, diff --git a/internal/provider/custom/openvpnconf.go b/internal/provider/custom/openvpnconf.go index ab6ffa42..2639804d 100644 --- a/internal/provider/custom/openvpnconf.go +++ b/internal/provider/custom/openvpnconf.go @@ -79,7 +79,7 @@ func modifyConfig(lines []string, connection models.Connection, } modified = append(modified, "verb "+strconv.Itoa(*settings.Verbosity)) if len(settings.Ciphers) > 0 { - modified = append(modified, utils.CipherLines(settings.Ciphers, settings.Version)...) + modified = append(modified, utils.CipherLines(settings.Ciphers)...) } if *settings.Auth != "" { modified = append(modified, "auth "+*settings.Auth) diff --git a/internal/provider/slickvpn/openvpnconf.go b/internal/provider/slickvpn/openvpnconf.go index 746ce1c3..0b3215f7 100644 --- a/internal/provider/slickvpn/openvpnconf.go +++ b/internal/provider/slickvpn/openvpnconf.go @@ -28,13 +28,11 @@ func (p *Provider) OpenVPNConfig(connection models.Connection, }, } - if settings.Version == openvpn.Openvpn25 { - // SlickVPN's certificate is sha1WithRSAEncryption and sha1 is now - // rejected by openssl 3.x.x which is used by OpenVPN >= 2.5. - // We lower the security level to 3 to allow this algorithm, - // see https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_set_security_level.html - providerSettings.TLSCipher = "DEFAULT:@SECLEVEL=0" - } + // SlickVPN's certificate is sha1WithRSAEncryption and sha1 is now + // rejected by openssl 3.x.x which is used by OpenVPN >= 2.5. + // We lower the security level to 3 to allow this algorithm, + // see https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_set_security_level.html + providerSettings.TLSCipher = "DEFAULT:@SECLEVEL=0" return utils.OpenVPNConfig(providerSettings, connection, settings, ipv6Supported) } diff --git a/internal/provider/utils/cipher.go b/internal/provider/utils/cipher.go index d8ea48c2..f407403c 100644 --- a/internal/provider/utils/cipher.go +++ b/internal/provider/utils/cipher.go @@ -2,25 +2,15 @@ package utils import ( "strings" - - "github.com/qdm12/gluetun/internal/constants/openvpn" ) -func CipherLines(ciphers []string, version string) (lines []string) { +func CipherLines(ciphers []string) (lines []string) { if len(ciphers) == 0 { return nil } - switch version { - case openvpn.Openvpn24: - return []string{ - "cipher " + ciphers[0], - "ncp-ciphers " + strings.Join(ciphers, ":"), - } - default: // 2.5 and above - return []string{ - "data-ciphers-fallback " + ciphers[0], - "data-ciphers " + strings.Join(ciphers, ":"), - } + return []string{ + "data-ciphers-fallback " + ciphers[0], + "data-ciphers " + strings.Join(ciphers, ":"), } } diff --git a/internal/provider/utils/cipher_test.go b/internal/provider/utils/cipher_test.go index d4bfc942..a48d06ed 100644 --- a/internal/provider/utils/cipher_test.go +++ b/internal/provider/utils/cipher_test.go @@ -20,14 +20,6 @@ func Test_CipherLines(t *testing.T) { "data-ciphers AES", }, }, - "2.4": { - ciphers: []string{"AES", "CBC"}, - version: "2.4", - lines: []string{ - "cipher AES", - "ncp-ciphers AES:CBC", - }, - }, "2.5": { ciphers: []string{"AES", "CBC"}, version: "2.5", @@ -42,7 +34,7 @@ func Test_CipherLines(t *testing.T) { t.Run(name, func(t *testing.T) { t.Parallel() - lines := CipherLines(testCase.ciphers, testCase.version) + lines := CipherLines(testCase.ciphers) assert.Equal(t, testCase.lines, lines) }) diff --git a/internal/provider/utils/openvpn.go b/internal/provider/utils/openvpn.go index 6bf012a1..98ff0877 100644 --- a/internal/provider/utils/openvpn.go +++ b/internal/provider/utils/openvpn.go @@ -119,7 +119,7 @@ func OpenVPNConfig(provider OpenVPNProviderSettings, } ciphers := defaultStringSlice(settings.Ciphers, provider.Ciphers) - cipherLines := CipherLines(ciphers, settings.Version) + cipherLines := CipherLines(ciphers) lines.addLines(cipherLines) auth := defaultString(*settings.Auth, provider.Auth) @@ -198,16 +198,14 @@ func OpenVPNConfig(provider OpenVPNProviderSettings, if *settings.EncryptedKey != "" { encryptedBase64DERKey := *settings.EncryptedKey - if settings.Version != openvpn.Openvpn24 { - // OpenVPN above 2.4 does not support old encryption schemes such as - // DES-CBC, so decrypt and reencrypt the key. - // This is a workaround for VPN secure. - var err error - encryptedBase64DERKey, err = pkcs8.UpgradeEncryptedKey(encryptedBase64DERKey, *settings.KeyPassphrase) - if err != nil { - // TODO return an error instead. - panic(fmt.Sprintf("upgrading encrypted key: %s", err)) - } + // OpenVPN above 2.4 does not support old encryption schemes such as + // DES-CBC, so decrypt and reencrypt the key. + // This is a workaround for VPN secure. + var err error + encryptedBase64DERKey, err = pkcs8.UpgradeEncryptedKey(encryptedBase64DERKey, *settings.KeyPassphrase) + if err != nil { + // TODO return an error instead. + panic(fmt.Sprintf("upgrading encrypted key: %s", err)) } lines.add("askpass", openvpn.AskPassPath) lines.addLines(WrapOpenvpnEncryptedKey(encryptedBase64DERKey)) diff --git a/internal/provider/vpnunlimited/openvpnconf.go b/internal/provider/vpnunlimited/openvpnconf.go index af836e3e..e11391c0 100644 --- a/internal/provider/vpnunlimited/openvpnconf.go +++ b/internal/provider/vpnunlimited/openvpnconf.go @@ -2,7 +2,6 @@ package vpnunlimited import ( "github.com/qdm12/gluetun/internal/configuration/settings" - "github.com/qdm12/gluetun/internal/constants/openvpn" "github.com/qdm12/gluetun/internal/models" "github.com/qdm12/gluetun/internal/provider/utils" ) @@ -20,13 +19,11 @@ func (p *Provider) OpenVPNConfig(connection models.Connection, }, } - if settings.Version != openvpn.Openvpn24 { - // VPN Unlimited's certificate is sha1WithRSAEncryption and sha1 is now - // rejected by openssl 3.x.x which is used by OpenVPN >= 2.5. - // We lower the security level to 0 to allow this algorithm, - // see https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_set_security_level.html - providerSettings.TLSCipher = `"DEFAULT:@SECLEVEL=0"` - } + // VPN Unlimited's certificate is sha1WithRSAEncryption and sha1 is now + // rejected by openssl 3.x.x which is used by OpenVPN >= 2.5. + // We lower the security level to 0 to allow this algorithm, + // see https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_set_security_level.html + providerSettings.TLSCipher = `"DEFAULT:@SECLEVEL=0"` return utils.OpenVPNConfig(providerSettings, connection, settings, ipv6Supported) }