From 7ff14a356c560f27bec8b935713a87e7666c84e6 Mon Sep 17 00:00:00 2001 From: Quentin McGaw Date: Mon, 25 Apr 2022 07:57:45 +0000 Subject: [PATCH] chore(internal/providers): simplify OpenVPN config building --- internal/cli/openvpnconfig.go | 6 +- internal/models/connection.go | 9 - internal/provider/custom/openvpnconf.go | 10 +- internal/provider/cyberghost/openvpnconf.go | 89 +------ internal/provider/expressvpn/openvpnconf.go | 99 ++----- internal/provider/fastestvpn/openvpnconf.go | 94 ++----- internal/provider/hidemyass/openvpnconf.go | 78 +----- internal/provider/ipvanish/openvpnconf.go | 72 +---- internal/provider/ivpn/openvpnconf.go | 86 ++---- internal/provider/mullvad/openvpnconf.go | 86 ++---- internal/provider/nordvpn/openvpnconf.go | 96 ++----- .../provider/perfectprivacy/openvpnconf.go | 103 ++------ internal/provider/privado/openvpnconf.go | 77 +----- .../privateinternetaccess/openvpnconf.go | 99 ++----- internal/provider/privatevpn/openvpnconf.go | 79 +----- internal/provider/protonvpn/openvpnconf.go | 90 ++----- internal/provider/provider.go | 2 +- internal/provider/purevpn/openvpnconf.go | 81 +----- internal/provider/surfshark/openvpnconf.go | 87 ++---- internal/provider/torguard/openvpnconf.go | 92 ++----- internal/provider/utils/cipher.go | 4 + internal/provider/utils/openvpn.go | 249 ++++++++++++++++++ internal/provider/vpnunlimited/openvpnconf.go | 85 +----- internal/provider/vyprvpn/openvpnconf.go | 77 ++---- internal/provider/wevpn/openvpnconf.go | 96 ++----- internal/provider/windscribe/openvpnconf.go | 83 +----- internal/vpn/openvpn.go | 5 +- 27 files changed, 596 insertions(+), 1438 deletions(-) diff --git a/internal/cli/openvpnconfig.go b/internal/cli/openvpnconfig.go index 0c8ade07..9e52c982 100644 --- a/internal/cli/openvpnconfig.go +++ b/internal/cli/openvpnconfig.go @@ -41,10 +41,8 @@ func (c *CLI) OpenvpnConfig(logger OpenvpnConfigLogger, source sources.Source) e if err != nil { return err } - lines, err := providerConf.BuildConf(connection, allSettings.VPN.OpenVPN) - if err != nil { - return err - } + + lines := providerConf.BuildConf(connection, allSettings.VPN.OpenVPN) fmt.Println(strings.Join(lines, "\n")) return nil diff --git a/internal/models/connection.go b/internal/models/connection.go index 8d7a9473..5e317a7d 100644 --- a/internal/models/connection.go +++ b/internal/models/connection.go @@ -1,7 +1,6 @@ package models import ( - "fmt" "net" ) @@ -28,14 +27,6 @@ func (c *Connection) Equal(other Connection) bool { c.PubKey == other.PubKey } -func (c Connection) OpenVPNRemoteLine() (line string) { - return "remote " + c.IP.String() + " " + fmt.Sprint(c.Port) -} - -func (c Connection) OpenVPNProtoLine() (line string) { - return "proto " + c.Protocol -} - // UpdateEmptyWith updates each field of the connection where the // value is not set using the value given as arguments. func (c *Connection) UpdateEmptyWith(ip net.IP, port uint16, protocol string) { diff --git a/internal/provider/custom/openvpnconf.go b/internal/provider/custom/openvpnconf.go index 110d479e..86cae925 100644 --- a/internal/provider/custom/openvpnconf.go +++ b/internal/provider/custom/openvpnconf.go @@ -15,8 +15,8 @@ import ( var ErrExtractData = errors.New("failed extracting information from custom configuration file") func (p *Provider) BuildConf(connection models.Connection, - settings settings.OpenVPN) (lines []string, err error) { - lines, _, err = p.extractor.Data(*settings.ConfFile) + settings settings.OpenVPN) (lines []string) { + lines, _, err := p.extractor.Data(*settings.ConfFile) if err != nil { // Configuration file is already validated in settings validation in // internal/configuration/settings/openvpn.go in `validateOpenVPNConfigFilepath`. @@ -26,7 +26,7 @@ func (p *Provider) BuildConf(connection models.Connection, lines = modifyConfig(lines, connection, settings) - return lines, nil + return lines } func modifyConfig(lines []string, connection models.Connection, @@ -66,8 +66,8 @@ func modifyConfig(lines []string, connection models.Connection, } // Add values - modified = append(modified, connection.OpenVPNProtoLine()) - modified = append(modified, connection.OpenVPNRemoteLine()) + modified = append(modified, "proto "+connection.Protocol) + modified = append(modified, fmt.Sprintf("remote %s %d", connection.IP, connection.Port)) modified = append(modified, "dev "+settings.Interface) modified = append(modified, "mute-replay-warnings") modified = append(modified, "auth-nocache") diff --git a/internal/provider/cyberghost/openvpnconf.go b/internal/provider/cyberghost/openvpnconf.go index c6ab38e8..05cd5957 100644 --- a/internal/provider/cyberghost/openvpnconf.go +++ b/internal/provider/cyberghost/openvpnconf.go @@ -1,93 +1,26 @@ package cyberghost import ( - "fmt" - "strconv" - "github.com/qdm12/gluetun/internal/configuration/settings" "github.com/qdm12/gluetun/internal/constants" "github.com/qdm12/gluetun/internal/models" - "github.com/qdm12/gluetun/internal/openvpn/parse" "github.com/qdm12/gluetun/internal/provider/utils" ) func (c *Cyberghost) BuildConf(connection models.Connection, - settings settings.OpenVPN) (lines []string, err error) { - if len(settings.Ciphers) == 0 { - settings.Ciphers = []string{ + settings settings.OpenVPN) (lines []string) { + //nolint:gomnd + providerSettings := utils.OpenVPNProviderSettings{ + RemoteCertTLS: true, + AuthUserPass: true, + Ciphers: []string{ constants.AES256gcm, constants.AES256cbc, constants.AES128gcm, - } + }, + Auth: constants.SHA256, + Ping: 10, + CA: constants.CyberghostCA, } - - auth := *settings.Auth - if auth == "" { - auth = constants.SHA256 - } - - lines = []string{ - "client", - "nobind", - "tls-exit", - "dev " + settings.Interface, - "verb " + strconv.Itoa(*settings.Verbosity), - - // Cyberghost specific - "ping 10", - "remote-cert-tls server", - "auth-user-pass " + constants.OpenVPNAuthConf, - "auth " + auth, - - // Added constant values - "auth-nocache", - "mute-replay-warnings", - "pull-filter ignore \"auth-token\"", // prevent auth failed loops - "auth-retry nointeract", - "suppress-timestamps", - - // Connection variables - connection.OpenVPNProtoLine(), - connection.OpenVPNRemoteLine(), - } - - lines = append(lines, utils.CipherLines(settings.Ciphers, settings.Version)...) - - if connection.Protocol == constants.UDP { - lines = append(lines, "explicit-exit-notify") - } - - if settings.ProcessUser != "root" { - lines = append(lines, "user "+settings.ProcessUser) - lines = append(lines, "persist-tun") - lines = append(lines, "persist-key") - } - - if *settings.MSSFix > 0 { - lines = append(lines, "mssfix "+strconv.Itoa(int(*settings.MSSFix))) - } - - if !*settings.IPv6 { - lines = append(lines, `pull-filter ignore "route-ipv6"`) - lines = append(lines, `pull-filter ignore "ifconfig-ipv6"`) - } - - lines = append(lines, utils.WrapOpenvpnCA( - constants.CyberghostCA)...) - - certData, err := parse.ExtractCert([]byte(*settings.ClientCrt)) - if err != nil { - return nil, fmt.Errorf("client cert is not valid: %w", err) - } - lines = append(lines, utils.WrapOpenvpnCert(certData)...) - - keyData, err := parse.ExtractPrivateKey([]byte(*settings.ClientKey)) - if err != nil { - return nil, fmt.Errorf("client key is not valid: %w", err) - } - lines = append(lines, utils.WrapOpenvpnKey(keyData)...) - - lines = append(lines, "") - - return lines, nil + return utils.OpenVPNConfig(providerSettings, connection, settings) } diff --git a/internal/provider/expressvpn/openvpnconf.go b/internal/provider/expressvpn/openvpnconf.go index 09e03e14..e1571a72 100644 --- a/internal/provider/expressvpn/openvpnconf.go +++ b/internal/provider/expressvpn/openvpnconf.go @@ -1,8 +1,6 @@ package expressvpn import ( - "strconv" - "github.com/qdm12/gluetun/internal/configuration/settings" "github.com/qdm12/gluetun/internal/constants" "github.com/qdm12/gluetun/internal/models" @@ -10,79 +8,28 @@ import ( ) func (p *Provider) BuildConf(connection models.Connection, - settings settings.OpenVPN) (lines []string, err error) { - if len(settings.Ciphers) == 0 { - settings.Ciphers = []string{constants.AES256cbc} + settings settings.OpenVPN) (lines []string) { + //nolint:gomnd + providerSettings := utils.OpenVPNProviderSettings{ + RemoteCertTLS: true, + AuthUserPass: true, + Ciphers: []string{ + constants.AES256cbc, + }, + Auth: constants.SHA512, + CA: constants.ExpressvpnCA, + Cert: constants.ExpressvpnCert, + RSAKey: constants.ExpressvpnRSAKey, + TLSAuth: constants.ExpressvpnTLSAuth, + MssFix: 1200, + FastIO: true, + Fragment: 1300, + SndBuf: 524288, + RcvBuf: 524288, + KeyDirection: "1", + VerifyX509Type: "name-prefix", + // Always verify against `Server` x509 name prefix, security hole I guess? + VerifyX509Name: "Server", } - auth := *settings.Auth - if auth == "" { - auth = constants.SHA512 - } - - mssFix := *settings.MSSFix - if mssFix == 0 { - const defaultMSSFix = 1200 - mssFix = defaultMSSFix - } - - lines = []string{ - "client", - "nobind", - "tls-exit", - "dev " + settings.Interface, - "verb " + strconv.Itoa(*settings.Verbosity), - - // Expressvpn specific - "fast-io", - "fragment 1300", - "mssfix " + strconv.Itoa(int(mssFix)), - "sndbuf 524288", - "rcvbuf 524288", - "verify-x509-name Server name-prefix", // security hole I guess? - "remote-cert-tls server", // updated name of ns-cert-type - "key-direction 1", - "auth-user-pass " + constants.OpenVPNAuthConf, - "auth " + auth, - - // Added constant values - "mute-replay-warnings", - "auth-nocache", - "pull-filter ignore \"auth-token\"", // prevent auth failed loops - "auth-retry nointeract", - "suppress-timestamps", - - // Modified variables - connection.OpenVPNProtoLine(), - connection.OpenVPNRemoteLine(), - } - - lines = append(lines, utils.CipherLines(settings.Ciphers, settings.Version)...) - - if connection.Protocol == constants.UDP { - lines = append(lines, "explicit-exit-notify") - } - - if settings.ProcessUser != "root" { - lines = append(lines, "user "+settings.ProcessUser) - lines = append(lines, "persist-tun") - lines = append(lines, "persist-key") - } - - if !*settings.IPv6 { - lines = append(lines, `pull-filter ignore "route-ipv6"`) - lines = append(lines, `pull-filter ignore "ifconfig-ipv6"`) - } - - lines = append(lines, utils.WrapOpenvpnCert( - constants.ExpressvpnCert)...) - lines = append(lines, utils.WrapOpenvpnRSAKey( - constants.ExpressvpnRSAKey)...) - lines = append(lines, utils.WrapOpenvpnTLSAuth( - constants.ExpressvpnTLSAuth)...) - lines = append(lines, utils.WrapOpenvpnCA( - constants.ExpressvpnCA)...) - - lines = append(lines, "") - - return lines, nil + return utils.OpenVPNConfig(providerSettings, connection, settings) } diff --git a/internal/provider/fastestvpn/openvpnconf.go b/internal/provider/fastestvpn/openvpnconf.go index b6d0a116..9c7fc568 100644 --- a/internal/provider/fastestvpn/openvpnconf.go +++ b/internal/provider/fastestvpn/openvpnconf.go @@ -1,8 +1,6 @@ package fastestvpn import ( - "strconv" - "github.com/qdm12/gluetun/internal/configuration/settings" "github.com/qdm12/gluetun/internal/constants" "github.com/qdm12/gluetun/internal/models" @@ -10,74 +8,28 @@ import ( ) func (f *Fastestvpn) BuildConf(connection models.Connection, - settings settings.OpenVPN) (lines []string, err error) { - if len(settings.Ciphers) == 0 { - settings.Ciphers = []string{constants.AES256cbc} + settings settings.OpenVPN) (lines []string) { + //nolint:gomnd + providerSettings := utils.OpenVPNProviderSettings{ + AuthUserPass: true, + Ciphers: []string{ + constants.AES256cbc, + }, + MssFix: 1450, + TLSCipher: "TLS-DHE-RSA-WITH-AES-256-GCM-SHA384:TLS-DHE-RSA-WITH-AES-256-CBC-SHA256:TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA:TLS-DHE-RSA-WITH-AES-256-CBC-SHA:TLS-RSA-WITH-CAMELLIA-256-CBC-SHA:TLS-RSA-WITH-AES-256-CBC-SHA", //nolint:lll + AuthToken: true, + KeyDirection: "1", + RenegDisabled: true, + CA: constants.FastestvpnCA, + TLSAuth: constants.FastestvpnTLSAuth, + UDPLines: []string{ + "tun-mtu 1500", + "tun-mtu-extra 32", + "ping 15", + }, + ExtraLines: []string{ + "comp-lzo", + }, } - auth := *settings.Auth - if auth == "" { - auth = constants.SHA256 - } - - mssFix := *settings.MSSFix - if mssFix == 0 { - mssFix = 1450 - } - - lines = []string{ - "client", - "nobind", - "tls-exit", - "dev " + settings.Interface, - "verb " + strconv.Itoa(*settings.Verbosity), - - // Fastestvpn specific - "mssfix " + strconv.Itoa(int(mssFix)), // defaults to 1450 - "tls-cipher TLS-DHE-RSA-WITH-AES-256-GCM-SHA384:TLS-DHE-RSA-WITH-AES-256-CBC-SHA256:TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA:TLS-DHE-RSA-WITH-AES-256-CBC-SHA:TLS-RSA-WITH-CAMELLIA-256-CBC-SHA:TLS-RSA-WITH-AES-256-CBC-SHA", //nolint:lll - "key-direction 1", - "auth-user-pass " + constants.OpenVPNAuthConf, - "auth " + auth, - "comp-lzo", - "reneg-sec 0", - - // Added constant values - "auth-nocache", - "mute-replay-warnings", - // "pull-filter ignore \"auth-token\"", // needed for FastestVPN - "auth-retry nointeract", - "suppress-timestamps", - - // Connection variables - connection.OpenVPNProtoLine(), - connection.OpenVPNRemoteLine(), - } - - lines = append(lines, utils.CipherLines(settings.Ciphers, settings.Version)...) - - if connection.Protocol == constants.UDP { - lines = append(lines, "explicit-exit-notify") - lines = append(lines, "tun-mtu 1500") // FastestVPN specific - lines = append(lines, "tun-mtu-extra 32") // FastestVPN specific - lines = append(lines, "ping 15") // FastestVPN specific - } - - if settings.ProcessUser != "root" { - lines = append(lines, "user "+settings.ProcessUser) - lines = append(lines, "persist-tun") - lines = append(lines, "persist-key") - } - - if !*settings.IPv6 { - lines = append(lines, `pull-filter ignore "route-ipv6"`) - lines = append(lines, `pull-filter ignore "ifconfig-ipv6"`) - } - - lines = append(lines, utils.WrapOpenvpnCA( - constants.FastestvpnCA)...) - lines = append(lines, utils.WrapOpenvpnTLSAuth( - constants.FastestvpnTLSAuth)...) - - lines = append(lines, "") - - return lines, nil + return utils.OpenVPNConfig(providerSettings, connection, settings) } diff --git a/internal/provider/hidemyass/openvpnconf.go b/internal/provider/hidemyass/openvpnconf.go index 0d1b808a..03618af4 100644 --- a/internal/provider/hidemyass/openvpnconf.go +++ b/internal/provider/hidemyass/openvpnconf.go @@ -1,8 +1,6 @@ package hidemyass import ( - "strconv" - "github.com/qdm12/gluetun/internal/configuration/settings" "github.com/qdm12/gluetun/internal/constants" "github.com/qdm12/gluetun/internal/models" @@ -10,68 +8,18 @@ import ( ) func (h *HideMyAss) BuildConf(connection models.Connection, - settings settings.OpenVPN) (lines []string, err error) { - if len(settings.Ciphers) == 0 { - settings.Ciphers = []string{constants.AES256cbc} + settings settings.OpenVPN) (lines []string) { + //nolint:gomnd + providerSettings := utils.OpenVPNProviderSettings{ + AuthUserPass: true, + Ciphers: []string{ + constants.AES256cbc, + }, + RemoteCertTLS: true, + CA: constants.HideMyAssCA, + Cert: constants.HideMyAssCert, + RSAKey: constants.HideMyAssRSAKey, + Ping: 5, } - - lines = []string{ - "client", - "nobind", - "tls-exit", - "dev " + settings.Interface, - "verb " + strconv.Itoa(*settings.Verbosity), - - // HideMyAss specific - "ping 5", - "remote-cert-tls server", // updated name of ns-cert-type - "auth-user-pass " + constants.OpenVPNAuthConf, - - // Added constant values - "mute-replay-warnings", - "auth-nocache", - "pull-filter ignore \"auth-token\"", // prevent auth failed loops - "auth-retry nointeract", - "suppress-timestamps", - - // Connection variables - connection.OpenVPNProtoLine(), - connection.OpenVPNRemoteLine(), - } - - lines = append(lines, utils.CipherLines(settings.Ciphers, settings.Version)...) - - if *settings.Auth != "" { - lines = append(lines, "auth "+*settings.Auth) - } - - if *settings.MSSFix > 0 { - lines = append(lines, "mssfix "+strconv.Itoa(int(*settings.MSSFix))) - } - - if connection.Protocol == constants.UDP { - lines = append(lines, "explicit-exit-notify") - } - - if settings.ProcessUser != "root" { - lines = append(lines, "user "+settings.ProcessUser) - lines = append(lines, "persist-tun") - lines = append(lines, "persist-key") - } - - if !*settings.IPv6 { - lines = append(lines, `pull-filter ignore "route-ipv6"`) - lines = append(lines, `pull-filter ignore "ifconfig-ipv6"`) - } - - lines = append(lines, utils.WrapOpenvpnCA( - constants.HideMyAssCA)...) - lines = append(lines, utils.WrapOpenvpnCert( - constants.HideMyAssCert)...) - lines = append(lines, utils.WrapOpenvpnRSAKey( - constants.HideMyAssRSAKey)...) - - lines = append(lines, "") - - return lines, nil + return utils.OpenVPNConfig(providerSettings, connection, settings) } diff --git a/internal/provider/ipvanish/openvpnconf.go b/internal/provider/ipvanish/openvpnconf.go index 87085f41..483c4e4b 100644 --- a/internal/provider/ipvanish/openvpnconf.go +++ b/internal/provider/ipvanish/openvpnconf.go @@ -1,8 +1,6 @@ package ipvanish import ( - "strconv" - "github.com/qdm12/gluetun/internal/configuration/settings" "github.com/qdm12/gluetun/internal/constants" "github.com/qdm12/gluetun/internal/models" @@ -10,64 +8,16 @@ import ( ) func (i *Ipvanish) BuildConf(connection models.Connection, - settings settings.OpenVPN) (lines []string, err error) { - if len(settings.Ciphers) == 0 { - settings.Ciphers = []string{constants.AES256cbc} + settings settings.OpenVPN) (lines []string) { + providerSettings := utils.OpenVPNProviderSettings{ + AuthUserPass: true, + Ciphers: []string{ + constants.AES256cbc, + }, + Auth: constants.SHA256, + VerifyX509Type: "name", + TLSCipher: "TLS-DHE-RSA-WITH-AES-256-CBC-SHA:TLS-DHE-DSS-WITH-AES-256-CBC-SHA:TLS-RSA-WITH-AES-256-CBC-SHA", + CA: constants.IpvanishCA, } - auth := *settings.Auth - if auth == "" { - auth = constants.SHA256 - } - - lines = []string{ - "client", - "nobind", - "tls-exit", - "dev " + settings.Interface, - "verb " + strconv.Itoa(*settings.Verbosity), - - // Ipvanish specific - "verify-x509-name " + connection.Hostname + " name", - "tls-cipher TLS-DHE-RSA-WITH-AES-256-CBC-SHA:TLS-DHE-DSS-WITH-AES-256-CBC-SHA:TLS-RSA-WITH-AES-256-CBC-SHA", - "auth-user-pass " + constants.OpenVPNAuthConf, - "auth " + auth, - - // Added constant values - "mute-replay-warnings", - "auth-nocache", - "pull-filter ignore \"auth-token\"", // prevent auth failed loops - "auth-retry nointeract", - "suppress-timestamps", - - // Connection variables - connection.OpenVPNProtoLine(), - connection.OpenVPNRemoteLine(), - } - - lines = append(lines, utils.CipherLines(settings.Ciphers, settings.Version)...) - - if *settings.MSSFix > 0 { - lines = append(lines, "mssfix "+strconv.Itoa(int(*settings.MSSFix))) - } - - if connection.Protocol == constants.UDP { - lines = append(lines, "explicit-exit-notify") - } - - if settings.ProcessUser != "root" { - lines = append(lines, "user "+settings.ProcessUser) - lines = append(lines, "persist-tun") - lines = append(lines, "persist-key") - } - - if !*settings.IPv6 { - lines = append(lines, `pull-filter ignore "route-ipv6"`) - lines = append(lines, `pull-filter ignore "ifconfig-ipv6"`) - } - - lines = append(lines, utils.WrapOpenvpnCA(constants.IpvanishCA)...) - - lines = append(lines, "") - - return lines, nil + return utils.OpenVPNConfig(providerSettings, connection, settings) } diff --git a/internal/provider/ivpn/openvpnconf.go b/internal/provider/ivpn/openvpnconf.go index c3616a55..fbff54a6 100644 --- a/internal/provider/ivpn/openvpnconf.go +++ b/internal/provider/ivpn/openvpnconf.go @@ -1,9 +1,6 @@ package ivpn import ( - "strconv" - "strings" - "github.com/qdm12/gluetun/internal/configuration/settings" "github.com/qdm12/gluetun/internal/constants" "github.com/qdm12/gluetun/internal/models" @@ -11,71 +8,22 @@ import ( ) func (i *Ivpn) BuildConf(connection models.Connection, - settings settings.OpenVPN) (lines []string, err error) { - if len(settings.Ciphers) == 0 { - settings.Ciphers = []string{constants.AES256cbc} + settings settings.OpenVPN) (lines []string) { + //nolint:gomnd + providerSettings := utils.OpenVPNProviderSettings{ + AuthUserPass: true, + Ciphers: []string{ + constants.AES256cbc, + }, + Ping: 5, + RemoteCertTLS: true, + VerifyX509Type: "name-prefix", + TLSCipher: "TLS-DHE-RSA-WITH-AES-256-CBC-SHA:TLS-DHE-DSS-WITH-AES-256-CBC-SHA:TLS-RSA-WITH-AES-256-CBC-SHA", + CA: constants.IvpnCA, + TLSAuth: constants.IvpnTLSAuth, + ExtraLines: []string{ + "key-direction 1", + }, } - - namePrefix := strings.Split(connection.Hostname, ".")[0] - - lines = []string{ - "client", - "nobind", - "tls-exit", - "dev " + settings.Interface, - "verb " + strconv.Itoa(*settings.Verbosity), - - // IVPN specific - "ping 5", - "remote-cert-tls server", // updated name of ns-cert-type - "key-direction 1", - "verify-x509-name " + namePrefix + " name-prefix", - "tls-cipher TLS-DHE-RSA-WITH-AES-256-CBC-SHA:TLS-DHE-DSS-WITH-AES-256-CBC-SHA:TLS-RSA-WITH-AES-256-CBC-SHA", - "auth-user-pass " + constants.OpenVPNAuthConf, - - // Added constant values - "mute-replay-warnings", - "auth-nocache", - "pull-filter ignore \"auth-token\"", // prevent auth failed loops - "auth-retry nointeract", - "suppress-timestamps", - - // Connection variables - connection.OpenVPNProtoLine(), - connection.OpenVPNRemoteLine(), - } - - lines = append(lines, utils.CipherLines(settings.Ciphers, settings.Version)...) - - if *settings.Auth != "" { - lines = append(lines, "auth "+*settings.Auth) - } - - if *settings.MSSFix > 0 { - lines = append(lines, "mssfix "+strconv.Itoa(int(*settings.MSSFix))) - } - - if connection.Protocol == constants.UDP { - lines = append(lines, "explicit-exit-notify") - } - - if settings.ProcessUser != "root" { - lines = append(lines, "user "+settings.ProcessUser) - lines = append(lines, "persist-tun") - lines = append(lines, "persist-key") - } - - if !*settings.IPv6 { - lines = append(lines, `pull-filter ignore "route-ipv6"`) - lines = append(lines, `pull-filter ignore "ifconfig-ipv6"`) - } - - lines = append(lines, utils.WrapOpenvpnCA( - constants.IvpnCA)...) - lines = append(lines, utils.WrapOpenvpnTLSAuth( - constants.IvpnTLSAuth)...) - - lines = append(lines, "") - - return lines, nil + return utils.OpenVPNConfig(providerSettings, connection, settings) } diff --git a/internal/provider/mullvad/openvpnconf.go b/internal/provider/mullvad/openvpnconf.go index cdccf984..c341e04c 100644 --- a/internal/provider/mullvad/openvpnconf.go +++ b/internal/provider/mullvad/openvpnconf.go @@ -1,8 +1,6 @@ package mullvad import ( - "strconv" - "github.com/qdm12/gluetun/internal/configuration/settings" "github.com/qdm12/gluetun/internal/constants" "github.com/qdm12/gluetun/internal/models" @@ -10,73 +8,21 @@ import ( ) func (m *Mullvad) BuildConf(connection models.Connection, - settings settings.OpenVPN) (lines []string, err error) { - if len(settings.Ciphers) == 0 { - settings.Ciphers = []string{constants.AES256cbc, constants.AES128gcm} + settings settings.OpenVPN) (lines []string) { + //nolint:gomnd + providerSettings := utils.OpenVPNProviderSettings{ + AuthUserPass: true, + Ciphers: []string{ + constants.AES256cbc, + constants.AES128gcm, + }, + Ping: 10, + RemoteCertTLS: true, + TLSCipher: "TLS-DHE-RSA-WITH-AES-256-GCM-SHA384:TLS-DHE-RSA-WITH-AES-256-CBC-SHA", + SndBuf: 524288, + RcvBuf: 524288, + CA: constants.MullvadCA, + UDPLines: []string{"fast-io"}, } - - lines = []string{ - "client", - "nobind", - "tls-exit", - "dev " + settings.Interface, - "verb " + strconv.Itoa(*settings.Verbosity), - "auth-user-pass " + constants.OpenVPNAuthConf, - - // Mullvad specific - "ping 10", - "remote-cert-tls server", - "sndbuf 524288", - "rcvbuf 524288", - "tls-cipher TLS-DHE-RSA-WITH-AES-256-GCM-SHA384:TLS-DHE-RSA-WITH-AES-256-CBC-SHA", - - // Added constant values - "auth-nocache", - "mute-replay-warnings", - "pull-filter ignore \"auth-token\"", // prevent auth failed loops - "auth-retry nointeract", - "suppress-timestamps", - - // Connection variables - connection.OpenVPNProtoLine(), - connection.OpenVPNRemoteLine(), - } - - lines = append(lines, utils.CipherLines(settings.Ciphers, settings.Version)...) - - if *settings.Auth != "" { - lines = append(lines, "auth "+*settings.Auth) - } - - if connection.Protocol == constants.UDP { - lines = append(lines, "fast-io") - lines = append(lines, "explicit-exit-notify") - } - - if !*settings.IPv6 { - lines = append(lines, `pull-filter ignore "route-ipv6"`) - lines = append(lines, `pull-filter ignore "ifconfig-ipv6"`) - } - - if settings.ProcessUser != "root" { - lines = append(lines, "user "+settings.ProcessUser) - lines = append(lines, "persist-tun") - lines = append(lines, "persist-key") - } - - if *settings.MSSFix > 0 { - lines = append(lines, "mssfix "+strconv.Itoa(int(*settings.MSSFix))) - } - - if !*settings.IPv6 { - lines = append(lines, `pull-filter ignore "route-ipv6"`) - lines = append(lines, `pull-filter ignore "ifconfig-ipv6"`) - } - - lines = append(lines, utils.WrapOpenvpnCA( - constants.MullvadCA)...) - - lines = append(lines, "") - - return lines, nil + return utils.OpenVPNConfig(providerSettings, connection, settings) } diff --git a/internal/provider/nordvpn/openvpnconf.go b/internal/provider/nordvpn/openvpnconf.go index 4b5f7d35..68a10fc0 100644 --- a/internal/provider/nordvpn/openvpnconf.go +++ b/internal/provider/nordvpn/openvpnconf.go @@ -1,8 +1,6 @@ package nordvpn import ( - "strconv" - "github.com/qdm12/gluetun/internal/configuration/settings" "github.com/qdm12/gluetun/internal/constants" "github.com/qdm12/gluetun/internal/models" @@ -10,75 +8,29 @@ import ( ) func (n *Nordvpn) BuildConf(connection models.Connection, - settings settings.OpenVPN) (lines []string, err error) { - if len(settings.Ciphers) == 0 { - settings.Ciphers = []string{constants.AES256cbc, constants.AES256gcm} + settings settings.OpenVPN) (lines []string) { + //nolint:gomnd + providerSettings := utils.OpenVPNProviderSettings{ + AuthUserPass: true, + Ciphers: []string{ + constants.AES256cbc, + constants.AES256gcm, + }, + Auth: constants.SHA512, + Ping: 15, + RemoteCertTLS: true, + MssFix: 1450, + CA: constants.NordvpnCA, + TLSAuth: constants.NordvpnTLSAuth, + TunMTUExtra: 32, + RenegDisabled: true, + KeyDirection: "1", + UDPLines: []string{ + "fast-io", + }, + ExtraLines: []string{ + "comp-lzo no", // Explicitly disable compression + }, } - - auth := *settings.Auth - if auth == "" { - auth = constants.SHA512 - } - - mssFix := *settings.MSSFix - if mssFix == 0 { - mssFix = 1450 - } - - lines = []string{ - "client", - "nobind", - "tls-exit", - "dev " + settings.Interface, - "verb " + strconv.Itoa(*settings.Verbosity), - - // Nordvpn specific - "tun-mtu-extra 32", - "mssfix " + strconv.Itoa(int(mssFix)), - "ping 15", - "remote-cert-tls server", - "reneg-sec 0", - "key-direction 1", - "auth-user-pass " + constants.OpenVPNAuthConf, - "auth " + auth, - "comp-lzo no", // Explicitly disable compression - - // Added constant values - "auth-nocache", - "mute-replay-warnings", - "pull-filter ignore \"auth-token\"", // prevent auth failed loops - "auth-retry nointeract", - "suppress-timestamps", - - // Connection variables - connection.OpenVPNProtoLine(), - connection.OpenVPNRemoteLine(), - } - - lines = append(lines, utils.CipherLines(settings.Ciphers, settings.Version)...) - - if connection.Protocol == constants.UDP { - lines = append(lines, "fast-io") - lines = append(lines, "explicit-exit-notify") - } - - if settings.ProcessUser != "root" { - lines = append(lines, "user "+settings.ProcessUser) - lines = append(lines, "persist-tun") - lines = append(lines, "persist-key") - } - - if !*settings.IPv6 { - lines = append(lines, `pull-filter ignore "route-ipv6"`) - lines = append(lines, `pull-filter ignore "ifconfig-ipv6"`) - } - - lines = append(lines, utils.WrapOpenvpnCA( - constants.NordvpnCA)...) - lines = append(lines, utils.WrapOpenvpnTLSAuth( - constants.NordvpnTLSAuth)...) - - lines = append(lines, "") - - return lines, nil + return utils.OpenVPNConfig(providerSettings, connection, settings) } diff --git a/internal/provider/perfectprivacy/openvpnconf.go b/internal/provider/perfectprivacy/openvpnconf.go index e7f018b8..45807d64 100644 --- a/internal/provider/perfectprivacy/openvpnconf.go +++ b/internal/provider/perfectprivacy/openvpnconf.go @@ -1,8 +1,6 @@ package perfectprivacy import ( - "strconv" - "github.com/qdm12/gluetun/internal/configuration/settings" "github.com/qdm12/gluetun/internal/constants" "github.com/qdm12/gluetun/internal/models" @@ -10,81 +8,30 @@ import ( ) func (p *Perfectprivacy) BuildConf(connection models.Connection, - settings settings.OpenVPN) (lines []string, err error) { - if len(settings.Ciphers) == 0 { - settings.Ciphers = []string{constants.AES256cbc, constants.AES256gcm} + settings settings.OpenVPN) (lines []string) { + //nolint:gomnd + providerSettings := utils.OpenVPNProviderSettings{ + AuthUserPass: true, + Ciphers: []string{ + constants.AES256cbc, + constants.AES256gcm, + }, + Auth: constants.SHA512, + MssFix: 1450, + Ping: 5, + CA: constants.PerfectprivacyCA, + Cert: constants.PerfectprivacyCert, + Key: constants.PerfectprivacyKey, + TLSCrypt: constants.PerfectprivacyTLSCrypt, + TLSCipher: "TLS_CHACHA20_POLY1305_SHA256:TLS-DHE-RSA-WITH-AES-256-GCM-SHA384:TLS-DHE-RSA-WITH-AES-256-CBC-SHA:TLS-DHE-RSA-WITH-AES-128-GCM-SHA256:TLS-DHE-RSA-WITH-AES-128-CBC-SHA:TLS_AES_256_GCM_SHA384:TLS-RSA-WITH-AES-256-CBC-SHA", //nolint:lll + TunMTU: 1500, + TunMTUExtra: 32, + RenegSec: 3600, + KeyDirection: "1", + IPv6Lines: []string{ + "redirect-gateway def1", + `pull-filter ignore "redirect-gateway def1 ipv6"`, + }, } - - auth := *settings.Auth - if auth == "" { - auth = constants.SHA512 - } - - mssFix := *settings.MSSFix - if mssFix == 0 { - mssFix = 1450 - } - - lines = []string{ - "client", - "nobind", - "tls-exit", - "dev " + settings.Interface, - "verb " + strconv.Itoa(*settings.Verbosity), - - // Perfect Privacy specific - "ping 5", - "tun-mtu 1500", - "tun-mtu-extra 32", - "mssfix " + strconv.Itoa(int(mssFix)), - "reneg-sec 3600", - "key-direction 1", - "tls-cipher TLS_CHACHA20_POLY1305_SHA256:TLS-DHE-RSA-WITH-AES-256-GCM-SHA384:TLS-DHE-RSA-WITH-AES-256-CBC-SHA:TLS-DHE-RSA-WITH-AES-128-GCM-SHA256:TLS-DHE-RSA-WITH-AES-128-CBC-SHA:TLS_AES_256_GCM_SHA384:TLS-RSA-WITH-AES-256-CBC-SHA", //nolint:lll - "auth-user-pass " + constants.OpenVPNAuthConf, - "auth " + auth, - - // Added constant values - "auth-nocache", - "mute-replay-warnings", - "pull-filter ignore \"auth-token\"", // prevent auth failed loops - "auth-retry nointeract", - "suppress-timestamps", - - // Modified variables - connection.OpenVPNProtoLine(), - connection.OpenVPNRemoteLine(), - } - - lines = append(lines, utils.CipherLines(settings.Ciphers, settings.Version)...) - - if connection.Protocol == constants.UDP { - lines = append(lines, "explicit-exit-notify") - } - - if settings.ProcessUser != "root" { - lines = append(lines, "user "+settings.ProcessUser) - lines = append(lines, "persist-tun") - lines = append(lines, "persist-key") - } - - if !*settings.IPv6 { - lines = append(lines, `pull-filter ignore "route-ipv6"`) - lines = append(lines, `pull-filter ignore "ifconfig-ipv6"`) - // Perfect Privacy specific IPv6 - lines = append(lines, "redirect-gateway def1") - lines = append(lines, `pull-filter ignore "redirect-gateway def1 ipv6"`) - } - - lines = append(lines, utils.WrapOpenvpnCA( - constants.PerfectprivacyCA)...) - lines = append(lines, utils.WrapOpenvpnCert( - constants.PerfectprivacyCert)...) - lines = append(lines, utils.WrapOpenvpnKey( - constants.PerfectprivacyKey)...) - lines = append(lines, utils.WrapOpenvpnTLSCrypt( - constants.PerfectprivacyTLSCrypt)...) - - lines = append(lines, "") - - return lines, nil + return utils.OpenVPNConfig(providerSettings, connection, settings) } diff --git a/internal/provider/privado/openvpnconf.go b/internal/provider/privado/openvpnconf.go index bc6a79c3..fd68005a 100644 --- a/internal/provider/privado/openvpnconf.go +++ b/internal/provider/privado/openvpnconf.go @@ -1,8 +1,6 @@ package privado import ( - "strconv" - "github.com/qdm12/gluetun/internal/configuration/settings" "github.com/qdm12/gluetun/internal/constants" "github.com/qdm12/gluetun/internal/models" @@ -10,67 +8,18 @@ import ( ) func (p *Privado) BuildConf(connection models.Connection, - settings settings.OpenVPN) (lines []string, err error) { - if len(settings.Ciphers) == 0 { - settings.Ciphers = []string{constants.AES256cbc} + settings settings.OpenVPN) (lines []string) { + //nolint:gomnd + providerSettings := utils.OpenVPNProviderSettings{ + AuthUserPass: true, + Ciphers: []string{ + constants.AES256cbc, + }, + Auth: constants.SHA256, + Ping: 10, + TLSCipher: "TLS-DHE-RSA-WITH-AES-256-CBC-SHA:TLS-DHE-DSS-WITH-AES-256-CBC-SHA:TLS-RSA-WITH-AES-256-CBC-SHA", + VerifyX509Type: "name", + CA: constants.PrivadoCA, } - - auth := *settings.Auth - if auth == "" { - auth = constants.SHA256 - } - - lines = []string{ - "client", - "nobind", - "tls-exit", - "dev " + settings.Interface, - "verb " + strconv.Itoa(*settings.Verbosity), - - // Privado specific - "ping 10", - "tls-cipher TLS-DHE-RSA-WITH-AES-256-CBC-SHA:TLS-DHE-DSS-WITH-AES-256-CBC-SHA:TLS-RSA-WITH-AES-256-CBC-SHA", - "verify-x509-name " + connection.Hostname + " name", - "auth-user-pass " + constants.OpenVPNAuthConf, - "auth " + auth, - - // Added constant values - "auth-nocache", - "mute-replay-warnings", - "pull-filter ignore \"auth-token\"", // prevent auth failed loops - "auth-retry nointeract", - "suppress-timestamps", - - // Connection variables - connection.OpenVPNProtoLine(), - connection.OpenVPNRemoteLine(), - } - - lines = append(lines, utils.CipherLines(settings.Ciphers, settings.Version)...) - - if settings.ProcessUser != "root" { - lines = append(lines, "user "+settings.ProcessUser) - lines = append(lines, "persist-tun") - lines = append(lines, "persist-key") - } - - if *settings.MSSFix > 0 { - lines = append(lines, "mssfix "+strconv.Itoa(int(*settings.MSSFix))) - } - - if connection.Protocol == constants.UDP { - lines = append(lines, "explicit-exit-notify") - } - - if !*settings.IPv6 { - lines = append(lines, `pull-filter ignore "route-ipv6"`) - lines = append(lines, `pull-filter ignore "ifconfig-ipv6"`) - } - - lines = append(lines, utils.WrapOpenvpnCA( - constants.PrivadoCA)...) - - lines = append(lines, "") - - return lines, nil + return utils.OpenVPNConfig(providerSettings, connection, settings) } diff --git a/internal/provider/privateinternetaccess/openvpnconf.go b/internal/provider/privateinternetaccess/openvpnconf.go index 362bd7b9..195322e1 100644 --- a/internal/provider/privateinternetaccess/openvpnconf.go +++ b/internal/provider/privateinternetaccess/openvpnconf.go @@ -1,8 +1,6 @@ package privateinternetaccess import ( - "strconv" - "github.com/qdm12/gluetun/internal/configuration/settings" "github.com/qdm12/gluetun/internal/constants" "github.com/qdm12/gluetun/internal/models" @@ -10,87 +8,30 @@ import ( ) func (p *PIA) BuildConf(connection models.Connection, - settings settings.OpenVPN) (lines []string, err error) { - var defaultCipher, defaultAuth, X509CRL, certificate string + settings settings.OpenVPN) (lines []string) { + providerSettings := utils.OpenVPNProviderSettings{ + RemoteCertTLS: true, + RenegDisabled: true, + AuthUserPass: true, + } + switch *settings.PIAEncPreset { case constants.PIAEncryptionPresetNormal: - defaultCipher = constants.AES128cbc - defaultAuth = constants.SHA1 - X509CRL = constants.PiaX509CRLNormal - certificate = constants.PiaCANormal + providerSettings.Ciphers = []string{constants.AES128cbc} + providerSettings.Auth = constants.SHA1 + providerSettings.CRLVerify = constants.PiaX509CRLNormal + providerSettings.CA = constants.PiaCANormal case constants.PIAEncryptionPresetNone: - defaultCipher = "none" - defaultAuth = "none" - X509CRL = constants.PiaX509CRLNormal - certificate = constants.PiaCANormal + providerSettings.Ciphers = []string{"none"} + providerSettings.Auth = "none" + providerSettings.CRLVerify = constants.PiaX509CRLNormal + providerSettings.CA = constants.PiaCANormal default: // strong - defaultCipher = constants.AES256cbc - defaultAuth = constants.SHA256 - X509CRL = constants.PiaX509CRLStrong - certificate = constants.PiaCAStrong + providerSettings.Ciphers = []string{constants.AES256cbc} + providerSettings.Auth = constants.SHA256 + providerSettings.CRLVerify = constants.PiaX509CRLStrong + providerSettings.CA = constants.PiaCAStrong } - if len(settings.Ciphers) == 0 { - settings.Ciphers = []string{defaultCipher} - } - - auth := *settings.Auth - if auth == "" { - auth = defaultAuth - } - - lines = []string{ - "client", - "nobind", - "tls-exit", - "dev " + settings.Interface, - "verb " + strconv.Itoa(*settings.Verbosity), - - // PIA specific - "remote-cert-tls server", - "reneg-sec 0", - "auth-user-pass " + constants.OpenVPNAuthConf, - "auth " + auth, - - // Added constant values - "auth-nocache", - "mute-replay-warnings", - "pull-filter ignore \"auth-token\"", // prevent auth failed loops - "auth-retry nointeract", - "suppress-timestamps", - - // Connection variables - connection.OpenVPNProtoLine(), - connection.OpenVPNRemoteLine(), - } - - if len(settings.Ciphers) > 0 { - lines = append(lines, utils.CipherLines(settings.Ciphers, settings.Version)...) - } - - if connection.Protocol == constants.UDP { - lines = append(lines, "explicit-exit-notify") - } - - if settings.ProcessUser != "root" { - lines = append(lines, "user "+settings.ProcessUser) - lines = append(lines, "persist-tun") - lines = append(lines, "persist-key") - } - - if *settings.MSSFix > 0 { - lines = append(lines, "mssfix "+strconv.Itoa(int(*settings.MSSFix))) - } - - if !*settings.IPv6 { - lines = append(lines, `pull-filter ignore "route-ipv6"`) - lines = append(lines, `pull-filter ignore "ifconfig-ipv6"`) - } - - lines = append(lines, utils.WrapOpenvpnCA(certificate)...) - lines = append(lines, utils.WrapOpenvpnCRLVerify(X509CRL)...) - - lines = append(lines, "") - - return lines, nil + return utils.OpenVPNConfig(providerSettings, connection, settings) } diff --git a/internal/provider/privatevpn/openvpnconf.go b/internal/provider/privatevpn/openvpnconf.go index cba83a6d..ca7ad2d7 100644 --- a/internal/provider/privatevpn/openvpnconf.go +++ b/internal/provider/privatevpn/openvpnconf.go @@ -1,8 +1,6 @@ package privatevpn import ( - "strconv" - "github.com/qdm12/gluetun/internal/configuration/settings" "github.com/qdm12/gluetun/internal/constants" "github.com/qdm12/gluetun/internal/models" @@ -10,68 +8,19 @@ import ( ) func (p *Privatevpn) BuildConf(connection models.Connection, - settings settings.OpenVPN) (lines []string, err error) { - if len(settings.Ciphers) == 0 { - settings.Ciphers = []string{constants.AES128gcm} + settings settings.OpenVPN) (lines []string) { + providerSettings := utils.OpenVPNProviderSettings{ + RemoteCertTLS: true, + AuthUserPass: true, + Ciphers: []string{ + constants.AES128gcm, + }, + Auth: constants.SHA256, + CA: constants.PrivatevpnCA, + TLSAuth: constants.PrivatevpnTLSAuth, + UDPLines: []string{ + "key-direction 1", + }, } - - auth := *settings.Auth - if auth == "" { - auth = constants.SHA256 - } - - lines = []string{ - "client", - "nobind", - "tls-exit", - "dev " + settings.Interface, - "verb " + strconv.Itoa(*settings.Verbosity), - - // Privatevpn specific - "remote-cert-tls server", - "auth-user-pass " + constants.OpenVPNAuthConf, - "auth " + auth, - - // Added constant values - "auth-nocache", - "mute-replay-warnings", - "pull-filter ignore \"auth-token\"", // prevent auth failed loops - "auth-retry nointeract", - "suppress-timestamps", - - // Connection variables - connection.OpenVPNProtoLine(), - connection.OpenVPNRemoteLine(), - } - - lines = append(lines, utils.CipherLines(settings.Ciphers, settings.Version)...) - - if connection.Protocol == constants.UDP { - lines = append(lines, "key-direction 1") - lines = append(lines, "explicit-exit-notify") - } - - if settings.ProcessUser != "root" { - lines = append(lines, "user "+settings.ProcessUser) - lines = append(lines, "persist-tun") - lines = append(lines, "persist-key") - } - - if *settings.MSSFix > 0 { - lines = append(lines, "mssfix "+strconv.Itoa(int(*settings.MSSFix))) - } - - if !*settings.IPv6 { - lines = append(lines, `pull-filter ignore "route-ipv6"`) - lines = append(lines, `pull-filter ignore "ifconfig-ipv6"`) - } - - lines = append(lines, utils.WrapOpenvpnCA( - constants.PrivatevpnCA)...) - lines = append(lines, utils.WrapOpenvpnTLSAuth( - constants.PrivatevpnTLSAuth)...) - - lines = append(lines, "") - - return lines, nil + return utils.OpenVPNConfig(providerSettings, connection, settings) } diff --git a/internal/provider/protonvpn/openvpnconf.go b/internal/provider/protonvpn/openvpnconf.go index 9ee20ec1..fa91acbf 100644 --- a/internal/provider/protonvpn/openvpnconf.go +++ b/internal/provider/protonvpn/openvpnconf.go @@ -1,8 +1,6 @@ package protonvpn import ( - "strconv" - "github.com/qdm12/gluetun/internal/configuration/settings" "github.com/qdm12/gluetun/internal/constants" "github.com/qdm12/gluetun/internal/models" @@ -10,74 +8,24 @@ import ( ) func (p *Protonvpn) BuildConf(connection models.Connection, - settings settings.OpenVPN) (lines []string, err error) { - if len(settings.Ciphers) == 0 { - settings.Ciphers = []string{constants.AES256cbc} + settings settings.OpenVPN) (lines []string) { + //nolint:gomnd + providerSettings := utils.OpenVPNProviderSettings{ + RemoteCertTLS: true, + AuthUserPass: true, + Ciphers: []string{ + constants.AES256cbc, + }, + Auth: constants.SHA512, + MssFix: 1450, + TunMTUExtra: 32, + RenegDisabled: true, + KeyDirection: "1", + CA: constants.ProtonvpnCA, + TLSAuth: constants.ProtonvpnTLSAuth, + UDPLines: []string{ + "fast-io", + }, } - - auth := *settings.Auth - if auth == "" { - auth = constants.SHA512 - } - - mssFix := *settings.MSSFix - if mssFix == 0 { - const defaultMSSFix = 1450 - mssFix = defaultMSSFix - } - - lines = []string{ - "client", - "nobind", - "tls-exit", - "dev " + settings.Interface, - "verb " + strconv.Itoa(*settings.Verbosity), - - // Protonvpn specific - "remote-cert-tls server", - "tun-mtu-extra 32", - "mssfix " + strconv.Itoa(int(mssFix)), - "reneg-sec 0", - "key-direction 1", - "auth-user-pass " + constants.OpenVPNAuthConf, - "auth " + auth, - - // Added constant values - "auth-nocache", - "mute-replay-warnings", - "pull-filter ignore \"auth-token\"", // prevent auth failed loops - "auth-retry nointeract", - "suppress-timestamps", - - // Connection variables - connection.OpenVPNProtoLine(), - connection.OpenVPNRemoteLine(), - } - - lines = append(lines, utils.CipherLines(settings.Ciphers, settings.Version)...) - - if connection.Protocol == constants.UDP { - lines = append(lines, "fast-io") - lines = append(lines, "explicit-exit-notify") - } - - if settings.ProcessUser != "root" { - lines = append(lines, "user "+settings.ProcessUser) - lines = append(lines, "persist-tun") - lines = append(lines, "persist-key") - } - - if !*settings.IPv6 { - lines = append(lines, `pull-filter ignore "route-ipv6"`) - lines = append(lines, `pull-filter ignore "ifconfig-ipv6"`) - } - - lines = append(lines, utils.WrapOpenvpnCA( - constants.ProtonvpnCA)...) - lines = append(lines, utils.WrapOpenvpnTLSAuth( - constants.ProtonvpnTLSAuth)...) - - lines = append(lines, "") - - return lines, nil + return utils.OpenVPNConfig(providerSettings, connection, settings) } diff --git a/internal/provider/provider.go b/internal/provider/provider.go index 2337239e..e0c81cbc 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -38,7 +38,7 @@ import ( // Provider contains methods to read and modify the openvpn configuration to connect as a client. type Provider interface { GetConnection(selection settings.ServerSelection) (connection models.Connection, err error) - BuildConf(connection models.Connection, settings settings.OpenVPN) (lines []string, err error) + BuildConf(connection models.Connection, settings settings.OpenVPN) (lines []string) PortForwarder } diff --git a/internal/provider/purevpn/openvpnconf.go b/internal/provider/purevpn/openvpnconf.go index 362a2039..2b28edeb 100644 --- a/internal/provider/purevpn/openvpnconf.go +++ b/internal/provider/purevpn/openvpnconf.go @@ -1,8 +1,6 @@ package purevpn import ( - "strconv" - "github.com/qdm12/gluetun/internal/configuration/settings" "github.com/qdm12/gluetun/internal/constants" "github.com/qdm12/gluetun/internal/models" @@ -10,71 +8,18 @@ import ( ) func (p *Purevpn) BuildConf(connection models.Connection, - settings settings.OpenVPN) (lines []string, err error) { - if len(settings.Ciphers) == 0 { - settings.Ciphers = []string{constants.AES256gcm} + settings settings.OpenVPN) (lines []string) { + providerSettings := utils.OpenVPNProviderSettings{ + RemoteCertTLS: true, + AuthUserPass: true, + Ciphers: []string{ + constants.AES256gcm, + }, + Ping: 10, //nolint:gomnd + CA: constants.PurevpnCA, + Cert: constants.PurevpnCert, + Key: constants.PurevpnKey, + TLSAuth: constants.PurevpnTLSAuth, } - - lines = []string{ - "client", - "nobind", - "tls-exit", - "dev " + settings.Interface, - "verb " + strconv.Itoa(*settings.Verbosity), - - // Purevpn specific - "ping 10", - "remote-cert-tls server", - "key-direction 1", - "auth-user-pass " + constants.OpenVPNAuthConf, - - // Added constant values - "auth-nocache", - "mute-replay-warnings", - "pull-filter ignore \"auth-token\"", // prevent auth failed loops - "auth-retry nointeract", - "suppress-timestamps", - - // Connection variables - connection.OpenVPNProtoLine(), - connection.OpenVPNRemoteLine(), - } - - lines = append(lines, utils.CipherLines(settings.Ciphers, settings.Version)...) - - if connection.Protocol == constants.UDP { - lines = append(lines, "explicit-exit-notify") - } - - if *settings.Auth != "" { - lines = append(lines, "auth "+*settings.Auth) - } - - if *settings.MSSFix > 0 { - lines = append(lines, "mssfix "+strconv.Itoa(int(*settings.MSSFix))) - } - - if settings.ProcessUser != "root" { - lines = append(lines, "user "+settings.ProcessUser) - lines = append(lines, "persist-tun") - lines = append(lines, "persist-key") - } - - if !*settings.IPv6 { - lines = append(lines, `pull-filter ignore "route-ipv6"`) - lines = append(lines, `pull-filter ignore "ifconfig-ipv6"`) - } - - lines = append(lines, utils.WrapOpenvpnCA( - constants.PurevpnCA)...) - lines = append(lines, utils.WrapOpenvpnCert( - constants.PurevpnCert)...) - lines = append(lines, utils.WrapOpenvpnKey( - constants.PurevpnKey)...) - lines = append(lines, utils.WrapOpenvpnTLSAuth( - constants.PurevpnTLSAuth)...) - - lines = append(lines, "") - - return lines, nil + return utils.OpenVPNConfig(providerSettings, connection, settings) } diff --git a/internal/provider/surfshark/openvpnconf.go b/internal/provider/surfshark/openvpnconf.go index b43eda4e..a6a0bdc5 100644 --- a/internal/provider/surfshark/openvpnconf.go +++ b/internal/provider/surfshark/openvpnconf.go @@ -1,8 +1,6 @@ package surfshark import ( - "strconv" - "github.com/qdm12/gluetun/internal/configuration/settings" "github.com/qdm12/gluetun/internal/constants" "github.com/qdm12/gluetun/internal/models" @@ -10,74 +8,21 @@ import ( ) func (s *Surfshark) BuildConf(connection models.Connection, - settings settings.OpenVPN) (lines []string, err error) { - if len(settings.Ciphers) == 0 { - settings.Ciphers = []string{constants.AES256gcm} + settings settings.OpenVPN) (lines []string) { + providerSettings := utils.OpenVPNProviderSettings{ + RemoteCertTLS: true, + AuthUserPass: true, + Ciphers: []string{ + constants.AES256gcm, + }, + Auth: constants.SHA512, + RenegDisabled: true, + KeyDirection: "1", + Ping: 15, //nolint:gomnd + MssFix: 1450, //nolint:gomnd + TunMTUExtra: 32, //nolint:gomnd + CA: constants.SurfsharkCA, + TLSAuth: constants.SurfsharkTLSAuth, } - - auth := *settings.Auth - if auth == "" { - auth = constants.SHA512 - } - - mssFix := *settings.MSSFix - if mssFix == 0 { - const defaultMSSFix = 1450 - mssFix = defaultMSSFix - } - - lines = []string{ - "client", - "nobind", - "tls-exit", - "dev " + settings.Interface, - "verb " + strconv.Itoa(*settings.Verbosity), - - // Surfshark specific - "tun-mtu-extra 32", - "mssfix " + strconv.Itoa(int(mssFix)), - "ping 15", - "remote-cert-tls server", - "reneg-sec 0", - "key-direction 1", - "auth-user-pass " + constants.OpenVPNAuthConf, - "auth " + auth, - - // Added constant values - "auth-nocache", - "mute-replay-warnings", - "pull-filter ignore \"auth-token\"", // prevent auth failed loops - "auth-retry nointeract", - "suppress-timestamps", - - // Connection variables - connection.OpenVPNProtoLine(), - connection.OpenVPNRemoteLine(), - } - - lines = append(lines, utils.CipherLines(settings.Ciphers, settings.Version)...) - - if connection.Protocol == constants.UDP { - lines = append(lines, "explicit-exit-notify") - } - - if settings.ProcessUser != "root" { - lines = append(lines, "user "+settings.ProcessUser) - lines = append(lines, "persist-tun") - lines = append(lines, "persist-key") - } - - if !*settings.IPv6 { - lines = append(lines, `pull-filter ignore "route-ipv6"`) - lines = append(lines, `pull-filter ignore "ifconfig-ipv6"`) - } - - lines = append(lines, utils.WrapOpenvpnCA( - constants.SurfsharkCA)...) - lines = append(lines, utils.WrapOpenvpnTLSAuth( - constants.SurfsharkTLSAuth)...) - - lines = append(lines, "") - - return lines, nil + return utils.OpenVPNConfig(providerSettings, connection, settings) } diff --git a/internal/provider/torguard/openvpnconf.go b/internal/provider/torguard/openvpnconf.go index 38b6f725..00a0e3ef 100644 --- a/internal/provider/torguard/openvpnconf.go +++ b/internal/provider/torguard/openvpnconf.go @@ -1,8 +1,6 @@ package torguard import ( - "strconv" - "github.com/qdm12/gluetun/internal/configuration/settings" "github.com/qdm12/gluetun/internal/constants" "github.com/qdm12/gluetun/internal/models" @@ -10,77 +8,23 @@ import ( ) func (t *Torguard) BuildConf(connection models.Connection, - settings settings.OpenVPN) (lines []string, err error) { - if len(settings.Ciphers) == 0 { - settings.Ciphers = []string{constants.AES256gcm} + settings settings.OpenVPN) (lines []string) { + providerSettings := utils.OpenVPNProviderSettings{ + RemoteCertTLS: true, + AuthUserPass: true, + Ciphers: []string{ + constants.AES256gcm, + }, + Auth: constants.SHA256, + MssFix: 1450, //nolint:gomnd + TunMTUExtra: 32, //nolint:gomnd + SndBuf: 393216, //nolint:gomnd + RcvBuf: 393216, //nolint:gomnd + Ping: 5, //nolint:gomnd + RenegDisabled: true, + KeyDirection: "1", + CA: constants.TorguardCA, + TLSAuth: constants.TorguardTLSAuth, } - - auth := *settings.Auth - if auth == "" { - auth = constants.SHA256 - } - - mssFix := *settings.MSSFix - if mssFix == 0 { - const defaultMSSFix = 1450 - mssFix = defaultMSSFix - } - - lines = []string{ - "client", - "nobind", - "tls-exit", - "dev " + settings.Interface, - "verb " + strconv.Itoa(*settings.Verbosity), - - // Torguard specific - "tun-mtu-extra 32", - "mssfix " + strconv.Itoa(int(mssFix)), - "sndbuf 393216", - "rcvbuf 393216", - "ping 5", - "remote-cert-tls server", - "reneg-sec 0", - "key-direction 1", - "auth-user-pass " + constants.OpenVPNAuthConf, - "auth " + auth, - - // Added constant values - "auth-nocache", - "mute-replay-warnings", - "pull-filter ignore \"auth-token\"", // prevent auth failed loops - "auth-retry nointeract", - "suppress-timestamps", - - // Connection variables - connection.OpenVPNProtoLine(), - connection.OpenVPNRemoteLine(), - } - - lines = append(lines, utils.CipherLines(settings.Ciphers, settings.Version)...) - - if settings.ProcessUser != "root" { - lines = append(lines, "user "+settings.ProcessUser) - lines = append(lines, "persist-tun") - lines = append(lines, "persist-key") - } - - if connection.Protocol == constants.UDP { - lines = append(lines, "fast-io") - lines = append(lines, "explicit-exit-notify") - } - - if !*settings.IPv6 { - lines = append(lines, `pull-filter ignore "route-ipv6"`) - lines = append(lines, `pull-filter ignore "ifconfig-ipv6"`) - } - - lines = append(lines, utils.WrapOpenvpnCA( - constants.TorguardCA)...) - lines = append(lines, utils.WrapOpenvpnTLSAuth( - constants.TorguardTLSAuth)...) - - lines = append(lines, "") - - return lines, nil + return utils.OpenVPNConfig(providerSettings, connection, settings) } diff --git a/internal/provider/utils/cipher.go b/internal/provider/utils/cipher.go index 6fa8334a..693680a5 100644 --- a/internal/provider/utils/cipher.go +++ b/internal/provider/utils/cipher.go @@ -7,6 +7,10 @@ import ( ) func CipherLines(ciphers []string, version string) (lines []string) { + if len(ciphers) == 0 { + return nil + } + switch version { case constants.Openvpn24: return []string{ diff --git a/internal/provider/utils/openvpn.go b/internal/provider/utils/openvpn.go index daf1b025..8005b0f1 100644 --- a/internal/provider/utils/openvpn.go +++ b/internal/provider/utils/openvpn.go @@ -1,5 +1,254 @@ package utils +import ( + "fmt" + "strings" + + "github.com/qdm12/gluetun/internal/configuration/settings" + "github.com/qdm12/gluetun/internal/constants" + "github.com/qdm12/gluetun/internal/models" + "github.com/qdm12/gluetun/internal/openvpn/parse" +) + +type OpenVPNProviderSettings struct { + Ping int + RemoteCertTLS bool + Ciphers []string + Auth string + CA string + CRLVerify string + Cert string + Key string + RSAKey string + TLSAuth string + TLSCrypt string + MssFix uint16 + FastIO bool + AuthUserPass bool + AuthToken bool + Fragment uint16 + SndBuf uint32 + RcvBuf uint32 + // VerifyX509Name can be set to a custom name to verify against. + // Note VerifyX509Type has to be set for it to be verified. + // If it is left unset, the code will deduce a name to verify against + // using the connection hostname and according to VerifyX509Type. + VerifyX509Name string + // VerifyX509Type can be "name-prefix", "name" + VerifyX509Type string + TLSCipher string + TunMTU uint16 + TunMTUExtra uint16 + RenegDisabled bool + RenegSec uint16 + KeyDirection string + ExtraLines []string + UDPLines []string + IPv6Lines []string +} + +//nolint:gocognit,gocyclo +func OpenVPNConfig(provider OpenVPNProviderSettings, + connection models.Connection, + settings settings.OpenVPN) []string { + var lines openvpnConfigLines + lines.add("client") + lines.add("nobind") + lines.add("tls-exit") // exit OpenVPN on a TLS error + lines.add("auth-nocache") // do not cache auth credentials + lines.add("mute-replay-warnings") // these are often ignored by some VPN providers + lines.add("auth-retry", "nointeract") // retry authenticating without interaction + lines.add("suppress-timestamps") // do not log timestamps, the Gluetun logger takes care of it + lines.add("dev", settings.Interface) + lines.add("verb", fmt.Sprint(*settings.Verbosity)) + lines.add("auth-user-pass", constants.OpenVPNAuthConf) + lines.add("proto", connection.Protocol) + lines.add("remote", connection.IP.String(), fmt.Sprint(connection.Port)) + + if !provider.AuthToken { + lines.add("pull-filter", "ignore", `"auth-token"`) // prevent auth failed loops + } + + if provider.KeyDirection != "" { + lines.add("key-direction", provider.KeyDirection) + } + + if provider.Ping > 0 { + lines.add("ping", fmt.Sprint(provider.Ping)) + } + + if provider.RenegDisabled { + lines.add("reneg-sec", "0") + } else if provider.RenegSec > 0 { + lines.add("reneg-sec", fmt.Sprint(provider.RenegSec)) + } + + if provider.RemoteCertTLS { + // equivalent to older 'ns-cert-type' option + lines.add("remote-cert-tls server") + } + + x509Type := provider.VerifyX509Type + if x509Type != "" { + x509Name := provider.VerifyX509Name + if x509Name == "" { + // find name from connection hostname depending on type + switch x509Type { + case "name": + x509Name = connection.Hostname + case "name-prefix": + x509Name = strings.Split(connection.Hostname, ".")[0] + default: + panic(fmt.Sprintf("verify-x509-name type not supported: %q", x509Type)) + } + } + lines.add("verify-x509-name", x509Name, x509Type) + } + + if provider.TLSCipher != "" { + lines.add("tls-cipher", provider.TLSCipher) + } + + if provider.FastIO { + lines.add("fast-io") + } + + ciphers := defaultStringSlice(settings.Ciphers, provider.Ciphers) + cipherLines := CipherLines(ciphers, settings.Version) + lines.addLines(cipherLines) + + auth := defaultString(*settings.Auth, provider.Auth) + if auth != "" { + lines.add("auth", auth) + } + + if provider.TunMTU > 0 { + lines.add("tun-mtu", fmt.Sprint(provider.TunMTU)) + } + + if provider.TunMTUExtra > 0 { + lines.add("tun-mtu-extra", fmt.Sprint(provider.TunMTUExtra)) + } + + mssFix := defaultUint16(*settings.MSSFix, provider.MssFix) + if mssFix > 0 { + lines.add("mssfix", fmt.Sprint(mssFix)) + } + + if provider.SndBuf > 0 { + lines.add("sndbuf", fmt.Sprint(provider.SndBuf)) + } + + if provider.RcvBuf > 0 { + lines.add("rcvbuf", fmt.Sprint(provider.RcvBuf)) + } + + if connection.Protocol == constants.UDP { + lines.add("explicit-exit-notify") + } + + if settings.ProcessUser != "root" { + lines.add("user", settings.ProcessUser) + lines.add("persist-tun") + lines.add("persist-key") + } + + if *settings.IPv6 { + lines.add("tun-ipv6") + } else { + lines.add("pull-filter", "ignore", `"route-ipv6"`) + lines.add("pull-filter", "ignore", `"ifconfig-ipv6"`) + lines.addLines(provider.IPv6Lines) + } + + if provider.CA != "" { + lines.addLines(WrapOpenvpnCA(provider.CA)) + } + if provider.CRLVerify != "" { + lines.addLines(WrapOpenvpnCRLVerify(provider.CRLVerify)) + } + if provider.Cert != "" { + lines.addLines(WrapOpenvpnCert(provider.Cert)) + } + if provider.Key != "" { + lines.addLines(WrapOpenvpnKey(provider.Key)) + } + if provider.RSAKey != "" { + lines.addLines(WrapOpenvpnRSAKey(provider.RSAKey)) + } + if provider.TLSAuth != "" { + lines.addLines(WrapOpenvpnTLSAuth(provider.TLSAuth)) + } + if provider.TLSCrypt != "" { + lines.addLines(WrapOpenvpnTLSCrypt(provider.TLSCrypt)) + } + + if *settings.ClientCrt != "" { + certData, err := parse.ExtractCert([]byte(*settings.ClientCrt)) + panicOnError(err, "cannot extract client crt") + lines.addLines(WrapOpenvpnCert(certData)) + } + + if *settings.ClientKey != "" { + keyData, err := parse.ExtractPrivateKey([]byte(*settings.ClientKey)) + panicOnError(err, "cannot extract client private key") + lines.addLines(WrapOpenvpnKey(keyData)) + } + + lines.addLines(provider.ExtraLines) + + // Add a trailing empty line + lines.add("") + + return lines +} + +type openvpnConfigLines []string + +func (o *openvpnConfigLines) add(words ...string) { + *o = append(*o, strings.Join(words, " ")) +} + +func (o *openvpnConfigLines) addLines(lines []string) { + for _, line := range lines { + o.add(line) + } +} + +func defaultString(value, defaultValue string) string { + if value == "" { + return defaultValue + } + return value +} + +func defaultUint16(value, defaultValue uint16) uint16 { + if value == 0 { + return defaultValue + } + return value +} + +func defaultStringSlice(value, defaultValue []string) ( + result []string) { + if len(value) > 0 { + result = make([]string, len(value)) + copy(result, value) + return result + } + result = make([]string, len(defaultValue)) + copy(result, defaultValue) + return result +} + +func panicOnError(err error, context string) { + if err == nil { + return + } + panicMessage := fmt.Sprintf("%s: %s", context, err) + panic(panicMessage) +} + func WrapOpenvpnCA(certificate string) (lines []string) { return []string{ "", diff --git a/internal/provider/vpnunlimited/openvpnconf.go b/internal/provider/vpnunlimited/openvpnconf.go index ba07c0d9..580c2bbe 100644 --- a/internal/provider/vpnunlimited/openvpnconf.go +++ b/internal/provider/vpnunlimited/openvpnconf.go @@ -1,86 +1,23 @@ package vpnunlimited import ( - "fmt" - "strconv" - "github.com/qdm12/gluetun/internal/configuration/settings" "github.com/qdm12/gluetun/internal/constants" "github.com/qdm12/gluetun/internal/models" - "github.com/qdm12/gluetun/internal/openvpn/parse" "github.com/qdm12/gluetun/internal/provider/utils" ) func (p *Provider) BuildConf(connection models.Connection, - settings settings.OpenVPN) (lines []string, err error) { - lines = []string{ - "client", - "nobind", - "tls-exit", - "dev " + settings.Interface, - "verb " + strconv.Itoa(*settings.Verbosity), - - // VPNUnlimited specific - "ping 5", - "remote-cert-tls server", - "reneg-sec 0", - "route-metric 1", - - // Added constant values - "auth-nocache", - "mute-replay-warnings", - "pull-filter ignore \"auth-token\"", // prevent auth failed loops - "auth-retry nointeract", - "suppress-timestamps", - - // Connection variables - connection.OpenVPNProtoLine(), - connection.OpenVPNRemoteLine(), + settings settings.OpenVPN) (lines []string) { + providerSettings := utils.OpenVPNProviderSettings{ + RemoteCertTLS: true, + AuthUserPass: false, + Ping: 5, //nolint:gomnd + RenegDisabled: true, + CA: constants.VPNUnlimitedCA, + ExtraLines: []string{ + "route-metric 1", + }, } - - if len(settings.Ciphers) > 0 { - lines = append(lines, utils.CipherLines(settings.Ciphers, settings.Version)...) - } - - if *settings.Auth != "" { - lines = append(lines, "auth "+*settings.Auth) - } - - if *settings.MSSFix > 0 { - lines = append(lines, "mssfix "+strconv.Itoa(int(*settings.MSSFix))) - } - - if connection.Protocol == constants.UDP { - lines = append(lines, "explicit-exit-notify") - } - - if settings.ProcessUser != "root" { - lines = append(lines, "user "+settings.ProcessUser) - lines = append(lines, "persist-tun") - lines = append(lines, "persist-key") - } - - if !*settings.IPv6 { - lines = append(lines, `pull-filter ignore "route-ipv6"`) - lines = append(lines, `pull-filter ignore "ifconfig-ipv6"`) - } - - lines = append(lines, utils.WrapOpenvpnCA( - constants.VPNUnlimitedCA)...) - - certData, err := parse.ExtractCert([]byte(*settings.ClientCrt)) - if err != nil { - return nil, fmt.Errorf("client cert is not valid: %w", err) - } - lines = append(lines, utils.WrapOpenvpnCert(certData)...) - - keyData, err := parse.ExtractPrivateKey([]byte(*settings.ClientKey)) - if err != nil { - return nil, fmt.Errorf("client key is not valid: %w", err) - } - lines = append(lines, utils.WrapOpenvpnKey(keyData)...) - - lines = append(lines, "") - - return lines, nil + return utils.OpenVPNConfig(providerSettings, connection, settings) } diff --git a/internal/provider/vyprvpn/openvpnconf.go b/internal/provider/vyprvpn/openvpnconf.go index 6dc92142..51140e34 100644 --- a/internal/provider/vyprvpn/openvpnconf.go +++ b/internal/provider/vyprvpn/openvpnconf.go @@ -1,8 +1,6 @@ package vyprvpn import ( - "strconv" - "github.com/qdm12/gluetun/internal/configuration/settings" "github.com/qdm12/gluetun/internal/constants" "github.com/qdm12/gluetun/internal/models" @@ -10,64 +8,21 @@ import ( ) func (v *Vyprvpn) BuildConf(connection models.Connection, - settings settings.OpenVPN) (lines []string, err error) { - if len(settings.Ciphers) == 0 { - settings.Ciphers = []string{constants.AES256cbc} + settings settings.OpenVPN) (lines []string) { + providerSettings := utils.OpenVPNProviderSettings{ + RemoteCertTLS: true, + AuthUserPass: true, + Ciphers: []string{ + constants.AES256cbc, + }, + Auth: constants.SHA256, + Ping: 10, //nolint:gomnd + CA: constants.VyprvpnCA, + TLSCipher: "TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384:TLS-DHE-RSA-WITH-AES-256-CBC-SHA256:TLS-DHE-RSA-WITH-AES-256-CBC-SHA", //nolint:lll + ExtraLines: []string{ + "comp-lzo", + }, + // VerifyX509Name: []string{"lu1.vyprvpn.com","name"}, } - - auth := *settings.Auth - if auth == "" { - auth = constants.SHA256 - } - - lines = []string{ - "client", - "nobind", - "tls-exit", - "dev " + settings.Interface, - "verb " + strconv.Itoa(*settings.Verbosity), - - // Vyprvpn specific - "ping 10", - "remote-cert-tls server", - // "verify-x509-name lu1.vyprvpn.com name", - "tls-cipher TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384:TLS-DHE-RSA-WITH-AES-256-CBC-SHA256:TLS-DHE-RSA-WITH-AES-256-CBC-SHA", //nolint:lll - "auth-user-pass " + constants.OpenVPNAuthConf, - "auth " + auth, - "comp-lzo", - - // Added constant values - "auth-nocache", - "mute-replay-warnings", - "pull-filter ignore \"auth-token\"", // prevent auth failed loops - "auth-retry nointeract", - "suppress-timestamps", - - // Connection variables - connection.OpenVPNProtoLine(), - connection.OpenVPNRemoteLine(), - } - - lines = append(lines, utils.CipherLines(settings.Ciphers, settings.Version)...) - - if connection.Protocol == constants.UDP { - lines = append(lines, "explicit-exit-notify") - } - - if settings.ProcessUser != "root" { - lines = append(lines, "user "+settings.ProcessUser) - lines = append(lines, "persist-tun") - lines = append(lines, "persist-key") - } - - if *settings.MSSFix > 0 { - lines = append(lines, "mssfix "+strconv.Itoa(int(*settings.MSSFix))) - } - - lines = append(lines, utils.WrapOpenvpnCA( - constants.VyprvpnCA)...) - - lines = append(lines, "") - - return lines, nil + return utils.OpenVPNConfig(providerSettings, connection, settings) } diff --git a/internal/provider/wevpn/openvpnconf.go b/internal/provider/wevpn/openvpnconf.go index 6c4b3d4d..eabb05cc 100644 --- a/internal/provider/wevpn/openvpnconf.go +++ b/internal/provider/wevpn/openvpnconf.go @@ -1,91 +1,29 @@ package wevpn import ( - "fmt" - "strconv" - "github.com/qdm12/gluetun/internal/configuration/settings" "github.com/qdm12/gluetun/internal/constants" "github.com/qdm12/gluetun/internal/models" - "github.com/qdm12/gluetun/internal/openvpn/parse" "github.com/qdm12/gluetun/internal/provider/utils" ) func (w *Wevpn) BuildConf(connection models.Connection, - settings settings.OpenVPN) (lines []string, err error) { - if len(settings.Ciphers) == 0 { - settings.Ciphers = []string{constants.AES256gcm} + settings settings.OpenVPN) (lines []string) { + providerSettings := utils.OpenVPNProviderSettings{ + RemoteCertTLS: true, + AuthUserPass: true, + Ciphers: []string{ + constants.AES256gcm, + }, + Auth: constants.SHA512, + Ping: 30, //nolint:gomnd + RenegDisabled: true, + CA: constants.WevpnCA, + Cert: constants.WevpnCert, + TLSCrypt: constants.WevpnTLSCrypt, + ExtraLines: []string{ + "redirect-gateway def1 bypass-dhcp", + }, } - - auth := *settings.Auth - if auth == "" { - auth = constants.SHA512 - } - - lines = []string{ - "client", - "nobind", - "tls-exit", - "dev " + settings.Interface, - "verb " + strconv.Itoa(*settings.Verbosity), - - // Wevpn specific - "ping 30", - "remote-cert-tls server", - "redirect-gateway def1 bypass-dhcp", - "reneg-sec 0", - "auth-user-pass " + constants.OpenVPNAuthConf, - "auth " + auth, - - // Added constant values - "auth-nocache", - "mute-replay-warnings", - "pull-filter ignore \"auth-token\"", // prevent auth failed loops - "auth-retry nointeract", - "suppress-timestamps", - - // Modified variables - connection.OpenVPNProtoLine(), - connection.OpenVPNRemoteLine(), - } - - if connection.Protocol == constants.UDP { - lines = append(lines, "explicit-exit-notify") - } - - lines = append(lines, utils.CipherLines(settings.Ciphers, settings.Version)...) - - if settings.ProcessUser != "root" { - lines = append(lines, "user "+settings.ProcessUser) - lines = append(lines, "persist-tun") - lines = append(lines, "persist-key") - } - - if *settings.MSSFix > 0 { - lines = append(lines, "mssfix "+strconv.Itoa(int(*settings.MSSFix))) - } - - if *settings.IPv6 { - lines = append(lines, "tun-ipv6") - } else { - lines = append(lines, `pull-filter ignore "route-ipv6"`) - lines = append(lines, `pull-filter ignore "ifconfig-ipv6"`) - } - - keyData, err := parse.ExtractPrivateKey([]byte(*settings.ClientKey)) - if err != nil { - return nil, fmt.Errorf("client key is not valid: %w", err) - } - lines = append(lines, utils.WrapOpenvpnKey(keyData)...) - - lines = append(lines, utils.WrapOpenvpnCA( - constants.WevpnCA)...) - lines = append(lines, utils.WrapOpenvpnCert( - constants.WevpnCert)...) - lines = append(lines, utils.WrapOpenvpnTLSCrypt( - constants.WevpnTLSCrypt)...) - - lines = append(lines, "") - - return lines, nil + return utils.OpenVPNConfig(providerSettings, connection, settings) } diff --git a/internal/provider/windscribe/openvpnconf.go b/internal/provider/windscribe/openvpnconf.go index a777e1b5..b53e6d57 100644 --- a/internal/provider/windscribe/openvpnconf.go +++ b/internal/provider/windscribe/openvpnconf.go @@ -1,8 +1,6 @@ package windscribe import ( - "strconv" - "github.com/qdm12/gluetun/internal/configuration/settings" "github.com/qdm12/gluetun/internal/constants" "github.com/qdm12/gluetun/internal/models" @@ -10,75 +8,22 @@ import ( ) func (w *Windscribe) BuildConf(connection models.Connection, - settings settings.OpenVPN) (lines []string, err error) { - if len(settings.Ciphers) == 0 { - settings.Ciphers = []string{ + settings settings.OpenVPN) (lines []string) { + providerSettings := utils.OpenVPNProviderSettings{ + RemoteCertTLS: true, + AuthUserPass: true, + Ciphers: []string{ constants.AES256gcm, constants.AES256cbc, constants.AES128gcm, - } + }, + Auth: constants.SHA512, + Ping: 10, //nolint:gomnd + VerifyX509Type: "name", + KeyDirection: "1", + RenegDisabled: true, + CA: constants.WindscribeCA, + TLSAuth: constants.WindscribeTLSAuth, } - - auth := *settings.Auth - if auth == "" { - auth = constants.SHA512 - } - - lines = []string{ - "client", - "nobind", - "tls-exit", - "dev " + settings.Interface, - "verb " + strconv.Itoa(*settings.Verbosity), - - // Windscribe specific - "ping 10", - "remote-cert-tls server", - "verify-x509-name " + connection.Hostname + " name", - "key-direction 1", - "reneg-sec 0", - "auth-user-pass " + constants.OpenVPNAuthConf, - "auth " + auth, - - // Added constant values - "auth-nocache", - "mute-replay-warnings", - "pull-filter ignore \"auth-token\"", // prevent auth failed loops - "auth-retry nointeract", - "suppress-timestamps", - - // Connection variables - connection.OpenVPNProtoLine(), - connection.OpenVPNRemoteLine(), - } - - lines = append(lines, utils.CipherLines(settings.Ciphers, settings.Version)...) - - if connection.Protocol == constants.UDP { - lines = append(lines, "explicit-exit-notify") - } - - if settings.ProcessUser != "root" { - lines = append(lines, "user "+settings.ProcessUser) - lines = append(lines, "persist-tun") - lines = append(lines, "persist-key") - } - - if *settings.MSSFix > 0 { - lines = append(lines, "mssfix "+strconv.Itoa(int(*settings.MSSFix))) - } - - if !*settings.IPv6 { - lines = append(lines, `pull-filter ignore "route-ipv6"`) - lines = append(lines, `pull-filter ignore "ifconfig-ipv6"`) - } - - lines = append(lines, utils.WrapOpenvpnCA( - constants.WindscribeCA)...) - lines = append(lines, utils.WrapOpenvpnTLSAuth( - constants.WindscribeTLSAuth)...) - - lines = append(lines, "") - - return lines, nil + return utils.OpenVPNConfig(providerSettings, connection, settings) } diff --git a/internal/vpn/openvpn.go b/internal/vpn/openvpn.go index f50a9c43..c7138de4 100644 --- a/internal/vpn/openvpn.go +++ b/internal/vpn/openvpn.go @@ -22,10 +22,7 @@ func setupOpenVPN(ctx context.Context, fw firewall.VPNConnectionSetter, return nil, "", fmt.Errorf("failed finding a valid server connection: %w", err) } - lines, err := providerConf.BuildConf(connection, settings.OpenVPN) - if err != nil { - return nil, "", fmt.Errorf("failed building configuration: %w", err) - } + lines := providerConf.BuildConf(connection, settings.OpenVPN) if err := openvpnConf.WriteConfig(lines); err != nil { return nil, "", fmt.Errorf("failed writing configuration to file: %w", err)