From b829490aac17ef1e853450c5861c79a23621ca5e Mon Sep 17 00:00:00 2001 From: "Quentin McGaw (desktop)" Date: Mon, 31 May 2021 18:54:36 +0000 Subject: [PATCH] Feature: OPENVPN_VERSION which can be 2.4 or 2.5 --- Dockerfile | 6 ++++- README.md | 2 +- cmd/gluetun/main.go | 5 ++-- internal/configuration/openvpn.go | 10 ++++++- internal/configuration/openvpn_test.go | 3 ++- internal/configuration/settings_test.go | 2 ++ internal/constants/openvpn.go | 5 ++++ internal/openvpn/command.go | 36 +++++++++++++++++++++---- internal/openvpn/loop.go | 2 +- internal/openvpn/openvpn.go | 7 ++--- internal/provider/utils/cipher.go | 8 +++--- internal/provider/utils/cipher_test.go | 8 +++--- 12 files changed, 71 insertions(+), 23 deletions(-) diff --git a/Dockerfile b/Dockerfile index 784a3520..81439ca2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -65,6 +65,7 @@ LABEL \ ENV VPNSP=pia \ VERSION_INFORMATION=on \ PROTOCOL=udp \ + OPENVPN_VERSION=2.5 \ OPENVPN_VERBOSITY=1 \ OPENVPN_ROOT=yes \ OPENVPN_TARGET_IP= \ @@ -145,7 +146,10 @@ ENV VPNSP=pia \ ENTRYPOINT ["/entrypoint"] EXPOSE 8000/tcp 8888/tcp 8388/tcp 8388/udp HEALTHCHECK --interval=5s --timeout=5s --start-period=10s --retries=1 CMD /entrypoint healthcheck -RUN apk add -q --progress --no-cache --update openvpn ca-certificates iptables ip6tables unbound tzdata && \ +RUN apk add --no-cache --update -X "https://dl-cdn.alpinelinux.org/alpine/v3.12/main" openvpn==2.4.11-r0 && \ + mv /usr/sbin/openvpn /usr/sbin/openvpn2.4 && \ + apk del openvpn && \ + apk add --no-cache --update openvpn ca-certificates iptables ip6tables unbound tzdata && \ rm -rf /var/cache/apk/* /etc/unbound/* /usr/sbin/unbound-* /etc/openvpn/*.sh /usr/lib/openvpn/plugins/openvpn-plugin-down-root.so && \ deluser openvpn && \ deluser unbound && \ diff --git a/README.md b/README.md index d4c28dde..ee2a38b6 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ using Go, OpenVPN, iptables, DNS over TLS, ShadowSocks and an HTTP proxy* ## Features -- Based on Alpine 3.13 for a small Docker image of 52MB +- Based on Alpine 3.13 for a small Docker image of 54MB - Supports: **Cyberghost**, **FastestVPN**, **HideMyAss**, **IVPN**, **Mullvad**, **NordVPN**, **Privado**, **Private Internet Access**, **PrivateVPN**, **ProtonVPN**, **PureVPN**, **Surfshark**, **TorGuard**, **Vyprvpn**, **Windscribe** servers - Supports Openvpn only for now - DNS over TLS baked in with service provider(s) of your choice diff --git a/cmd/gluetun/main.go b/cmd/gluetun/main.go index 33c4eceb..f8bf4fab 100644 --- a/cmd/gluetun/main.go +++ b/cmd/gluetun/main.go @@ -150,7 +150,8 @@ func _main(ctx context.Context, buildInfo models.BuildInformation, if err := printVersions(ctx, logger, []printVersionElement{ {name: "Alpine", getVersion: alpineConf.Version}, - {name: "OpenVPN", getVersion: ovpnConf.Version}, + {name: "OpenVPN 2.4", getVersion: ovpnConf.Version24}, + {name: "OpenVPN 2.5", getVersion: ovpnConf.Version25}, {name: "Unbound", getVersion: dnsConf.Version}, {name: "IPtables", getVersion: firewallConf.Version}, }); err != nil { @@ -165,8 +166,6 @@ func _main(ctx context.Context, buildInfo models.BuildInformation, } logger.Info(allSettings.String()) - allSettings.OpenVPN.Version, _ = ovpnConf.Version(ctx) - if err := os.MkdirAll("/tmp/gluetun", 0644); err != nil { return err } diff --git a/internal/configuration/openvpn.go b/internal/configuration/openvpn.go index 023a5e29..bdd2f83e 100644 --- a/internal/configuration/openvpn.go +++ b/internal/configuration/openvpn.go @@ -21,7 +21,7 @@ type OpenVPN struct { Auth string `json:"auth"` Provider Provider `json:"provider"` Config string `json:"custom_config"` - Version string `json:"-"` // injected at runtime + Version string `json:"version"` } func (settings *OpenVPN) String() string { @@ -31,6 +31,8 @@ func (settings *OpenVPN) String() string { func (settings *OpenVPN) lines() (lines []string) { lines = append(lines, lastIndent+"OpenVPN:") + lines = append(lines, indent+lastIndent+"Version: "+settings.Version) + lines = append(lines, indent+lastIndent+"Verbosity level: "+strconv.Itoa(settings.Verbosity)) if settings.Root { @@ -98,6 +100,12 @@ func (settings *OpenVPN) read(r reader) (err error) { } } + settings.Version, err = r.env.Inside("OPENVPN_VERSION", + []string{constants.Openvpn24, constants.Openvpn25}, params.Default(constants.Openvpn25)) + if err != nil { + return err + } + settings.Verbosity, err = r.env.IntRange("OPENVPN_VERBOSITY", 0, 6, params.Default("1")) if err != nil { return err diff --git a/internal/configuration/openvpn_test.go b/internal/configuration/openvpn_test.go index 6a78caa6..7f7e1421 100644 --- a/internal/configuration/openvpn_test.go +++ b/internal/configuration/openvpn_test.go @@ -52,7 +52,8 @@ func Test_OpenVPN_JSON(t *testing.T) { "filepath": "" } }, - "custom_config": "" + "custom_config": "", + "version": "" }`, string(data)) var out OpenVPN err = json.Unmarshal(data, &out) diff --git a/internal/configuration/settings_test.go b/internal/configuration/settings_test.go index 59890599..a9eee96b 100644 --- a/internal/configuration/settings_test.go +++ b/internal/configuration/settings_test.go @@ -17,6 +17,7 @@ func Test_Settings_lines(t *testing.T) { "default settings": { settings: Settings{ OpenVPN: OpenVPN{ + Version: constants.Openvpn25, Provider: Provider{ Name: constants.Mullvad, }, @@ -25,6 +26,7 @@ func Test_Settings_lines(t *testing.T) { lines: []string{ "Settings summary below:", "|--OpenVPN:", + " |--Version: 2.5", " |--Verbosity level: 0", " |--Provider:", " |--Mullvad settings:", diff --git a/internal/constants/openvpn.go b/internal/constants/openvpn.go index a6fd3471..6b66b1f8 100644 --- a/internal/constants/openvpn.go +++ b/internal/constants/openvpn.go @@ -14,3 +14,8 @@ const ( SHA256 = "sha256" SHA512 = "sha512" ) + +const ( + Openvpn24 = "2.4" + Openvpn25 = "2.5" +) diff --git a/internal/openvpn/command.go b/internal/openvpn/command.go index 49cd2ae2..87fb37bd 100644 --- a/internal/openvpn/command.go +++ b/internal/openvpn/command.go @@ -9,16 +9,42 @@ import ( "github.com/qdm12/gluetun/internal/constants" ) -func (c *configurator) Start(ctx context.Context) ( +var ErrVersionUnknown = errors.New("OpenVPN version is unknown") + +const ( + binOpenvpn24 = "openvpn2.4" + binOpenvpn25 = "openvpn" +) + +func (c *configurator) Start(ctx context.Context, version string) ( stdoutLines, stderrLines chan string, waitError chan error, err error) { - c.logger.Info("starting openvpn") - return c.commander.Start(ctx, "openvpn", "--config", constants.OpenVPNConf) + var bin string + switch version { + case constants.Openvpn24: + bin = binOpenvpn24 + case constants.Openvpn25: + bin = binOpenvpn25 + default: + return nil, nil, nil, fmt.Errorf("%w: %s", ErrVersionUnknown, version) + } + + c.logger.Info("starting OpenVPN " + version) + + return c.commander.Start(ctx, bin, "--config", constants.OpenVPNConf) +} + +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) } var ErrVersionTooShort = errors.New("version output is too short") -func (c *configurator) Version(ctx context.Context) (string, error) { - output, err := c.commander.Run(ctx, "openvpn", "--version") +func (c *configurator) version(ctx context.Context, binName string) (version string, err error) { + output, err := c.commander.Run(ctx, binName, "--version") if err != nil && err.Error() != "exit status 1" { return "", err } diff --git a/internal/openvpn/loop.go b/internal/openvpn/loop.go index 0222e0c4..20d30384 100644 --- a/internal/openvpn/loop.go +++ b/internal/openvpn/loop.go @@ -157,7 +157,7 @@ func (l *looper) Run(ctx context.Context, done chan<- struct{}) { //nolint:gocog openvpnCtx, openvpnCancel := context.WithCancel(context.Background()) - stdoutLines, stderrLines, waitError, err := l.conf.Start(openvpnCtx) + stdoutLines, stderrLines, waitError, err := l.conf.Start(openvpnCtx, settings.Version) if err != nil { openvpnCancel() l.signalCrashedStatus() diff --git a/internal/openvpn/openvpn.go b/internal/openvpn/openvpn.go index 63b93242..b21b4690 100644 --- a/internal/openvpn/openvpn.go +++ b/internal/openvpn/openvpn.go @@ -12,12 +12,13 @@ import ( ) type Configurator interface { - Version(ctx context.Context) (string, error) + Version24(ctx context.Context) (version string, err error) + Version25(ctx context.Context) (version string, err error) WriteAuthFile(user, password string, puid, pgid int) error CheckTUN() error CreateTUN() error - Start(ctx context.Context) (stdoutLines, stderrLines chan string, - waitError chan error, err error) + Start(ctx context.Context, version string) ( + stdoutLines, stderrLines chan string, waitError chan error, err error) } type configurator struct { diff --git a/internal/provider/utils/cipher.go b/internal/provider/utils/cipher.go index 2ae51863..fde34566 100644 --- a/internal/provider/utils/cipher.go +++ b/internal/provider/utils/cipher.go @@ -1,10 +1,12 @@ package utils -import "strings" +import ( + "github.com/qdm12/gluetun/internal/constants" +) func CipherLines(cipher, version string) (lines []string) { - switch { - case strings.HasPrefix(version, "2.4"): + switch version { + case constants.Openvpn24: return []string{"cipher " + cipher} default: // 2.5 and above return []string{ diff --git a/internal/provider/utils/cipher_test.go b/internal/provider/utils/cipher_test.go index 5d203bca..cf1b7b44 100644 --- a/internal/provider/utils/cipher_test.go +++ b/internal/provider/utils/cipher_test.go @@ -18,12 +18,12 @@ func Test_CipherLines(t *testing.T) { "data-ciphers AES", }, }, - "2.4.5": { - version: "2.4.5", + "2.4": { + version: "2.4", lines: []string{"cipher AES"}, }, - "2.5.3": { - version: "2.5.3", + "2.5": { + version: "2.5", lines: []string{ "data-ciphers-fallback AES", "data-ciphers AES",