From fae6544431d2b478dbaf412b87fc27180258ffc3 Mon Sep 17 00:00:00 2001 From: Quentin McGaw Date: Fri, 30 Jun 2023 19:24:01 +0200 Subject: [PATCH] feat(pf): `VPN_PORT_FORWARDING_PROVIDER` variable (#1616) --- Dockerfile | 1 + .../configuration/settings/portforward.go | 26 ++++++++++++++++--- .../configuration/sources/env/portforward.go | 2 ++ internal/vpn/run.go | 8 +++++- 4 files changed, 33 insertions(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index 450f3899..7ed456b2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -110,6 +110,7 @@ ENV VPN_SERVICE_PROVIDER=pia \ # # Private Internet Access only: PRIVATE_INTERNET_ACCESS_OPENVPN_ENCRYPTION_PRESET= \ VPN_PORT_FORWARDING=off \ + VPN_PORT_FORWARDING_PROVIDER= \ VPN_PORT_FORWARDING_STATUS_FILE="/tmp/gluetun/forwarded_port" \ # # Cyberghost only: OPENVPN_CERT= \ diff --git a/internal/configuration/settings/portforward.go b/internal/configuration/settings/portforward.go index 6c81ca62..cc4c4fd6 100644 --- a/internal/configuration/settings/portforward.go +++ b/internal/configuration/settings/portforward.go @@ -15,6 +15,14 @@ type PortForwarding struct { // Enabled is true if port forwarding should be activated. // It cannot be nil for the internal state. Enabled *bool `json:"enabled"` + // Provider is set to specify which custom port forwarding code + // should be used. This is especially necessary for the custom + // provider using Wireguard for a provider where Wireguard is not + // natively supported but custom port forwading code is available. + // It defaults to the empty string, meaning the current provider + // should be the one used for port forwarding. + // It cannot be nil for the internal state. + Provider *string `json:"provider"` // Filepath is the port forwarding status file path // to use. It can be the empty string to indicate not // to write to a file. It cannot be nil for the @@ -27,9 +35,13 @@ func (p PortForwarding) validate(vpnProvider string) (err error) { return nil } - // Validate Enabled + // Validate current provider or custom provider specified + providerSelected := vpnProvider + if *p.Provider != "" { + providerSelected = *p.Provider + } validProviders := []string{providers.PrivateInternetAccess} - if err = validate.IsOneOf(vpnProvider, validProviders...); err != nil { + if err = validate.IsOneOf(providerSelected, validProviders...); err != nil { return fmt.Errorf("%w: %w", ErrPortForwardingEnabled, err) } @@ -47,22 +59,26 @@ func (p PortForwarding) validate(vpnProvider string) (err error) { func (p *PortForwarding) copy() (copied PortForwarding) { return PortForwarding{ Enabled: gosettings.CopyPointer(p.Enabled), + Provider: gosettings.CopyPointer(p.Provider), Filepath: gosettings.CopyPointer(p.Filepath), } } func (p *PortForwarding) mergeWith(other PortForwarding) { p.Enabled = gosettings.MergeWithPointer(p.Enabled, other.Enabled) + p.Provider = gosettings.MergeWithPointer(p.Provider, other.Provider) p.Filepath = gosettings.MergeWithPointer(p.Filepath, other.Filepath) } func (p *PortForwarding) overrideWith(other PortForwarding) { p.Enabled = gosettings.OverrideWithPointer(p.Enabled, other.Enabled) + p.Provider = gosettings.OverrideWithPointer(p.Provider, other.Provider) p.Filepath = gosettings.OverrideWithPointer(p.Filepath, other.Filepath) } func (p *PortForwarding) setDefaults() { p.Enabled = gosettings.DefaultPointer(p.Enabled, false) + p.Provider = gosettings.DefaultPointer(p.Provider, "") p.Filepath = gosettings.DefaultPointer(p.Filepath, "/tmp/gluetun/forwarded_port") } @@ -76,7 +92,11 @@ func (p PortForwarding) toLinesNode() (node *gotree.Node) { } node = gotree.New("Automatic port forwarding settings:") - node.Appendf("Enabled: yes") + if *p.Provider == "" { + node.Appendf("Use port forwarding code for current provider") + } else { + node.Appendf("Use code for provider: %s", *p.Provider) + } filepath := *p.Filepath if filepath == "" { diff --git a/internal/configuration/sources/env/portforward.go b/internal/configuration/sources/env/portforward.go index e2f6acb6..521581f3 100644 --- a/internal/configuration/sources/env/portforward.go +++ b/internal/configuration/sources/env/portforward.go @@ -16,6 +16,8 @@ func (s *Source) readPortForward() ( return portForwarding, err } + portForwarding.Provider = s.env.Get("VPN_PORT_FORWARDING_PROVIDER") + portForwarding.Filepath = s.env.Get("VPN_PORT_FORWARDING_STATUS_FILE", env.ForceLowercase(false), env.RetroKeys( diff --git a/internal/vpn/run.go b/internal/vpn/run.go index ee9ee901..082cf9ba 100644 --- a/internal/vpn/run.go +++ b/internal/vpn/run.go @@ -23,6 +23,12 @@ func (l *Loop) Run(ctx context.Context, done chan<- struct{}) { providerConf := l.providers.Get(*settings.Provider.Name) portForwarding := *settings.Provider.PortForwarding.Enabled + customPortForwardingProvider := *settings.Provider.PortForwarding.Provider + portForwader := providerConf + if portForwarding && customPortForwardingProvider != "" { + portForwader = l.providers.Get(customPortForwardingProvider) + } + var vpnRunner interface { Run(ctx context.Context, waitError chan<- error, tunnelReady chan<- struct{}) } @@ -45,7 +51,7 @@ func (l *Loop) Run(ctx context.Context, done chan<- struct{}) { tunnelUpData := tunnelUpData{ portForwarding: portForwarding, serverName: serverName, - portForwarder: providerConf, + portForwarder: portForwader, vpnIntf: vpnInterface, }