From c5c37e7f969ee88aad8287d6679bc5f26b0ec461 Mon Sep 17 00:00:00 2001 From: Quentin McGaw Date: Wed, 31 Jul 2024 14:43:59 +0000 Subject: [PATCH] hotfix(protonvpn): port forward only option - Allow to use with Protonvpn (not just PIA) - Update code comments - Check server supports port forwarding when invoking port forward code --- internal/configuration/settings/serverselection.go | 11 +++++------ internal/provider/protonvpn/portforward.go | 8 ++++++++ internal/vpn/tunnelup.go | 2 +- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/internal/configuration/settings/serverselection.go b/internal/configuration/settings/serverselection.go index f3962141..7716dda0 100644 --- a/internal/configuration/settings/serverselection.go +++ b/internal/configuration/settings/serverselection.go @@ -61,7 +61,8 @@ type ServerSelection struct { //nolint:maligned // should be filtered. This is used with Surfshark. MultiHopOnly *bool `json:"multi_hop_only"` // PortForwardOnly is true if VPN servers that don't support - // port forwarding should be filtered. This is used with PIA. + // port forwarding should be filtered. This is used with PIA + // and ProtonVPN. PortForwardOnly *bool `json:"port_forward_only"` // SecureCoreOnly is true if VPN servers without secure core should // be filtered. This is used with ProtonVPN. @@ -233,10 +234,8 @@ func validateFeatureFilters(settings ServerSelection, vpnServiceProvider string) return fmt.Errorf("%w", ErrStreamOnlyNotSupported) case *settings.MultiHopOnly && vpnServiceProvider != providers.Surfshark: return fmt.Errorf("%w", ErrMultiHopOnlyNotSupported) - case *settings.PortForwardOnly && vpnServiceProvider != providers.PrivateInternetAccess: - // ProtonVPN also supports port forwarding, but on all their servers, so these - // don't have the port forwarding boolean field. As a consequence, we only allow - // the use of PortForwardOnly for Private Internet Access. + case *settings.PortForwardOnly && + !helpers.IsOneOf(vpnServiceProvider, providers.PrivateInternetAccess, providers.Protonvpn): return fmt.Errorf("%w", ErrPortForwardOnlyNotSupported) case *settings.SecureCoreOnly && vpnServiceProvider != providers.Protonvpn: return fmt.Errorf("%w", ErrSecureCoreOnlyNotSupported) @@ -469,7 +468,7 @@ func (ss *ServerSelection) read(r *reader.Reader, return err } - // PIA only + // PIA and ProtonVPN only ss.PortForwardOnly, err = r.BoolPtr("PORT_FORWARD_ONLY") if err != nil { return err diff --git a/internal/provider/protonvpn/portforward.go b/internal/provider/protonvpn/portforward.go index 54d3fca7..0635f0bf 100644 --- a/internal/provider/protonvpn/portforward.go +++ b/internal/provider/protonvpn/portforward.go @@ -11,9 +11,17 @@ import ( "github.com/qdm12/gluetun/internal/provider/utils" ) +var ( + ErrServerPortForwardNotSupported = errors.New("server does not support port forwarding") +) + // PortForward obtains a VPN server side port forwarded from ProtonVPN gateway. func (p *Provider) PortForward(ctx context.Context, objects utils.PortForwardObjects) ( ports []uint16, err error) { + if !objects.CanPortForward { + return nil, fmt.Errorf("%w", ErrServerPortForwardNotSupported) + } + client := natpmp.New() _, externalIPv4Address, err := client.ExternalAddress(ctx, objects.Gateway) diff --git a/internal/vpn/tunnelup.go b/internal/vpn/tunnelup.go index 6e723041..80a4a219 100644 --- a/internal/vpn/tunnelup.go +++ b/internal/vpn/tunnelup.go @@ -11,7 +11,7 @@ type tunnelUpData struct { // Port forwarding vpnIntf string serverName string // used for PIA - canPortForward bool // used for PIA + canPortForward bool // used for PIA and ProtonVPN username string // used for PIA password string // used for PIA portForwarder PortForwarder