feat(pia): PORT_FORWARD_ONLY variable (#2070)

This commit is contained in:
Anton Nesterov
2024-03-18 17:40:09 +00:00
committed by GitHub
parent 84d00b42f1
commit b51aa0c6b9
6 changed files with 51 additions and 7 deletions

View File

@@ -134,6 +134,8 @@ ENV VPN_SERVICE_PROVIDER=pia \
MULTIHOP_ONLY= \ MULTIHOP_ONLY= \
# # VPN Secure only: # # VPN Secure only:
PREMIUM_ONLY= \ PREMIUM_ONLY= \
# # PIA only:
PORT_FORWARD_ONLY= \
# Firewall # Firewall
FIREWALL=on \ FIREWALL=on \
FIREWALL_VPN_INPUT_PORTS= \ FIREWALL_VPN_INPUT_PORTS= \

View File

@@ -57,7 +57,9 @@ type ServerSelection struct { //nolint:maligned
// MultiHopOnly is true if VPN servers that are not multihop // MultiHopOnly is true if VPN servers that are not multihop
// should be filtered. This is used with Surfshark. // should be filtered. This is used with Surfshark.
MultiHopOnly *bool `json:"multi_hop_only"` 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.
PortForwardOnly *bool `json:"port_forward_only"`
// OpenVPN contains settings to select OpenVPN servers // OpenVPN contains settings to select OpenVPN servers
// and the final connection. // and the final connection.
OpenVPN OpenVPNSelection `json:"openvpn"` OpenVPN OpenVPNSelection `json:"openvpn"`
@@ -72,6 +74,7 @@ var (
ErrPremiumOnlyNotSupported = errors.New("premium only filter is not supported") ErrPremiumOnlyNotSupported = errors.New("premium only filter is not supported")
ErrStreamOnlyNotSupported = errors.New("stream only filter is not supported") ErrStreamOnlyNotSupported = errors.New("stream only filter is not supported")
ErrMultiHopOnlyNotSupported = errors.New("multi hop only filter is not supported") ErrMultiHopOnlyNotSupported = errors.New("multi hop only filter is not supported")
ErrPortForwardOnlyNotSupported = errors.New("port forwarding only filter is not supported")
ErrFreePremiumBothSet = errors.New("free only and premium only filters are both set") ErrFreePremiumBothSet = errors.New("free only and premium only filters are both set")
) )
@@ -143,6 +146,15 @@ func (ss *ServerSelection) validate(vpnServiceProvider string,
ErrMultiHopOnlyNotSupported, vpnServiceProvider) ErrMultiHopOnlyNotSupported, vpnServiceProvider)
} }
if *ss.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.
return fmt.Errorf("%w: for VPN service provider %s",
ErrPortForwardOnlyNotSupported, vpnServiceProvider)
}
if ss.VPN == vpn.OpenVPN { if ss.VPN == vpn.OpenVPN {
err = ss.OpenVPN.validate(vpnServiceProvider) err = ss.OpenVPN.validate(vpnServiceProvider)
if err != nil { if err != nil {
@@ -251,6 +263,7 @@ func (ss *ServerSelection) mergeWith(other ServerSelection) {
ss.PremiumOnly = gosettings.MergeWithPointer(ss.PremiumOnly, other.PremiumOnly) ss.PremiumOnly = gosettings.MergeWithPointer(ss.PremiumOnly, other.PremiumOnly)
ss.StreamOnly = gosettings.MergeWithPointer(ss.StreamOnly, other.StreamOnly) ss.StreamOnly = gosettings.MergeWithPointer(ss.StreamOnly, other.StreamOnly)
ss.MultiHopOnly = gosettings.MergeWithPointer(ss.MultiHopOnly, other.MultiHopOnly) ss.MultiHopOnly = gosettings.MergeWithPointer(ss.MultiHopOnly, other.MultiHopOnly)
ss.PortForwardOnly = gosettings.MergeWithPointer(ss.PortForwardOnly, other.PortForwardOnly)
ss.OpenVPN.mergeWith(other.OpenVPN) ss.OpenVPN.mergeWith(other.OpenVPN)
ss.Wireguard.mergeWith(other.Wireguard) ss.Wireguard.mergeWith(other.Wireguard)
@@ -271,6 +284,7 @@ func (ss *ServerSelection) overrideWith(other ServerSelection) {
ss.PremiumOnly = gosettings.OverrideWithPointer(ss.PremiumOnly, other.PremiumOnly) ss.PremiumOnly = gosettings.OverrideWithPointer(ss.PremiumOnly, other.PremiumOnly)
ss.StreamOnly = gosettings.OverrideWithPointer(ss.StreamOnly, other.StreamOnly) ss.StreamOnly = gosettings.OverrideWithPointer(ss.StreamOnly, other.StreamOnly)
ss.MultiHopOnly = gosettings.OverrideWithPointer(ss.MultiHopOnly, other.MultiHopOnly) ss.MultiHopOnly = gosettings.OverrideWithPointer(ss.MultiHopOnly, other.MultiHopOnly)
ss.PortForwardOnly = gosettings.OverrideWithPointer(ss.PortForwardOnly, other.PortForwardOnly)
ss.OpenVPN.overrideWith(other.OpenVPN) ss.OpenVPN.overrideWith(other.OpenVPN)
ss.Wireguard.overrideWith(other.Wireguard) ss.Wireguard.overrideWith(other.Wireguard)
} }
@@ -283,6 +297,7 @@ func (ss *ServerSelection) setDefaults(vpnProvider string) {
ss.PremiumOnly = gosettings.DefaultPointer(ss.PremiumOnly, false) ss.PremiumOnly = gosettings.DefaultPointer(ss.PremiumOnly, false)
ss.StreamOnly = gosettings.DefaultPointer(ss.StreamOnly, false) ss.StreamOnly = gosettings.DefaultPointer(ss.StreamOnly, false)
ss.MultiHopOnly = gosettings.DefaultPointer(ss.MultiHopOnly, false) ss.MultiHopOnly = gosettings.DefaultPointer(ss.MultiHopOnly, false)
ss.PortForwardOnly = gosettings.DefaultPointer(ss.PortForwardOnly, false)
ss.OpenVPN.setDefaults(vpnProvider) ss.OpenVPN.setDefaults(vpnProvider)
ss.Wireguard.setDefaults() ss.Wireguard.setDefaults()
} }

View File

@@ -67,6 +67,12 @@ func (s *Source) readServerSelection(vpnProvider, vpnType string) (
return ss, err return ss, err
} }
// PIA only
ss.PortForwardOnly, err = s.env.BoolPtr("PORT_FORWARD_ONLY")
if err != nil {
return ss, err
}
ss.OpenVPN, err = s.readOpenVPNSelection() ss.OpenVPN, err = s.readOpenVPNSelection()
if err != nil { if err != nil {
return ss, err return ss, err

View File

@@ -53,6 +53,10 @@ func filterServer(server models.Server,
return true return true
} }
if *selection.PortForwardOnly && !server.PortForward {
return true
}
if filterByPossibilities(server.Country, selection.Countries) { if filterByPossibilities(server.Country, selection.Countries) {
return true return true
} }

View File

@@ -127,6 +127,19 @@ func Test_FilterServers(t *testing.T) {
{Owned: true, VPN: vpn.OpenVPN, UDP: true}, {Owned: true, VPN: vpn.OpenVPN, UDP: true},
}, },
}, },
"filter by port forwarding only": {
selection: settings.ServerSelection{
PortForwardOnly: boolPtr(true),
}.WithDefaults(providers.PrivateInternetAccess),
servers: []models.Server{
{PortForward: false, VPN: vpn.OpenVPN, UDP: true},
{PortForward: true, VPN: vpn.OpenVPN, UDP: true},
{PortForward: false, VPN: vpn.OpenVPN, UDP: true},
},
filtered: []models.Server{
{PortForward: true, VPN: vpn.OpenVPN, UDP: true},
},
},
"filter by country": { "filter by country": {
selection: settings.ServerSelection{ selection: settings.ServerSelection{
Countries: []string{"b"}, Countries: []string{"b"},

View File

@@ -74,6 +74,10 @@ func filterServer(server models.Server,
return true return true
} }
if *selection.PortForwardOnly && !server.PortForward {
return true
}
if filterByPossibilities(server.Country, selection.Countries) { if filterByPossibilities(server.Country, selection.Countries) {
return true return true
} }