diff --git a/cmd/gluetun/main.go b/cmd/gluetun/main.go index 1092d9a1..a4a77cc3 100644 --- a/cmd/gluetun/main.go +++ b/cmd/gluetun/main.go @@ -152,7 +152,10 @@ func _main(background context.Context, buildInfo models.BuildInformation, "IPtables": firewallConf.Version, }) - allSettings, err := settings.GetAllSettings(paramsReader) + allSettings, warnings, err := settings.GetAllSettings(paramsReader) + for _, warning := range warnings { + logger.Warn(warning) + } if err != nil { return err } diff --git a/go.mod b/go.mod index 2113ef47..394b3598 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/golang/mock v1.4.4 github.com/kyokomi/emoji v2.2.4+incompatible github.com/qdm12/dns v1.4.0-rc4 - github.com/qdm12/golibs v0.0.0-20210102020307-17bc97def973 + github.com/qdm12/golibs v0.0.0-20210110211000-0a3a4541ae09 github.com/qdm12/ss-server v0.1.0 github.com/qdm12/updated v0.0.0-20210102005021-dd457d77f94a github.com/stretchr/testify v1.6.1 diff --git a/go.sum b/go.sum index 9f34a1aa..fa70aeba 100644 --- a/go.sum +++ b/go.sum @@ -97,6 +97,8 @@ github.com/qdm12/dns v1.4.0-rc4/go.mod h1:JhUKBhuDRYBUQ2XwW/jbeWx/qS0sSJjIFjGTCF github.com/qdm12/golibs v0.0.0-20201227203847-2fd99ffdfdba/go.mod h1:pikkTN7g7zRuuAnERwqW1yAFq6pYmxrxpjiwGvb0Ysc= github.com/qdm12/golibs v0.0.0-20210102020307-17bc97def973 h1:5YeJALmDjvg2wSi6XB8MpQQekbT/eBnwGahJrh01HHQ= github.com/qdm12/golibs v0.0.0-20210102020307-17bc97def973/go.mod h1:pikkTN7g7zRuuAnERwqW1yAFq6pYmxrxpjiwGvb0Ysc= +github.com/qdm12/golibs v0.0.0-20210110211000-0a3a4541ae09 h1:zP+ZRwV3GldgTWFgKNBQ2zoFA8mIczb+fvTvrX8LZRo= +github.com/qdm12/golibs v0.0.0-20210110211000-0a3a4541ae09/go.mod h1:pikkTN7g7zRuuAnERwqW1yAFq6pYmxrxpjiwGvb0Ysc= github.com/qdm12/ss-server v0.1.0 h1:WV9MkHCDEWRwe4WpnYFeR/zcZAxYoTbfntLDnw9AQ50= github.com/qdm12/ss-server v0.1.0/go.mod h1:ABVUkxubboL3vqBkOwDV9glX1/x7SnYrckBe5d+M/zw= github.com/qdm12/updated v0.0.0-20210102005021-dd457d77f94a h1:gkyP+gMEeBgMgyRYGrVNcoy6cL1065IvXsyfB6xboIc= diff --git a/internal/cli/ci.go b/internal/cli/ci.go new file mode 100644 index 00000000..efbaac57 --- /dev/null +++ b/internal/cli/ci.go @@ -0,0 +1,7 @@ +package cli + +import "context" + +func (c *cli) CI(context context.Context) error { + return nil +} diff --git a/internal/cli/openvpnconfig.go b/internal/cli/openvpnconfig.go index 07404037..069188a0 100644 --- a/internal/cli/openvpnconfig.go +++ b/internal/cli/openvpnconfig.go @@ -20,7 +20,7 @@ func (c *cli) OpenvpnConfig(os os.OS) error { return err } paramsReader := params.NewReader(logger, os) - allSettings, err := settings.GetAllSettings(paramsReader) + allSettings, _, err := settings.GetAllSettings(paramsReader) if err != nil { return err } diff --git a/internal/params/cyberghost.go b/internal/params/cyberghost.go index 80430ff0..9a2cba59 100644 --- a/internal/params/cyberghost.go +++ b/internal/params/cyberghost.go @@ -11,23 +11,23 @@ import ( // GetCyberghostGroup obtains the server group for the Cyberghost server from the // environment variable CYBERGHOST_GROUP. -func (p *reader) GetCyberghostGroup() (group string, err error) { - s, err := p.envParams.GetValueIfInside("CYBERGHOST_GROUP", +func (r *reader) GetCyberghostGroup() (group string, err error) { + s, err := r.env.Inside("CYBERGHOST_GROUP", constants.CyberghostGroupChoices(), libparams.Default("Premium UDP Europe")) return s, err } // GetCyberghostRegions obtains the country names for the Cyberghost servers from the // environment variable REGION. -func (p *reader) GetCyberghostRegions() (regions []string, err error) { - return p.envParams.GetCSVInPossibilities("REGION", constants.CyberghostRegionChoices()) +func (r *reader) GetCyberghostRegions() (regions []string, err error) { + return r.env.CSVInside("REGION", constants.CyberghostRegionChoices()) } // GetCyberghostClientKey obtains the client key to use for openvpn // from the secret file /run/secrets/openvpn_clientkey or from the file // /gluetun/client.key. -func (p *reader) GetCyberghostClientKey() (clientKey string, err error) { - b, err := p.getFromFileOrSecretFile("OPENVPN_CLIENTKEY", string(constants.ClientKey)) +func (r *reader) GetCyberghostClientKey() (clientKey string, err error) { + b, err := r.getFromFileOrSecretFile("OPENVPN_CLIENTKEY", string(constants.ClientKey)) if err != nil { return "", err } @@ -50,8 +50,8 @@ func extractClientKey(b []byte) (key string, err error) { // GetCyberghostClientCertificate obtains the client certificate to use for openvpn // from the secret file /run/secrets/openvpn_clientcrt or from the file // /gluetun/client.crt. -func (p *reader) GetCyberghostClientCertificate() (clientCertificate string, err error) { - b, err := p.getFromFileOrSecretFile("OPENVPN_CLIENTCRT", string(constants.ClientCertificate)) +func (r *reader) GetCyberghostClientCertificate() (clientCertificate string, err error) { + b, err := r.getFromFileOrSecretFile("OPENVPN_CLIENTCRT", string(constants.ClientCertificate)) if err != nil { return "", err } diff --git a/internal/params/dns.go b/internal/params/dns.go index 88de683a..5e040338 100644 --- a/internal/params/dns.go +++ b/internal/params/dns.go @@ -13,13 +13,13 @@ import ( // GetDNSOverTLS obtains if the DNS over TLS should be enabled // from the environment variable DOT. func (r *reader) GetDNSOverTLS() (DNSOverTLS bool, err error) { //nolint:gocritic - return r.envParams.GetOnOff("DOT", libparams.Default("on")) + return r.env.OnOff("DOT", libparams.Default("on")) } // GetDNSOverTLSProviders obtains the DNS over TLS providers to use // from the environment variable DOT_PROVIDERS. func (r *reader) GetDNSOverTLSProviders() (providers []string, err error) { - s, err := r.envParams.GetEnv("DOT_PROVIDERS", libparams.Default("cloudflare")) + s, err := r.env.Get("DOT_PROVIDERS", libparams.Default("cloudflare")) if err != nil { return nil, err } @@ -36,28 +36,28 @@ func (r *reader) GetDNSOverTLSProviders() (providers []string, err error) { // GetDNSOverTLSVerbosity obtains the verbosity level to use for Unbound // from the environment variable DOT_VERBOSITY. func (r *reader) GetDNSOverTLSVerbosity() (verbosityLevel uint8, err error) { - n, err := r.envParams.GetEnvIntRange("DOT_VERBOSITY", 0, 5, libparams.Default("1")) + n, err := r.env.IntRange("DOT_VERBOSITY", 0, 5, libparams.Default("1")) return uint8(n), err } // GetDNSOverTLSVerbosityDetails obtains the log level to use for Unbound // from the environment variable DOT_VERBOSITY_DETAILS. func (r *reader) GetDNSOverTLSVerbosityDetails() (verbosityDetailsLevel uint8, err error) { - n, err := r.envParams.GetEnvIntRange("DOT_VERBOSITY_DETAILS", 0, 4, libparams.Default("0")) + n, err := r.env.IntRange("DOT_VERBOSITY_DETAILS", 0, 4, libparams.Default("0")) return uint8(n), err } // GetDNSOverTLSValidationLogLevel obtains the log level to use for Unbound DOT validation // from the environment variable DOT_VALIDATION_LOGLEVEL. func (r *reader) GetDNSOverTLSValidationLogLevel() (validationLogLevel uint8, err error) { - n, err := r.envParams.GetEnvIntRange("DOT_VALIDATION_LOGLEVEL", 0, 2, libparams.Default("0")) + n, err := r.env.IntRange("DOT_VALIDATION_LOGLEVEL", 0, 2, libparams.Default("0")) return uint8(n), err } // GetDNSMaliciousBlocking obtains if malicious hostnames/IPs should be blocked // from being resolved by Unbound, using the environment variable BLOCK_MALICIOUS. func (r *reader) GetDNSMaliciousBlocking() (blocking bool, err error) { - return r.envParams.GetOnOff("BLOCK_MALICIOUS", libparams.Default("on")) + return r.env.OnOff("BLOCK_MALICIOUS", libparams.Default("on")) } // GetDNSSurveillanceBlocking obtains if surveillance hostnames/IPs should be blocked @@ -65,26 +65,26 @@ func (r *reader) GetDNSMaliciousBlocking() (blocking bool, err error) { // and BLOCK_NSA for retrocompatibility. func (r *reader) GetDNSSurveillanceBlocking() (blocking bool, err error) { // Retro-compatibility - s, err := r.envParams.GetEnv("BLOCK_NSA") + s, err := r.env.Get("BLOCK_NSA") if err != nil { return false, err } else if len(s) != 0 { r.logger.Warn("You are using the old environment variable BLOCK_NSA, please consider changing it to BLOCK_SURVEILLANCE") //nolint:lll - return r.envParams.GetOnOff("BLOCK_NSA", libparams.Compulsory()) + return r.env.OnOff("BLOCK_NSA", libparams.Compulsory()) } - return r.envParams.GetOnOff("BLOCK_SURVEILLANCE", libparams.Default("off")) + return r.env.OnOff("BLOCK_SURVEILLANCE", libparams.Default("off")) } // GetDNSAdsBlocking obtains if ads hostnames/IPs should be blocked // from being resolved by Unbound, using the environment variable BLOCK_ADS. func (r *reader) GetDNSAdsBlocking() (blocking bool, err error) { - return r.envParams.GetOnOff("BLOCK_ADS", libparams.Default("off")) + return r.env.OnOff("BLOCK_ADS", libparams.Default("off")) } // GetDNSUnblockedHostnames obtains a list of hostnames to unblock from block lists // from the comma separated list for the environment variable UNBLOCK. func (r *reader) GetDNSUnblockedHostnames() (hostnames []string, err error) { - s, err := r.envParams.GetEnv("UNBLOCK") + s, err := r.env.Get("UNBLOCK") if err != nil { return nil, err } else if len(s) == 0 { @@ -92,7 +92,7 @@ func (r *reader) GetDNSUnblockedHostnames() (hostnames []string, err error) { } hostnames = strings.Split(s, ",") for _, hostname := range hostnames { - if !r.verifier.MatchHostname(hostname) { + if !r.regex.MatchHostname(hostname) { return nil, fmt.Errorf("hostname %q does not seem valid", hostname) } } @@ -102,13 +102,13 @@ func (r *reader) GetDNSUnblockedHostnames() (hostnames []string, err error) { // GetDNSOverTLSCaching obtains if Unbound caching should be enable or not // from the environment variable DOT_CACHING. func (r *reader) GetDNSOverTLSCaching() (caching bool, err error) { - return r.envParams.GetOnOff("DOT_CACHING", libparams.Default("on")) + return r.env.OnOff("DOT_CACHING", libparams.Default("on")) } // GetDNSOverTLSPrivateAddresses obtains if Unbound caching should be enable or not // from the environment variable DOT_PRIVATE_ADDRESS. func (r *reader) GetDNSOverTLSPrivateAddresses() (privateAddresses []string, err error) { - s, err := r.envParams.GetEnv("DOT_PRIVATE_ADDRESS") + s, err := r.env.Get("DOT_PRIVATE_ADDRESS") if err != nil { return nil, err } else if len(s) == 0 { @@ -128,13 +128,13 @@ func (r *reader) GetDNSOverTLSPrivateAddresses() (privateAddresses []string, err // GetDNSOverTLSIPv6 obtains if Unbound should resolve ipv6 addresses using // ipv6 DNS over TLS from the environment variable DOT_IPV6. func (r *reader) GetDNSOverTLSIPv6() (ipv6 bool, err error) { - return r.envParams.GetOnOff("DOT_IPV6", libparams.Default("off")) + return r.env.OnOff("DOT_IPV6", libparams.Default("off")) } // GetDNSUpdatePeriod obtains the period to use to update the block lists and cryptographic files // and restart Unbound from the environment variable DNS_UPDATE_PERIOD. func (r *reader) GetDNSUpdatePeriod() (period time.Duration, err error) { - s, err := r.envParams.GetEnv("DNS_UPDATE_PERIOD", libparams.Default("24h")) + s, err := r.env.Get("DNS_UPDATE_PERIOD", libparams.Default("24h")) if err != nil { return period, err } @@ -144,7 +144,7 @@ func (r *reader) GetDNSUpdatePeriod() (period time.Duration, err error) { // GetDNSPlaintext obtains the plaintext DNS address to use if DNS over TLS is disabled // from the environment variable DNS_PLAINTEXT_ADDRESS. func (r *reader) GetDNSPlaintext() (ip net.IP, err error) { - s, err := r.envParams.GetEnv("DNS_PLAINTEXT_ADDRESS", libparams.Default("1.1.1.1")) + s, err := r.env.Get("DNS_PLAINTEXT_ADDRESS", libparams.Default("1.1.1.1")) if err != nil { return nil, err } @@ -158,5 +158,5 @@ func (r *reader) GetDNSPlaintext() (ip net.IP, err error) { // GetDNSKeepNameserver obtains if the nameserver present in /etc/resolv.conf // should be kept instead of overridden, from the environment variable DNS_KEEP_NAMESERVER. func (r *reader) GetDNSKeepNameserver() (on bool, err error) { - return r.envParams.GetOnOff("DNS_KEEP_NAMESERVER", libparams.Default("off")) + return r.env.OnOff("DNS_KEEP_NAMESERVER", libparams.Default("off")) } diff --git a/internal/params/firewall.go b/internal/params/firewall.go index cf6e51e2..ecf23e8e 100644 --- a/internal/params/firewall.go +++ b/internal/params/firewall.go @@ -10,13 +10,13 @@ import ( // GetFirewall obtains if the firewall should be enabled from the environment variable FIREWALL. func (r *reader) GetFirewall() (enabled bool, err error) { - return r.envParams.GetOnOff("FIREWALL", libparams.Default("on")) + return r.env.OnOff("FIREWALL", libparams.Default("on")) } // GetAllowedVPNInputPorts obtains a list of input ports to allow from the // VPN server side in the firewall, from the environment variable FIREWALL_VPN_INPUT_PORTS. func (r *reader) GetVPNInputPorts() (ports []uint16, err error) { - s, err := r.envParams.GetEnv("FIREWALL_VPN_INPUT_PORTS", libparams.Default("")) + s, err := r.env.Get("FIREWALL_VPN_INPUT_PORTS", libparams.Default("")) if err != nil { return nil, err } @@ -40,7 +40,7 @@ func (r *reader) GetVPNInputPorts() (ports []uint16, err error) { // GetInputPorts obtains a list of input ports to allow through the // default interface in the firewall, from the environment variable FIREWALL_INPUT_PORTS. func (r *reader) GetInputPorts() (ports []uint16, err error) { - s, err := r.envParams.GetEnv("FIREWALL_INPUT_PORTS", libparams.Default("")) + s, err := r.env.Get("FIREWALL_INPUT_PORTS", libparams.Default("")) if err != nil { return nil, err } @@ -64,5 +64,5 @@ func (r *reader) GetInputPorts() (ports []uint16, err error) { // GetFirewallDebug obtains if the firewall should run in debug verbose mode // from the environment variable FIREWALL_DEBUG. func (r *reader) GetFirewallDebug() (debug bool, err error) { - return r.envParams.GetOnOff("FIREWALL_DEBUG", libparams.Default("off")) + return r.env.OnOff("FIREWALL_DEBUG", libparams.Default("off")) } diff --git a/internal/params/httpproxy.go b/internal/params/httpproxy.go index c1c7823f..8b2edb97 100644 --- a/internal/params/httpproxy.go +++ b/internal/params/httpproxy.go @@ -13,18 +13,18 @@ func (r *reader) GetHTTPProxy() (enabled bool, err error) { []string{"TINYPROXY", "PROXY"}, r.onRetroActive, ) - return r.envParams.GetOnOff("HTTPPROXY", retroKeysOption, libparams.Default("off")) + return r.env.OnOff("HTTPPROXY", retroKeysOption, libparams.Default("off")) } // GetHTTPProxyLog obtains the if http proxy requests should be logged from // the environment variable HTTPPROXY_LOG, and using PROXY_LOG_LEVEL and // TINYPROXY_LOG as retro-compatibility names. func (r *reader) GetHTTPProxyLog() (log bool, err error) { - s, _ := r.envParams.GetEnv("HTTPPROXY_LOG") + s, _ := r.env.Get("HTTPPROXY_LOG") if len(s) == 0 { - s, _ = r.envParams.GetEnv("PROXY_LOG_LEVEL") + s, _ = r.env.Get("PROXY_LOG_LEVEL") if len(s) == 0 { - s, _ = r.envParams.GetEnv("TINYPROXY_LOG") + s, _ = r.env.Get("TINYPROXY_LOG") if len(s) == 0 { return false, nil // default log disabled } @@ -36,17 +36,17 @@ func (r *reader) GetHTTPProxyLog() (log bool, err error) { return false, nil } } - return r.envParams.GetOnOff("HTTPPROXY_LOG", libparams.Default("off")) + return r.env.OnOff("HTTPPROXY_LOG", libparams.Default("off")) } // GetHTTPProxyPort obtains the HTTP proxy listening port from the environment variable // HTTPPROXY_PORT, and using PROXY_PORT and TINYPROXY_PORT as retro-compatibility names. -func (r *reader) GetHTTPProxyPort() (port uint16, err error) { +func (r *reader) GetHTTPProxyPort() (port uint16, warning string, err error) { retroKeysOption := libparams.RetroKeys( []string{"TINYPROXY_PORT", "PROXY_PORT"}, r.onRetroActive, ) - return r.envParams.GetPort("HTTPPROXY_PORT", retroKeysOption, libparams.Default("8888")) + return r.env.ListeningPort("HTTPPROXY_PORT", retroKeysOption, libparams.Default("8888")) } // GetHTTPProxyUser obtains the HTTP proxy server user. @@ -76,5 +76,5 @@ func (r *reader) GetHTTPProxyPassword() (password string, err error) { // GetHTTPProxyStealth obtains the HTTP proxy server stealth mode // from the environment variable HTTPPROXY_STEALTH. func (r *reader) GetHTTPProxyStealth() (stealth bool, err error) { - return r.envParams.GetOnOff("HTTPPROXY_STEALTH", libparams.Default("off")) + return r.env.OnOff("HTTPPROXY_STEALTH", libparams.Default("off")) } diff --git a/internal/params/mullvad.go b/internal/params/mullvad.go index c63d4c62..66228e67 100644 --- a/internal/params/mullvad.go +++ b/internal/params/mullvad.go @@ -8,30 +8,30 @@ import ( // GetMullvadCountries obtains the countries for the Mullvad servers from the // environment variable COUNTRY. func (r *reader) GetMullvadCountries() (countries []string, err error) { - return r.envParams.GetCSVInPossibilities("COUNTRY", constants.MullvadCountryChoices()) + return r.env.CSVInside("COUNTRY", constants.MullvadCountryChoices()) } // GetMullvadCity obtains the cities for the Mullvad servers from the // environment variable CITY. func (r *reader) GetMullvadCities() (cities []string, err error) { - return r.envParams.GetCSVInPossibilities("CITY", constants.MullvadCityChoices()) + return r.env.CSVInside("CITY", constants.MullvadCityChoices()) } // GetMullvadISPs obtains the ISPs for the Mullvad servers from the // environment variable ISP. func (r *reader) GetMullvadISPs() (isps []string, err error) { - return r.envParams.GetCSVInPossibilities("ISP", constants.MullvadISPChoices()) + return r.env.CSVInside("ISP", constants.MullvadISPChoices()) } // GetMullvadPort obtains the port to reach the Mullvad server on from the // environment variable PORT. func (r *reader) GetMullvadPort() (port uint16, err error) { - n, err := r.envParams.GetEnvIntRange("PORT", 0, 65535, libparams.Default("0")) + n, err := r.env.IntRange("PORT", 0, 65535, libparams.Default("0")) return uint16(n), err } // GetMullvadOwned obtains if the server should be owned by Mullvad or not from the // environment variable OWNED. func (r *reader) GetMullvadOwned() (owned bool, err error) { - return r.envParams.GetYesNo("OWNED", libparams.Default("no")) + return r.env.YesNo("OWNED", libparams.Default("no")) } diff --git a/internal/params/nordvpn.go b/internal/params/nordvpn.go index 1f17f9ff..3007a161 100644 --- a/internal/params/nordvpn.go +++ b/internal/params/nordvpn.go @@ -10,7 +10,7 @@ import ( // GetNordvpnRegions obtains the regions (countries) for the NordVPN server from the // environment variable REGION. func (r *reader) GetNordvpnRegions() (regions []string, err error) { - return r.envParams.GetCSVInPossibilities("REGION", constants.NordvpnRegionChoices()) + return r.env.CSVInside("REGION", constants.NordvpnRegionChoices()) } // GetNordvpnRegion obtains the server numbers (optional) for the NordVPN servers from the @@ -21,7 +21,7 @@ func (r *reader) GetNordvpnNumbers() (numbers []uint16, err error) { possibilities[i] = fmt.Sprintf("%d", i) } possibilities[65536] = "" - values, err := r.envParams.GetCSVInPossibilities("SERVER_NUMBER", possibilities) + values, err := r.env.CSVInside("SERVER_NUMBER", possibilities) if err != nil { return nil, err } diff --git a/internal/params/openvpn.go b/internal/params/openvpn.go index 2718ec3d..4e2631e0 100644 --- a/internal/params/openvpn.go +++ b/internal/params/openvpn.go @@ -27,26 +27,26 @@ func (r *reader) GetPassword() (s string, err error) { // GetNetworkProtocol obtains the network protocol to use to connect to the // VPN servers from the environment variable PROTOCOL. func (r *reader) GetNetworkProtocol() (protocol models.NetworkProtocol, err error) { - s, err := r.envParams.GetValueIfInside("PROTOCOL", []string{"tcp", "udp"}, libparams.Default("udp")) + s, err := r.env.Inside("PROTOCOL", []string{"tcp", "udp"}, libparams.Default("udp")) return models.NetworkProtocol(s), err } // GetOpenVPNVerbosity obtains the verbosity level for verbosity between 0 and 6 // from the environment variable OPENVPN_VERBOSITY. func (r *reader) GetOpenVPNVerbosity() (verbosity int, err error) { - return r.envParams.GetEnvIntRange("OPENVPN_VERBOSITY", 0, 6, libparams.Default("1")) + return r.env.IntRange("OPENVPN_VERBOSITY", 0, 6, libparams.Default("1")) } // GetOpenVPNRoot obtains if openvpn should be run as root // from the environment variable OPENVPN_ROOT. func (r *reader) GetOpenVPNRoot() (root bool, err error) { - return r.envParams.GetYesNo("OPENVPN_ROOT", libparams.Default("no")) + return r.env.YesNo("OPENVPN_ROOT", libparams.Default("no")) } // GetTargetIP obtains the IP address to override over the list of IP addresses filtered // from the environment variable OPENVPN_TARGET_IP. func (r *reader) GetTargetIP() (ip net.IP, err error) { - s, err := r.envParams.GetEnv("OPENVPN_TARGET_IP") + s, err := r.env.Get("OPENVPN_TARGET_IP") if len(s) == 0 { return nil, nil } else if err != nil { @@ -62,17 +62,17 @@ func (r *reader) GetTargetIP() (ip net.IP, err error) { // GetOpenVPNCipher obtains a custom cipher to use with OpenVPN // from the environment variable OPENVPN_CIPHER. func (r *reader) GetOpenVPNCipher() (cipher string, err error) { - return r.envParams.GetEnv("OPENVPN_CIPHER") + return r.env.Get("OPENVPN_CIPHER") } // GetOpenVPNAuth obtains a custom auth algorithm to use with OpenVPN // from the environment variable OPENVPN_AUTH. func (r *reader) GetOpenVPNAuth() (auth string, err error) { - return r.envParams.GetEnv("OPENVPN_AUTH") + return r.env.Get("OPENVPN_AUTH") } // GetOpenVPNIPv6 obtains if ipv6 should be tunneled through the // openvpn tunnel from the environment variable OPENVPN_IPV6. func (r *reader) GetOpenVPNIPv6() (ipv6 bool, err error) { - return r.envParams.GetOnOff("OPENVPN_IPV6", libparams.Default("off")) + return r.env.OnOff("OPENVPN_IPV6", libparams.Default("off")) } diff --git a/internal/params/params.go b/internal/params/params.go index ce6b504c..6c77c077 100644 --- a/internal/params/params.go +++ b/internal/params/params.go @@ -102,14 +102,14 @@ type Reader interface { // Shadowsocks getters GetShadowSocks() (activated bool, err error) GetShadowSocksLog() (activated bool, err error) - GetShadowSocksPort() (port uint16, err error) + GetShadowSocksPort() (port uint16, warning string, err error) GetShadowSocksPassword() (password string, err error) GetShadowSocksMethod() (method string, err error) // HTTP proxy getters GetHTTPProxy() (activated bool, err error) GetHTTPProxyLog() (log bool, err error) - GetHTTPProxyPort() (port uint16, err error) + GetHTTPProxyPort() (port uint16, warning string, err error) GetHTTPProxyUser() (user string, err error) GetHTTPProxyPassword() (password string, err error) GetHTTPProxyStealth() (stealth bool, err error) @@ -118,7 +118,7 @@ type Reader interface { GetPublicIPPeriod() (period time.Duration, err error) // Control server - GetControlServerPort() (port uint16, err error) + GetControlServerPort() (port uint16, warning string, err error) GetControlServerLog() (enabled bool, err error) GetVersionInformation() (enabled bool, err error) @@ -127,26 +127,26 @@ type Reader interface { } type reader struct { - envParams libparams.EnvParams - logger logging.Logger - verifier verification.Verifier - os os.OS + env libparams.Env + logger logging.Logger + regex verification.Regex + os os.OS } // Newreader returns a paramsReadeer object to read parameters from // environment variables. func NewReader(logger logging.Logger, os os.OS) Reader { return &reader{ - envParams: libparams.NewEnvParams(), - logger: logger, - verifier: verification.NewVerifier(), - os: os, + env: libparams.NewEnv(), + logger: logger, + regex: verification.NewRegex(), + os: os, } } // GetVPNSP obtains the VPN service provider to use from the environment variable VPNSP. func (r *reader) GetVPNSP() (vpnServiceProvider models.VPNProvider, err error) { - s, err := r.envParams.GetValueIfInside( + s, err := r.env.Inside( "VPNSP", []string{ "pia", "private internet access", @@ -160,7 +160,7 @@ func (r *reader) GetVPNSP() (vpnServiceProvider models.VPNProvider, err error) { } func (r *reader) GetVersionInformation() (enabled bool, err error) { - return r.envParams.GetOnOff("VERSION_INFORMATION", libparams.Default("on")) + return r.env.OnOff("VERSION_INFORMATION", libparams.Default("on")) } func (r *reader) onRetroActive(oldKey, newKey string) { diff --git a/internal/params/pia.go b/internal/params/pia.go index 8d274d39..330e1012 100644 --- a/internal/params/pia.go +++ b/internal/params/pia.go @@ -12,7 +12,7 @@ import ( // side is enabled or not from the environment variable PORT_FORWARDING // Only valid for older PIA servers for now. func (r *reader) GetPortForwarding() (activated bool, err error) { - s, err := r.envParams.GetEnv("PORT_FORWARDING", libparams.Default("off")) + s, err := r.env.Get("PORT_FORWARDING", libparams.Default("off")) if err != nil { return false, err } @@ -28,7 +28,7 @@ func (r *reader) GetPortForwarding() (activated bool, err error) { // GetPortForwardingStatusFilepath obtains the port forwarding status file path // from the environment variable PORT_FORWARDING_STATUS_FILE. func (r *reader) GetPortForwardingStatusFilepath() (filepath models.Filepath, err error) { - filepathStr, err := r.envParams.GetPath( + filepathStr, err := r.env.Path( "PORT_FORWARDING_STATUS_FILE", libparams.Default("/tmp/gluetun/forwarded_port"), libparams.CaseSensitiveValue()) @@ -40,7 +40,7 @@ func (r *reader) GetPortForwardingStatusFilepath() (filepath models.Filepath, er // retro compatibility. func (r *reader) GetPIAEncryptionPreset() (preset string, err error) { // Retro-compatibility - s, err := r.envParams.GetValueIfInside("ENCRYPTION", []string{ + s, err := r.env.Inside("ENCRYPTION", []string{ constants.PIAEncryptionPresetNormal, constants.PIAEncryptionPresetStrong}) if err != nil { @@ -49,7 +49,7 @@ func (r *reader) GetPIAEncryptionPreset() (preset string, err error) { r.logger.Warn("You are using the old environment variable ENCRYPTION, please consider changing it to PIA_ENCRYPTION") return s, nil } - return r.envParams.GetValueIfInside( + return r.env.Inside( "PIA_ENCRYPTION", []string{ constants.PIAEncryptionPresetNormal, @@ -61,5 +61,5 @@ func (r *reader) GetPIAEncryptionPreset() (preset string, err error) { // GetPIARegions obtains the regions for the PIA servers from the // environment variable REGION. func (r *reader) GetPIARegions() (regions []string, err error) { - return r.envParams.GetCSVInPossibilities("REGION", constants.PIAGeoChoices()) + return r.env.CSVInside("REGION", constants.PIAGeoChoices()) } diff --git a/internal/params/privado.go b/internal/params/privado.go index b54e36da..b84c1a53 100644 --- a/internal/params/privado.go +++ b/internal/params/privado.go @@ -8,7 +8,7 @@ import ( // GetPrivadoHostnames obtains the hostnames for the Privado server from the // environment variable SERVER_HOSTNAME. func (r *reader) GetPrivadoHostnames() (hosts []string, err error) { - return r.envParams.GetCSVInPossibilities("SERVER_HOSTNAME", + return r.env.CSVInside("SERVER_HOSTNAME", constants.PrivadoHostnameChoices(), libparams.RetroKeys([]string{"HOSTNAME"}, r.onRetroActive)) } diff --git a/internal/params/publicip.go b/internal/params/publicip.go index 369008ab..19c3d1f5 100644 --- a/internal/params/publicip.go +++ b/internal/params/publicip.go @@ -10,7 +10,7 @@ import ( // GetPublicIPPeriod obtains the period to fetch the IP address periodically. // Set to 0 to disable. func (r *reader) GetPublicIPPeriod() (period time.Duration, err error) { - s, err := r.envParams.GetEnv("PUBLICIP_PERIOD", libparams.Default("12h")) + s, err := r.env.Get("PUBLICIP_PERIOD", libparams.Default("12h")) if err != nil { return 0, err } @@ -21,7 +21,7 @@ func (r *reader) GetPublicIPPeriod() (period time.Duration, err error) { // from the environment variable PUBLICIP_FILE with retro-compatible // environment variable IP_STATUS_FILE. func (r *reader) GetPublicIPFilepath() (filepath models.Filepath, err error) { - filepathStr, err := r.envParams.GetPath("PUBLICIP_FILE", + filepathStr, err := r.env.Path("PUBLICIP_FILE", libparams.RetroKeys([]string{"IP_STATUS_FILE"}, r.onRetroActive), libparams.Default("/tmp/gluetun/ip"), libparams.CaseSensitiveValue()) return models.Filepath(filepathStr), err diff --git a/internal/params/purevpn.go b/internal/params/purevpn.go index c8fa00e8..a2b93164 100644 --- a/internal/params/purevpn.go +++ b/internal/params/purevpn.go @@ -7,17 +7,17 @@ import ( // GetPurevpnRegions obtains the regions (continents) for the PureVPN servers from the // environment variable REGION. func (r *reader) GetPurevpnRegions() (regions []string, err error) { - return r.envParams.GetCSVInPossibilities("REGION", constants.PurevpnRegionChoices()) + return r.env.CSVInside("REGION", constants.PurevpnRegionChoices()) } // GetPurevpnCountries obtains the countries for the PureVPN servers from the // environment variable COUNTRY. func (r *reader) GetPurevpnCountries() (countries []string, err error) { - return r.envParams.GetCSVInPossibilities("COUNTRY", constants.PurevpnCountryChoices()) + return r.env.CSVInside("COUNTRY", constants.PurevpnCountryChoices()) } // GetPurevpnCities obtains the cities for the PureVPN servers from the // environment variable CITY. func (r *reader) GetPurevpnCities() (cities []string, err error) { - return r.envParams.GetCSVInPossibilities("CITY", constants.PurevpnCityChoices()) + return r.env.CSVInside("CITY", constants.PurevpnCityChoices()) } diff --git a/internal/params/routing.go b/internal/params/routing.go index d383cc35..33809491 100644 --- a/internal/params/routing.go +++ b/internal/params/routing.go @@ -16,7 +16,7 @@ func (r *reader) GetOutboundSubnets() (outboundSubnets []net.IPNet, err error) { []string{"EXTRA_SUBNETS"}, r.onRetroActive, ) - s, err := r.envParams.GetEnv(key, retroOption) + s, err := r.env.Get(key, retroOption) if err != nil { return nil, err } else if s == "" { diff --git a/internal/params/secrets.go b/internal/params/secrets.go index a91ec985..86031326 100644 --- a/internal/params/secrets.go +++ b/internal/params/secrets.go @@ -19,19 +19,19 @@ var ( ) func (r *reader) getFromEnvOrSecretFile(envKey string, compulsory bool, retroKeys []string) (value string, err error) { - envOptions := []libparams.GetEnvSetter{ + envOptions := []libparams.OptionSetter{ libparams.Compulsory(), // to fallback on file reading libparams.CaseSensitiveValue(), libparams.Unset(), libparams.RetroKeys(retroKeys, r.onRetroActive), } - value, envErr := r.envParams.GetEnv(envKey, envOptions...) + value, envErr := r.env.Get(envKey, envOptions...) if envErr == nil { return value, nil } defaultSecretFile := "/run/secrets/" + strings.ToLower(envKey) - filepath, err := r.envParams.GetEnv(envKey+"_SECRETFILE", + filepath, err := r.env.Get(envKey+"_SECRETFILE", libparams.CaseSensitiveValue(), libparams.Default(defaultSecretFile), ) @@ -67,7 +67,7 @@ func (r *reader) getFromEnvOrSecretFile(envKey string, compulsory bool, retroKey func (r *reader) getFromFileOrSecretFile(secretName, filepath string) ( b []byte, err error) { defaultSecretFile := "/run/secrets/" + strings.ToLower(secretName) - secretFilepath, err := r.envParams.GetEnv(strings.ToUpper(secretName)+"_SECRETFILE", + secretFilepath, err := r.env.Get(strings.ToUpper(secretName)+"_SECRETFILE", libparams.CaseSensitiveValue(), libparams.Default(defaultSecretFile), ) diff --git a/internal/params/server.go b/internal/params/server.go index 9df90676..cde5d4ad 100644 --- a/internal/params/server.go +++ b/internal/params/server.go @@ -4,14 +4,10 @@ import ( libparams "github.com/qdm12/golibs/params" ) -func (r *reader) GetControlServerPort() (port uint16, err error) { - n, err := r.envParams.GetEnvIntRange("HTTP_CONTROL_SERVER_PORT", 1, 65535, libparams.Default("8000")) - if err != nil { - return 0, err - } - return uint16(n), nil +func (r *reader) GetControlServerPort() (port uint16, warning string, err error) { + return r.env.ListeningPort("HTTP_CONTROL_SERVER_PORT", libparams.Default("8000")) } func (r *reader) GetControlServerLog() (enabled bool, err error) { - return r.envParams.GetOnOff("HTTP_CONTROL_SERVER_LOG", libparams.Default("on")) + return r.env.OnOff("HTTP_CONTROL_SERVER_LOG", libparams.Default("on")) } diff --git a/internal/params/shadowsocks.go b/internal/params/shadowsocks.go index 9590653c..8e71cb49 100644 --- a/internal/params/shadowsocks.go +++ b/internal/params/shadowsocks.go @@ -1,35 +1,25 @@ package params import ( - "strconv" - libparams "github.com/qdm12/golibs/params" ) // GetShadowSocks obtains if ShadowSocks is on from the environment variable // SHADOWSOCKS. func (r *reader) GetShadowSocks() (activated bool, err error) { - return r.envParams.GetOnOff("SHADOWSOCKS", libparams.Default("off")) + return r.env.OnOff("SHADOWSOCKS", libparams.Default("off")) } // GetShadowSocksLog obtains the ShadowSocks log level from the environment variable // SHADOWSOCKS_LOG. func (r *reader) GetShadowSocksLog() (activated bool, err error) { - return r.envParams.GetOnOff("SHADOWSOCKS_LOG", libparams.Default("off")) + return r.env.OnOff("SHADOWSOCKS_LOG", libparams.Default("off")) } // GetShadowSocksPort obtains the ShadowSocks listening port from the environment variable // SHADOWSOCKS_PORT. -func (r *reader) GetShadowSocksPort() (port uint16, err error) { - portStr, err := r.envParams.GetEnv("SHADOWSOCKS_PORT", libparams.Default("8388")) - if err != nil { - return 0, err - } - if err := r.verifier.VerifyPort(portStr); err != nil { - return 0, err - } - portUint64, err := strconv.ParseUint(portStr, 10, 16) - return uint16(portUint64), err +func (r *reader) GetShadowSocksPort() (port uint16, warning string, err error) { + return r.env.ListeningPort("SHADOWSOCKS_PORT", libparams.Default("8388")) } // GetShadowSocksPassword obtains the ShadowSocks server password. @@ -43,5 +33,5 @@ func (r *reader) GetShadowSocksPassword() (password string, err error) { // GetShadowSocksMethod obtains the ShadowSocks method to use from the environment variable // SHADOWSOCKS_METHOD. func (r *reader) GetShadowSocksMethod() (method string, err error) { - return r.envParams.GetEnv("SHADOWSOCKS_METHOD", libparams.Default("chacha20-ietf-poly1305")) + return r.env.Get("SHADOWSOCKS_METHOD", libparams.Default("chacha20-ietf-poly1305")) } diff --git a/internal/params/surfshark.go b/internal/params/surfshark.go index 86867c94..ce2f6004 100644 --- a/internal/params/surfshark.go +++ b/internal/params/surfshark.go @@ -7,5 +7,5 @@ import ( // GetSurfsharkRegions obtains the regions for the Surfshark servers from the // environment variable REGION. func (r *reader) GetSurfsharkRegions() (regions []string, err error) { - return r.envParams.GetCSVInPossibilities("REGION", constants.SurfsharkRegionChoices()) + return r.env.CSVInside("REGION", constants.SurfsharkRegionChoices()) } diff --git a/internal/params/system.go b/internal/params/system.go index 9b98974d..91dcfdbc 100644 --- a/internal/params/system.go +++ b/internal/params/system.go @@ -7,7 +7,7 @@ import ( // GetPUID obtains the user ID to use from the environment variable PUID // with retro compatible variable UID. func (r *reader) GetPUID() (ppuid int, err error) { - return r.envParams.GetEnvIntRange("PUID", 0, 65535, + return r.env.IntRange("PUID", 0, 65535, libparams.Default("1000"), libparams.RetroKeys([]string{"UID"}, r.onRetroActive)) } @@ -15,12 +15,12 @@ func (r *reader) GetPUID() (ppuid int, err error) { // GetGID obtains the group ID to use from the environment variable PGID // with retro compatible variable PGID. func (r *reader) GetPGID() (pgid int, err error) { - return r.envParams.GetEnvIntRange("PGID", 0, 65535, + return r.env.IntRange("PGID", 0, 65535, libparams.Default("1000"), libparams.RetroKeys([]string{"GID"}, r.onRetroActive)) } // GetTZ obtains the timezone from the environment variable TZ. func (r *reader) GetTimezone() (timezone string, err error) { - return r.envParams.GetEnv("TZ") + return r.env.Get("TZ") } diff --git a/internal/params/updater.go b/internal/params/updater.go index 8d83a002..8884b259 100644 --- a/internal/params/updater.go +++ b/internal/params/updater.go @@ -9,7 +9,7 @@ import ( // GetUpdaterPeriod obtains the period to fetch the servers information when the tunnel is up. // Set to 0 to disable. func (r *reader) GetUpdaterPeriod() (period time.Duration, err error) { - s, err := r.envParams.GetEnv("UPDATER_PERIOD", libparams.Default("0")) + s, err := r.env.Get("UPDATER_PERIOD", libparams.Default("0")) if err != nil { return 0, err } diff --git a/internal/params/vypervpn.go b/internal/params/vypervpn.go index a9d94d9d..ed162645 100644 --- a/internal/params/vypervpn.go +++ b/internal/params/vypervpn.go @@ -7,5 +7,5 @@ import ( // GetVyprvpnRegions obtains the regions for the Vyprvpn servers from the // environment variable REGION. func (r *reader) GetVyprvpnRegions() (regions []string, err error) { - return r.envParams.GetCSVInPossibilities("REGION", constants.VyprvpnRegionChoices()) + return r.env.CSVInside("REGION", constants.VyprvpnRegionChoices()) } diff --git a/internal/params/windscribe.go b/internal/params/windscribe.go index 7b1ba3d3..726a0b6a 100644 --- a/internal/params/windscribe.go +++ b/internal/params/windscribe.go @@ -11,19 +11,19 @@ import ( // GetWindscribeRegions obtains the regions for the Windscribe servers from the // environment variable REGION. func (r *reader) GetWindscribeRegions() (regions []string, err error) { - return r.envParams.GetCSVInPossibilities("REGION", constants.WindscribeRegionChoices()) + return r.env.CSVInside("REGION", constants.WindscribeRegionChoices()) } // GetWindscribeCities obtains the cities for the Windscribe servers from the // environment variable CITY. func (r *reader) GetWindscribeCities() (cities []string, err error) { - return r.envParams.GetCSVInPossibilities("CITY", constants.WindscribeCityChoices()) + return r.env.CSVInside("CITY", constants.WindscribeCityChoices()) } // GetWindscribeHostnames obtains the hostnames for the Windscribe servers from the // environment variable SERVER_HOSTNAME. func (r *reader) GetWindscribeHostnames() (hostnames []string, err error) { - return r.envParams.GetCSVInPossibilities("SERVER_HOSTNAME", + return r.env.CSVInside("SERVER_HOSTNAME", constants.WindscribeHostnameChoices(), libparams.RetroKeys([]string{"HOSTNAME"}, r.onRetroActive), ) @@ -33,7 +33,7 @@ func (r *reader) GetWindscribeHostnames() (hostnames []string, err error) { // environment variable PORT. //nolint:gomnd func (r *reader) GetWindscribePort(protocol models.NetworkProtocol) (port uint16, err error) { - n, err := r.envParams.GetEnvIntRange("PORT", 0, 65535, libparams.Default("0")) + n, err := r.env.IntRange("PORT", 0, 65535, libparams.Default("0")) if err != nil { return 0, err } diff --git a/internal/settings/httpproxy.go b/internal/settings/httpproxy.go index 306b266a..f2bbc754 100644 --- a/internal/settings/httpproxy.go +++ b/internal/settings/httpproxy.go @@ -42,30 +42,30 @@ func (h *HTTPProxy) String() string { } // GetHTTPProxySettings obtains HTTPProxy settings from environment variables using the params package. -func GetHTTPProxySettings(paramsReader params.Reader) (settings HTTPProxy, err error) { +func GetHTTPProxySettings(paramsReader params.Reader) (settings HTTPProxy, warning string, err error) { settings.Enabled, err = paramsReader.GetHTTPProxy() if err != nil || !settings.Enabled { - return settings, err - } - settings.Port, err = paramsReader.GetHTTPProxyPort() - if err != nil { - return settings, err + return settings, "", err } settings.User, err = paramsReader.GetHTTPProxyUser() if err != nil { - return settings, err + return settings, "", err } settings.Password, err = paramsReader.GetHTTPProxyPassword() if err != nil { - return settings, err + return settings, "", err } settings.Stealth, err = paramsReader.GetHTTPProxyStealth() if err != nil { - return settings, err + return settings, "", err } settings.Log, err = paramsReader.GetHTTPProxyLog() if err != nil { - return settings, err + return settings, "", err } - return settings, nil + settings.Port, warning, err = paramsReader.GetHTTPProxyPort() + if err != nil { + return settings, warning, err + } + return settings, warning, nil } diff --git a/internal/settings/server.go b/internal/settings/server.go index 75f8cb76..757efb34 100644 --- a/internal/settings/server.go +++ b/internal/settings/server.go @@ -24,14 +24,14 @@ func (c *ControlServer) String() string { // GetControlServerSettings obtains the HTTP control server settings from // environment variables using the params package. -func GetControlServerSettings(paramsReader params.Reader) (settings ControlServer, err error) { - settings.Port, err = paramsReader.GetControlServerPort() - if err != nil { - return settings, err - } +func GetControlServerSettings(paramsReader params.Reader) (settings ControlServer, warning string, err error) { settings.Log, err = paramsReader.GetControlServerLog() if err != nil { - return settings, err + return settings, "", err } - return settings, nil + settings.Port, warning, err = paramsReader.GetControlServerPort() + if err != nil { + return settings, warning, err + } + return settings, warning, nil } diff --git a/internal/settings/settings.go b/internal/settings/settings.go index a299f9d0..127540c7 100644 --- a/internal/settings/settings.go +++ b/internal/settings/settings.go @@ -50,50 +50,64 @@ func (s *Settings) String() string { // GetAllSettings obtains all settings for the program and returns an error as soon // as an error is encountered reading them. -func GetAllSettings(paramsReader params.Reader) (settings Settings, err error) { +func GetAllSettings(paramsReader params.Reader) (settings Settings, warnings []string, err error) { settings.VPNSP, err = paramsReader.GetVPNSP() if err != nil { - return settings, err + return settings, nil, err } settings.OpenVPN, err = GetOpenVPNSettings(paramsReader, settings.VPNSP) if err != nil { - return settings, err + return settings, nil, err } settings.DNS, err = GetDNSSettings(paramsReader) if err != nil { - return settings, err + return settings, nil, err } settings.Firewall, err = GetFirewallSettings(paramsReader) if err != nil { - return settings, err - } - settings.HTTPProxy, err = GetHTTPProxySettings(paramsReader) - if err != nil { - return settings, err - } - settings.ShadowSocks, err = GetShadowSocksSettings(paramsReader) - if err != nil { - return settings, err + return settings, nil, err } settings.System, err = GetSystemSettings(paramsReader) if err != nil { - return settings, err + return settings, nil, err } settings.PublicIP, err = getPublicIPSettings(paramsReader) if err != nil { - return settings, err + return settings, nil, err } settings.VersionInformation, err = paramsReader.GetVersionInformation() if err != nil { - return settings, err + return settings, nil, err } settings.Updater, err = GetUpdaterSettings(paramsReader) if err != nil { - return settings, err + return settings, nil, err + } + + var warning string + settings.HTTPProxy, warning, err = GetHTTPProxySettings(paramsReader) + if warning != "" { + warnings = append(warnings, warning) } - settings.ControlServer, err = GetControlServerSettings(paramsReader) if err != nil { - return settings, err + return settings, warnings, err } - return settings, nil + + settings.ShadowSocks, warning, err = GetShadowSocksSettings(paramsReader) + if warning != "" { + warnings = append(warnings, warning) + } + if err != nil { + return settings, warnings, err + } + + settings.ControlServer, warning, err = GetControlServerSettings(paramsReader) + if warning != "" { + warnings = append(warnings, warning) + } + if err != nil { + return settings, warnings, err + } + + return settings, warnings, nil } diff --git a/internal/settings/shadowsocks.go b/internal/settings/shadowsocks.go index 4a1a76dc..8744422f 100644 --- a/internal/settings/shadowsocks.go +++ b/internal/settings/shadowsocks.go @@ -35,26 +35,26 @@ func (s *ShadowSocks) String() string { } // GetShadowSocksSettings obtains ShadowSocks settings from environment variables using the params package. -func GetShadowSocksSettings(paramsReader params.Reader) (settings ShadowSocks, err error) { +func GetShadowSocksSettings(paramsReader params.Reader) (settings ShadowSocks, warning string, err error) { settings.Enabled, err = paramsReader.GetShadowSocks() if err != nil || !settings.Enabled { - return settings, err - } - settings.Port, err = paramsReader.GetShadowSocksPort() - if err != nil { - return settings, err + return settings, "", err } settings.Password, err = paramsReader.GetShadowSocksPassword() if err != nil { - return settings, err + return settings, "", err } settings.Log, err = paramsReader.GetShadowSocksLog() if err != nil { - return settings, err + return settings, "", err } settings.Method, err = paramsReader.GetShadowSocksMethod() if err != nil { - return settings, err + return settings, "", err } - return settings, nil + settings.Port, warning, err = paramsReader.GetShadowSocksPort() + if err != nil { + return settings, warning, err + } + return settings, warning, nil }