fix(wireguard): WIREGUARD_ENDPOINT_IP overrides the IP address of a picked connection
- Regression introduced in v3.39.0 - Fix #2759
This commit is contained in:
@@ -2,6 +2,7 @@ package settings
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/netip"
|
||||
"strings"
|
||||
|
||||
"github.com/qdm12/gluetun/internal/configuration/settings/helpers"
|
||||
@@ -24,6 +25,12 @@ type OpenVPNSelection struct {
|
||||
// and can be udp or tcp. It cannot be the empty string
|
||||
// in the internal state.
|
||||
Protocol string `json:"protocol"`
|
||||
// EndpointIP is the server endpoint IP address.
|
||||
// If set, it overrides any IP address from the picked
|
||||
// built-in server connection. To indicate it should
|
||||
// not be used, it should be set to [netip.IPv4Unspecified].
|
||||
// It can never be the zero value in the internal state.
|
||||
EndpointIP netip.Addr `json:"endpoint_ip"`
|
||||
// CustomPort is the OpenVPN server endpoint port.
|
||||
// It can be set to 0 to indicate no custom port should
|
||||
// be used. It cannot be nil in the internal state.
|
||||
@@ -142,6 +149,7 @@ func (o *OpenVPNSelection) copy() (copied OpenVPNSelection) {
|
||||
return OpenVPNSelection{
|
||||
ConfFile: gosettings.CopyPointer(o.ConfFile),
|
||||
Protocol: o.Protocol,
|
||||
EndpointIP: o.EndpointIP,
|
||||
CustomPort: gosettings.CopyPointer(o.CustomPort),
|
||||
PIAEncPreset: gosettings.CopyPointer(o.PIAEncPreset),
|
||||
}
|
||||
@@ -151,12 +159,14 @@ func (o *OpenVPNSelection) overrideWith(other OpenVPNSelection) {
|
||||
o.ConfFile = gosettings.OverrideWithPointer(o.ConfFile, other.ConfFile)
|
||||
o.Protocol = gosettings.OverrideWithComparable(o.Protocol, other.Protocol)
|
||||
o.CustomPort = gosettings.OverrideWithPointer(o.CustomPort, other.CustomPort)
|
||||
o.EndpointIP = gosettings.OverrideWithValidator(o.EndpointIP, other.EndpointIP)
|
||||
o.PIAEncPreset = gosettings.OverrideWithPointer(o.PIAEncPreset, other.PIAEncPreset)
|
||||
}
|
||||
|
||||
func (o *OpenVPNSelection) setDefaults(vpnProvider string) {
|
||||
o.ConfFile = gosettings.DefaultPointer(o.ConfFile, "")
|
||||
o.Protocol = gosettings.DefaultComparable(o.Protocol, constants.UDP)
|
||||
o.EndpointIP = gosettings.DefaultValidator(o.EndpointIP, netip.IPv4Unspecified())
|
||||
o.CustomPort = gosettings.DefaultPointer(o.CustomPort, 0)
|
||||
|
||||
var defaultEncPreset string
|
||||
@@ -174,6 +184,10 @@ func (o OpenVPNSelection) toLinesNode() (node *gotree.Node) {
|
||||
node = gotree.New("OpenVPN server selection settings:")
|
||||
node.Appendf("Protocol: %s", strings.ToUpper(o.Protocol))
|
||||
|
||||
if !o.EndpointIP.IsUnspecified() {
|
||||
node.Appendf("Endpoint IP address: %s", o.EndpointIP)
|
||||
}
|
||||
|
||||
if *o.CustomPort != 0 {
|
||||
node.Appendf("Custom port: %d", *o.CustomPort)
|
||||
}
|
||||
@@ -194,6 +208,12 @@ func (o *OpenVPNSelection) read(r *reader.Reader) (err error) {
|
||||
|
||||
o.Protocol = r.String("OPENVPN_PROTOCOL", reader.RetroKeys("PROTOCOL"))
|
||||
|
||||
o.EndpointIP, err = r.NetipAddr("OPENVPN_ENDPOINT_IP",
|
||||
reader.RetroKeys("OPENVPN_TARGET_IP", "VPN_ENDPOINT_IP"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
o.CustomPort, err = r.Uint16Ptr("OPENVPN_ENDPOINT_PORT",
|
||||
reader.RetroKeys("PORT", "OPENVPN_PORT", "VPN_ENDPOINT_PORT"))
|
||||
if err != nil {
|
||||
|
||||
@@ -3,7 +3,6 @@ package settings
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/netip"
|
||||
"strings"
|
||||
|
||||
"github.com/qdm12/gluetun/internal/configuration/settings/helpers"
|
||||
@@ -22,12 +21,6 @@ type ServerSelection struct {
|
||||
// or 'wireguard'. It cannot be the empty string
|
||||
// in the internal state.
|
||||
VPN string `json:"vpn"`
|
||||
// TargetIP is the server endpoint IP address to use.
|
||||
// It will override any IP address from the picked
|
||||
// built-in server. It cannot be the empty value in the internal
|
||||
// state, and can be set to the unspecified address to indicate
|
||||
// there is not target IP address to use.
|
||||
TargetIP netip.Addr `json:"target_ip"`
|
||||
// Countries is the list of countries to filter VPN servers with.
|
||||
Countries []string `json:"countries"`
|
||||
// Categories is the list of categories to filter VPN servers with.
|
||||
@@ -299,7 +292,6 @@ func validateFeatureFilters(settings ServerSelection, vpnServiceProvider string)
|
||||
func (ss *ServerSelection) copy() (copied ServerSelection) {
|
||||
return ServerSelection{
|
||||
VPN: ss.VPN,
|
||||
TargetIP: ss.TargetIP,
|
||||
Countries: gosettings.CopySlice(ss.Countries),
|
||||
Categories: gosettings.CopySlice(ss.Categories),
|
||||
Regions: gosettings.CopySlice(ss.Regions),
|
||||
@@ -323,7 +315,6 @@ func (ss *ServerSelection) copy() (copied ServerSelection) {
|
||||
|
||||
func (ss *ServerSelection) overrideWith(other ServerSelection) {
|
||||
ss.VPN = gosettings.OverrideWithComparable(ss.VPN, other.VPN)
|
||||
ss.TargetIP = gosettings.OverrideWithValidator(ss.TargetIP, other.TargetIP)
|
||||
ss.Countries = gosettings.OverrideWithSlice(ss.Countries, other.Countries)
|
||||
ss.Categories = gosettings.OverrideWithSlice(ss.Categories, other.Categories)
|
||||
ss.Regions = gosettings.OverrideWithSlice(ss.Regions, other.Regions)
|
||||
@@ -346,7 +337,6 @@ func (ss *ServerSelection) overrideWith(other ServerSelection) {
|
||||
|
||||
func (ss *ServerSelection) setDefaults(vpnProvider string, portForwardingEnabled bool) {
|
||||
ss.VPN = gosettings.DefaultComparable(ss.VPN, vpn.OpenVPN)
|
||||
ss.TargetIP = gosettings.DefaultValidator(ss.TargetIP, netip.IPv4Unspecified())
|
||||
ss.OwnedOnly = gosettings.DefaultPointer(ss.OwnedOnly, false)
|
||||
ss.FreeOnly = gosettings.DefaultPointer(ss.FreeOnly, false)
|
||||
ss.PremiumOnly = gosettings.DefaultPointer(ss.PremiumOnly, false)
|
||||
@@ -368,9 +358,6 @@ func (ss ServerSelection) String() string {
|
||||
func (ss ServerSelection) toLinesNode() (node *gotree.Node) {
|
||||
node = gotree.New("Server selection settings:")
|
||||
node.Appendf("VPN type: %s", ss.VPN)
|
||||
if !ss.TargetIP.IsUnspecified() {
|
||||
node.Appendf("Target IP address: %s", ss.TargetIP)
|
||||
}
|
||||
|
||||
if len(ss.Countries) > 0 {
|
||||
node.Appendf("Countries: %s", strings.Join(ss.Countries, ", "))
|
||||
@@ -461,12 +448,6 @@ func (ss *ServerSelection) read(r *reader.Reader,
|
||||
) (err error) {
|
||||
ss.VPN = vpnType
|
||||
|
||||
ss.TargetIP, err = r.NetipAddr("OPENVPN_ENDPOINT_IP",
|
||||
reader.RetroKeys("OPENVPN_TARGET_IP", "VPN_ENDPOINT_IP"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
countriesRetroKeys := []string{"COUNTRY"}
|
||||
if vpnProvider == providers.Cyberghost {
|
||||
countriesRetroKeys = append(countriesRetroKeys, "REGION")
|
||||
|
||||
@@ -14,11 +14,11 @@ import (
|
||||
|
||||
type WireguardSelection struct {
|
||||
// EndpointIP is the server endpoint IP address.
|
||||
// It is only used with VPN providers generating Wireguard
|
||||
// configurations specific to each server and user.
|
||||
// To indicate it should not be used, it should be set
|
||||
// to netip.IPv4Unspecified(). It can never be the zero value
|
||||
// in the internal state.
|
||||
// It is notably required with the custom provider.
|
||||
// Otherwise it overrides any IP address from the picked
|
||||
// built-in server connection. To indicate it should
|
||||
// not be used, it should be set to [netip.IPv4Unspecified].
|
||||
// It can never be the zero value in the internal state.
|
||||
EndpointIP netip.Addr `json:"endpoint_ip"`
|
||||
// EndpointPort is a the server port to use for the VPN server.
|
||||
// It is optional for VPN providers IVPN, Mullvad, Surfshark
|
||||
|
||||
@@ -26,16 +26,25 @@ func pickConnection(connections []models.Connection,
|
||||
return connection, ErrNoConnectionToPickFrom
|
||||
}
|
||||
|
||||
targetIPSet := selection.TargetIP.IsValid() && !selection.TargetIP.IsUnspecified()
|
||||
var targetIP netip.Addr
|
||||
switch selection.VPN {
|
||||
case vpn.OpenVPN:
|
||||
targetIP = selection.OpenVPN.EndpointIP
|
||||
case vpn.Wireguard:
|
||||
targetIP = selection.Wireguard.EndpointIP
|
||||
default:
|
||||
panic("unknown VPN type: " + selection.VPN)
|
||||
}
|
||||
targetIPSet := targetIP.IsValid() && !targetIP.IsUnspecified()
|
||||
|
||||
if targetIPSet && selection.VPN == vpn.Wireguard {
|
||||
// we need the right public key
|
||||
return getTargetIPConnection(connections, selection.TargetIP)
|
||||
return getTargetIPConnection(connections, targetIP)
|
||||
}
|
||||
|
||||
connection = pickRandomConnection(connections, randSource)
|
||||
if targetIPSet {
|
||||
connection.IP = selection.TargetIP
|
||||
connection.IP = targetIP
|
||||
}
|
||||
|
||||
return connection, nil
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
|
||||
"github.com/qdm12/gluetun/internal/configuration/settings"
|
||||
"github.com/qdm12/gluetun/internal/constants"
|
||||
"github.com/qdm12/gluetun/internal/constants/vpn"
|
||||
)
|
||||
|
||||
func commaJoin(slice []string) string {
|
||||
@@ -148,9 +149,13 @@ func noServerFoundError(selection settings.ServerSelection) (err error) {
|
||||
messageParts = append(messageParts, "tor only")
|
||||
}
|
||||
|
||||
if selection.TargetIP.IsValid() {
|
||||
targetIP := selection.OpenVPN.EndpointIP
|
||||
if selection.VPN == vpn.Wireguard {
|
||||
targetIP = selection.Wireguard.EndpointIP
|
||||
}
|
||||
if targetIP.IsValid() {
|
||||
messageParts = append(messageParts,
|
||||
"target ip address "+selection.TargetIP.String())
|
||||
"target ip address "+targetIP.String())
|
||||
}
|
||||
|
||||
message := "for " + strings.Join(messageParts, "; ")
|
||||
|
||||
Reference in New Issue
Block a user