mirror of
https://github.com/qdm12/gluetun.git
synced 2025-12-12 00:07:43 -06:00
chore: use gofumpt for code formatting
This commit is contained in:
parent
3daf15a612
commit
76a4bb5dc3
@ -81,7 +81,8 @@
|
|||||||
},
|
},
|
||||||
"gopls": {
|
"gopls": {
|
||||||
"usePlaceholders": false,
|
"usePlaceholders": false,
|
||||||
"staticcheck": true
|
"staticcheck": true,
|
||||||
|
"formatting.gofumpt": true,
|
||||||
},
|
},
|
||||||
"go.lintTool": "golangci-lint",
|
"go.lintTool": "golangci-lint",
|
||||||
"go.lintOnSave": "package",
|
"go.lintOnSave": "package",
|
||||||
|
|||||||
@ -52,6 +52,7 @@ linters:
|
|||||||
- gocritic
|
- gocritic
|
||||||
- gocyclo
|
- gocyclo
|
||||||
- godot
|
- godot
|
||||||
|
- gofumpt
|
||||||
- goheader
|
- goheader
|
||||||
- goimports
|
- goimports
|
||||||
- gomoddirectives
|
- gomoddirectives
|
||||||
|
|||||||
@ -140,15 +140,14 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var errCommandUnknown = errors.New("command is unknown")
|
||||||
errCommandUnknown = errors.New("command is unknown")
|
|
||||||
)
|
|
||||||
|
|
||||||
//nolint:gocognit,gocyclo,maintidx
|
//nolint:gocognit,gocyclo,maintidx
|
||||||
func _main(ctx context.Context, buildInfo models.BuildInformation,
|
func _main(ctx context.Context, buildInfo models.BuildInformation,
|
||||||
args []string, logger log.LoggerInterface, reader *reader.Reader,
|
args []string, logger log.LoggerInterface, reader *reader.Reader,
|
||||||
tun Tun, netLinker netLinker, cmder RunStarter,
|
tun Tun, netLinker netLinker, cmder RunStarter,
|
||||||
cli clier) error {
|
cli clier,
|
||||||
|
) error {
|
||||||
if len(args) > 1 { // cli operation
|
if len(args) > 1 { // cli operation
|
||||||
switch args[1] {
|
switch args[1] {
|
||||||
case "healthcheck":
|
case "healthcheck":
|
||||||
@ -288,7 +287,7 @@ func _main(ctx context.Context, buildInfo models.BuildInformation,
|
|||||||
logger.Warn(warning)
|
logger.Warn(warning)
|
||||||
}
|
}
|
||||||
|
|
||||||
const permission = fs.FileMode(0644)
|
const permission = fs.FileMode(0o644)
|
||||||
err = os.MkdirAll("/tmp/gluetun", permission)
|
err = os.MkdirAll("/tmp/gluetun", permission)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -366,7 +365,8 @@ func _main(ctx context.Context, buildInfo models.BuildInformation,
|
|||||||
}
|
}
|
||||||
defaultGroupOptions := []group.Option{
|
defaultGroupOptions := []group.Option{
|
||||||
group.OptionTimeout(defaultShutdownTimeout),
|
group.OptionTimeout(defaultShutdownTimeout),
|
||||||
group.OptionOnSuccess(defaultShutdownOnSuccess)}
|
group.OptionOnSuccess(defaultShutdownOnSuccess),
|
||||||
|
}
|
||||||
|
|
||||||
controlGroupHandler := goshutdown.NewGroupHandler("control", defaultGroupOptions...)
|
controlGroupHandler := goshutdown.NewGroupHandler("control", defaultGroupOptions...)
|
||||||
tickersGroupHandler := goshutdown.NewGroupHandler("tickers", defaultGroupOptions...)
|
tickersGroupHandler := goshutdown.NewGroupHandler("tickers", defaultGroupOptions...)
|
||||||
@ -532,7 +532,8 @@ type infoer interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func printVersions(ctx context.Context, logger infoer,
|
func printVersions(ctx context.Context, logger infoer,
|
||||||
elements []printVersionElement) (err error) {
|
elements []printVersionElement,
|
||||||
|
) (err error) {
|
||||||
const timeout = 5 * time.Second
|
const timeout = 5 * time.Second
|
||||||
ctx, cancel := context.WithTimeout(ctx, timeout)
|
ctx, cancel := context.WithTimeout(ctx, timeout)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|||||||
@ -9,9 +9,7 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var ErrUserAlreadyExists = errors.New("user already exists")
|
||||||
ErrUserAlreadyExists = errors.New("user already exists")
|
|
||||||
)
|
|
||||||
|
|
||||||
// CreateUser creates a user in Alpine with the given UID.
|
// CreateUser creates a user in Alpine with the given UID.
|
||||||
func (a *Alpine) CreateUser(username string, uid int) (createdUsername string, err error) {
|
func (a *Alpine) CreateUser(username string, uid int) (createdUsername string, err error) {
|
||||||
@ -40,7 +38,7 @@ func (a *Alpine) CreateUser(username string, uid int) (createdUsername string, e
|
|||||||
ErrUserAlreadyExists, username, u.Uid, uid)
|
ErrUserAlreadyExists, username, u.Uid, uid)
|
||||||
}
|
}
|
||||||
|
|
||||||
const permission = fs.FileMode(0644)
|
const permission = fs.FileMode(0o644)
|
||||||
file, err := os.OpenFile(a.passwdPath, os.O_APPEND|os.O_WRONLY, permission)
|
file, err := os.OpenFile(a.passwdPath, os.O_APPEND|os.O_WRONLY, permission)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
|
|||||||
@ -22,7 +22,8 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func addProviderFlag(flagSet *flag.FlagSet, providerToFormat map[string]*bool,
|
func addProviderFlag(flagSet *flag.FlagSet, providerToFormat map[string]*bool,
|
||||||
provider string, titleCaser cases.Caser) {
|
provider string, titleCaser cases.Caser,
|
||||||
|
) {
|
||||||
boolPtr, ok := providerToFormat[provider]
|
boolPtr, ok := providerToFormat[provider]
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Sprintf("unknown provider in format map: %s", provider))
|
panic(fmt.Sprintf("unknown provider in format map: %s", provider))
|
||||||
@ -91,7 +92,7 @@ func (c *CLI) FormatServers(args []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
output = filepath.Clean(output)
|
output = filepath.Clean(output)
|
||||||
const permission = fs.FileMode(0644)
|
const permission = fs.FileMode(0o644)
|
||||||
file, err := os.OpenFile(output, os.O_TRUNC|os.O_WRONLY|os.O_CREATE, permission)
|
file, err := os.OpenFile(output, os.O_TRUNC|os.O_WRONLY|os.O_CREATE, permission)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("opening output file: %w", err)
|
return fmt.Errorf("opening output file: %w", err)
|
||||||
|
|||||||
@ -42,7 +42,8 @@ type IPv6Checker interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *CLI) OpenvpnConfig(logger OpenvpnConfigLogger, reader *reader.Reader,
|
func (c *CLI) OpenvpnConfig(logger OpenvpnConfigLogger, reader *reader.Reader,
|
||||||
ipv6Checker IPv6Checker) error {
|
ipv6Checker IPv6Checker,
|
||||||
|
) error {
|
||||||
storage, err := storage.New(logger, constants.ServersData)
|
storage, err := storage.New(logger, constants.ServersData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@ -13,12 +13,14 @@ import (
|
|||||||
// if the command fails later.
|
// if the command fails later.
|
||||||
func (c *Cmder) Start(cmd *exec.Cmd) (
|
func (c *Cmder) Start(cmd *exec.Cmd) (
|
||||||
stdoutLines, stderrLines <-chan string,
|
stdoutLines, stderrLines <-chan string,
|
||||||
waitError <-chan error, startErr error) {
|
waitError <-chan error, startErr error,
|
||||||
|
) {
|
||||||
return start(cmd)
|
return start(cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
func start(cmd execCmd) (stdoutLines, stderrLines <-chan string,
|
func start(cmd execCmd) (stdoutLines, stderrLines <-chan string,
|
||||||
waitError <-chan error, startErr error) {
|
waitError <-chan error, startErr error,
|
||||||
|
) {
|
||||||
stop := make(chan struct{})
|
stop := make(chan struct{})
|
||||||
stdoutReady := make(chan struct{})
|
stdoutReady := make(chan struct{})
|
||||||
stdoutLinesCh := make(chan string)
|
stdoutLinesCh := make(chan string)
|
||||||
@ -68,7 +70,8 @@ func start(cmd execCmd) (stdoutLines, stderrLines <-chan string,
|
|||||||
|
|
||||||
func streamToChannel(ready chan<- struct{},
|
func streamToChannel(ready chan<- struct{},
|
||||||
stop <-chan struct{}, done chan<- struct{},
|
stop <-chan struct{}, done chan<- struct{},
|
||||||
stream io.Reader, lines chan<- string) {
|
stream io.Reader, lines chan<- string,
|
||||||
|
) {
|
||||||
defer close(done)
|
defer close(done)
|
||||||
close(ready)
|
close(ready)
|
||||||
scanner := bufio.NewScanner(stream)
|
scanner := bufio.NewScanner(stream)
|
||||||
|
|||||||
@ -76,7 +76,8 @@ func (b *DNSBlacklist) overrideWith(other DNSBlacklist) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b DNSBlacklist) ToBlockBuilderSettings(client *http.Client) (
|
func (b DNSBlacklist) ToBlockBuilderSettings(client *http.Client) (
|
||||||
settings blockbuilder.Settings) {
|
settings blockbuilder.Settings,
|
||||||
|
) {
|
||||||
return blockbuilder.Settings{
|
return blockbuilder.Settings{
|
||||||
Client: client,
|
Client: client,
|
||||||
BlockMalicious: b.BlockMalicious,
|
BlockMalicious: b.BlockMalicious,
|
||||||
@ -159,12 +160,11 @@ func (b *DNSBlacklist) read(r *reader.Reader) (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var ErrPrivateAddressNotValid = errors.New("private address is not a valid IP or CIDR range")
|
||||||
ErrPrivateAddressNotValid = errors.New("private address is not a valid IP or CIDR range")
|
|
||||||
)
|
|
||||||
|
|
||||||
func readDoTPrivateAddresses(reader *reader.Reader) (ips []netip.Addr,
|
func readDoTPrivateAddresses(reader *reader.Reader) (ips []netip.Addr,
|
||||||
ipPrefixes []netip.Prefix, err error) {
|
ipPrefixes []netip.Prefix, err error,
|
||||||
|
) {
|
||||||
privateAddresses := reader.CSV("DOT_PRIVATE_ADDRESS")
|
privateAddresses := reader.CSV("DOT_PRIVATE_ADDRESS")
|
||||||
if len(privateAddresses) == 0 {
|
if len(privateAddresses) == 0 {
|
||||||
return nil, nil, nil
|
return nil, nil, nil
|
||||||
|
|||||||
@ -35,9 +35,7 @@ type DoT struct {
|
|||||||
Blacklist DNSBlacklist
|
Blacklist DNSBlacklist
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var ErrDoTUpdatePeriodTooShort = errors.New("update period is too short")
|
||||||
ErrDoTUpdatePeriodTooShort = errors.New("update period is too short")
|
|
||||||
)
|
|
||||||
|
|
||||||
func (d DoT) validate() (err error) {
|
func (d DoT) validate() (err error) {
|
||||||
const minUpdatePeriod = 30 * time.Second
|
const minUpdatePeriod = 30 * time.Second
|
||||||
|
|||||||
@ -4,7 +4,8 @@ package settings
|
|||||||
// and SERVER_REGIONS is now the continent field for servers.
|
// and SERVER_REGIONS is now the continent field for servers.
|
||||||
// TODO v4 remove.
|
// TODO v4 remove.
|
||||||
func nordvpnRetroRegion(selection ServerSelection, validRegions, validCountries []string) (
|
func nordvpnRetroRegion(selection ServerSelection, validRegions, validCountries []string) (
|
||||||
updatedSelection ServerSelection) {
|
updatedSelection ServerSelection,
|
||||||
|
) {
|
||||||
validRegionsMap := stringSliceToMap(validRegions)
|
validRegionsMap := stringSliceToMap(validRegions)
|
||||||
validCountriesMap := stringSliceToMap(validCountries)
|
validCountriesMap := stringSliceToMap(validCountries)
|
||||||
|
|
||||||
|
|||||||
@ -155,7 +155,8 @@ func (o OpenVPN) validate(vpnProvider string) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func validateOpenVPNConfigFilepath(isCustom bool,
|
func validateOpenVPNConfigFilepath(isCustom bool,
|
||||||
confFile string) (err error) {
|
confFile string,
|
||||||
|
) (err error) {
|
||||||
if !isCustom {
|
if !isCustom {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -179,7 +180,8 @@ func validateOpenVPNConfigFilepath(isCustom bool,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func validateOpenVPNClientCertificate(vpnProvider,
|
func validateOpenVPNClientCertificate(vpnProvider,
|
||||||
clientCert string) (err error) {
|
clientCert string,
|
||||||
|
) (err error) {
|
||||||
switch vpnProvider {
|
switch vpnProvider {
|
||||||
case
|
case
|
||||||
providers.Airvpn,
|
providers.Airvpn,
|
||||||
@ -226,7 +228,8 @@ func validateOpenVPNClientKey(vpnProvider, clientKey string) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func validateOpenVPNEncryptedKey(vpnProvider,
|
func validateOpenVPNEncryptedKey(vpnProvider,
|
||||||
encryptedPrivateKey string) (err error) {
|
encryptedPrivateKey string,
|
||||||
|
) (err error) {
|
||||||
if vpnProvider == providers.VPNSecure && encryptedPrivateKey == "" {
|
if vpnProvider == providers.VPNSecure && encryptedPrivateKey == "" {
|
||||||
return fmt.Errorf("%w", ErrMissingValue)
|
return fmt.Errorf("%w", ErrMissingValue)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -122,7 +122,8 @@ func (p *PublicIP) read(r *reader.Reader, warner Warner) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func readPublicIPEnabled(r *reader.Reader, warner Warner) (
|
func readPublicIPEnabled(r *reader.Reader, warner Warner) (
|
||||||
enabled *bool, err error) {
|
enabled *bool, err error,
|
||||||
|
) {
|
||||||
periodPtr, err := r.DurationPtr("PUBLICIP_PERIOD") // Retro-compatibility
|
periodPtr, err := r.DurationPtr("PUBLICIP_PERIOD") // Retro-compatibility
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@ -91,7 +91,8 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (ss *ServerSelection) validate(vpnServiceProvider string,
|
func (ss *ServerSelection) validate(vpnServiceProvider string,
|
||||||
filterChoicesGetter FilterChoicesGetter, warner Warner) (err error) {
|
filterChoicesGetter FilterChoicesGetter, warner Warner,
|
||||||
|
) (err error) {
|
||||||
switch ss.VPN {
|
switch ss.VPN {
|
||||||
case vpn.OpenVPN, vpn.Wireguard:
|
case vpn.OpenVPN, vpn.Wireguard:
|
||||||
default:
|
default:
|
||||||
@ -143,7 +144,8 @@ func (ss *ServerSelection) validate(vpnServiceProvider string,
|
|||||||
|
|
||||||
func getLocationFilterChoices(vpnServiceProvider string,
|
func getLocationFilterChoices(vpnServiceProvider string,
|
||||||
ss *ServerSelection, filterChoicesGetter FilterChoicesGetter, warner Warner) (
|
ss *ServerSelection, filterChoicesGetter FilterChoicesGetter, warner Warner) (
|
||||||
filterChoices models.FilterChoices, err error) {
|
filterChoices models.FilterChoices, err error,
|
||||||
|
) {
|
||||||
filterChoices = filterChoicesGetter.GetFilterChoices(vpnServiceProvider)
|
filterChoices = filterChoicesGetter.GetFilterChoices(vpnServiceProvider)
|
||||||
|
|
||||||
if vpnServiceProvider == providers.Surfshark {
|
if vpnServiceProvider == providers.Surfshark {
|
||||||
@ -165,7 +167,8 @@ func getLocationFilterChoices(vpnServiceProvider string,
|
|||||||
// validateServerFilters validates filters against the choices given as arguments.
|
// validateServerFilters validates filters against the choices given as arguments.
|
||||||
// Set an argument to nil to pass the check for a particular filter.
|
// Set an argument to nil to pass the check for a particular filter.
|
||||||
func validateServerFilters(settings ServerSelection, filterChoices models.FilterChoices,
|
func validateServerFilters(settings ServerSelection, filterChoices models.FilterChoices,
|
||||||
vpnServiceProvider string, warner Warner) (err error) {
|
vpnServiceProvider string, warner Warner,
|
||||||
|
) (err error) {
|
||||||
err = atLeastOneIsOneOfCaseInsensitive(settings.Countries, filterChoices.Countries, warner)
|
err = atLeastOneIsOneOfCaseInsensitive(settings.Countries, filterChoices.Countries, warner)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("%w: %w", ErrCountryNotValid, err)
|
return fmt.Errorf("%w: %w", ErrCountryNotValid, err)
|
||||||
@ -219,7 +222,8 @@ func validateServerFilters(settings ServerSelection, filterChoices models.Filter
|
|||||||
}
|
}
|
||||||
|
|
||||||
func atLeastOneIsOneOfCaseInsensitive(values, choices []string,
|
func atLeastOneIsOneOfCaseInsensitive(values, choices []string,
|
||||||
warner Warner) (err error) {
|
warner Warner,
|
||||||
|
) (err error) {
|
||||||
if len(values) > 0 && len(choices) == 0 {
|
if len(values) > 0 && len(choices) == 0 {
|
||||||
return fmt.Errorf("%w", validate.ErrNoChoice)
|
return fmt.Errorf("%w", validate.ErrNoChoice)
|
||||||
}
|
}
|
||||||
@ -456,7 +460,8 @@ func (ss ServerSelection) WithDefaults(provider string) ServerSelection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ss *ServerSelection) read(r *reader.Reader,
|
func (ss *ServerSelection) read(r *reader.Reader,
|
||||||
vpnProvider, vpnType string) (err error) {
|
vpnProvider, vpnType string,
|
||||||
|
) (err error) {
|
||||||
ss.VPN = vpnType
|
ss.VPN = vpnType
|
||||||
|
|
||||||
ss.TargetIP, err = r.NetipAddr("OPENVPN_ENDPOINT_IP",
|
ss.TargetIP, err = r.NetipAddr("OPENVPN_ENDPOINT_IP",
|
||||||
|
|||||||
@ -38,7 +38,8 @@ type FilterChoicesGetter interface {
|
|||||||
// if one of them is not valid.
|
// if one of them is not valid.
|
||||||
// TODO v4 remove pointer for receiver (because of Surfshark).
|
// TODO v4 remove pointer for receiver (because of Surfshark).
|
||||||
func (s *Settings) Validate(filterChoicesGetter FilterChoicesGetter, ipv6Supported bool,
|
func (s *Settings) Validate(filterChoicesGetter FilterChoicesGetter, ipv6Supported bool,
|
||||||
warner Warner) (err error) {
|
warner Warner,
|
||||||
|
) (err error) {
|
||||||
nameToValidation := map[string]func() error{
|
nameToValidation := map[string]func() error{
|
||||||
"control server": s.ControlServer.validate,
|
"control server": s.ControlServer.validate,
|
||||||
"dns": s.DNS.validate,
|
"dns": s.DNS.validate,
|
||||||
@ -88,7 +89,8 @@ func (s *Settings) copy() (copied Settings) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Settings) OverrideWith(other Settings,
|
func (s *Settings) OverrideWith(other Settings,
|
||||||
filterChoicesGetter FilterChoicesGetter, ipv6Supported bool, warner Warner) (err error) {
|
filterChoicesGetter FilterChoicesGetter, ipv6Supported bool, warner Warner,
|
||||||
|
) (err error) {
|
||||||
patchedSettings := s.copy()
|
patchedSettings := s.copy()
|
||||||
patchedSettings.ControlServer.overrideWith(other.ControlServer)
|
patchedSettings.ControlServer.overrideWith(other.ControlServer)
|
||||||
patchedSettings.DNS.overrideWith(other.DNS)
|
patchedSettings.DNS.overrideWith(other.DNS)
|
||||||
|
|||||||
@ -7,7 +7,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func surfsharkRetroRegion(selection ServerSelection) (
|
func surfsharkRetroRegion(selection ServerSelection) (
|
||||||
updatedSelection ServerSelection) {
|
updatedSelection ServerSelection,
|
||||||
|
) {
|
||||||
locationData := servers.LocationData()
|
locationData := servers.LocationData()
|
||||||
|
|
||||||
retroToLocation := make(map[string]servers.ServerLocation, len(locationData))
|
retroToLocation := make(map[string]servers.ServerLocation, len(locationData))
|
||||||
|
|||||||
@ -34,9 +34,7 @@ type WireguardConfig struct {
|
|||||||
EndpointPort *string
|
EndpointPort *string
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var regexINISectionNotExist = regexp.MustCompile(`^section ".+" does not exist$`)
|
||||||
regexINISectionNotExist = regexp.MustCompile(`^section ".+" does not exist$`)
|
|
||||||
)
|
|
||||||
|
|
||||||
func ParseWireguardConf(path string) (config WireguardConfig, err error) {
|
func ParseWireguardConf(path string) (config WireguardConfig, err error) {
|
||||||
iniFile, err := ini.InsensitiveLoad(path)
|
iniFile, err := ini.InsensitiveLoad(path)
|
||||||
@ -68,18 +66,18 @@ func ParseWireguardConf(path string) (config WireguardConfig, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func parseWireguardInterfaceSection(interfaceSection *ini.Section) (
|
func parseWireguardInterfaceSection(interfaceSection *ini.Section) (
|
||||||
privateKey, addresses *string) {
|
privateKey, addresses *string,
|
||||||
|
) {
|
||||||
privateKey = getINIKeyFromSection(interfaceSection, "PrivateKey")
|
privateKey = getINIKeyFromSection(interfaceSection, "PrivateKey")
|
||||||
addresses = getINIKeyFromSection(interfaceSection, "Address")
|
addresses = getINIKeyFromSection(interfaceSection, "Address")
|
||||||
return privateKey, addresses
|
return privateKey, addresses
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var ErrEndpointHostNotIP = errors.New("endpoint host is not an IP")
|
||||||
ErrEndpointHostNotIP = errors.New("endpoint host is not an IP")
|
|
||||||
)
|
|
||||||
|
|
||||||
func parseWireguardPeerSection(peerSection *ini.Section) (
|
func parseWireguardPeerSection(peerSection *ini.Section) (
|
||||||
preSharedKey, publicKey, endpointIP, endpointPort *string) {
|
preSharedKey, publicKey, endpointIP, endpointPort *string,
|
||||||
|
) {
|
||||||
preSharedKey = getINIKeyFromSection(peerSection, "PresharedKey")
|
preSharedKey = getINIKeyFromSection(peerSection, "PresharedKey")
|
||||||
publicKey = getINIKeyFromSection(peerSection, "PublicKey")
|
publicKey = getINIKeyFromSection(peerSection, "PublicKey")
|
||||||
endpoint := getINIKeyFromSection(peerSection, "Endpoint")
|
endpoint := getINIKeyFromSection(peerSection, "Endpoint")
|
||||||
@ -96,9 +94,7 @@ func parseWireguardPeerSection(peerSection *ini.Section) (
|
|||||||
return preSharedKey, publicKey, endpointIP, endpointPort
|
return preSharedKey, publicKey, endpointIP, endpointPort
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var regexINIKeyNotExist = regexp.MustCompile(`key ".*" not exists$`)
|
||||||
regexINIKeyNotExist = regexp.MustCompile(`key ".*" not exists$`)
|
|
||||||
)
|
|
||||||
|
|
||||||
func getINIKeyFromSection(section *ini.Section, key string) (value *string) {
|
func getINIKeyFromSection(section *ini.Section, key string) (value *string) {
|
||||||
iniKey, err := section.GetKey(key)
|
iniKey, err := section.GetKey(key)
|
||||||
|
|||||||
@ -77,7 +77,7 @@ PresharedKey = YJ680VN+dGrdsWNjSFqZ6vvwuiNhbq502ZL3G7Q3o3g=
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
configFile := filepath.Join(t.TempDir(), "wg.conf")
|
configFile := filepath.Join(t.TempDir(), "wg.conf")
|
||||||
const permission = fs.FileMode(0600)
|
const permission = fs.FileMode(0o600)
|
||||||
err := os.WriteFile(configFile, []byte(testCase.fileContent), permission)
|
err := os.WriteFile(configFile, []byte(testCase.fileContent), permission)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
|||||||
@ -39,7 +39,7 @@ func Test_Source_Get(t *testing.T) {
|
|||||||
"empty_secret_file": {
|
"empty_secret_file": {
|
||||||
makeSource: func(tempDir string) (source *Source, err error) {
|
makeSource: func(tempDir string) (source *Source, err error) {
|
||||||
secretFilepath := filepath.Join(tempDir, "test_file")
|
secretFilepath := filepath.Join(tempDir, "test_file")
|
||||||
const permission = fs.FileMode(0600)
|
const permission = fs.FileMode(0o600)
|
||||||
err = os.WriteFile(secretFilepath, nil, permission)
|
err = os.WriteFile(secretFilepath, nil, permission)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -55,7 +55,7 @@ func Test_Source_Get(t *testing.T) {
|
|||||||
"default_secret_file": {
|
"default_secret_file": {
|
||||||
makeSource: func(tempDir string) (source *Source, err error) {
|
makeSource: func(tempDir string) (source *Source, err error) {
|
||||||
secretFilepath := filepath.Join(tempDir, "test_file")
|
secretFilepath := filepath.Join(tempDir, "test_file")
|
||||||
const permission = fs.FileMode(0600)
|
const permission = fs.FileMode(0o600)
|
||||||
err = os.WriteFile(secretFilepath, []byte{'A'}, permission)
|
err = os.WriteFile(secretFilepath, []byte{'A'}, permission)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -72,7 +72,7 @@ func Test_Source_Get(t *testing.T) {
|
|||||||
"env_specified_secret_file": {
|
"env_specified_secret_file": {
|
||||||
makeSource: func(tempDir string) (source *Source, err error) {
|
makeSource: func(tempDir string) (source *Source, err error) {
|
||||||
secretFilepath := filepath.Join(tempDir, "test_file_custom")
|
secretFilepath := filepath.Join(tempDir, "test_file_custom")
|
||||||
const permission = fs.FileMode(0600)
|
const permission = fs.FileMode(0o600)
|
||||||
err = os.WriteFile(secretFilepath, []byte{'A'}, permission)
|
err = os.WriteFile(secretFilepath, []byte{'A'}, permission)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@ -37,7 +37,8 @@ type Loop struct {
|
|||||||
const defaultBackoffTime = 10 * time.Second
|
const defaultBackoffTime = 10 * time.Second
|
||||||
|
|
||||||
func NewLoop(settings settings.DNS,
|
func NewLoop(settings settings.DNS,
|
||||||
client *http.Client, logger Logger) (loop *Loop, err error) {
|
client *http.Client, logger Logger,
|
||||||
|
) (loop *Loop, err error) {
|
||||||
start := make(chan struct{})
|
start := make(chan struct{})
|
||||||
running := make(chan models.LoopStatus)
|
running := make(chan models.LoopStatus)
|
||||||
stop := make(chan struct{})
|
stop := make(chan struct{})
|
||||||
|
|||||||
@ -16,13 +16,15 @@ import (
|
|||||||
func (l *Loop) GetSettings() (settings settings.DNS) { return l.state.GetSettings() }
|
func (l *Loop) GetSettings() (settings settings.DNS) { return l.state.GetSettings() }
|
||||||
|
|
||||||
func (l *Loop) SetSettings(ctx context.Context, settings settings.DNS) (
|
func (l *Loop) SetSettings(ctx context.Context, settings settings.DNS) (
|
||||||
outcome string) {
|
outcome string,
|
||||||
|
) {
|
||||||
return l.state.SetSettings(ctx, settings)
|
return l.state.SetSettings(ctx, settings)
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildDoTSettings(settings settings.DNS,
|
func buildDoTSettings(settings settings.DNS,
|
||||||
filter *mapfilter.Filter, logger Logger) (
|
filter *mapfilter.Filter, logger Logger) (
|
||||||
dotSettings dot.ServerSettings, err error) {
|
dotSettings dot.ServerSettings, err error,
|
||||||
|
) {
|
||||||
var middlewares []dot.Middleware
|
var middlewares []dot.Middleware
|
||||||
|
|
||||||
if *settings.DoT.Caching {
|
if *settings.DoT.Caching {
|
||||||
|
|||||||
@ -15,7 +15,8 @@ func (s *State) GetSettings() (settings settings.DNS) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *State) SetSettings(ctx context.Context, settings settings.DNS) (
|
func (s *State) SetSettings(ctx context.Context, settings settings.DNS) (
|
||||||
outcome string) {
|
outcome string,
|
||||||
|
) {
|
||||||
s.settingsMu.Lock()
|
s.settingsMu.Lock()
|
||||||
|
|
||||||
settingsUnchanged := reflect.DeepEqual(s.settings, settings)
|
settingsUnchanged := reflect.DeepEqual(s.settings, settings)
|
||||||
|
|||||||
@ -10,7 +10,8 @@ import (
|
|||||||
|
|
||||||
func New(statusApplier StatusApplier,
|
func New(statusApplier StatusApplier,
|
||||||
settings settings.DNS,
|
settings settings.DNS,
|
||||||
updateTicker chan<- struct{}) *State {
|
updateTicker chan<- struct{},
|
||||||
|
) *State {
|
||||||
return &State{
|
return &State{
|
||||||
statusApplier: statusApplier,
|
statusApplier: statusApplier,
|
||||||
settings: settings,
|
settings: settings,
|
||||||
|
|||||||
@ -11,6 +11,7 @@ func (l *Loop) GetStatus() (status models.LoopStatus) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (l *Loop) ApplyStatus(ctx context.Context, status models.LoopStatus) (
|
func (l *Loop) ApplyStatus(ctx context.Context, status models.LoopStatus) (
|
||||||
outcome string, err error) {
|
outcome string, err error,
|
||||||
|
) {
|
||||||
return l.statusManager.ApplyStatus(ctx, status)
|
return l.statusManager.ApplyStatus(ctx, status)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -33,7 +33,8 @@ func isDeleteMatchInstruction(instruction string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func deleteIPTablesRule(ctx context.Context, iptablesBinary, instruction string,
|
func deleteIPTablesRule(ctx context.Context, iptablesBinary, instruction string,
|
||||||
runner CmdRunner, logger Logger) (err error) {
|
runner CmdRunner, logger Logger,
|
||||||
|
) (err error) {
|
||||||
targetRule, err := parseIptablesInstruction(instruction)
|
targetRule, err := parseIptablesInstruction(instruction)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("parsing iptables command: %w", err)
|
return fmt.Errorf("parsing iptables command: %w", err)
|
||||||
@ -69,9 +70,12 @@ func deleteIPTablesRule(ctx context.Context, iptablesBinary, instruction string,
|
|||||||
// It returns 0 if the rule is not found.
|
// It returns 0 if the rule is not found.
|
||||||
func findLineNumber(ctx context.Context, iptablesBinary string,
|
func findLineNumber(ctx context.Context, iptablesBinary string,
|
||||||
instruction iptablesInstruction, runner CmdRunner, logger Logger) (
|
instruction iptablesInstruction, runner CmdRunner, logger Logger) (
|
||||||
lineNumber uint16, err error) {
|
lineNumber uint16, err error,
|
||||||
listFlags := []string{"-t", instruction.table, "-L", instruction.chain,
|
) {
|
||||||
"--line-numbers", "-n", "-v"}
|
listFlags := []string{
|
||||||
|
"-t", instruction.table, "-L", instruction.chain,
|
||||||
|
"--line-numbers", "-n", "-v",
|
||||||
|
}
|
||||||
cmd := exec.CommandContext(ctx, iptablesBinary, listFlags...) // #nosec G204
|
cmd := exec.CommandContext(ctx, iptablesBinary, listFlags...) // #nosec G204
|
||||||
logger.Debug(cmd.String())
|
logger.Debug(cmd.String())
|
||||||
output, err := runner.Run(cmd)
|
output, err := runner.Run(cmd)
|
||||||
|
|||||||
@ -36,7 +36,8 @@ type Config struct { //nolint:maligned
|
|||||||
// if no iptables implementation is available.
|
// if no iptables implementation is available.
|
||||||
func NewConfig(ctx context.Context, logger Logger,
|
func NewConfig(ctx context.Context, logger Logger,
|
||||||
runner CmdRunner, defaultRoutes []routing.DefaultRoute,
|
runner CmdRunner, defaultRoutes []routing.DefaultRoute,
|
||||||
localNetworks []routing.LocalNetwork) (config *Config, err error) {
|
localNetworks []routing.LocalNetwork,
|
||||||
|
) (config *Config, err error) {
|
||||||
iptables, err := checkIptablesSupport(ctx, runner, "iptables", "iptables-nft", "iptables-legacy")
|
iptables, err := checkIptablesSupport(ctx, runner, "iptables", "iptables-nft", "iptables-legacy")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@ -12,7 +12,8 @@ import (
|
|||||||
// and returns the iptables path that is supported. If none work, an
|
// and returns the iptables path that is supported. If none work, an
|
||||||
// empty string path is returned.
|
// empty string path is returned.
|
||||||
func findIP6tablesSupported(ctx context.Context, runner CmdRunner) (
|
func findIP6tablesSupported(ctx context.Context, runner CmdRunner) (
|
||||||
ip6tablesPath string, err error) {
|
ip6tablesPath string, err error,
|
||||||
|
) {
|
||||||
ip6tablesPath, err = checkIptablesSupport(ctx, runner, "ip6tables", "ip6tables-nft", "ip6tables-legacy")
|
ip6tablesPath, err = checkIptablesSupport(ctx, runner, "ip6tables", "ip6tables-nft", "ip6tables-legacy")
|
||||||
if errors.Is(err, ErrIPTablesNotSupported) {
|
if errors.Is(err, ErrIPTablesNotSupported) {
|
||||||
return "", nil
|
return "", nil
|
||||||
|
|||||||
@ -112,7 +112,8 @@ func (c *Config) acceptInputThroughInterface(ctx context.Context, intf string, r
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) acceptInputToSubnet(ctx context.Context, intf string,
|
func (c *Config) acceptInputToSubnet(ctx context.Context, intf string,
|
||||||
destination netip.Prefix, remove bool) error {
|
destination netip.Prefix, remove bool,
|
||||||
|
) error {
|
||||||
interfaceFlag := "-i " + intf
|
interfaceFlag := "-i " + intf
|
||||||
if intf == "*" { // all interfaces
|
if intf == "*" { // all interfaces
|
||||||
interfaceFlag = ""
|
interfaceFlag = ""
|
||||||
@ -144,7 +145,8 @@ func (c *Config) acceptEstablishedRelatedTraffic(ctx context.Context, remove boo
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) acceptOutputTrafficToVPN(ctx context.Context,
|
func (c *Config) acceptOutputTrafficToVPN(ctx context.Context,
|
||||||
defaultInterface string, connection models.Connection, remove bool) error {
|
defaultInterface string, connection models.Connection, remove bool,
|
||||||
|
) error {
|
||||||
protocol := connection.Protocol
|
protocol := connection.Protocol
|
||||||
if protocol == "tcp-client" {
|
if protocol == "tcp-client" {
|
||||||
protocol = "tcp" //nolint:goconst
|
protocol = "tcp" //nolint:goconst
|
||||||
@ -162,7 +164,8 @@ func (c *Config) acceptOutputTrafficToVPN(ctx context.Context,
|
|||||||
|
|
||||||
// Thanks to @npawelek.
|
// Thanks to @npawelek.
|
||||||
func (c *Config) acceptOutputFromIPToSubnet(ctx context.Context,
|
func (c *Config) acceptOutputFromIPToSubnet(ctx context.Context,
|
||||||
intf string, sourceIP netip.Addr, destinationSubnet netip.Prefix, remove bool) error {
|
intf string, sourceIP netip.Addr, destinationSubnet netip.Prefix, remove bool,
|
||||||
|
) error {
|
||||||
doIPv4 := sourceIP.Is4() && destinationSubnet.Addr().Is4()
|
doIPv4 := sourceIP.Is4() && destinationSubnet.Addr().Is4()
|
||||||
|
|
||||||
interfaceFlag := "-o " + intf
|
interfaceFlag := "-o " + intf
|
||||||
@ -183,7 +186,8 @@ func (c *Config) acceptOutputFromIPToSubnet(ctx context.Context,
|
|||||||
|
|
||||||
// NDP uses multicast address (theres no broadcast in IPv6 like ARP uses in IPv4).
|
// NDP uses multicast address (theres no broadcast in IPv6 like ARP uses in IPv4).
|
||||||
func (c *Config) acceptIpv6MulticastOutput(ctx context.Context,
|
func (c *Config) acceptIpv6MulticastOutput(ctx context.Context,
|
||||||
intf string, remove bool) error {
|
intf string, remove bool,
|
||||||
|
) error {
|
||||||
interfaceFlag := "-o " + intf
|
interfaceFlag := "-o " + intf
|
||||||
if intf == "*" { // all interfaces
|
if intf == "*" { // all interfaces
|
||||||
interfaceFlag = ""
|
interfaceFlag = ""
|
||||||
@ -207,7 +211,8 @@ func (c *Config) acceptInputToPort(ctx context.Context, intf string, port uint16
|
|||||||
|
|
||||||
// Used for VPN server side port forwarding, with intf set to the VPN tunnel interface.
|
// Used for VPN server side port forwarding, with intf set to the VPN tunnel interface.
|
||||||
func (c *Config) redirectPort(ctx context.Context, intf string,
|
func (c *Config) redirectPort(ctx context.Context, intf string,
|
||||||
sourcePort, destinationPort uint16, remove bool) (err error) {
|
sourcePort, destinationPort uint16, remove bool,
|
||||||
|
) (err error) {
|
||||||
interfaceFlag := "-i " + intf
|
interfaceFlag := "-i " + intf
|
||||||
if intf == "*" { // all interfaces
|
if intf == "*" { // all interfaces
|
||||||
interfaceFlag = ""
|
interfaceFlag = ""
|
||||||
|
|||||||
@ -32,9 +32,7 @@ type chainRule struct {
|
|||||||
ctstate []string // for example ["RELATED","ESTABLISHED"]. Can be empty.
|
ctstate []string // for example ["RELATED","ESTABLISHED"]. Can be empty.
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var ErrChainListMalformed = errors.New("iptables chain list output is malformed")
|
||||||
ErrChainListMalformed = errors.New("iptables chain list output is malformed")
|
|
||||||
)
|
|
||||||
|
|
||||||
func parseChain(iptablesOutput string) (c chain, err error) {
|
func parseChain(iptablesOutput string) (c chain, err error) {
|
||||||
// Text example:
|
// Text example:
|
||||||
@ -146,9 +144,7 @@ func parseChainGeneralDataLine(line string) (base chain, err error) {
|
|||||||
return base, nil
|
return base, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var ErrChainRuleMalformed = errors.New("chain rule is malformed")
|
||||||
ErrChainRuleMalformed = errors.New("chain rule is malformed")
|
|
||||||
)
|
|
||||||
|
|
||||||
func parseChainRuleLine(line string) (rule chainRule, err error) {
|
func parseChainRuleLine(line string) (rule chainRule, err error) {
|
||||||
line = strings.TrimSpace(line)
|
line = strings.TrimSpace(line)
|
||||||
@ -300,9 +296,7 @@ func parsePortsCSV(s string) (ports []uint16, err error) {
|
|||||||
return ports, nil
|
return ports, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var ErrLineNumberIsZero = errors.New("line number is zero")
|
||||||
ErrLineNumberIsZero = errors.New("line number is zero")
|
|
||||||
)
|
|
||||||
|
|
||||||
func parseLineNumber(s string) (n uint16, err error) {
|
func parseLineNumber(s string) (n uint16, err error) {
|
||||||
const base, bitLength = 10, 16
|
const base, bitLength = 10, 16
|
||||||
@ -315,9 +309,7 @@ func parseLineNumber(s string) (n uint16, err error) {
|
|||||||
return uint16(lineNumber), nil
|
return uint16(lineNumber), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var ErrTargetUnknown = errors.New("unknown target")
|
||||||
ErrTargetUnknown = errors.New("unknown target")
|
|
||||||
)
|
|
||||||
|
|
||||||
func checkTarget(target string) (err error) {
|
func checkTarget(target string) (err error) {
|
||||||
switch target {
|
switch target {
|
||||||
@ -327,9 +319,7 @@ func checkTarget(target string) (err error) {
|
|||||||
return fmt.Errorf("%w: %s", ErrTargetUnknown, target)
|
return fmt.Errorf("%w: %s", ErrTargetUnknown, target)
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var ErrProtocolUnknown = errors.New("unknown protocol")
|
||||||
ErrProtocolUnknown = errors.New("unknown protocol")
|
|
||||||
)
|
|
||||||
|
|
||||||
func parseProtocol(s string) (protocol string, err error) {
|
func parseProtocol(s string) (protocol string, err error) {
|
||||||
switch s {
|
switch s {
|
||||||
@ -344,9 +334,7 @@ func parseProtocol(s string) (protocol string, err error) {
|
|||||||
return protocol, nil
|
return protocol, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var ErrMetricSizeMalformed = errors.New("metric size is malformed")
|
||||||
ErrMetricSizeMalformed = errors.New("metric size is malformed")
|
|
||||||
)
|
|
||||||
|
|
||||||
// parseMetricSize parses a metric size string like 140K or 226M and
|
// parseMetricSize parses a metric size string like 140K or 226M and
|
||||||
// returns the raw integer matching it.
|
// returns the raw integer matching it.
|
||||||
|
|||||||
@ -70,9 +70,7 @@ func ipPrefixesEqual(instruction, chainRule netip.Prefix) bool {
|
|||||||
(!instruction.IsValid() && chainRule.Bits() == 0 && chainRule.Addr().IsUnspecified())
|
(!instruction.IsValid() && chainRule.Bits() == 0 && chainRule.Addr().IsUnspecified())
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var ErrIptablesCommandMalformed = errors.New("iptables command is malformed")
|
||||||
ErrIptablesCommandMalformed = errors.New("iptables command is malformed")
|
|
||||||
)
|
|
||||||
|
|
||||||
func parseIptablesInstruction(s string) (instruction iptablesInstruction, err error) {
|
func parseIptablesInstruction(s string) (instruction iptablesInstruction, err error) {
|
||||||
if s == "" {
|
if s == "" {
|
||||||
|
|||||||
@ -11,7 +11,8 @@ import (
|
|||||||
// If the destination port is zero, the redirection for the source port is removed
|
// If the destination port is zero, the redirection for the source port is removed
|
||||||
// and no new redirection is added.
|
// and no new redirection is added.
|
||||||
func (c *Config) RedirectPort(ctx context.Context, intf string, sourcePort,
|
func (c *Config) RedirectPort(ctx context.Context, intf string, sourcePort,
|
||||||
destinationPort uint16) (err error) {
|
destinationPort uint16,
|
||||||
|
) (err error) {
|
||||||
c.stateMutex.Lock()
|
c.stateMutex.Lock()
|
||||||
defer c.stateMutex.Unlock()
|
defer c.stateMutex.Unlock()
|
||||||
|
|
||||||
@ -90,7 +91,8 @@ func (p *portRedirections) remove(intf string, sourcePort uint16) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *portRedirections) check(dryRun portRedirection) (alreadyExists bool,
|
func (p *portRedirections) check(dryRun portRedirection) (alreadyExists bool,
|
||||||
conflict *portRedirection) {
|
conflict *portRedirection,
|
||||||
|
) {
|
||||||
slice := *p
|
slice := *p
|
||||||
for _, redirection := range slice {
|
for _, redirection := range slice {
|
||||||
interfaceMatch := redirection.interfaceName == "" ||
|
interfaceMatch := redirection.interfaceName == "" ||
|
||||||
|
|||||||
@ -18,7 +18,8 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func checkIptablesSupport(ctx context.Context, runner CmdRunner,
|
func checkIptablesSupport(ctx context.Context, runner CmdRunner,
|
||||||
iptablesPathsToTry ...string) (iptablesPath string, err error) {
|
iptablesPathsToTry ...string,
|
||||||
|
) (iptablesPath string, err error) {
|
||||||
iptablesPathToUnsupportedMessage := make(map[string]string, len(iptablesPathsToTry))
|
iptablesPathToUnsupportedMessage := make(map[string]string, len(iptablesPathsToTry))
|
||||||
for _, pathToTest := range iptablesPathsToTry {
|
for _, pathToTest := range iptablesPathsToTry {
|
||||||
ok, unsupportedMessage, err := testIptablesPath(ctx, pathToTest, runner)
|
ok, unsupportedMessage, err := testIptablesPath(ctx, pathToTest, runner)
|
||||||
@ -61,7 +62,8 @@ func checkIptablesSupport(ctx context.Context, runner CmdRunner,
|
|||||||
|
|
||||||
func testIptablesPath(ctx context.Context, path string,
|
func testIptablesPath(ctx context.Context, path string,
|
||||||
runner CmdRunner) (ok bool, unsupportedMessage string,
|
runner CmdRunner) (ok bool, unsupportedMessage string,
|
||||||
criticalErr error) {
|
criticalErr error,
|
||||||
|
) {
|
||||||
// Just listing iptables rules often work but we need
|
// Just listing iptables rules often work but we need
|
||||||
// to modify them to ensure we can support the iptables
|
// to modify them to ensure we can support the iptables
|
||||||
// being tested.
|
// being tested.
|
||||||
|
|||||||
@ -116,8 +116,7 @@ func Test_checkIptablesSupport(t *testing.T) {
|
|||||||
|
|
||||||
runner := testCase.buildRunner(ctrl)
|
runner := testCase.buildRunner(ctrl)
|
||||||
|
|
||||||
iptablesPath, err :=
|
iptablesPath, err := checkIptablesSupport(ctx, runner, testCase.iptablesPathsToTry...)
|
||||||
checkIptablesSupport(ctx, runner, testCase.iptablesPathsToTry...)
|
|
||||||
|
|
||||||
require.ErrorIs(t, err, testCase.errSentinel)
|
require.ErrorIs(t, err, testCase.errSentinel)
|
||||||
if testCase.errSentinel != nil {
|
if testCase.errSentinel != nil {
|
||||||
@ -254,8 +253,7 @@ func Test_testIptablesPath(t *testing.T) {
|
|||||||
|
|
||||||
runner := testCase.buildRunner(ctrl)
|
runner := testCase.buildRunner(ctrl)
|
||||||
|
|
||||||
ok, unsupportedMessage, criticalErr :=
|
ok, unsupportedMessage, criticalErr := testIptablesPath(ctx, path, runner)
|
||||||
testIptablesPath(ctx, path, runner)
|
|
||||||
|
|
||||||
assert.Equal(t, testCase.ok, ok)
|
assert.Equal(t, testCase.ok, ok)
|
||||||
assert.Equal(t, testCase.unsupportedMessage, unsupportedMessage)
|
assert.Equal(t, testCase.unsupportedMessage, unsupportedMessage)
|
||||||
|
|||||||
@ -8,7 +8,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (c *Config) SetVPNConnection(ctx context.Context,
|
func (c *Config) SetVPNConnection(ctx context.Context,
|
||||||
connection models.Connection, vpnIntf string) (err error) {
|
connection models.Connection, vpnIntf string,
|
||||||
|
) (err error) {
|
||||||
c.stateMutex.Lock()
|
c.stateMutex.Lock()
|
||||||
defer c.stateMutex.Unlock()
|
defer c.stateMutex.Unlock()
|
||||||
|
|
||||||
|
|||||||
@ -8,9 +8,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var ErrHTTPStatusNotOK = errors.New("HTTP response status is not OK")
|
||||||
ErrHTTPStatusNotOK = errors.New("HTTP response status is not OK")
|
|
||||||
)
|
|
||||||
|
|
||||||
type Client struct {
|
type Client struct {
|
||||||
httpClient *http.Client
|
httpClient *http.Client
|
||||||
|
|||||||
@ -17,7 +17,8 @@ type Server struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewServer(config settings.Health,
|
func NewServer(config settings.Health,
|
||||||
logger Logger, vpnLoop StatusApplier) *Server {
|
logger Logger, vpnLoop StatusApplier,
|
||||||
|
) *Server {
|
||||||
return &Server{
|
return &Server{
|
||||||
logger: logger,
|
logger: logger,
|
||||||
handler: newHandler(),
|
handler: newHandler(),
|
||||||
|
|||||||
@ -8,14 +8,16 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func newHandler(ctx context.Context, wg *sync.WaitGroup, logger Logger,
|
func newHandler(ctx context.Context, wg *sync.WaitGroup, logger Logger,
|
||||||
stealth, verbose bool, username, password string) http.Handler {
|
stealth, verbose bool, username, password string,
|
||||||
|
) http.Handler {
|
||||||
const httpTimeout = 24 * time.Hour
|
const httpTimeout = 24 * time.Hour
|
||||||
return &handler{
|
return &handler{
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
wg: wg,
|
wg: wg,
|
||||||
client: &http.Client{
|
client: &http.Client{
|
||||||
Timeout: httpTimeout,
|
Timeout: httpTimeout,
|
||||||
CheckRedirect: returnRedirect},
|
CheckRedirect: returnRedirect,
|
||||||
|
},
|
||||||
logger: logger,
|
logger: logger,
|
||||||
verbose: verbose,
|
verbose: verbose,
|
||||||
stealth: stealth,
|
stealth: stealth,
|
||||||
|
|||||||
@ -18,7 +18,8 @@ type Server struct {
|
|||||||
|
|
||||||
func New(ctx context.Context, address string, logger Logger,
|
func New(ctx context.Context, address string, logger Logger,
|
||||||
stealth, verbose bool, username, password string,
|
stealth, verbose bool, username, password string,
|
||||||
readHeaderTimeout, readTimeout time.Duration) *Server {
|
readHeaderTimeout, readTimeout time.Duration,
|
||||||
|
) *Server {
|
||||||
wg := &sync.WaitGroup{}
|
wg := &sync.WaitGroup{}
|
||||||
return &Server{
|
return &Server{
|
||||||
address: address,
|
address: address,
|
||||||
|
|||||||
@ -11,6 +11,7 @@ func (l *Loop) GetSettings() (settings settings.HTTPProxy) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (l *Loop) SetSettings(ctx context.Context, settings settings.HTTPProxy) (
|
func (l *Loop) SetSettings(ctx context.Context, settings settings.HTTPProxy) (
|
||||||
outcome string) {
|
outcome string,
|
||||||
|
) {
|
||||||
return l.state.SetSettings(ctx, settings)
|
return l.state.SetSettings(ctx, settings)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,7 +15,8 @@ func (s *State) GetSettings() (settings settings.HTTPProxy) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *State) SetSettings(ctx context.Context,
|
func (s *State) SetSettings(ctx context.Context,
|
||||||
settings settings.HTTPProxy) (outcome string) {
|
settings settings.HTTPProxy,
|
||||||
|
) (outcome string) {
|
||||||
s.settingsMu.Lock()
|
s.settingsMu.Lock()
|
||||||
settingsUnchanged := reflect.DeepEqual(settings, s.settings)
|
settingsUnchanged := reflect.DeepEqual(settings, s.settings)
|
||||||
if settingsUnchanged {
|
if settingsUnchanged {
|
||||||
|
|||||||
@ -9,7 +9,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func New(statusApplier StatusApplier,
|
func New(statusApplier StatusApplier,
|
||||||
settings settings.HTTPProxy) *State {
|
settings settings.HTTPProxy,
|
||||||
|
) *State {
|
||||||
return &State{
|
return &State{
|
||||||
statusApplier: statusApplier,
|
statusApplier: statusApplier,
|
||||||
settings: settings,
|
settings: settings,
|
||||||
|
|||||||
@ -11,6 +11,7 @@ func (l *Loop) GetStatus() (status models.LoopStatus) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (l *Loop) ApplyStatus(ctx context.Context, status models.LoopStatus) (
|
func (l *Loop) ApplyStatus(ctx context.Context, status models.LoopStatus) (
|
||||||
outcome string, err error) {
|
outcome string, err error,
|
||||||
|
) {
|
||||||
return l.statusManager.ApplyStatus(ctx, status)
|
return l.statusManager.ApplyStatus(ctx, status)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,7 +16,8 @@ var ErrInvalidStatus = errors.New("invalid status")
|
|||||||
// matches the requested one. It is thread safe and a synchronous call
|
// matches the requested one. It is thread safe and a synchronous call
|
||||||
// since it waits to the loop to fully change its status.
|
// since it waits to the loop to fully change its status.
|
||||||
func (s *State) ApplyStatus(ctx context.Context, status models.LoopStatus) (
|
func (s *State) ApplyStatus(ctx context.Context, status models.LoopStatus) (
|
||||||
outcome string, err error) {
|
outcome string, err error,
|
||||||
|
) {
|
||||||
// prevent simultaneous loop changes by restricting
|
// prevent simultaneous loop changes by restricting
|
||||||
// multiple ApplyStatus calls to run sequentially.
|
// multiple ApplyStatus calls to run sequentially.
|
||||||
s.loopMu.Lock()
|
s.loopMu.Lock()
|
||||||
|
|||||||
@ -8,7 +8,8 @@ import (
|
|||||||
|
|
||||||
func New(status models.LoopStatus,
|
func New(status models.LoopStatus,
|
||||||
start chan<- struct{}, running <-chan models.LoopStatus,
|
start chan<- struct{}, running <-chan models.LoopStatus,
|
||||||
stop chan<- struct{}, stopped <-chan struct{}) *State {
|
stop chan<- struct{}, stopped <-chan struct{},
|
||||||
|
) *State {
|
||||||
return &State{
|
return &State{
|
||||||
status: status,
|
status: status,
|
||||||
start: start,
|
start: start,
|
||||||
|
|||||||
@ -26,9 +26,7 @@ type moduleInfo struct {
|
|||||||
dependencyPaths []string
|
dependencyPaths []string
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var ErrModulesDirectoryNotFound = errors.New("modules directory not found")
|
||||||
ErrModulesDirectoryNotFound = errors.New("modules directory not found")
|
|
||||||
)
|
|
||||||
|
|
||||||
func getModulesInfo() (modulesInfo map[string]moduleInfo, err error) {
|
func getModulesInfo() (modulesInfo map[string]moduleInfo, err error) {
|
||||||
var utsName unix.Utsname
|
var utsName unix.Utsname
|
||||||
@ -177,9 +175,7 @@ func getLoadedModules(modulesInfo map[string]moduleInfo) (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var ErrModulePathNotFound = errors.New("module path not found")
|
||||||
ErrModulePathNotFound = errors.New("module path not found")
|
|
||||||
)
|
|
||||||
|
|
||||||
func findModulePath(moduleName string, modulesInfo map[string]moduleInfo) (modulePath string, err error) {
|
func findModulePath(moduleName string, modulesInfo map[string]moduleInfo) (modulePath string, err error) {
|
||||||
// Kernel module names can have underscores or hyphens in their names,
|
// Kernel module names can have underscores or hyphens in their names,
|
||||||
|
|||||||
@ -109,15 +109,15 @@ func (s *Servers) toMarkdown(vpnProvider string) (formatted string, err error) {
|
|||||||
return formatted, nil
|
return formatted, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var ErrMarkdownHeadersNotDefined = errors.New("markdown headers not defined")
|
||||||
ErrMarkdownHeadersNotDefined = errors.New("markdown headers not defined")
|
|
||||||
)
|
|
||||||
|
|
||||||
func getMarkdownHeaders(vpnProvider string) (headers []string, err error) {
|
func getMarkdownHeaders(vpnProvider string) (headers []string, err error) {
|
||||||
switch vpnProvider {
|
switch vpnProvider {
|
||||||
case providers.Airvpn:
|
case providers.Airvpn:
|
||||||
return []string{regionHeader, countryHeader, cityHeader, vpnHeader,
|
return []string{
|
||||||
udpHeader, tcpHeader, hostnameHeader, nameHeader}, nil
|
regionHeader, countryHeader, cityHeader, vpnHeader,
|
||||||
|
udpHeader, tcpHeader, hostnameHeader, nameHeader,
|
||||||
|
}, nil
|
||||||
case providers.Cyberghost:
|
case providers.Cyberghost:
|
||||||
return []string{countryHeader, hostnameHeader, tcpHeader, udpHeader}, nil
|
return []string{countryHeader, hostnameHeader, tcpHeader, udpHeader}, nil
|
||||||
case providers.Expressvpn:
|
case providers.Expressvpn:
|
||||||
@ -145,15 +145,19 @@ func getMarkdownHeaders(vpnProvider string) (headers []string, err error) {
|
|||||||
case providers.Privatevpn:
|
case providers.Privatevpn:
|
||||||
return []string{countryHeader, cityHeader, hostnameHeader}, nil
|
return []string{countryHeader, cityHeader, hostnameHeader}, nil
|
||||||
case providers.Protonvpn:
|
case providers.Protonvpn:
|
||||||
return []string{countryHeader, regionHeader, cityHeader, hostnameHeader, vpnHeader,
|
return []string{
|
||||||
freeHeader, portForwardHeader, secureHeader, torHeader}, nil
|
countryHeader, regionHeader, cityHeader, hostnameHeader, vpnHeader,
|
||||||
|
freeHeader, portForwardHeader, secureHeader, torHeader,
|
||||||
|
}, nil
|
||||||
case providers.Purevpn:
|
case providers.Purevpn:
|
||||||
return []string{countryHeader, regionHeader, cityHeader, hostnameHeader, tcpHeader, udpHeader}, nil
|
return []string{countryHeader, regionHeader, cityHeader, hostnameHeader, tcpHeader, udpHeader}, nil
|
||||||
case providers.SlickVPN:
|
case providers.SlickVPN:
|
||||||
return []string{regionHeader, countryHeader, cityHeader, hostnameHeader}, nil
|
return []string{regionHeader, countryHeader, cityHeader, hostnameHeader}, nil
|
||||||
case providers.Surfshark:
|
case providers.Surfshark:
|
||||||
return []string{regionHeader, countryHeader, cityHeader, hostnameHeader,
|
return []string{
|
||||||
vpnHeader, multiHopHeader, tcpHeader, udpHeader}, nil
|
regionHeader, countryHeader, cityHeader, hostnameHeader,
|
||||||
|
vpnHeader, multiHopHeader, tcpHeader, udpHeader,
|
||||||
|
}, nil
|
||||||
case providers.Torguard:
|
case providers.Torguard:
|
||||||
return []string{countryHeader, cityHeader, hostnameHeader, tcpHeader, udpHeader}, nil
|
return []string{countryHeader, cityHeader, hostnameHeader, tcpHeader, udpHeader}, nil
|
||||||
case providers.VPNSecure:
|
case providers.VPNSecure:
|
||||||
|
|||||||
@ -158,9 +158,7 @@ type Servers struct {
|
|||||||
Servers []Server `json:"servers,omitempty"`
|
Servers []Server `json:"servers,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var ErrServersFormatNotSupported = errors.New("servers format not supported")
|
||||||
ErrServersFormatNotSupported = errors.New("servers format not supported")
|
|
||||||
)
|
|
||||||
|
|
||||||
func (s *Servers) Format(vpnProvider, format string) (formatted string, err error) {
|
func (s *Servers) Format(vpnProvider, format string) (formatted string, err error) {
|
||||||
switch format {
|
switch format {
|
||||||
|
|||||||
@ -6,9 +6,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var ErrRequestSizeTooSmall = errors.New("message size is too small")
|
||||||
ErrRequestSizeTooSmall = errors.New("message size is too small")
|
|
||||||
)
|
|
||||||
|
|
||||||
func checkRequest(request []byte) (err error) {
|
func checkRequest(request []byte) (err error) {
|
||||||
const minMessageSize = 2 // version number + operation code
|
const minMessageSize = 2 // version number + operation code
|
||||||
@ -28,7 +26,8 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func checkResponse(response []byte, expectedOperationCode byte,
|
func checkResponse(response []byte, expectedOperationCode byte,
|
||||||
expectedResponseSize uint) (err error) {
|
expectedResponseSize uint,
|
||||||
|
) (err error) {
|
||||||
const minResponseSize = 4
|
const minResponseSize = 4
|
||||||
if len(response) < minResponseSize {
|
if len(response) < minResponseSize {
|
||||||
return fmt.Errorf("%w: need at least %d bytes and got %d byte(s)",
|
return fmt.Errorf("%w: need at least %d bytes and got %d byte(s)",
|
||||||
|
|||||||
@ -13,7 +13,8 @@ import (
|
|||||||
// See https://www.ietf.org/rfc/rfc6886.html#section-3.2
|
// See https://www.ietf.org/rfc/rfc6886.html#section-3.2
|
||||||
func (c *Client) ExternalAddress(ctx context.Context, gateway netip.Addr) (
|
func (c *Client) ExternalAddress(ctx context.Context, gateway netip.Addr) (
|
||||||
durationSinceStartOfEpoch time.Duration,
|
durationSinceStartOfEpoch time.Duration,
|
||||||
externalIPv4Address netip.Addr, err error) {
|
externalIPv4Address netip.Addr, err error,
|
||||||
|
) {
|
||||||
request := []byte{0, 0} // version 0, operationCode 0
|
request := []byte{0, 0} // version 0, operationCode 0
|
||||||
const responseSize = 12
|
const responseSize = 12
|
||||||
response, err := c.rpc(ctx, gateway, request, responseSize)
|
response, err := c.rpc(ctx, gateway, request, responseSize)
|
||||||
|
|||||||
@ -57,8 +57,7 @@ func Test_Client_ExternalAddress(t *testing.T) {
|
|||||||
maxRetries: 1,
|
maxRetries: 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
durationSinceStartOfEpoch, externalIPv4Address, err :=
|
durationSinceStartOfEpoch, externalIPv4Address, err := client.ExternalAddress(testCase.ctx, testCase.gateway)
|
||||||
client.ExternalAddress(testCase.ctx, testCase.gateway)
|
|
||||||
assert.ErrorIs(t, err, testCase.err)
|
assert.ErrorIs(t, err, testCase.err)
|
||||||
if testCase.err != nil {
|
if testCase.err != nil {
|
||||||
assert.EqualError(t, err, testCase.errMessage)
|
assert.EqualError(t, err, testCase.errMessage)
|
||||||
|
|||||||
@ -27,7 +27,8 @@ type udpExchange struct {
|
|||||||
// port is dynamically assigned by the OS so calling tests
|
// port is dynamically assigned by the OS so calling tests
|
||||||
// can run in parallel.
|
// can run in parallel.
|
||||||
func launchUDPServer(t *testing.T, exchanges []udpExchange) (
|
func launchUDPServer(t *testing.T, exchanges []udpExchange) (
|
||||||
remoteAddress *net.UDPAddr) {
|
remoteAddress *net.UDPAddr,
|
||||||
|
) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
conn, err := net.ListenUDP("udp", nil)
|
conn, err := net.ListenUDP("udp", nil)
|
||||||
|
|||||||
@ -21,7 +21,8 @@ func (c *Client) AddPortMapping(ctx context.Context, gateway netip.Addr,
|
|||||||
protocol string, internalPort, requestedExternalPort uint16,
|
protocol string, internalPort, requestedExternalPort uint16,
|
||||||
lifetime time.Duration) (durationSinceStartOfEpoch time.Duration,
|
lifetime time.Duration) (durationSinceStartOfEpoch time.Duration,
|
||||||
assignedInternalPort, assignedExternalPort uint16, assignedLifetime time.Duration,
|
assignedInternalPort, assignedExternalPort uint16, assignedLifetime time.Duration,
|
||||||
err error) {
|
err error,
|
||||||
|
) {
|
||||||
lifetimeSecondsFloat := lifetime.Seconds()
|
lifetimeSecondsFloat := lifetime.Seconds()
|
||||||
const maxLifetimeSeconds = uint64(^uint32(0))
|
const maxLifetimeSeconds = uint64(^uint32(0))
|
||||||
if uint64(lifetimeSecondsFloat) > maxLifetimeSeconds {
|
if uint64(lifetimeSecondsFloat) > maxLifetimeSeconds {
|
||||||
|
|||||||
@ -127,10 +127,9 @@ func Test_Client_AddPortMapping(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
durationSinceStartOfEpoch, assignedInternalPort,
|
durationSinceStartOfEpoch, assignedInternalPort,
|
||||||
assignedExternalPort, assignedLifetime, err :=
|
assignedExternalPort, assignedLifetime, err := client.AddPortMapping(testCase.ctx, testCase.gateway,
|
||||||
client.AddPortMapping(testCase.ctx, testCase.gateway,
|
testCase.protocol, testCase.internalPort,
|
||||||
testCase.protocol, testCase.internalPort,
|
testCase.requestedExternalPort, testCase.lifetime)
|
||||||
testCase.requestedExternalPort, testCase.lifetime)
|
|
||||||
|
|
||||||
assert.Equal(t, testCase.durationSinceStartOfEpoch, durationSinceStartOfEpoch)
|
assert.Equal(t, testCase.durationSinceStartOfEpoch, durationSinceStartOfEpoch)
|
||||||
assert.Equal(t, testCase.assignedInternalPort, assignedInternalPort)
|
assert.Equal(t, testCase.assignedInternalPort, assignedInternalPort)
|
||||||
|
|||||||
@ -18,7 +18,8 @@ var (
|
|||||||
|
|
||||||
func (c *Client) rpc(ctx context.Context, gateway netip.Addr,
|
func (c *Client) rpc(ctx context.Context, gateway netip.Addr,
|
||||||
request []byte, responseSize uint) (
|
request []byte, responseSize uint) (
|
||||||
response []byte, err error) {
|
response []byte, err error,
|
||||||
|
) {
|
||||||
if gateway.IsUnspecified() || !gateway.IsValid() {
|
if gateway.IsUnspecified() || !gateway.IsValid() {
|
||||||
return nil, fmt.Errorf("%w", ErrGatewayIPUnspecified)
|
return nil, fmt.Errorf("%w", ErrGatewayIPUnspecified)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,7 +7,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (n *NetLink) AddrList(link Link, family int) (
|
func (n *NetLink) AddrList(link Link, family int) (
|
||||||
addresses []Addr, err error) {
|
addresses []Addr, err error,
|
||||||
|
) {
|
||||||
netlinkLink := linkToNetlinkLink(&link)
|
netlinkLink := linkToNetlinkLink(&link)
|
||||||
netlinkAddresses, err := netlink.AddrList(netlinkLink, family)
|
netlinkAddresses, err := netlink.AddrList(netlinkLink, family)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@ -3,7 +3,8 @@
|
|||||||
package netlink
|
package netlink
|
||||||
|
|
||||||
func (n *NetLink) AddrList(link Link, family int) (
|
func (n *NetLink) AddrList(link Link, family int) (
|
||||||
addresses []Addr, err error) {
|
addresses []Addr, err error,
|
||||||
|
) {
|
||||||
panic("not implemented")
|
panic("not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3,7 +3,8 @@
|
|||||||
package netlink
|
package netlink
|
||||||
|
|
||||||
func (n *NetLink) RouteList(family int) (
|
func (n *NetLink) RouteList(family int) (
|
||||||
routes []Route, err error) {
|
routes []Route, err error,
|
||||||
|
) {
|
||||||
panic("not implemented")
|
panic("not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -23,7 +23,7 @@ func writeIfDifferent(path, content string, puid, pgid int) (err error) {
|
|||||||
return fmt.Errorf("obtaining file information: %w", err)
|
return fmt.Errorf("obtaining file information: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
const perm = os.FileMode(0400)
|
const perm = os.FileMode(0o400)
|
||||||
var writeData, setChown bool
|
var writeData, setChown bool
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
writeData = true
|
writeData = true
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (c *Configurator) WriteConfig(lines []string) error {
|
func (c *Configurator) WriteConfig(lines []string) error {
|
||||||
const permission = 0644
|
const permission = 0o644
|
||||||
file, err := os.OpenFile(c.configPath, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, permission)
|
file, err := os.OpenFile(c.configPath, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, permission)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@ -14,7 +14,8 @@ var (
|
|||||||
|
|
||||||
// Data extracts the lines and connection from the OpenVPN configuration file.
|
// Data extracts the lines and connection from the OpenVPN configuration file.
|
||||||
func (e *Extractor) Data(filepath string) (lines []string,
|
func (e *Extractor) Data(filepath string) (lines []string,
|
||||||
connection models.Connection, err error) {
|
connection models.Connection, err error,
|
||||||
|
) {
|
||||||
lines, err = readCustomConfigLines(filepath)
|
lines, err = readCustomConfigLines(filepath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, connection, fmt.Errorf("reading configuration file: %w", err)
|
return nil, connection, fmt.Errorf("reading configuration file: %w", err)
|
||||||
|
|||||||
@ -11,12 +11,11 @@ import (
|
|||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var errRemoteLineNotFound = errors.New("remote line not found")
|
||||||
errRemoteLineNotFound = errors.New("remote line not found")
|
|
||||||
)
|
|
||||||
|
|
||||||
func extractDataFromLines(lines []string) (
|
func extractDataFromLines(lines []string) (
|
||||||
connection models.Connection, err error) {
|
connection models.Connection, err error,
|
||||||
|
) {
|
||||||
for i, line := range lines {
|
for i, line := range lines {
|
||||||
hashSymbolIndex := strings.Index(line, "#")
|
hashSymbolIndex := strings.Index(line, "#")
|
||||||
if hashSymbolIndex >= 0 {
|
if hashSymbolIndex >= 0 {
|
||||||
@ -54,7 +53,8 @@ func extractDataFromLines(lines []string) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
func extractDataFromLine(line string) (
|
func extractDataFromLine(line string) (
|
||||||
ip netip.Addr, port uint16, protocol string, err error) {
|
ip netip.Addr, port uint16, protocol string, err error,
|
||||||
|
) {
|
||||||
switch {
|
switch {
|
||||||
case strings.HasPrefix(line, "proto "):
|
case strings.HasPrefix(line, "proto "):
|
||||||
protocol, err = extractProto(line)
|
protocol, err = extractProto(line)
|
||||||
@ -108,7 +108,8 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func extractRemote(line string) (ip netip.Addr, port uint16,
|
func extractRemote(line string) (ip netip.Addr, port uint16,
|
||||||
protocol string, err error) {
|
protocol string, err error,
|
||||||
|
) {
|
||||||
fields := strings.Fields(line)
|
fields := strings.Fields(line)
|
||||||
n := len(fields)
|
n := len(fields)
|
||||||
|
|
||||||
@ -146,9 +147,7 @@ func extractRemote(line string) (ip netip.Addr, port uint16,
|
|||||||
return ip, port, protocol, nil
|
return ip, port, protocol, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var errPostLineFieldsCount = errors.New("post line has not 2 fields as expected")
|
||||||
errPostLineFieldsCount = errors.New("post line has not 2 fields as expected")
|
|
||||||
)
|
|
||||||
|
|
||||||
func extractPort(line string) (port uint16, err error) {
|
func extractPort(line string) (port uint16, err error) {
|
||||||
fields := strings.Fields(line)
|
fields := strings.Fields(line)
|
||||||
|
|||||||
@ -7,9 +7,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var errPEMDecode = errors.New("cannot decode PEM encoded block")
|
||||||
errPEMDecode = errors.New("cannot decode PEM encoded block")
|
|
||||||
)
|
|
||||||
|
|
||||||
func PEM(b []byte) (encodedData string, err error) {
|
func PEM(b []byte) (encodedData string, err error) {
|
||||||
pemBlock, _ := pem.Decode(b)
|
pemBlock, _ := pem.Decode(b)
|
||||||
|
|||||||
@ -7,7 +7,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func readCustomConfigLines(filepath string) (
|
func readCustomConfigLines(filepath string) (
|
||||||
lines []string, err error) {
|
lines []string, err error,
|
||||||
|
) {
|
||||||
file, err := os.Open(filepath)
|
file, err := os.Open(filepath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@ -18,31 +18,38 @@ func Test_processLogLine(t *testing.T) {
|
|||||||
"openvpn unknown": {
|
"openvpn unknown": {
|
||||||
"message",
|
"message",
|
||||||
"message",
|
"message",
|
||||||
levelInfo},
|
levelInfo,
|
||||||
|
},
|
||||||
"openvpn note": {
|
"openvpn note": {
|
||||||
"NOTE: message",
|
"NOTE: message",
|
||||||
"message",
|
"message",
|
||||||
levelInfo},
|
levelInfo,
|
||||||
|
},
|
||||||
"openvpn warning": {
|
"openvpn warning": {
|
||||||
"WARNING: message",
|
"WARNING: message",
|
||||||
"message",
|
"message",
|
||||||
levelWarn},
|
levelWarn,
|
||||||
|
},
|
||||||
"openvpn options error": {
|
"openvpn options error": {
|
||||||
"Options error: message",
|
"Options error: message",
|
||||||
"message",
|
"message",
|
||||||
levelError},
|
levelError,
|
||||||
|
},
|
||||||
"openvpn ignored message": {
|
"openvpn ignored message": {
|
||||||
"NOTE: UID/GID downgrade will be delayed because of --client, --pull, or --up-delay",
|
"NOTE: UID/GID downgrade will be delayed because of --client, --pull, or --up-delay",
|
||||||
"",
|
"",
|
||||||
levelInfo},
|
levelInfo,
|
||||||
|
},
|
||||||
"openvpn success": {
|
"openvpn success": {
|
||||||
"Initialization Sequence Completed",
|
"Initialization Sequence Completed",
|
||||||
"Initialization Sequence Completed",
|
"Initialization Sequence Completed",
|
||||||
levelInfo},
|
levelInfo,
|
||||||
|
},
|
||||||
"openvpn auth failed": {
|
"openvpn auth failed": {
|
||||||
"AUTH: Received control message: AUTH_FAILED",
|
"AUTH: Received control message: AUTH_FAILED",
|
||||||
"AUTH: Received control message: AUTH_FAILED\n\nYour credentials might be wrong 🤨\n\n",
|
"AUTH: Received control message: AUTH_FAILED\n\nYour credentials might be wrong 🤨\n\n",
|
||||||
levelError},
|
levelError,
|
||||||
|
},
|
||||||
"TLS key negotiation error": {
|
"TLS key negotiation error": {
|
||||||
s: "TLS Error: TLS key negotiation failed to occur within " +
|
s: "TLS Error: TLS key negotiation failed to occur within " +
|
||||||
"60 seconds (check your network connectivity)",
|
"60 seconds (check your network connectivity)",
|
||||||
|
|||||||
@ -14,7 +14,8 @@ type Configurator struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func New(logger Infoer, cmder CmdRunStarter,
|
func New(logger Infoer, cmder CmdRunStarter,
|
||||||
puid, pgid int) *Configurator {
|
puid, pgid int,
|
||||||
|
) *Configurator {
|
||||||
return &Configurator{
|
return &Configurator{
|
||||||
logger: logger,
|
logger: logger,
|
||||||
cmder: cmder,
|
cmder: cmder,
|
||||||
|
|||||||
@ -7,15 +7,11 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
// Algorithm identifiers are listed at
|
||||||
// Algorithm identifiers are listed at
|
// https://www.ibm.com/docs/en/zos/2.3.0?topic=programming-object-identifiers
|
||||||
// https://www.ibm.com/docs/en/zos/2.3.0?topic=programming-object-identifiers
|
var oidDESCBC = asn1.ObjectIdentifier{1, 3, 14, 3, 2, 7} //nolint:gochecknoglobals
|
||||||
oidDESCBC = asn1.ObjectIdentifier{1, 3, 14, 3, 2, 7} //nolint:gochecknoglobals
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
var ErrEncryptionAlgorithmNotPBES2 = errors.New("encryption algorithm is not PBES2")
|
||||||
ErrEncryptionAlgorithmNotPBES2 = errors.New("encryption algorithm is not PBES2")
|
|
||||||
)
|
|
||||||
|
|
||||||
type encryptedPrivateKey struct {
|
type encryptedPrivateKey struct {
|
||||||
EncryptionAlgorithm pkix.AlgorithmIdentifier
|
EncryptionAlgorithm pkix.AlgorithmIdentifier
|
||||||
@ -28,7 +24,8 @@ type encryptedAlgorithmParams struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func getEncryptionAlgorithmOid(der []byte) (
|
func getEncryptionAlgorithmOid(der []byte) (
|
||||||
encryptionSchemeAlgorithm asn1.ObjectIdentifier, err error) {
|
encryptionSchemeAlgorithm asn1.ObjectIdentifier, err error,
|
||||||
|
) {
|
||||||
var encryptedPrivateKeyData encryptedPrivateKey
|
var encryptedPrivateKeyData encryptedPrivateKey
|
||||||
_, err = asn1.Unmarshal(der, &encryptedPrivateKeyData)
|
_, err = asn1.Unmarshal(der, &encryptedPrivateKeyData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@ -8,9 +8,7 @@ import (
|
|||||||
pkcs8lib "github.com/youmark/pkcs8"
|
pkcs8lib "github.com/youmark/pkcs8"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var ErrUnsupportedKeyType = errors.New("unsupported key type")
|
||||||
ErrUnsupportedKeyType = errors.New("unsupported key type")
|
|
||||||
)
|
|
||||||
|
|
||||||
// UpgradeEncryptedKey eventually upgrades an encrypted key to a newer encryption
|
// UpgradeEncryptedKey eventually upgrades an encrypted key to a newer encryption
|
||||||
// if its encryption is too weak for Openvpn/Openssl.
|
// if its encryption is too weak for Openvpn/Openssl.
|
||||||
|
|||||||
@ -13,7 +13,8 @@ type Runner struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewRunner(settings settings.OpenVPN, starter CmdStarter,
|
func NewRunner(settings settings.OpenVPN, starter CmdStarter,
|
||||||
logger Logger) *Runner {
|
logger Logger,
|
||||||
|
) *Runner {
|
||||||
return &Runner{
|
return &Runner{
|
||||||
starter: starter,
|
starter: starter,
|
||||||
logger: logger,
|
logger: logger,
|
||||||
|
|||||||
@ -18,7 +18,8 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func start(ctx context.Context, starter CmdStarter, version string, flags []string) (
|
func start(ctx context.Context, starter CmdStarter, version string, flags []string) (
|
||||||
stdoutLines, stderrLines <-chan string, waitError <-chan error, err error) {
|
stdoutLines, stderrLines <-chan string, waitError <-chan error, err error,
|
||||||
|
) {
|
||||||
var bin string
|
var bin string
|
||||||
switch version {
|
switch version {
|
||||||
case openvpn.Openvpn25:
|
case openvpn.Openvpn25:
|
||||||
|
|||||||
@ -7,7 +7,8 @@ import (
|
|||||||
|
|
||||||
func streamLines(ctx context.Context, done chan<- struct{},
|
func streamLines(ctx context.Context, done chan<- struct{},
|
||||||
logger Logger, stdout, stderr <-chan string,
|
logger Logger, stdout, stderr <-chan string,
|
||||||
tunnelReady chan<- struct{}) {
|
tunnelReady chan<- struct{},
|
||||||
|
) {
|
||||||
defer close(done)
|
defer close(done)
|
||||||
|
|
||||||
var line string
|
var line string
|
||||||
|
|||||||
@ -34,7 +34,8 @@ type Loop struct {
|
|||||||
|
|
||||||
func NewLoop(settings settings.PortForwarding, routing Routing,
|
func NewLoop(settings settings.PortForwarding, routing Routing,
|
||||||
client *http.Client, portAllower PortAllower,
|
client *http.Client, portAllower PortAllower,
|
||||||
logger Logger, uid, gid int) *Loop {
|
logger Logger, uid, gid int,
|
||||||
|
) *Loop {
|
||||||
return &Loop{
|
return &Loop{
|
||||||
settings: Settings{
|
settings: Settings{
|
||||||
VPNIsUp: ptrTo(false),
|
VPNIsUp: ptrTo(false),
|
||||||
@ -75,7 +76,8 @@ func (l *Loop) Start(_ context.Context) (runError <-chan error, _ error) {
|
|||||||
|
|
||||||
func (l *Loop) run(runCtx context.Context, runDone chan<- struct{},
|
func (l *Loop) run(runCtx context.Context, runDone chan<- struct{},
|
||||||
runErrorCh chan<- error, updateTrigger <-chan Settings,
|
runErrorCh chan<- error, updateTrigger <-chan Settings,
|
||||||
updateResult chan<- error) {
|
updateResult chan<- error,
|
||||||
|
) {
|
||||||
defer close(runDone)
|
defer close(runDone)
|
||||||
|
|
||||||
var serviceRunError <-chan error
|
var serviceRunError <-chan error
|
||||||
|
|||||||
@ -15,7 +15,7 @@ func (s *Service) writePortForwardedFile(ports []uint16) (err error) {
|
|||||||
|
|
||||||
filepath := s.settings.Filepath
|
filepath := s.settings.Filepath
|
||||||
s.logger.Info("writing port file " + filepath)
|
s.logger.Info("writing port file " + filepath)
|
||||||
const perms = os.FileMode(0644)
|
const perms = os.FileMode(0o644)
|
||||||
err = os.WriteFile(filepath, fileData, perms)
|
err = os.WriteFile(filepath, fileData, perms)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("writing file: %w", err)
|
return fmt.Errorf("writing file: %w", err)
|
||||||
|
|||||||
@ -26,7 +26,8 @@ type Service struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func New(settings Settings, routing Routing, client *http.Client,
|
func New(settings Settings, routing Routing, client *http.Client,
|
||||||
portAllower PortAllower, logger Logger, puid, pgid int) *Service {
|
portAllower PortAllower, logger Logger, puid, pgid int,
|
||||||
|
) *Service {
|
||||||
return &Service{
|
return &Service{
|
||||||
// Fixed parameters
|
// Fixed parameters
|
||||||
settings: settings,
|
settings: settings,
|
||||||
|
|||||||
@ -82,7 +82,8 @@ func (s *Service) Start(ctx context.Context) (runError <-chan error, err error)
|
|||||||
readyCh := make(chan struct{})
|
readyCh := make(chan struct{})
|
||||||
go func(ctx context.Context, portForwarder PortForwarder,
|
go func(ctx context.Context, portForwarder PortForwarder,
|
||||||
obj utils.PortForwardObjects, readyCh chan<- struct{},
|
obj utils.PortForwardObjects, readyCh chan<- struct{},
|
||||||
runError chan<- error, doneCh chan<- struct{}) {
|
runError chan<- error, doneCh chan<- struct{},
|
||||||
|
) {
|
||||||
defer close(doneCh)
|
defer close(doneCh)
|
||||||
close(readyCh)
|
close(readyCh)
|
||||||
err = portForwarder.KeepPortForward(ctx, obj)
|
err = portForwarder.KeepPortForward(ctx, obj)
|
||||||
|
|||||||
@ -18,7 +18,8 @@ type Settings struct {
|
|||||||
// and returns them if they are valid, or returns an error otherwise.
|
// and returns them if they are valid, or returns an error otherwise.
|
||||||
// In all cases, the receiving settings are unmodified.
|
// In all cases, the receiving settings are unmodified.
|
||||||
func (s Settings) updateWith(partialUpdate Settings,
|
func (s Settings) updateWith(partialUpdate Settings,
|
||||||
forStartup bool) (updated Settings, err error) {
|
forStartup bool,
|
||||||
|
) (updated Settings, err error) {
|
||||||
updated = s.copy()
|
updated = s.copy()
|
||||||
updated.overrideWith(partialUpdate)
|
updated.overrideWith(partialUpdate)
|
||||||
err = updated.validate(forStartup)
|
err = updated.validate(forStartup)
|
||||||
|
|||||||
@ -7,7 +7,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (p *Provider) GetConnection(selection settings.ServerSelection, ipv6Supported bool) (
|
func (p *Provider) GetConnection(selection settings.ServerSelection, ipv6Supported bool) (
|
||||||
connection models.Connection, err error) {
|
connection models.Connection, err error,
|
||||||
|
) {
|
||||||
defaults := utils.NewConnectionDefaults(443, 1194, 1637) //nolint:mnd
|
defaults := utils.NewConnectionDefaults(443, 1194, 1637) //nolint:mnd
|
||||||
return utils.GetConnection(p.Name(),
|
return utils.GetConnection(p.Name(),
|
||||||
p.storage, selection, defaults, ipv6Supported, p.randSource)
|
p.storage, selection, defaults, ipv6Supported, p.randSource)
|
||||||
|
|||||||
@ -10,7 +10,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (p *Provider) OpenVPNConfig(connection models.Connection,
|
func (p *Provider) OpenVPNConfig(connection models.Connection,
|
||||||
settings settings.OpenVPN, ipv6Supported bool) (lines []string) {
|
settings settings.OpenVPN, ipv6Supported bool,
|
||||||
|
) (lines []string) {
|
||||||
const defaultMTU = 1320 // see https://github.com/qdm12/gluetun/issues/1650#issuecomment-1988298206
|
const defaultMTU = 1320 // see https://github.com/qdm12/gluetun/issues/1650#issuecomment-1988298206
|
||||||
const defaultMSSFix = defaultMTU - 28 // 28 bytes of IPv4 UDP header size
|
const defaultMSSFix = defaultMTU - 28 // 28 bytes of IPv4 UDP header size
|
||||||
providerSettings := utils.OpenVPNProviderSettings{
|
providerSettings := utils.OpenVPNProviderSettings{
|
||||||
@ -31,7 +32,8 @@ func (p *Provider) OpenVPNConfig(connection models.Connection,
|
|||||||
providerSettings.Ciphers = []string{
|
providerSettings.Ciphers = []string{
|
||||||
openvpn.AES256gcm, openvpn.AES256cbc, openvpn.AES192gcm,
|
openvpn.AES256gcm, openvpn.AES256cbc, openvpn.AES192gcm,
|
||||||
openvpn.AES192cbc, openvpn.AES128gcm, openvpn.AES128cbc,
|
openvpn.AES192cbc, openvpn.AES128gcm, openvpn.AES128cbc,
|
||||||
openvpn.Chacha20Poly1305}
|
openvpn.Chacha20Poly1305,
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("openvpn version %q is not implemented", settings.Version))
|
panic(fmt.Sprintf("openvpn version %q is not implemented", settings.Version))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,7 +16,8 @@ type Provider struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func New(storage common.Storage, randSource rand.Source,
|
func New(storage common.Storage, randSource rand.Source,
|
||||||
client *http.Client) *Provider {
|
client *http.Client,
|
||||||
|
) *Provider {
|
||||||
return &Provider{
|
return &Provider{
|
||||||
storage: storage,
|
storage: storage,
|
||||||
randSource: randSource,
|
randSource: randSource,
|
||||||
|
|||||||
@ -32,7 +32,8 @@ type apiServer struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func fetchAPI(ctx context.Context, client *http.Client) (
|
func fetchAPI(ctx context.Context, client *http.Client) (
|
||||||
data apiData, err error) {
|
data apiData, err error,
|
||||||
|
) {
|
||||||
const url = "https://airvpn.org/api/status/"
|
const url = "https://airvpn.org/api/status/"
|
||||||
|
|
||||||
request, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
request, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
||||||
|
|||||||
@ -13,7 +13,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (u *Updater) FetchServers(ctx context.Context, minServers int) (
|
func (u *Updater) FetchServers(ctx context.Context, minServers int) (
|
||||||
servers []models.Server, err error) {
|
servers []models.Server, err error,
|
||||||
|
) {
|
||||||
data, err := fetchAPI(ctx, u.client)
|
data, err := fetchAPI(ctx, u.client)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("fetching API: %w", err)
|
return nil, fmt.Errorf("fetching API: %w", err)
|
||||||
|
|||||||
@ -2,6 +2,4 @@ package common
|
|||||||
|
|
||||||
import "errors"
|
import "errors"
|
||||||
|
|
||||||
var (
|
var ErrPortForwardNotSupported = errors.New("port forwarding not supported")
|
||||||
ErrPortForwardNotSupported = errors.New("port forwarding not supported")
|
|
||||||
)
|
|
||||||
|
|||||||
@ -10,13 +10,12 @@ import (
|
|||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var ErrVPNTypeNotSupported = errors.New("VPN type not supported for custom provider")
|
||||||
ErrVPNTypeNotSupported = errors.New("VPN type not supported for custom provider")
|
|
||||||
)
|
|
||||||
|
|
||||||
// GetConnection gets the connection from the OpenVPN configuration file.
|
// GetConnection gets the connection from the OpenVPN configuration file.
|
||||||
func (p *Provider) GetConnection(selection settings.ServerSelection, _ bool) (
|
func (p *Provider) GetConnection(selection settings.ServerSelection, _ bool) (
|
||||||
connection models.Connection, err error) {
|
connection models.Connection, err error,
|
||||||
|
) {
|
||||||
switch selection.VPN {
|
switch selection.VPN {
|
||||||
case vpn.OpenVPN:
|
case vpn.OpenVPN:
|
||||||
return getOpenVPNConnection(p.extractor, selection)
|
return getOpenVPNConnection(p.extractor, selection)
|
||||||
@ -29,7 +28,8 @@ func (p *Provider) GetConnection(selection settings.ServerSelection, _ bool) (
|
|||||||
|
|
||||||
func getOpenVPNConnection(extractor Extractor,
|
func getOpenVPNConnection(extractor Extractor,
|
||||||
selection settings.ServerSelection) (
|
selection settings.ServerSelection) (
|
||||||
connection models.Connection, err error) {
|
connection models.Connection, err error,
|
||||||
|
) {
|
||||||
_, connection, err = extractor.Data(*selection.OpenVPN.ConfFile)
|
_, connection, err = extractor.Data(*selection.OpenVPN.ConfFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return connection, fmt.Errorf("extracting connection: %w", err)
|
return connection, fmt.Errorf("extracting connection: %w", err)
|
||||||
@ -52,7 +52,8 @@ func getOpenVPNConnection(extractor Extractor,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func getWireguardConnection(selection settings.ServerSelection) (
|
func getWireguardConnection(selection settings.ServerSelection) (
|
||||||
connection models.Connection) {
|
connection models.Connection,
|
||||||
|
) {
|
||||||
connection = models.Connection{
|
connection = models.Connection{
|
||||||
Type: vpn.Wireguard,
|
Type: vpn.Wireguard,
|
||||||
IP: selection.Wireguard.EndpointIP,
|
IP: selection.Wireguard.EndpointIP,
|
||||||
|
|||||||
@ -15,7 +15,8 @@ import (
|
|||||||
var ErrExtractData = errors.New("failed extracting information from custom configuration file")
|
var ErrExtractData = errors.New("failed extracting information from custom configuration file")
|
||||||
|
|
||||||
func (p *Provider) OpenVPNConfig(connection models.Connection,
|
func (p *Provider) OpenVPNConfig(connection models.Connection,
|
||||||
settings settings.OpenVPN, ipv6Supported bool) (lines []string) {
|
settings settings.OpenVPN, ipv6Supported bool,
|
||||||
|
) (lines []string) {
|
||||||
lines, _, err := p.extractor.Data(*settings.ConfFile)
|
lines, _, err := p.extractor.Data(*settings.ConfFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Configuration file is already validated in settings validation in
|
// Configuration file is already validated in settings validation in
|
||||||
@ -30,7 +31,8 @@ func (p *Provider) OpenVPNConfig(connection models.Connection,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func modifyConfig(lines []string, connection models.Connection,
|
func modifyConfig(lines []string, connection models.Connection,
|
||||||
settings settings.OpenVPN, ipv6Supported bool) (modified []string) {
|
settings settings.OpenVPN, ipv6Supported bool,
|
||||||
|
) (modified []string) {
|
||||||
// Remove some lines
|
// Remove some lines
|
||||||
for _, line := range lines {
|
for _, line := range lines {
|
||||||
switch {
|
switch {
|
||||||
|
|||||||
@ -7,7 +7,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (p *Provider) GetConnection(selection settings.ServerSelection, ipv6Supported bool) (
|
func (p *Provider) GetConnection(selection settings.ServerSelection, ipv6Supported bool) (
|
||||||
connection models.Connection, err error) {
|
connection models.Connection, err error,
|
||||||
|
) {
|
||||||
defaults := utils.NewConnectionDefaults(443, 443, 0) //nolint:mnd
|
defaults := utils.NewConnectionDefaults(443, 443, 0) //nolint:mnd
|
||||||
return utils.GetConnection(p.Name(),
|
return utils.GetConnection(p.Name(),
|
||||||
p.storage, selection, defaults, ipv6Supported, p.randSource)
|
p.storage, selection, defaults, ipv6Supported, p.randSource)
|
||||||
|
|||||||
@ -8,7 +8,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (p *Provider) OpenVPNConfig(connection models.Connection,
|
func (p *Provider) OpenVPNConfig(connection models.Connection,
|
||||||
settings settings.OpenVPN, ipv6Supported bool) (lines []string) {
|
settings settings.OpenVPN, ipv6Supported bool,
|
||||||
|
) (lines []string) {
|
||||||
//nolint:mnd
|
//nolint:mnd
|
||||||
providerSettings := utils.OpenVPNProviderSettings{
|
providerSettings := utils.OpenVPNProviderSettings{
|
||||||
RemoteCertTLS: true,
|
RemoteCertTLS: true,
|
||||||
|
|||||||
@ -15,7 +15,8 @@ type Provider struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func New(storage common.Storage, randSource rand.Source,
|
func New(storage common.Storage, randSource rand.Source,
|
||||||
parallelResolver common.ParallelResolver) *Provider {
|
parallelResolver common.ParallelResolver,
|
||||||
|
) *Provider {
|
||||||
return &Provider{
|
return &Provider{
|
||||||
storage: storage,
|
storage: storage,
|
||||||
randSource: randSource,
|
randSource: randSource,
|
||||||
|
|||||||
@ -10,7 +10,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (u *Updater) FetchServers(ctx context.Context, minServers int) (
|
func (u *Updater) FetchServers(ctx context.Context, minServers int) (
|
||||||
servers []models.Server, err error) {
|
servers []models.Server, err error,
|
||||||
|
) {
|
||||||
possibleServers := getPossibleServers()
|
possibleServers := getPossibleServers()
|
||||||
|
|
||||||
possibleHosts := possibleServers.hostsSlice()
|
possibleHosts := possibleServers.hostsSlice()
|
||||||
|
|||||||
@ -7,7 +7,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (p *Provider) GetConnection(selection settings.ServerSelection, ipv6Supported bool) (
|
func (p *Provider) GetConnection(selection settings.ServerSelection, ipv6Supported bool) (
|
||||||
connection models.Connection, err error) {
|
connection models.Connection, err error,
|
||||||
|
) {
|
||||||
// TODO: Set the default ports for each VPN protocol+network protocol
|
// TODO: Set the default ports for each VPN protocol+network protocol
|
||||||
// combination. If one combination is not supported, set it to `0`.
|
// combination. If one combination is not supported, set it to `0`.
|
||||||
defaults := utils.NewConnectionDefaults(443, 1194, 51820) //nolint:mnd
|
defaults := utils.NewConnectionDefaults(443, 1194, 51820) //nolint:mnd
|
||||||
|
|||||||
@ -8,7 +8,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (p *Provider) OpenVPNConfig(connection models.Connection,
|
func (p *Provider) OpenVPNConfig(connection models.Connection,
|
||||||
settings settings.OpenVPN, ipv6Supported bool) (lines []string) {
|
settings settings.OpenVPN, ipv6Supported bool,
|
||||||
|
) (lines []string) {
|
||||||
// TODO: Set the necessary fields in `providerSettings` to
|
// TODO: Set the necessary fields in `providerSettings` to
|
||||||
// generate the right OpenVPN configuration file.
|
// generate the right OpenVPN configuration file.
|
||||||
//nolint:mnd
|
//nolint:mnd
|
||||||
|
|||||||
@ -18,7 +18,8 @@ type Provider struct {
|
|||||||
// TODO: remove unneeded arguments once the updater is implemented.
|
// TODO: remove unneeded arguments once the updater is implemented.
|
||||||
func New(storage common.Storage, randSource rand.Source,
|
func New(storage common.Storage, randSource rand.Source,
|
||||||
updaterWarner common.Warner, client *http.Client,
|
updaterWarner common.Warner, client *http.Client,
|
||||||
unzipper common.Unzipper, parallelResolver common.ParallelResolver) *Provider {
|
unzipper common.Unzipper, parallelResolver common.ParallelResolver,
|
||||||
|
) *Provider {
|
||||||
return &Provider{
|
return &Provider{
|
||||||
storage: storage,
|
storage: storage,
|
||||||
randSource: randSource,
|
randSource: randSource,
|
||||||
|
|||||||
@ -8,9 +8,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var errHTTPStatusCodeNotOK = errors.New("HTTP status code not OK")
|
||||||
errHTTPStatusCodeNotOK = errors.New("HTTP status code not OK")
|
|
||||||
)
|
|
||||||
|
|
||||||
type apiData struct {
|
type apiData struct {
|
||||||
Servers []apiServer `json:"servers"`
|
Servers []apiServer `json:"servers"`
|
||||||
@ -26,7 +24,8 @@ type apiServer struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func fetchAPI(ctx context.Context, client *http.Client) (
|
func fetchAPI(ctx context.Context, client *http.Client) (
|
||||||
data apiData, err error) {
|
data apiData, err error,
|
||||||
|
) {
|
||||||
// TODO: adapt this URL and the structures above to match the real
|
// TODO: adapt this URL and the structures above to match the real
|
||||||
// API models you have.
|
// API models you have.
|
||||||
const url = "https://example.com/servers"
|
const url = "https://example.com/servers"
|
||||||
|
|||||||
@ -11,7 +11,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (u *Updater) FetchServers(ctx context.Context, minServers int) (
|
func (u *Updater) FetchServers(ctx context.Context, minServers int) (
|
||||||
servers []models.Server, err error) {
|
servers []models.Server, err error,
|
||||||
|
) {
|
||||||
// FetchServers obtains information for each VPN server
|
// FetchServers obtains information for each VPN server
|
||||||
// for the VPN service provider.
|
// for the VPN service provider.
|
||||||
//
|
//
|
||||||
|
|||||||
@ -15,7 +15,8 @@ type Updater struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func New(warner common.Warner, unzipper common.Unzipper,
|
func New(warner common.Warner, unzipper common.Unzipper,
|
||||||
client *http.Client, parallelResolver common.ParallelResolver) *Updater {
|
client *http.Client, parallelResolver common.ParallelResolver,
|
||||||
|
) *Updater {
|
||||||
// TODO: remove arguments not used by the updater
|
// TODO: remove arguments not used by the updater
|
||||||
return &Updater{
|
return &Updater{
|
||||||
client: client,
|
client: client,
|
||||||
|
|||||||
@ -7,7 +7,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (p *Provider) GetConnection(selection settings.ServerSelection, ipv6Supported bool) (
|
func (p *Provider) GetConnection(selection settings.ServerSelection, ipv6Supported bool) (
|
||||||
connection models.Connection, err error) {
|
connection models.Connection, err error,
|
||||||
|
) {
|
||||||
defaults := utils.NewConnectionDefaults(0, 1195, 0) //nolint:mnd
|
defaults := utils.NewConnectionDefaults(0, 1195, 0) //nolint:mnd
|
||||||
return utils.GetConnection(p.Name(),
|
return utils.GetConnection(p.Name(),
|
||||||
p.storage, selection, defaults, ipv6Supported, p.randSource)
|
p.storage, selection, defaults, ipv6Supported, p.randSource)
|
||||||
|
|||||||
@ -8,7 +8,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (p *Provider) OpenVPNConfig(connection models.Connection,
|
func (p *Provider) OpenVPNConfig(connection models.Connection,
|
||||||
settings settings.OpenVPN, ipv6Supported bool) (lines []string) {
|
settings settings.OpenVPN, ipv6Supported bool,
|
||||||
|
) (lines []string) {
|
||||||
//nolint:mnd
|
//nolint:mnd
|
||||||
providerSettings := utils.OpenVPNProviderSettings{
|
providerSettings := utils.OpenVPNProviderSettings{
|
||||||
RemoteCertTLS: true,
|
RemoteCertTLS: true,
|
||||||
|
|||||||
@ -16,7 +16,8 @@ type Provider struct {
|
|||||||
|
|
||||||
func New(storage common.Storage, randSource rand.Source,
|
func New(storage common.Storage, randSource rand.Source,
|
||||||
unzipper common.Unzipper, updaterWarner common.Warner,
|
unzipper common.Unzipper, updaterWarner common.Warner,
|
||||||
parallelResolver common.ParallelResolver) *Provider {
|
parallelResolver common.ParallelResolver,
|
||||||
|
) *Provider {
|
||||||
return &Provider{
|
return &Provider{
|
||||||
storage: storage,
|
storage: storage,
|
||||||
randSource: randSource,
|
randSource: randSource,
|
||||||
|
|||||||
@ -11,7 +11,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (u *Updater) FetchServers(ctx context.Context, minServers int) (
|
func (u *Updater) FetchServers(ctx context.Context, minServers int) (
|
||||||
servers []models.Server, err error) {
|
servers []models.Server, err error,
|
||||||
|
) {
|
||||||
servers = hardcodedServers()
|
servers = hardcodedServers()
|
||||||
|
|
||||||
hosts := make([]string, len(servers))
|
hosts := make([]string, len(servers))
|
||||||
|
|||||||
@ -11,7 +11,8 @@ type Updater struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func New(unzipper common.Unzipper, warner common.Warner,
|
func New(unzipper common.Unzipper, warner common.Warner,
|
||||||
parallelResolver common.ParallelResolver) *Updater {
|
parallelResolver common.ParallelResolver,
|
||||||
|
) *Updater {
|
||||||
return &Updater{
|
return &Updater{
|
||||||
unzipper: unzipper,
|
unzipper: unzipper,
|
||||||
parallelResolver: parallelResolver,
|
parallelResolver: parallelResolver,
|
||||||
|
|||||||
@ -7,7 +7,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (p *Provider) GetConnection(selection settings.ServerSelection, ipv6Supported bool) (
|
func (p *Provider) GetConnection(selection settings.ServerSelection, ipv6Supported bool) (
|
||||||
connection models.Connection, err error) {
|
connection models.Connection, err error,
|
||||||
|
) {
|
||||||
defaults := utils.NewConnectionDefaults(4443, 4443, 51820) //nolint:mnd
|
defaults := utils.NewConnectionDefaults(4443, 4443, 51820) //nolint:mnd
|
||||||
return utils.GetConnection(p.Name(),
|
return utils.GetConnection(p.Name(),
|
||||||
p.storage, selection, defaults, ipv6Supported, p.randSource)
|
p.storage, selection, defaults, ipv6Supported, p.randSource)
|
||||||
|
|||||||
@ -8,7 +8,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (p *Provider) OpenVPNConfig(connection models.Connection,
|
func (p *Provider) OpenVPNConfig(connection models.Connection,
|
||||||
settings settings.OpenVPN, ipv6Supported bool) (lines []string) {
|
settings settings.OpenVPN, ipv6Supported bool,
|
||||||
|
) (lines []string) {
|
||||||
//nolint:mnd
|
//nolint:mnd
|
||||||
providerSettings := utils.OpenVPNProviderSettings{
|
providerSettings := utils.OpenVPNProviderSettings{
|
||||||
AuthUserPass: true,
|
AuthUserPass: true,
|
||||||
|
|||||||
@ -17,7 +17,8 @@ type Provider struct {
|
|||||||
|
|
||||||
func New(storage common.Storage, randSource rand.Source,
|
func New(storage common.Storage, randSource rand.Source,
|
||||||
client *http.Client, updaterWarner common.Warner,
|
client *http.Client, updaterWarner common.Warner,
|
||||||
parallelResolver common.ParallelResolver) *Provider {
|
parallelResolver common.ParallelResolver,
|
||||||
|
) *Provider {
|
||||||
return &Provider{
|
return &Provider{
|
||||||
storage: storage,
|
storage: storage,
|
||||||
randSource: randSource,
|
randSource: randSource,
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user