chore(all): replace net.IP with netip.Addr
This commit is contained in:
@@ -3,8 +3,8 @@ package cli
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/netip"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -28,11 +28,11 @@ type Unzipper interface {
|
|||||||
|
|
||||||
type ParallelResolver interface {
|
type ParallelResolver interface {
|
||||||
Resolve(ctx context.Context, settings resolver.ParallelSettings) (
|
Resolve(ctx context.Context, settings resolver.ParallelSettings) (
|
||||||
hostToIPs map[string][]net.IP, warnings []string, err error)
|
hostToIPs map[string][]netip.Addr, warnings []string, err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type IPFetcher interface {
|
type IPFetcher interface {
|
||||||
FetchMultiInfo(ctx context.Context, ips []net.IP) (data []ipinfo.Response, err error)
|
FetchMultiInfo(ctx context.Context, ips []netip.Addr) (data []ipinfo.Response, err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type IPv6Checker interface {
|
type IPv6Checker interface {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package settings
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net/netip"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/configuration/settings/helpers"
|
"github.com/qdm12/gluetun/internal/configuration/settings/helpers"
|
||||||
"github.com/qdm12/gotree"
|
"github.com/qdm12/gotree"
|
||||||
@@ -13,9 +13,9 @@ type DNS struct {
|
|||||||
// ServerAddress is the DNS server to use inside
|
// ServerAddress is the DNS server to use inside
|
||||||
// the Go program and for the system.
|
// the Go program and for the system.
|
||||||
// It defaults to '127.0.0.1' to be used with the
|
// It defaults to '127.0.0.1' to be used with the
|
||||||
// DoT server. It cannot be nil in the internal
|
// DoT server. It cannot be the zero value in the internal
|
||||||
// state.
|
// state.
|
||||||
ServerAddress net.IP
|
ServerAddress netip.Addr
|
||||||
// KeepNameserver is true if the Docker DNS server
|
// KeepNameserver is true if the Docker DNS server
|
||||||
// found in /etc/resolv.conf should be kept.
|
// found in /etc/resolv.conf should be kept.
|
||||||
// Note settings this to true will go around the
|
// Note settings this to true will go around the
|
||||||
@@ -39,7 +39,7 @@ func (d DNS) validate() (err error) {
|
|||||||
|
|
||||||
func (d *DNS) Copy() (copied DNS) {
|
func (d *DNS) Copy() (copied DNS) {
|
||||||
return DNS{
|
return DNS{
|
||||||
ServerAddress: helpers.CopyIP(d.ServerAddress),
|
ServerAddress: d.ServerAddress,
|
||||||
KeepNameserver: helpers.CopyBoolPtr(d.KeepNameserver),
|
KeepNameserver: helpers.CopyBoolPtr(d.KeepNameserver),
|
||||||
DoT: d.DoT.copy(),
|
DoT: d.DoT.copy(),
|
||||||
}
|
}
|
||||||
@@ -63,7 +63,7 @@ func (d *DNS) overrideWith(other DNS) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *DNS) setDefaults() {
|
func (d *DNS) setDefaults() {
|
||||||
localhost := net.IPv4(127, 0, 0, 1) //nolint:gomnd
|
localhost := netip.AddrFrom4([4]byte{127, 0, 0, 1})
|
||||||
d.ServerAddress = helpers.DefaultIP(d.ServerAddress, localhost)
|
d.ServerAddress = helpers.DefaultIP(d.ServerAddress, localhost)
|
||||||
d.KeepNameserver = helpers.DefaultBool(d.KeepNameserver, false)
|
d.KeepNameserver = helpers.DefaultBool(d.KeepNameserver, false)
|
||||||
d.DoT.setDefaults()
|
d.DoT.setDefaults()
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
package helpers
|
package helpers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -81,25 +79,6 @@ func CopyLogLevelPtr(original *log.Level) (copied *log.Level) {
|
|||||||
return copied
|
return copied
|
||||||
}
|
}
|
||||||
|
|
||||||
func CopyIP(original net.IP) (copied net.IP) {
|
|
||||||
if original == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
copied = make(net.IP, len(original))
|
|
||||||
copy(copied, original)
|
|
||||||
return copied
|
|
||||||
}
|
|
||||||
|
|
||||||
func CopyNetipAddress(original netip.Addr) (copied netip.Addr) {
|
|
||||||
// AsSlice creates a new byte slice so no need to copy the bytes.
|
|
||||||
bytes := original.AsSlice()
|
|
||||||
copied, ok := netip.AddrFromSlice(bytes)
|
|
||||||
if !ok {
|
|
||||||
panic(fmt.Sprintf("cannot deep copy address with bytes %#v", bytes))
|
|
||||||
}
|
|
||||||
return copied
|
|
||||||
}
|
|
||||||
|
|
||||||
func CopyStringSlice(original []string) (copied []string) {
|
func CopyStringSlice(original []string) (copied []string) {
|
||||||
if original == nil {
|
if original == nil {
|
||||||
return nil
|
return nil
|
||||||
@@ -136,9 +115,6 @@ func CopyNetipAddressesSlice(original []netip.Addr) (copied []netip.Addr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
copied = make([]netip.Addr, len(original))
|
copied = make([]netip.Addr, len(original))
|
||||||
for i := range original {
|
copy(copied, original)
|
||||||
copied[i] = CopyNetipAddress(original[i])
|
|
||||||
}
|
|
||||||
|
|
||||||
return copied
|
return copied
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package helpers
|
package helpers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net/netip"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/qdm12/log"
|
"github.com/qdm12/log"
|
||||||
@@ -101,9 +101,9 @@ func DefaultLogLevel(existing *log.Level,
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func DefaultIP(existing net.IP, defaultValue net.IP) (
|
func DefaultIP(existing netip.Addr, defaultValue netip.Addr) (
|
||||||
result net.IP) {
|
result netip.Addr) {
|
||||||
if existing != nil {
|
if existing.IsValid() {
|
||||||
return existing
|
return existing
|
||||||
}
|
}
|
||||||
return defaultValue
|
return defaultValue
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package helpers
|
package helpers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"time"
|
"time"
|
||||||
@@ -96,14 +96,17 @@ func MergeWithUint32(existing, other *uint32) (result *uint32) {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func MergeWithIP(existing, other net.IP) (result net.IP) {
|
func MergeWithIP(existing, other netip.Addr) (result netip.Addr) {
|
||||||
if existing != nil {
|
if existing.IsValid() {
|
||||||
|
return existing
|
||||||
|
} else if !other.IsValid() {
|
||||||
return existing
|
return existing
|
||||||
} else if other == nil {
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
result = make(net.IP, len(other))
|
|
||||||
copy(result, other)
|
result, ok := netip.AddrFromSlice(other.AsSlice())
|
||||||
|
if !ok {
|
||||||
|
panic(fmt.Sprintf("failed copying other address: %s", other))
|
||||||
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package helpers
|
package helpers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"time"
|
"time"
|
||||||
@@ -84,12 +84,14 @@ func OverrideWithUint32(existing, other *uint32) (result *uint32) {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func OverrideWithIP(existing, other net.IP) (result net.IP) {
|
func OverrideWithIP(existing, other netip.Addr) (result netip.Addr) {
|
||||||
if other == nil {
|
if !other.IsValid() {
|
||||||
return existing
|
return existing
|
||||||
}
|
}
|
||||||
result = make(net.IP, len(other))
|
result, ok := netip.AddrFromSlice(other.AsSlice())
|
||||||
copy(result, other)
|
if !ok {
|
||||||
|
panic(fmt.Sprintf("failed copying other address: %s", other))
|
||||||
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package settings
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net/netip"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/configuration/settings/helpers"
|
"github.com/qdm12/gluetun/internal/configuration/settings/helpers"
|
||||||
@@ -21,10 +21,10 @@ type ServerSelection struct { //nolint:maligned
|
|||||||
VPN string
|
VPN string
|
||||||
// TargetIP is the server endpoint IP address to use.
|
// TargetIP is the server endpoint IP address to use.
|
||||||
// It will override any IP address from the picked
|
// It will override any IP address from the picked
|
||||||
// built-in server. It cannot be nil in the internal
|
// built-in server. It cannot be the empty value in the internal
|
||||||
// state, and can be set to an empty net.IP{} to indicate
|
// state, and can be set to the unspecified address to indicate
|
||||||
// there is not target IP address to use.
|
// there is not target IP address to use.
|
||||||
TargetIP net.IP
|
TargetIP netip.Addr
|
||||||
// Counties is the list of countries to filter VPN servers with.
|
// Counties is the list of countries to filter VPN servers with.
|
||||||
Countries []string
|
Countries []string
|
||||||
// Regions is the list of regions to filter VPN servers with.
|
// Regions is the list of regions to filter VPN servers with.
|
||||||
@@ -202,7 +202,7 @@ func validateServerFilters(settings ServerSelection, filterChoices models.Filter
|
|||||||
func (ss *ServerSelection) copy() (copied ServerSelection) {
|
func (ss *ServerSelection) copy() (copied ServerSelection) {
|
||||||
return ServerSelection{
|
return ServerSelection{
|
||||||
VPN: ss.VPN,
|
VPN: ss.VPN,
|
||||||
TargetIP: helpers.CopyIP(ss.TargetIP),
|
TargetIP: ss.TargetIP,
|
||||||
Countries: helpers.CopyStringSlice(ss.Countries),
|
Countries: helpers.CopyStringSlice(ss.Countries),
|
||||||
Regions: helpers.CopyStringSlice(ss.Regions),
|
Regions: helpers.CopyStringSlice(ss.Regions),
|
||||||
Cities: helpers.CopyStringSlice(ss.Cities),
|
Cities: helpers.CopyStringSlice(ss.Cities),
|
||||||
@@ -261,7 +261,7 @@ func (ss *ServerSelection) overrideWith(other ServerSelection) {
|
|||||||
|
|
||||||
func (ss *ServerSelection) setDefaults(vpnProvider string) {
|
func (ss *ServerSelection) setDefaults(vpnProvider string) {
|
||||||
ss.VPN = helpers.DefaultString(ss.VPN, vpn.OpenVPN)
|
ss.VPN = helpers.DefaultString(ss.VPN, vpn.OpenVPN)
|
||||||
ss.TargetIP = helpers.DefaultIP(ss.TargetIP, net.IP{})
|
ss.TargetIP = helpers.DefaultIP(ss.TargetIP, netip.IPv4Unspecified())
|
||||||
ss.OwnedOnly = helpers.DefaultBool(ss.OwnedOnly, false)
|
ss.OwnedOnly = helpers.DefaultBool(ss.OwnedOnly, false)
|
||||||
ss.FreeOnly = helpers.DefaultBool(ss.FreeOnly, false)
|
ss.FreeOnly = helpers.DefaultBool(ss.FreeOnly, false)
|
||||||
ss.PremiumOnly = helpers.DefaultBool(ss.PremiumOnly, false)
|
ss.PremiumOnly = helpers.DefaultBool(ss.PremiumOnly, false)
|
||||||
@@ -278,7 +278,7 @@ func (ss ServerSelection) String() string {
|
|||||||
func (ss ServerSelection) toLinesNode() (node *gotree.Node) {
|
func (ss ServerSelection) toLinesNode() (node *gotree.Node) {
|
||||||
node = gotree.New("Server selection settings:")
|
node = gotree.New("Server selection settings:")
|
||||||
node.Appendf("VPN type: %s", ss.VPN)
|
node.Appendf("VPN type: %s", ss.VPN)
|
||||||
if len(ss.TargetIP) > 0 {
|
if !ss.TargetIP.IsUnspecified() {
|
||||||
node.Appendf("Target IP address: %s", ss.TargetIP)
|
node.Appendf("Target IP address: %s", ss.TargetIP)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package settings
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
|
||||||
"net/netip"
|
"net/netip"
|
||||||
|
|
||||||
"github.com/qdm12/dns/pkg/provider"
|
"github.com/qdm12/dns/pkg/provider"
|
||||||
@@ -155,14 +154,24 @@ func (u Unbound) ToUnboundFormat() (settings unbound.Settings, err error) {
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u Unbound) GetFirstPlaintextIPv4() (ipv4 net.IP, err error) {
|
var (
|
||||||
|
ErrConvertingNetip = errors.New("converting net.IP to netip.Addr failed")
|
||||||
|
)
|
||||||
|
|
||||||
|
func (u Unbound) GetFirstPlaintextIPv4() (ipv4 netip.Addr, err error) {
|
||||||
s := u.Providers[0]
|
s := u.Providers[0]
|
||||||
provider, err := provider.Parse(s)
|
provider, err := provider.Parse(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return ipv4, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return provider.DNS().IPv4[0], nil
|
ip := provider.DNS().IPv4[0]
|
||||||
|
ipv4, ok := netip.AddrFromSlice(ip)
|
||||||
|
if !ok {
|
||||||
|
return ipv4, fmt.Errorf("%w: for ip %s (%#v)",
|
||||||
|
ErrConvertingNetip, ip, ip)
|
||||||
|
}
|
||||||
|
return ipv4.Unmap(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u Unbound) String() string {
|
func (u Unbound) String() string {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package settings
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net/netip"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/configuration/settings/helpers"
|
"github.com/qdm12/gluetun/internal/configuration/settings/helpers"
|
||||||
"github.com/qdm12/gluetun/internal/constants/providers"
|
"github.com/qdm12/gluetun/internal/constants/providers"
|
||||||
@@ -15,9 +15,9 @@ type WireguardSelection struct {
|
|||||||
// It is only used with VPN providers generating Wireguard
|
// It is only used with VPN providers generating Wireguard
|
||||||
// configurations specific to each server and user.
|
// configurations specific to each server and user.
|
||||||
// To indicate it should not be used, it should be set
|
// To indicate it should not be used, it should be set
|
||||||
// to the empty net.IP{} slice. It can never be nil
|
// to netaddr.IPv4Unspecified(). It can never be the zero value
|
||||||
// in the internal state.
|
// in the internal state.
|
||||||
EndpointIP net.IP
|
EndpointIP netip.Addr
|
||||||
// EndpointPort is a the server port to use for the VPN server.
|
// EndpointPort is a the server port to use for the VPN server.
|
||||||
// It is optional for VPN providers IVPN, Mullvad, Surfshark
|
// It is optional for VPN providers IVPN, Mullvad, Surfshark
|
||||||
// and Windscribe, and compulsory for the others.
|
// and Windscribe, and compulsory for the others.
|
||||||
@@ -40,7 +40,7 @@ func (w WireguardSelection) validate(vpnProvider string) (err error) {
|
|||||||
providers.Surfshark, providers.Windscribe:
|
providers.Surfshark, providers.Windscribe:
|
||||||
// endpoint IP addresses are baked in
|
// endpoint IP addresses are baked in
|
||||||
case providers.Custom:
|
case providers.Custom:
|
||||||
if len(w.EndpointIP) == 0 {
|
if !w.EndpointIP.IsValid() || w.EndpointIP.IsUnspecified() {
|
||||||
return fmt.Errorf("%w", ErrWireguardEndpointIPNotSet)
|
return fmt.Errorf("%w", ErrWireguardEndpointIPNotSet)
|
||||||
}
|
}
|
||||||
default: // Providers not supporting Wireguard
|
default: // Providers not supporting Wireguard
|
||||||
@@ -109,7 +109,7 @@ func (w WireguardSelection) validate(vpnProvider string) (err error) {
|
|||||||
|
|
||||||
func (w *WireguardSelection) copy() (copied WireguardSelection) {
|
func (w *WireguardSelection) copy() (copied WireguardSelection) {
|
||||||
return WireguardSelection{
|
return WireguardSelection{
|
||||||
EndpointIP: helpers.CopyIP(w.EndpointIP),
|
EndpointIP: w.EndpointIP,
|
||||||
EndpointPort: helpers.CopyUint16Ptr(w.EndpointPort),
|
EndpointPort: helpers.CopyUint16Ptr(w.EndpointPort),
|
||||||
PublicKey: w.PublicKey,
|
PublicKey: w.PublicKey,
|
||||||
}
|
}
|
||||||
@@ -128,7 +128,7 @@ func (w *WireguardSelection) overrideWith(other WireguardSelection) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (w *WireguardSelection) setDefaults() {
|
func (w *WireguardSelection) setDefaults() {
|
||||||
w.EndpointIP = helpers.DefaultIP(w.EndpointIP, net.IP{})
|
w.EndpointIP = helpers.DefaultIP(w.EndpointIP, netip.IPv4Unspecified())
|
||||||
w.EndpointPort = helpers.DefaultUint16(w.EndpointPort, 0)
|
w.EndpointPort = helpers.DefaultUint16(w.EndpointPort, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,7 +139,7 @@ func (w WireguardSelection) String() string {
|
|||||||
func (w WireguardSelection) toLinesNode() (node *gotree.Node) {
|
func (w WireguardSelection) toLinesNode() (node *gotree.Node) {
|
||||||
node = gotree.New("Wireguard selection settings:")
|
node = gotree.New("Wireguard selection settings:")
|
||||||
|
|
||||||
if len(w.EndpointIP) > 0 {
|
if !w.EndpointIP.IsUnspecified() {
|
||||||
node.Appendf("Endpoint IP address: %s", w.EndpointIP)
|
node.Appendf("Endpoint IP address: %s", w.EndpointIP)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
14
internal/configuration/sources/env/dns.go
vendored
14
internal/configuration/sources/env/dns.go
vendored
@@ -2,7 +2,7 @@ package env
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net/netip"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/configuration/settings"
|
"github.com/qdm12/gluetun/internal/configuration/settings"
|
||||||
)
|
)
|
||||||
@@ -26,19 +26,19 @@ func (s *Source) readDNS() (dns settings.DNS, err error) {
|
|||||||
return dns, nil
|
return dns, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Source) readDNSServerAddress() (address net.IP, err error) {
|
func (s *Source) readDNSServerAddress() (address netip.Addr, err error) {
|
||||||
key, value := s.getEnvWithRetro("DNS_ADDRESS", "DNS_PLAINTEXT_ADDRESS")
|
key, value := s.getEnvWithRetro("DNS_ADDRESS", "DNS_PLAINTEXT_ADDRESS")
|
||||||
if value == "" {
|
if value == "" {
|
||||||
return nil, nil
|
return address, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
address = net.ParseIP(value)
|
address, err = netip.ParseAddr(value)
|
||||||
if address == nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("environment variable %s: %w: %s", key, ErrIPAddressParse, value)
|
return address, fmt.Errorf("environment variable %s: %w", key, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO remove in v4
|
// TODO remove in v4
|
||||||
if !address.Equal(net.IPv4(127, 0, 0, 1)) { //nolint:gomnd
|
if address.Unmap().Compare(netip.AddrFrom4([4]byte{127, 0, 0, 1})) != 0 {
|
||||||
s.warner.Warn(key + " is set to " + value +
|
s.warner.Warn(key + " is set to " + value +
|
||||||
" so the DNS over TLS (DoT) server will not be used." +
|
" so the DNS over TLS (DoT) server will not be used." +
|
||||||
" The default value changed to 127.0.0.1 so it uses the internal DoT serves." +
|
" The default value changed to 127.0.0.1 so it uses the internal DoT serves." +
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package env
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net/netip"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -113,16 +113,15 @@ var (
|
|||||||
ErrInvalidIP = errors.New("invalid IP address")
|
ErrInvalidIP = errors.New("invalid IP address")
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *Source) readOpenVPNTargetIP() (ip net.IP, err error) {
|
func (s *Source) readOpenVPNTargetIP() (ip netip.Addr, err error) {
|
||||||
envKey, value := s.getEnvWithRetro("VPN_ENDPOINT_IP", "OPENVPN_TARGET_IP")
|
envKey, value := s.getEnvWithRetro("VPN_ENDPOINT_IP", "OPENVPN_TARGET_IP")
|
||||||
if value == "" {
|
if value == "" {
|
||||||
return nil, nil
|
return ip, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
ip = net.ParseIP(value)
|
ip, err = netip.ParseAddr(value)
|
||||||
if ip == nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("environment variable %s: %w: %s",
|
return ip, fmt.Errorf("environment variable %s: %w", envKey, err)
|
||||||
envKey, ErrInvalidIP, value)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ip, nil
|
return ip, nil
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
package env
|
package env
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net/netip"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/configuration/settings"
|
"github.com/qdm12/gluetun/internal/configuration/settings"
|
||||||
"github.com/qdm12/govalid/port"
|
"github.com/qdm12/govalid/port"
|
||||||
@@ -26,18 +25,15 @@ func (s *Source) readWireguardSelection() (
|
|||||||
return selection, nil
|
return selection, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var ErrIPAddressParse = errors.New("cannot parse IP address")
|
func (s *Source) readWireguardEndpointIP() (endpointIP netip.Addr, err error) {
|
||||||
|
|
||||||
func (s *Source) readWireguardEndpointIP() (endpointIP net.IP, err error) {
|
|
||||||
key, value := s.getEnvWithRetro("VPN_ENDPOINT_IP", "WIREGUARD_ENDPOINT_IP")
|
key, value := s.getEnvWithRetro("VPN_ENDPOINT_IP", "WIREGUARD_ENDPOINT_IP")
|
||||||
if value == "" {
|
if value == "" {
|
||||||
return nil, nil
|
return endpointIP, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
endpointIP = net.ParseIP(value)
|
endpointIP, err = netip.ParseAddr(value)
|
||||||
if endpointIP == nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("environment variable %s: %w: %s",
|
return endpointIP, fmt.Errorf("environment variable %s: %w", key, err)
|
||||||
key, ErrIPAddressParse, value)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return endpointIP, nil
|
return endpointIP, nil
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package dns
|
package dns
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net/netip"
|
||||||
|
|
||||||
"github.com/qdm12/dns/pkg/nameserver"
|
"github.com/qdm12/dns/pkg/nameserver"
|
||||||
)
|
)
|
||||||
@@ -12,14 +12,14 @@ func (l *Loop) useUnencryptedDNS(fallback bool) {
|
|||||||
// Try with user provided plaintext ip address
|
// Try with user provided plaintext ip address
|
||||||
// if it's not 127.0.0.1 (default for DoT)
|
// if it's not 127.0.0.1 (default for DoT)
|
||||||
targetIP := settings.ServerAddress
|
targetIP := settings.ServerAddress
|
||||||
if targetIP != nil && !targetIP.Equal(net.IPv4(127, 0, 0, 1)) { //nolint:gomnd
|
if targetIP.Compare(netip.AddrFrom4([4]byte{127, 0, 0, 1})) != 0 {
|
||||||
if fallback {
|
if fallback {
|
||||||
l.logger.Info("falling back on plaintext DNS at address " + targetIP.String())
|
l.logger.Info("falling back on plaintext DNS at address " + targetIP.String())
|
||||||
} else {
|
} else {
|
||||||
l.logger.Info("using plaintext DNS at address " + targetIP.String())
|
l.logger.Info("using plaintext DNS at address " + targetIP.String())
|
||||||
}
|
}
|
||||||
nameserver.UseDNSInternally(targetIP)
|
nameserver.UseDNSInternally(targetIP.AsSlice())
|
||||||
err := nameserver.UseDNSSystemWide(l.resolvConf, targetIP, *settings.KeepNameserver)
|
err := nameserver.UseDNSSystemWide(l.resolvConf, targetIP.AsSlice(), *settings.KeepNameserver)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.logger.Error(err.Error())
|
l.logger.Error(err.Error())
|
||||||
}
|
}
|
||||||
@@ -38,8 +38,8 @@ func (l *Loop) useUnencryptedDNS(fallback bool) {
|
|||||||
} else {
|
} else {
|
||||||
l.logger.Info("using plaintext DNS at address " + targetIP.String())
|
l.logger.Info("using plaintext DNS at address " + targetIP.String())
|
||||||
}
|
}
|
||||||
nameserver.UseDNSInternally(targetIP)
|
nameserver.UseDNSInternally(targetIP.AsSlice())
|
||||||
err = nameserver.UseDNSSystemWide(l.resolvConf, targetIP, *settings.KeepNameserver)
|
err = nameserver.UseDNSSystemWide(l.resolvConf, targetIP.AsSlice(), *settings.KeepNameserver)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.logger.Error(err.Error())
|
l.logger.Error(err.Error())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,8 +43,8 @@ func (l *Loop) setupUnbound(ctx context.Context) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
// use Unbound
|
// use Unbound
|
||||||
nameserver.UseDNSInternally(settings.ServerAddress)
|
nameserver.UseDNSInternally(settings.ServerAddress.AsSlice())
|
||||||
err = nameserver.UseDNSSystemWide(l.resolvConf, settings.ServerAddress,
|
err = nameserver.UseDNSSystemWide(l.resolvConf, settings.ServerAddress.AsSlice(),
|
||||||
*settings.KeepNameserver)
|
*settings.KeepNameserver)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.logger.Error(err.Error())
|
l.logger.Error(err.Error())
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ func (c *Config) enable(ctx context.Context) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) allowVPNIP(ctx context.Context) (err error) {
|
func (c *Config) allowVPNIP(ctx context.Context) (err error) {
|
||||||
if c.vpnConnection.IP == nil {
|
if !c.vpnConnection.IP.IsValid() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
@@ -146,8 +145,7 @@ func (c *Config) acceptOutputTrafficToVPN(ctx context.Context,
|
|||||||
instruction := fmt.Sprintf("%s OUTPUT -d %s -o %s -p %s -m %s --dport %d -j ACCEPT",
|
instruction := fmt.Sprintf("%s OUTPUT -d %s -o %s -p %s -m %s --dport %d -j ACCEPT",
|
||||||
appendOrDelete(remove), connection.IP, defaultInterface, connection.Protocol,
|
appendOrDelete(remove), connection.IP, defaultInterface, connection.Protocol,
|
||||||
connection.Protocol, connection.Port)
|
connection.Protocol, connection.Port)
|
||||||
isIPv4 := connection.IP.To4() != nil
|
if connection.IP.Is4() {
|
||||||
if isIPv4 {
|
|
||||||
return c.runIptablesInstruction(ctx, instruction)
|
return c.runIptablesInstruction(ctx, instruction)
|
||||||
} else if c.ip6Tables == "" {
|
} else if c.ip6Tables == "" {
|
||||||
return fmt.Errorf("accept output to VPN server: %w", ErrNeedIP6Tables)
|
return fmt.Errorf("accept output to VPN server: %w", ErrNeedIP6Tables)
|
||||||
@@ -157,8 +155,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 net.IP, destinationSubnet netip.Prefix, remove bool) error {
|
intf string, sourceIP netip.Addr, destinationSubnet netip.Prefix, remove bool) error {
|
||||||
doIPv4 := sourceIP.To4() != nil && destinationSubnet.Addr().Is4()
|
doIPv4 := sourceIP.Is4() && destinationSubnet.Addr().Is4()
|
||||||
|
|
||||||
interfaceFlag := "-o " + intf
|
interfaceFlag := "-o " + intf
|
||||||
if intf == "*" { // all interfaces
|
if intf == "*" { // all interfaces
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ func (c *Config) SetVPNConnection(ctx context.Context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
remove := true
|
remove := true
|
||||||
if c.vpnConnection.IP != nil {
|
if c.vpnConnection.IP.IsValid() {
|
||||||
for _, defaultRoute := range c.defaultRoutes {
|
for _, defaultRoute := range c.defaultRoutes {
|
||||||
if err := c.acceptOutputTrafficToVPN(ctx, defaultRoute.NetInterface, c.vpnConnection, remove); err != nil {
|
if err := c.acceptOutputTrafficToVPN(ctx, defaultRoute.NetInterface, c.vpnConnection, remove); err != nil {
|
||||||
c.logger.Error("cannot remove outdated VPN connection rule: " + err.Error())
|
c.logger.Error("cannot remove outdated VPN connection rule: " + err.Error())
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net/netip"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Connection struct {
|
type Connection struct {
|
||||||
// Type is the connection type and can be "openvpn" or "wireguard"
|
// Type is the connection type and can be "openvpn" or "wireguard"
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
// IP is the VPN server IP address.
|
// IP is the VPN server IP address.
|
||||||
IP net.IP `json:"ip"`
|
IP netip.Addr `json:"ip"`
|
||||||
// Port is the VPN server port.
|
// Port is the VPN server port.
|
||||||
Port uint16 `json:"port"`
|
Port uint16 `json:"port"`
|
||||||
// Protocol can be "tcp" or "udp".
|
// Protocol can be "tcp" or "udp".
|
||||||
@@ -24,15 +24,15 @@ type Connection struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Connection) Equal(other Connection) bool {
|
func (c *Connection) Equal(other Connection) bool {
|
||||||
return c.IP.Equal(other.IP) && c.Port == other.Port &&
|
return c.IP.Compare(other.IP) == 0 && c.Port == other.Port &&
|
||||||
c.Protocol == other.Protocol && c.Hostname == other.Hostname &&
|
c.Protocol == other.Protocol && c.Hostname == other.Hostname &&
|
||||||
c.ServerName == other.ServerName && c.PubKey == other.PubKey
|
c.ServerName == other.ServerName && c.PubKey == other.PubKey
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateEmptyWith updates each field of the connection where the
|
// UpdateEmptyWith updates each field of the connection where the
|
||||||
// value is not set using the value given as arguments.
|
// value is not set using the value given as arguments.
|
||||||
func (c *Connection) UpdateEmptyWith(ip net.IP, port uint16, protocol string) {
|
func (c *Connection) UpdateEmptyWith(ip netip.Addr, port uint16, protocol string) {
|
||||||
if c.IP == nil {
|
if !c.IP.IsValid() {
|
||||||
c.IP = ip
|
c.IP = ip
|
||||||
}
|
}
|
||||||
if c.Port == 0 {
|
if c.Port == 0 {
|
||||||
|
|||||||
@@ -1,22 +1,24 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
import "net"
|
import (
|
||||||
|
"net/netip"
|
||||||
|
)
|
||||||
|
|
||||||
type PublicIP struct {
|
type PublicIP struct {
|
||||||
IP net.IP `json:"public_ip,omitempty"`
|
IP netip.Addr `json:"public_ip,omitempty"`
|
||||||
Region string `json:"region,omitempty"`
|
Region string `json:"region,omitempty"`
|
||||||
Country string `json:"country,omitempty"`
|
Country string `json:"country,omitempty"`
|
||||||
City string `json:"city,omitempty"`
|
City string `json:"city,omitempty"`
|
||||||
Hostname string `json:"hostname,omitempty"`
|
Hostname string `json:"hostname,omitempty"`
|
||||||
Location string `json:"location,omitempty"`
|
Location string `json:"location,omitempty"`
|
||||||
Organization string `json:"organization,omitempty"`
|
Organization string `json:"organization,omitempty"`
|
||||||
PostalCode string `json:"postal_code,omitempty"`
|
PostalCode string `json:"postal_code,omitempty"`
|
||||||
Timezone string `json:"timezone,omitempty"`
|
Timezone string `json:"timezone,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PublicIP) Copy() (publicIPCopy PublicIP) {
|
func (p *PublicIP) Copy() (publicIPCopy PublicIP) {
|
||||||
publicIPCopy = PublicIP{
|
publicIPCopy = PublicIP{
|
||||||
IP: make(net.IP, len(p.IP)),
|
IP: p.IP,
|
||||||
Region: p.Region,
|
Region: p.Region,
|
||||||
Country: p.Country,
|
Country: p.Country,
|
||||||
City: p.City,
|
City: p.City,
|
||||||
@@ -26,6 +28,5 @@ func (p *PublicIP) Copy() (publicIPCopy PublicIP) {
|
|||||||
PostalCode: p.PostalCode,
|
PostalCode: p.PostalCode,
|
||||||
Timezone: p.Timezone,
|
Timezone: p.Timezone,
|
||||||
}
|
}
|
||||||
copy(publicIPCopy.IP, p.IP)
|
|
||||||
return publicIPCopy
|
return publicIPCopy
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package models
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net/netip"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -13,26 +13,26 @@ import (
|
|||||||
type Server struct {
|
type Server struct {
|
||||||
VPN string `json:"vpn,omitempty"`
|
VPN string `json:"vpn,omitempty"`
|
||||||
// Surfshark: country is also used for multi-hop
|
// Surfshark: country is also used for multi-hop
|
||||||
Country string `json:"country,omitempty"`
|
Country string `json:"country,omitempty"`
|
||||||
Region string `json:"region,omitempty"`
|
Region string `json:"region,omitempty"`
|
||||||
City string `json:"city,omitempty"`
|
City string `json:"city,omitempty"`
|
||||||
ISP string `json:"isp,omitempty"`
|
ISP string `json:"isp,omitempty"`
|
||||||
Owned bool `json:"owned,omitempty"`
|
Owned bool `json:"owned,omitempty"`
|
||||||
Number uint16 `json:"number,omitempty"`
|
Number uint16 `json:"number,omitempty"`
|
||||||
ServerName string `json:"server_name,omitempty"`
|
ServerName string `json:"server_name,omitempty"`
|
||||||
Hostname string `json:"hostname,omitempty"`
|
Hostname string `json:"hostname,omitempty"`
|
||||||
TCP bool `json:"tcp,omitempty"`
|
TCP bool `json:"tcp,omitempty"`
|
||||||
UDP bool `json:"udp,omitempty"`
|
UDP bool `json:"udp,omitempty"`
|
||||||
OvpnX509 string `json:"x509,omitempty"`
|
OvpnX509 string `json:"x509,omitempty"`
|
||||||
RetroLoc string `json:"retroloc,omitempty"` // TODO remove in v4
|
RetroLoc string `json:"retroloc,omitempty"` // TODO remove in v4
|
||||||
MultiHop bool `json:"multihop,omitempty"`
|
MultiHop bool `json:"multihop,omitempty"`
|
||||||
WgPubKey string `json:"wgpubkey,omitempty"`
|
WgPubKey string `json:"wgpubkey,omitempty"`
|
||||||
Free bool `json:"free,omitempty"`
|
Free bool `json:"free,omitempty"`
|
||||||
Stream bool `json:"stream,omitempty"`
|
Stream bool `json:"stream,omitempty"`
|
||||||
Premium bool `json:"premium,omitempty"`
|
Premium bool `json:"premium,omitempty"`
|
||||||
PortForward bool `json:"port_forward,omitempty"`
|
PortForward bool `json:"port_forward,omitempty"`
|
||||||
Keep bool `json:"keep,omitempty"`
|
Keep bool `json:"keep,omitempty"`
|
||||||
IPs []net.IP `json:"ips,omitempty"`
|
IPs []netip.Addr `json:"ips,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -72,13 +72,13 @@ func (s *Server) Equal(other Server) (equal bool) {
|
|||||||
return reflect.DeepEqual(serverCopy, other)
|
return reflect.DeepEqual(serverCopy, other)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ipsAreEqual(a, b []net.IP) (equal bool) {
|
func ipsAreEqual(a, b []netip.Addr) (equal bool) {
|
||||||
if len(a) != len(b) {
|
if len(a) != len(b) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := range a {
|
for i := range a {
|
||||||
if !a[i].Equal(b[i]) {
|
if a[i].Compare(b[i]) != 0 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net/netip"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@@ -17,28 +17,28 @@ func Test_Server_Equal(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
"same IPs": {
|
"same IPs": {
|
||||||
a: &Server{
|
a: &Server{
|
||||||
IPs: []net.IP{net.IPv4(1, 2, 3, 4)},
|
IPs: []netip.Addr{netip.AddrFrom4([4]byte{1, 2, 3, 4})},
|
||||||
},
|
},
|
||||||
b: Server{
|
b: Server{
|
||||||
IPs: []net.IP{net.IPv4(1, 2, 3, 4)},
|
IPs: []netip.Addr{netip.AddrFrom4([4]byte{1, 2, 3, 4})},
|
||||||
},
|
},
|
||||||
equal: true,
|
equal: true,
|
||||||
},
|
},
|
||||||
"same IP strings": {
|
"same IP strings": {
|
||||||
a: &Server{
|
a: &Server{
|
||||||
IPs: []net.IP{net.IPv4(1, 2, 3, 4)},
|
IPs: []netip.Addr{netip.AddrFrom4([4]byte{1, 2, 3, 4})},
|
||||||
},
|
},
|
||||||
b: Server{
|
b: Server{
|
||||||
IPs: []net.IP{{1, 2, 3, 4}},
|
IPs: []netip.Addr{netip.AddrFrom4([4]byte{1, 2, 3, 4})},
|
||||||
},
|
},
|
||||||
equal: true,
|
equal: true,
|
||||||
},
|
},
|
||||||
"different IPs": {
|
"different IPs": {
|
||||||
a: &Server{
|
a: &Server{
|
||||||
IPs: []net.IP{{1, 2, 3, 4}, {2, 3, 4, 5}},
|
IPs: []netip.Addr{netip.AddrFrom4([4]byte{1, 2, 3, 4}), netip.AddrFrom4([4]byte{2, 3, 4, 5})},
|
||||||
},
|
},
|
||||||
b: Server{
|
b: Server{
|
||||||
IPs: []net.IP{{1, 2, 3, 4}, {1, 2, 3, 4}},
|
IPs: []netip.Addr{netip.AddrFrom4([4]byte{1, 2, 3, 4}), netip.AddrFrom4([4]byte{1, 2, 3, 4})},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"all fields equal": {
|
"all fields equal": {
|
||||||
@@ -61,7 +61,7 @@ func Test_Server_Equal(t *testing.T) {
|
|||||||
Free: true,
|
Free: true,
|
||||||
Stream: true,
|
Stream: true,
|
||||||
PortForward: true,
|
PortForward: true,
|
||||||
IPs: []net.IP{net.IPv4(1, 2, 3, 4)},
|
IPs: []netip.Addr{netip.AddrFrom4([4]byte{1, 2, 3, 4})},
|
||||||
Keep: true,
|
Keep: true,
|
||||||
},
|
},
|
||||||
b: Server{
|
b: Server{
|
||||||
@@ -83,7 +83,7 @@ func Test_Server_Equal(t *testing.T) {
|
|||||||
Free: true,
|
Free: true,
|
||||||
Stream: true,
|
Stream: true,
|
||||||
PortForward: true,
|
PortForward: true,
|
||||||
IPs: []net.IP{net.IPv4(1, 2, 3, 4)},
|
IPs: []netip.Addr{netip.AddrFrom4([4]byte{1, 2, 3, 4})},
|
||||||
Keep: true,
|
Keep: true,
|
||||||
},
|
},
|
||||||
equal: true,
|
equal: true,
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package extract
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net/netip"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -25,12 +25,12 @@ func extractDataFromLines(lines []string) (
|
|||||||
|
|
||||||
connection.UpdateEmptyWith(ip, port, protocol)
|
connection.UpdateEmptyWith(ip, port, protocol)
|
||||||
|
|
||||||
if connection.Protocol != "" && connection.IP != nil {
|
if connection.Protocol != "" && connection.IP.IsValid() {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if connection.IP == nil {
|
if !connection.IP.IsValid() {
|
||||||
return connection, errRemoteLineNotFound
|
return connection, errRemoteLineNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,24 +49,24 @@ func extractDataFromLines(lines []string) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
func extractDataFromLine(line string) (
|
func extractDataFromLine(line string) (
|
||||||
ip net.IP, 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)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, "", fmt.Errorf("extracting protocol from proto line: %w", err)
|
return ip, 0, "", fmt.Errorf("extracting protocol from proto line: %w", err)
|
||||||
}
|
}
|
||||||
return nil, 0, protocol, nil
|
return ip, 0, protocol, nil
|
||||||
|
|
||||||
case strings.HasPrefix(line, "remote "):
|
case strings.HasPrefix(line, "remote "):
|
||||||
ip, port, protocol, err = extractRemote(line)
|
ip, port, protocol, err = extractRemote(line)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, "", fmt.Errorf("extracting from remote line: %w", err)
|
return ip, 0, "", fmt.Errorf("extracting from remote line: %w", err)
|
||||||
}
|
}
|
||||||
return ip, port, protocol, nil
|
return ip, port, protocol, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, 0, "", nil
|
return ip, 0, "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -95,19 +95,19 @@ var (
|
|||||||
errPortNotValid = errors.New("port is not valid")
|
errPortNotValid = errors.New("port is not valid")
|
||||||
)
|
)
|
||||||
|
|
||||||
func extractRemote(line string) (ip net.IP, 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)
|
||||||
|
|
||||||
if n < 2 || n > 4 {
|
if n < 2 || n > 4 {
|
||||||
return nil, 0, "", fmt.Errorf("%w: %s", errRemoteLineFieldsCount, line)
|
return netip.Addr{}, 0, "", fmt.Errorf("%w: %s", errRemoteLineFieldsCount, line)
|
||||||
}
|
}
|
||||||
|
|
||||||
host := fields[1]
|
host := fields[1]
|
||||||
ip = net.ParseIP(host)
|
ip, err = netip.ParseAddr(host)
|
||||||
if ip == nil {
|
if err != nil {
|
||||||
return nil, 0, "", fmt.Errorf("%w: %s", errHostNotIP, host)
|
return netip.Addr{}, 0, "", fmt.Errorf("%w: %s", errHostNotIP, host)
|
||||||
// TODO resolve hostname once there is an option to allow it through
|
// TODO resolve hostname once there is an option to allow it through
|
||||||
// the firewall before the VPN is up.
|
// the firewall before the VPN is up.
|
||||||
}
|
}
|
||||||
@@ -115,9 +115,9 @@ func extractRemote(line string) (ip net.IP, port uint16,
|
|||||||
if n > 2 { //nolint:gomnd
|
if n > 2 { //nolint:gomnd
|
||||||
portInt, err := strconv.Atoi(fields[2])
|
portInt, err := strconv.Atoi(fields[2])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, "", fmt.Errorf("%w: %s", errPortNotValid, line)
|
return netip.Addr{}, 0, "", fmt.Errorf("%w: %s", errPortNotValid, line)
|
||||||
} else if portInt < 1 || portInt > 65535 {
|
} else if portInt < 1 || portInt > 65535 {
|
||||||
return nil, 0, "", fmt.Errorf("%w: %d must be between 1 and 65535", errPortNotValid, portInt)
|
return netip.Addr{}, 0, "", fmt.Errorf("%w: %d must be between 1 and 65535", errPortNotValid, portInt)
|
||||||
}
|
}
|
||||||
port = uint16(portInt)
|
port = uint16(portInt)
|
||||||
}
|
}
|
||||||
@@ -127,7 +127,7 @@ func extractRemote(line string) (ip net.IP, port uint16,
|
|||||||
case "tcp", "udp":
|
case "tcp", "udp":
|
||||||
protocol = fields[3]
|
protocol = fields[3]
|
||||||
default:
|
default:
|
||||||
return nil, 0, "", fmt.Errorf("%w: %s", errProtocolNotSupported, fields[3])
|
return netip.Addr{}, 0, "", fmt.Errorf("%w: %s", errProtocolNotSupported, fields[3])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package extract
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"net"
|
"net/netip"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/constants"
|
"github.com/qdm12/gluetun/internal/constants"
|
||||||
@@ -22,7 +22,7 @@ func Test_extractDataFromLines(t *testing.T) {
|
|||||||
"success": {
|
"success": {
|
||||||
lines: []string{"bla bla", "proto tcp", "remote 1.2.3.4 1194 tcp", "dev tun6"},
|
lines: []string{"bla bla", "proto tcp", "remote 1.2.3.4 1194 tcp", "dev tun6"},
|
||||||
connection: models.Connection{
|
connection: models.Connection{
|
||||||
IP: net.IPv4(1, 2, 3, 4),
|
IP: netip.AddrFrom4([4]byte{1, 2, 3, 4}),
|
||||||
Port: 1194,
|
Port: 1194,
|
||||||
Protocol: constants.TCP,
|
Protocol: constants.TCP,
|
||||||
},
|
},
|
||||||
@@ -34,7 +34,7 @@ func Test_extractDataFromLines(t *testing.T) {
|
|||||||
"only use first values found": {
|
"only use first values found": {
|
||||||
lines: []string{"proto udp", "proto tcp", "remote 1.2.3.4 443 tcp", "remote 5.2.3.4 1194 udp"},
|
lines: []string{"proto udp", "proto tcp", "remote 1.2.3.4 443 tcp", "remote 5.2.3.4 1194 udp"},
|
||||||
connection: models.Connection{
|
connection: models.Connection{
|
||||||
IP: net.IPv4(1, 2, 3, 4),
|
IP: netip.AddrFrom4([4]byte{1, 2, 3, 4}),
|
||||||
Port: 443,
|
Port: 443,
|
||||||
Protocol: constants.UDP,
|
Protocol: constants.UDP,
|
||||||
},
|
},
|
||||||
@@ -49,7 +49,7 @@ func Test_extractDataFromLines(t *testing.T) {
|
|||||||
"default TCP port": {
|
"default TCP port": {
|
||||||
lines: []string{"remote 1.2.3.4", "proto tcp"},
|
lines: []string{"remote 1.2.3.4", "proto tcp"},
|
||||||
connection: models.Connection{
|
connection: models.Connection{
|
||||||
IP: net.IPv4(1, 2, 3, 4),
|
IP: netip.AddrFrom4([4]byte{1, 2, 3, 4}),
|
||||||
Port: 443,
|
Port: 443,
|
||||||
Protocol: constants.TCP,
|
Protocol: constants.TCP,
|
||||||
},
|
},
|
||||||
@@ -57,7 +57,7 @@ func Test_extractDataFromLines(t *testing.T) {
|
|||||||
"default UDP port": {
|
"default UDP port": {
|
||||||
lines: []string{"remote 1.2.3.4", "proto udp"},
|
lines: []string{"remote 1.2.3.4", "proto udp"},
|
||||||
connection: models.Connection{
|
connection: models.Connection{
|
||||||
IP: net.IPv4(1, 2, 3, 4),
|
IP: netip.AddrFrom4([4]byte{1, 2, 3, 4}),
|
||||||
Port: 1194,
|
Port: 1194,
|
||||||
Protocol: constants.UDP,
|
Protocol: constants.UDP,
|
||||||
},
|
},
|
||||||
@@ -88,7 +88,7 @@ func Test_extractDataFromLine(t *testing.T) {
|
|||||||
|
|
||||||
testCases := map[string]struct {
|
testCases := map[string]struct {
|
||||||
line string
|
line string
|
||||||
ip net.IP
|
ip netip.Addr
|
||||||
port uint16
|
port uint16
|
||||||
protocol string
|
protocol string
|
||||||
isErr error
|
isErr error
|
||||||
@@ -110,7 +110,7 @@ func Test_extractDataFromLine(t *testing.T) {
|
|||||||
},
|
},
|
||||||
"extract remote success": {
|
"extract remote success": {
|
||||||
line: "remote 1.2.3.4 1194 udp",
|
line: "remote 1.2.3.4 1194 udp",
|
||||||
ip: net.IPv4(1, 2, 3, 4),
|
ip: netip.AddrFrom4([4]byte{1, 2, 3, 4}),
|
||||||
port: 1194,
|
port: 1194,
|
||||||
protocol: constants.UDP,
|
protocol: constants.UDP,
|
||||||
},
|
},
|
||||||
@@ -186,7 +186,7 @@ func Test_extractRemote(t *testing.T) {
|
|||||||
|
|
||||||
testCases := map[string]struct {
|
testCases := map[string]struct {
|
||||||
line string
|
line string
|
||||||
ip net.IP
|
ip netip.Addr
|
||||||
port uint16
|
port uint16
|
||||||
protocol string
|
protocol string
|
||||||
err error
|
err error
|
||||||
@@ -205,7 +205,7 @@ func Test_extractRemote(t *testing.T) {
|
|||||||
},
|
},
|
||||||
"only IP host": {
|
"only IP host": {
|
||||||
line: "remote 1.2.3.4",
|
line: "remote 1.2.3.4",
|
||||||
ip: net.IPv4(1, 2, 3, 4),
|
ip: netip.AddrFrom4([4]byte{1, 2, 3, 4}),
|
||||||
},
|
},
|
||||||
"port not an integer": {
|
"port not an integer": {
|
||||||
line: "remote 1.2.3.4 bad",
|
line: "remote 1.2.3.4 bad",
|
||||||
@@ -225,7 +225,7 @@ func Test_extractRemote(t *testing.T) {
|
|||||||
},
|
},
|
||||||
"IP host and port": {
|
"IP host and port": {
|
||||||
line: "remote 1.2.3.4 8000",
|
line: "remote 1.2.3.4 8000",
|
||||||
ip: net.IPv4(1, 2, 3, 4),
|
ip: netip.AddrFrom4([4]byte{1, 2, 3, 4}),
|
||||||
port: 8000,
|
port: 8000,
|
||||||
},
|
},
|
||||||
"invalid protocol": {
|
"invalid protocol": {
|
||||||
@@ -234,7 +234,7 @@ func Test_extractRemote(t *testing.T) {
|
|||||||
},
|
},
|
||||||
"IP host and port and protocol": {
|
"IP host and port and protocol": {
|
||||||
line: "remote 1.2.3.4 8000 udp",
|
line: "remote 1.2.3.4 8000 udp",
|
||||||
ip: net.IPv4(1, 2, 3, 4),
|
ip: netip.AddrFrom4([4]byte{1, 2, 3, 4}),
|
||||||
port: 8000,
|
port: 8000,
|
||||||
protocol: constants.UDP,
|
protocol: constants.UDP,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
package state
|
package state
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net/netip"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/provider"
|
"github.com/qdm12/gluetun/internal/provider"
|
||||||
)
|
)
|
||||||
|
|
||||||
type StartData struct {
|
type StartData struct {
|
||||||
PortForwarder provider.PortForwarder
|
PortForwarder provider.PortForwarder
|
||||||
Gateway net.IP // needed for PIA
|
Gateway netip.Addr // needed for PIA
|
||||||
ServerName string // needed for PIA
|
ServerName string // needed for PIA
|
||||||
Interface string // tun0 for example
|
Interface string // tun0 for example
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *State) GetStartData() (startData StartData) {
|
func (s *State) GetStartData() (startData StartData) {
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/netip"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/provider/common"
|
"github.com/qdm12/gluetun/internal/provider/common"
|
||||||
)
|
)
|
||||||
@@ -15,20 +15,20 @@ type apiData struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type apiServer struct {
|
type apiServer struct {
|
||||||
PublicName string `json:"public_name"`
|
PublicName string `json:"public_name"`
|
||||||
CountryName string `json:"country_name"`
|
CountryName string `json:"country_name"`
|
||||||
CountryCode string `json:"country_code"`
|
CountryCode string `json:"country_code"`
|
||||||
Location string `json:"location"`
|
Location string `json:"location"`
|
||||||
Continent string `json:"continent"`
|
Continent string `json:"continent"`
|
||||||
IPv4In1 net.IP `json:"ip_v4_in1"`
|
IPv4In1 netip.Addr `json:"ip_v4_in1"`
|
||||||
IPv4In2 net.IP `json:"ip_v4_in2"`
|
IPv4In2 netip.Addr `json:"ip_v4_in2"`
|
||||||
IPv4In3 net.IP `json:"ip_v4_in3"`
|
IPv4In3 netip.Addr `json:"ip_v4_in3"`
|
||||||
IPv4In4 net.IP `json:"ip_v4_in4"`
|
IPv4In4 netip.Addr `json:"ip_v4_in4"`
|
||||||
IPv6In1 net.IP `json:"ip_v6_in1"`
|
IPv6In1 netip.Addr `json:"ip_v6_in1"`
|
||||||
IPv6In2 net.IP `json:"ip_v6_in2"`
|
IPv6In2 netip.Addr `json:"ip_v6_in2"`
|
||||||
IPv6In3 net.IP `json:"ip_v6_in3"`
|
IPv6In3 netip.Addr `json:"ip_v6_in3"`
|
||||||
IPv6In4 net.IP `json:"ip_v6_in4"`
|
IPv6In4 netip.Addr `json:"ip_v6_in4"`
|
||||||
Health string `json:"health"`
|
Health string `json:"health"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func fetchAPI(ctx context.Context, client *http.Client) (
|
func fetchAPI(ctx context.Context, client *http.Client) (
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package updater
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net/netip"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -57,12 +57,12 @@ func (u *Updater) FetchServers(ctx context.Context, minServers int) (
|
|||||||
baseWireguardServer.WgPubKey = "PyLCXAQT8KkM4T+dUsOQfn+Ub3pGxfGlxkIApuig+hk="
|
baseWireguardServer.WgPubKey = "PyLCXAQT8KkM4T+dUsOQfn+Ub3pGxfGlxkIApuig+hk="
|
||||||
|
|
||||||
ipv4WireguadServer := baseWireguardServer
|
ipv4WireguadServer := baseWireguardServer
|
||||||
ipv4WireguadServer.IPs = []net.IP{apiServer.IPv4In1}
|
ipv4WireguadServer.IPs = []netip.Addr{apiServer.IPv4In1}
|
||||||
ipv4WireguadServer.Hostname = apiServer.CountryCode + ".vpn.airdns.org"
|
ipv4WireguadServer.Hostname = apiServer.CountryCode + ".vpn.airdns.org"
|
||||||
servers = append(servers, ipv4WireguadServer)
|
servers = append(servers, ipv4WireguadServer)
|
||||||
|
|
||||||
ipv6WireguadServer := baseWireguardServer
|
ipv6WireguadServer := baseWireguardServer
|
||||||
ipv6WireguadServer.IPs = []net.IP{apiServer.IPv6In1}
|
ipv6WireguadServer.IPs = []netip.Addr{apiServer.IPv6In1}
|
||||||
ipv6WireguadServer.Hostname = apiServer.CountryCode + ".ipv6.vpn.airdns.org"
|
ipv6WireguadServer.Hostname = apiServer.CountryCode + ".ipv6.vpn.airdns.org"
|
||||||
servers = append(servers, ipv6WireguadServer)
|
servers = append(servers, ipv6WireguadServer)
|
||||||
|
|
||||||
@@ -74,22 +74,22 @@ func (u *Updater) FetchServers(ctx context.Context, minServers int) (
|
|||||||
// Ignore IPs 1 and 2 since tls-crypt is superior to tls-auth really.
|
// Ignore IPs 1 and 2 since tls-crypt is superior to tls-auth really.
|
||||||
|
|
||||||
ipv4In3OpenVPNServer := baseOpenVPNServer
|
ipv4In3OpenVPNServer := baseOpenVPNServer
|
||||||
ipv4In3OpenVPNServer.IPs = []net.IP{apiServer.IPv4In3}
|
ipv4In3OpenVPNServer.IPs = []netip.Addr{apiServer.IPv4In3}
|
||||||
ipv4In3OpenVPNServer.Hostname = apiServer.CountryCode + "3.vpn.airdns.org"
|
ipv4In3OpenVPNServer.Hostname = apiServer.CountryCode + "3.vpn.airdns.org"
|
||||||
servers = append(servers, ipv4In3OpenVPNServer)
|
servers = append(servers, ipv4In3OpenVPNServer)
|
||||||
|
|
||||||
ipv6In3OpenVPNServer := baseOpenVPNServer
|
ipv6In3OpenVPNServer := baseOpenVPNServer
|
||||||
ipv6In3OpenVPNServer.IPs = []net.IP{apiServer.IPv6In3}
|
ipv6In3OpenVPNServer.IPs = []netip.Addr{apiServer.IPv6In3}
|
||||||
ipv6In3OpenVPNServer.Hostname = apiServer.CountryCode + "3.ipv6.vpn.airdns.org"
|
ipv6In3OpenVPNServer.Hostname = apiServer.CountryCode + "3.ipv6.vpn.airdns.org"
|
||||||
servers = append(servers, ipv6In3OpenVPNServer)
|
servers = append(servers, ipv6In3OpenVPNServer)
|
||||||
|
|
||||||
ipv4In4OpenVPNServer := baseOpenVPNServer
|
ipv4In4OpenVPNServer := baseOpenVPNServer
|
||||||
ipv4In4OpenVPNServer.IPs = []net.IP{apiServer.IPv4In4}
|
ipv4In4OpenVPNServer.IPs = []netip.Addr{apiServer.IPv4In4}
|
||||||
ipv4In4OpenVPNServer.Hostname = apiServer.CountryCode + "4.vpn.airdns.org"
|
ipv4In4OpenVPNServer.Hostname = apiServer.CountryCode + "4.vpn.airdns.org"
|
||||||
servers = append(servers, ipv4In4OpenVPNServer)
|
servers = append(servers, ipv4In4OpenVPNServer)
|
||||||
|
|
||||||
ipv6In4OpenVPNServer := baseOpenVPNServer
|
ipv6In4OpenVPNServer := baseOpenVPNServer
|
||||||
ipv6In4OpenVPNServer.IPs = []net.IP{apiServer.IPv6In4}
|
ipv6In4OpenVPNServer.IPs = []netip.Addr{apiServer.IPv6In4}
|
||||||
ipv6In4OpenVPNServer.Hostname = apiServer.CountryCode + "4.ipv6.vpn.airdns.org"
|
ipv6In4OpenVPNServer.Hostname = apiServer.CountryCode + "4.ipv6.vpn.airdns.org"
|
||||||
servers = append(servers, ipv6In4OpenVPNServer)
|
servers = append(servers, ipv6In4OpenVPNServer)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ package common
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
context "context"
|
context "context"
|
||||||
net "net"
|
netip "net/netip"
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
|
|
||||||
gomock "github.com/golang/mock/gomock"
|
gomock "github.com/golang/mock/gomock"
|
||||||
@@ -39,10 +39,10 @@ func (m *MockParallelResolver) EXPECT() *MockParallelResolverMockRecorder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Resolve mocks base method.
|
// Resolve mocks base method.
|
||||||
func (m *MockParallelResolver) Resolve(arg0 context.Context, arg1 resolver.ParallelSettings) (map[string][]net.IP, []string, error) {
|
func (m *MockParallelResolver) Resolve(arg0 context.Context, arg1 resolver.ParallelSettings) (map[string][]netip.Addr, []string, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "Resolve", arg0, arg1)
|
ret := m.ctrl.Call(m, "Resolve", arg0, arg1)
|
||||||
ret0, _ := ret[0].(map[string][]net.IP)
|
ret0, _ := ret[0].(map[string][]netip.Addr)
|
||||||
ret1, _ := ret[1].([]string)
|
ret1, _ := ret[1].([]string)
|
||||||
ret2, _ := ret[2].(error)
|
ret2, _ := ret[2].(error)
|
||||||
return ret0, ret1, ret2
|
return ret0, ret1, ret2
|
||||||
|
|||||||
@@ -2,4 +2,5 @@ package common
|
|||||||
|
|
||||||
// Exceptionally, these mocks are exported since they are used by all
|
// Exceptionally, these mocks are exported since they are used by all
|
||||||
// provider subpackages tests, and it reduces test code duplication a lot.
|
// provider subpackages tests, and it reduces test code duplication a lot.
|
||||||
|
// Note mocks.go might need to be removed before re-generating it.
|
||||||
//go:generate mockgen -destination=mocks.go -package $GOPACKAGE . ParallelResolver,Storage,Unzipper,Warner
|
//go:generate mockgen -destination=mocks.go -package $GOPACKAGE . ParallelResolver,Storage,Unzipper,Warner
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package common
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"net"
|
"net/netip"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
"github.com/qdm12/gluetun/internal/publicip/ipinfo"
|
"github.com/qdm12/gluetun/internal/publicip/ipinfo"
|
||||||
@@ -21,7 +21,7 @@ type Fetcher interface {
|
|||||||
|
|
||||||
type ParallelResolver interface {
|
type ParallelResolver interface {
|
||||||
Resolve(ctx context.Context, settings resolver.ParallelSettings) (
|
Resolve(ctx context.Context, settings resolver.ParallelSettings) (
|
||||||
hostToIPs map[string][]net.IP, warnings []string, err error)
|
hostToIPs map[string][]netip.Addr, warnings []string, err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Unzipper interface {
|
type Unzipper interface {
|
||||||
@@ -34,5 +34,5 @@ type Warner interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type IPFetcher interface {
|
type IPFetcher interface {
|
||||||
FetchMultiInfo(ctx context.Context, ips []net.IP) (data []ipinfo.Response, err error)
|
FetchMultiInfo(ctx context.Context, ips []netip.Addr) (data []ipinfo.Response, err error)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package custom
|
package custom
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net/netip"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/configuration/settings"
|
"github.com/qdm12/gluetun/internal/configuration/settings"
|
||||||
@@ -46,7 +46,7 @@ func Test_modifyConfig(t *testing.T) {
|
|||||||
Verbosity: intPtr(0),
|
Verbosity: intPtr(0),
|
||||||
}.WithDefaults(providers.Custom),
|
}.WithDefaults(providers.Custom),
|
||||||
connection: models.Connection{
|
connection: models.Connection{
|
||||||
IP: net.IPv4(1, 2, 3, 4),
|
IP: netip.AddrFrom4([4]byte{1, 2, 3, 4}),
|
||||||
Port: 1194,
|
Port: 1194,
|
||||||
Protocol: constants.UDP,
|
Protocol: constants.UDP,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package updater
|
package updater
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net/netip"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/constants"
|
"github.com/qdm12/gluetun/internal/constants"
|
||||||
"github.com/qdm12/gluetun/internal/constants/vpn"
|
"github.com/qdm12/gluetun/internal/constants/vpn"
|
||||||
@@ -47,7 +47,7 @@ func (hts hostToServer) hostsSlice() (hosts []string) {
|
|||||||
return hosts
|
return hosts
|
||||||
}
|
}
|
||||||
|
|
||||||
func (hts hostToServer) adaptWithIPs(hostToIPs map[string][]net.IP) {
|
func (hts hostToServer) adaptWithIPs(hostToIPs map[string][]netip.Addr) {
|
||||||
for host, IPs := range hostToIPs {
|
for host, IPs := range hostToIPs {
|
||||||
server := hts[host]
|
server := hts[host]
|
||||||
server.IPs = IPs
|
server.IPs = IPs
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package expressvpn
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net"
|
"net/netip"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/golang/mock/gomock"
|
"github.com/golang/mock/gomock"
|
||||||
@@ -41,7 +41,7 @@ func Test_Provider_GetConnection(t *testing.T) {
|
|||||||
},
|
},
|
||||||
"default OpenVPN TCP port": {
|
"default OpenVPN TCP port": {
|
||||||
filteredServers: []models.Server{
|
filteredServers: []models.Server{
|
||||||
{IPs: []net.IP{net.IPv4(1, 1, 1, 1)}},
|
{IPs: []netip.Addr{netip.AddrFrom4([4]byte{1, 1, 1, 1})}},
|
||||||
},
|
},
|
||||||
selection: settings.ServerSelection{
|
selection: settings.ServerSelection{
|
||||||
OpenVPN: settings.OpenVPNSelection{
|
OpenVPN: settings.OpenVPNSelection{
|
||||||
@@ -52,7 +52,7 @@ func Test_Provider_GetConnection(t *testing.T) {
|
|||||||
},
|
},
|
||||||
"default OpenVPN UDP port": {
|
"default OpenVPN UDP port": {
|
||||||
filteredServers: []models.Server{
|
filteredServers: []models.Server{
|
||||||
{IPs: []net.IP{net.IPv4(1, 1, 1, 1)}},
|
{IPs: []netip.Addr{netip.AddrFrom4([4]byte{1, 1, 1, 1})}},
|
||||||
},
|
},
|
||||||
selection: settings.ServerSelection{
|
selection: settings.ServerSelection{
|
||||||
OpenVPN: settings.OpenVPNSelection{
|
OpenVPN: settings.OpenVPNSelection{
|
||||||
@@ -61,14 +61,14 @@ func Test_Provider_GetConnection(t *testing.T) {
|
|||||||
}.WithDefaults(provider),
|
}.WithDefaults(provider),
|
||||||
connection: models.Connection{
|
connection: models.Connection{
|
||||||
Type: vpn.OpenVPN,
|
Type: vpn.OpenVPN,
|
||||||
IP: net.IPv4(1, 1, 1, 1),
|
IP: netip.AddrFrom4([4]byte{1, 1, 1, 1}),
|
||||||
Port: 1195,
|
Port: 1195,
|
||||||
Protocol: constants.UDP,
|
Protocol: constants.UDP,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"default Wireguard port": {
|
"default Wireguard port": {
|
||||||
filteredServers: []models.Server{
|
filteredServers: []models.Server{
|
||||||
{IPs: []net.IP{net.IPv4(1, 1, 1, 1)}},
|
{IPs: []netip.Addr{netip.AddrFrom4([4]byte{1, 1, 1, 1})}},
|
||||||
},
|
},
|
||||||
selection: settings.ServerSelection{
|
selection: settings.ServerSelection{
|
||||||
VPN: vpn.Wireguard,
|
VPN: vpn.Wireguard,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package updater
|
package updater
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net/netip"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/constants/vpn"
|
"github.com/qdm12/gluetun/internal/constants/vpn"
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
@@ -33,7 +33,7 @@ func (hts hostToServer) toHostsSlice() (hosts []string) {
|
|||||||
return hosts
|
return hosts
|
||||||
}
|
}
|
||||||
|
|
||||||
func (hts hostToServer) adaptWithIPs(hostToIPs map[string][]net.IP) {
|
func (hts hostToServer) adaptWithIPs(hostToIPs map[string][]netip.Addr) {
|
||||||
for host, IPs := range hostToIPs {
|
for host, IPs := range hostToIPs {
|
||||||
server := hts[host]
|
server := hts[host]
|
||||||
server.IPs = IPs
|
server.IPs = IPs
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package updater
|
package updater
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net/netip"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/constants/vpn"
|
"github.com/qdm12/gluetun/internal/constants/vpn"
|
||||||
@@ -38,7 +38,7 @@ func (hts hostToServer) toHostsSlice() (hosts []string) {
|
|||||||
return hosts
|
return hosts
|
||||||
}
|
}
|
||||||
|
|
||||||
func (hts hostToServer) adaptWithIPs(hostToIPs map[string][]net.IP) {
|
func (hts hostToServer) adaptWithIPs(hostToIPs map[string][]netip.Addr) {
|
||||||
for host, IPs := range hostToIPs {
|
for host, IPs := range hostToIPs {
|
||||||
server := hts[host]
|
server := hts[host]
|
||||||
server.IPs = IPs
|
server.IPs = IPs
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package updater
|
package updater
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net/netip"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/constants/vpn"
|
"github.com/qdm12/gluetun/internal/constants/vpn"
|
||||||
@@ -134,17 +134,17 @@ func Test_hostToServer_adaptWithIPs(t *testing.T) {
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
testCases := map[string]struct {
|
testCases := map[string]struct {
|
||||||
initialHTS hostToServer
|
initialHTS hostToServer
|
||||||
hostToIPs map[string][]net.IP
|
hostToIPs map[string][]netip.Addr
|
||||||
expectedHTS hostToServer
|
expectedHTS hostToServer
|
||||||
}{
|
}{
|
||||||
"create server": {
|
"create server": {
|
||||||
initialHTS: hostToServer{},
|
initialHTS: hostToServer{},
|
||||||
hostToIPs: map[string][]net.IP{
|
hostToIPs: map[string][]netip.Addr{
|
||||||
"A": {{1, 2, 3, 4}},
|
"A": {netip.AddrFrom4([4]byte{1, 2, 3, 4})},
|
||||||
},
|
},
|
||||||
expectedHTS: hostToServer{
|
expectedHTS: hostToServer{
|
||||||
"A": models.Server{
|
"A": models.Server{
|
||||||
IPs: []net.IP{{1, 2, 3, 4}},
|
IPs: []netip.Addr{netip.AddrFrom4([4]byte{1, 2, 3, 4})},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -154,13 +154,13 @@ func Test_hostToServer_adaptWithIPs(t *testing.T) {
|
|||||||
Country: "country",
|
Country: "country",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
hostToIPs: map[string][]net.IP{
|
hostToIPs: map[string][]netip.Addr{
|
||||||
"A": {{1, 2, 3, 4}},
|
"A": {netip.AddrFrom4([4]byte{1, 2, 3, 4})},
|
||||||
},
|
},
|
||||||
expectedHTS: hostToServer{
|
expectedHTS: hostToServer{
|
||||||
"A": models.Server{
|
"A": models.Server{
|
||||||
Country: "country",
|
Country: "country",
|
||||||
IPs: []net.IP{{1, 2, 3, 4}},
|
IPs: []netip.Addr{netip.AddrFrom4([4]byte{1, 2, 3, 4})},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -170,7 +170,7 @@ func Test_hostToServer_adaptWithIPs(t *testing.T) {
|
|||||||
Country: "country",
|
Country: "country",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
hostToIPs: map[string][]net.IP{},
|
hostToIPs: map[string][]netip.Addr{},
|
||||||
expectedHTS: hostToServer{},
|
expectedHTS: hostToServer{},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package updater
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"net"
|
"net/netip"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@ func Test_Updater_GetServers(t *testing.T) {
|
|||||||
// Resolution
|
// Resolution
|
||||||
expectResolve bool
|
expectResolve bool
|
||||||
resolverSettings resolver.ParallelSettings
|
resolverSettings resolver.ParallelSettings
|
||||||
hostToIPs map[string][]net.IP
|
hostToIPs map[string][]netip.Addr
|
||||||
resolveWarnings []string
|
resolveWarnings []string
|
||||||
resolveErr error
|
resolveErr error
|
||||||
|
|
||||||
@@ -161,9 +161,9 @@ func Test_Updater_GetServers(t *testing.T) {
|
|||||||
SortIPs: true,
|
SortIPs: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
hostToIPs: map[string][]net.IP{
|
hostToIPs: map[string][]netip.Addr{
|
||||||
"hosta": {{1, 1, 1, 1}, {2, 2, 2, 2}},
|
"hosta": {netip.AddrFrom4([4]byte{1, 1, 1, 1}), netip.AddrFrom4([4]byte{2, 2, 2, 2})},
|
||||||
"hostb": {{3, 3, 3, 3}, {4, 4, 4, 4}},
|
"hostb": {netip.AddrFrom4([4]byte{3, 3, 3, 3}), netip.AddrFrom4([4]byte{4, 4, 4, 4})},
|
||||||
},
|
},
|
||||||
resolveWarnings: []string{"resolve warning"},
|
resolveWarnings: []string{"resolve warning"},
|
||||||
servers: []models.Server{
|
servers: []models.Server{
|
||||||
@@ -173,7 +173,7 @@ func Test_Updater_GetServers(t *testing.T) {
|
|||||||
City: "City A",
|
City: "City A",
|
||||||
Hostname: "hosta",
|
Hostname: "hosta",
|
||||||
UDP: true,
|
UDP: true,
|
||||||
IPs: []net.IP{{1, 1, 1, 1}, {2, 2, 2, 2}},
|
IPs: []netip.Addr{netip.AddrFrom4([4]byte{1, 1, 1, 1}), netip.AddrFrom4([4]byte{2, 2, 2, 2})},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
VPN: vpn.OpenVPN,
|
VPN: vpn.OpenVPN,
|
||||||
@@ -181,7 +181,7 @@ func Test_Updater_GetServers(t *testing.T) {
|
|||||||
City: "City B",
|
City: "City B",
|
||||||
Hostname: "hostb",
|
Hostname: "hostb",
|
||||||
UDP: true,
|
UDP: true,
|
||||||
IPs: []net.IP{{3, 3, 3, 3}, {4, 4, 4, 4}},
|
IPs: []netip.Addr{netip.AddrFrom4([4]byte{3, 3, 3, 3}), netip.AddrFrom4([4]byte{4, 4, 4, 4})},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ package ivpn
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/netip"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/golang/mock/gomock"
|
"github.com/golang/mock/gomock"
|
||||||
@@ -41,7 +41,7 @@ func Test_Provider_GetConnection(t *testing.T) {
|
|||||||
},
|
},
|
||||||
"default OpenVPN TCP port": {
|
"default OpenVPN TCP port": {
|
||||||
filteredServers: []models.Server{
|
filteredServers: []models.Server{
|
||||||
{IPs: []net.IP{net.IPv4(1, 1, 1, 1)}},
|
{IPs: []netip.Addr{netip.AddrFrom4([4]byte{1, 1, 1, 1})}},
|
||||||
},
|
},
|
||||||
selection: settings.ServerSelection{
|
selection: settings.ServerSelection{
|
||||||
OpenVPN: settings.OpenVPNSelection{
|
OpenVPN: settings.OpenVPNSelection{
|
||||||
@@ -50,14 +50,14 @@ func Test_Provider_GetConnection(t *testing.T) {
|
|||||||
}.WithDefaults(provider),
|
}.WithDefaults(provider),
|
||||||
connection: models.Connection{
|
connection: models.Connection{
|
||||||
Type: vpn.OpenVPN,
|
Type: vpn.OpenVPN,
|
||||||
IP: net.IPv4(1, 1, 1, 1),
|
IP: netip.AddrFrom4([4]byte{1, 1, 1, 1}),
|
||||||
Port: 443,
|
Port: 443,
|
||||||
Protocol: constants.TCP,
|
Protocol: constants.TCP,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"default OpenVPN UDP port": {
|
"default OpenVPN UDP port": {
|
||||||
filteredServers: []models.Server{
|
filteredServers: []models.Server{
|
||||||
{IPs: []net.IP{net.IPv4(1, 1, 1, 1)}},
|
{IPs: []netip.Addr{netip.AddrFrom4([4]byte{1, 1, 1, 1})}},
|
||||||
},
|
},
|
||||||
selection: settings.ServerSelection{
|
selection: settings.ServerSelection{
|
||||||
OpenVPN: settings.OpenVPNSelection{
|
OpenVPN: settings.OpenVPNSelection{
|
||||||
@@ -66,21 +66,21 @@ func Test_Provider_GetConnection(t *testing.T) {
|
|||||||
}.WithDefaults(provider),
|
}.WithDefaults(provider),
|
||||||
connection: models.Connection{
|
connection: models.Connection{
|
||||||
Type: vpn.OpenVPN,
|
Type: vpn.OpenVPN,
|
||||||
IP: net.IPv4(1, 1, 1, 1),
|
IP: netip.AddrFrom4([4]byte{1, 1, 1, 1}),
|
||||||
Port: 1194,
|
Port: 1194,
|
||||||
Protocol: constants.UDP,
|
Protocol: constants.UDP,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"default Wireguard port": {
|
"default Wireguard port": {
|
||||||
filteredServers: []models.Server{
|
filteredServers: []models.Server{
|
||||||
{IPs: []net.IP{net.IPv4(1, 1, 1, 1)}, WgPubKey: "x"},
|
{IPs: []netip.Addr{netip.AddrFrom4([4]byte{1, 1, 1, 1})}, WgPubKey: "x"},
|
||||||
},
|
},
|
||||||
selection: settings.ServerSelection{
|
selection: settings.ServerSelection{
|
||||||
VPN: vpn.Wireguard,
|
VPN: vpn.Wireguard,
|
||||||
}.WithDefaults(provider),
|
}.WithDefaults(provider),
|
||||||
connection: models.Connection{
|
connection: models.Connection{
|
||||||
Type: vpn.Wireguard,
|
Type: vpn.Wireguard,
|
||||||
IP: net.IPv4(1, 1, 1, 1),
|
IP: netip.AddrFrom4([4]byte{1, 1, 1, 1}),
|
||||||
Port: 58237,
|
Port: 58237,
|
||||||
Protocol: constants.UDP,
|
Protocol: constants.UDP,
|
||||||
PubKey: "x",
|
PubKey: "x",
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/netip"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
@@ -36,7 +36,7 @@ func Test_Updater_GetServers(t *testing.T) {
|
|||||||
// Resolution
|
// Resolution
|
||||||
expectResolve bool
|
expectResolve bool
|
||||||
resolveSettings resolver.ParallelSettings
|
resolveSettings resolver.ParallelSettings
|
||||||
hostToIPs map[string][]net.IP
|
hostToIPs map[string][]netip.Addr
|
||||||
resolveWarnings []string
|
resolveWarnings []string
|
||||||
resolveErr error
|
resolveErr error
|
||||||
|
|
||||||
@@ -109,24 +109,24 @@ func Test_Updater_GetServers(t *testing.T) {
|
|||||||
SortIPs: true,
|
SortIPs: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
hostToIPs: map[string][]net.IP{
|
hostToIPs: map[string][]netip.Addr{
|
||||||
"hosta": {{1, 1, 1, 1}, {2, 2, 2, 2}},
|
"hosta": {netip.AddrFrom4([4]byte{1, 1, 1, 1}), netip.AddrFrom4([4]byte{2, 2, 2, 2})},
|
||||||
"hostb": {{3, 3, 3, 3}, {4, 4, 4, 4}},
|
"hostb": {netip.AddrFrom4([4]byte{3, 3, 3, 3}), netip.AddrFrom4([4]byte{4, 4, 4, 4})},
|
||||||
"hostc": {{5, 5, 5, 5}, {6, 6, 6, 6}},
|
"hostc": {netip.AddrFrom4([4]byte{5, 5, 5, 5}), netip.AddrFrom4([4]byte{6, 6, 6, 6})},
|
||||||
},
|
},
|
||||||
resolveWarnings: []string{"resolve warning"},
|
resolveWarnings: []string{"resolve warning"},
|
||||||
servers: []models.Server{
|
servers: []models.Server{
|
||||||
{VPN: vpn.OpenVPN, Country: "Country1",
|
{VPN: vpn.OpenVPN, Country: "Country1",
|
||||||
City: "City A", Hostname: "hosta", TCP: true, UDP: true,
|
City: "City A", Hostname: "hosta", TCP: true, UDP: true,
|
||||||
IPs: []net.IP{{1, 1, 1, 1}, {2, 2, 2, 2}}},
|
IPs: []netip.Addr{netip.AddrFrom4([4]byte{1, 1, 1, 1}), netip.AddrFrom4([4]byte{2, 2, 2, 2})}},
|
||||||
{VPN: vpn.OpenVPN, Country: "Country2",
|
{VPN: vpn.OpenVPN, Country: "Country2",
|
||||||
City: "City B", Hostname: "hostb", TCP: true, UDP: true,
|
City: "City B", Hostname: "hostb", TCP: true, UDP: true,
|
||||||
IPs: []net.IP{{3, 3, 3, 3}, {4, 4, 4, 4}}},
|
IPs: []netip.Addr{netip.AddrFrom4([4]byte{3, 3, 3, 3}), netip.AddrFrom4([4]byte{4, 4, 4, 4})}},
|
||||||
{VPN: vpn.Wireguard,
|
{VPN: vpn.Wireguard,
|
||||||
Country: "Country3", City: "City C",
|
Country: "Country3", City: "City C",
|
||||||
Hostname: "hostc",
|
Hostname: "hostc",
|
||||||
WgPubKey: "xyz",
|
WgPubKey: "xyz",
|
||||||
IPs: []net.IP{{5, 5, 5, 5}, {6, 6, 6, 6}}},
|
IPs: []netip.Addr{netip.AddrFrom4([4]byte{5, 5, 5, 5}), netip.AddrFrom4([4]byte{6, 6, 6, 6})}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ package mullvad
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/netip"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/golang/mock/gomock"
|
"github.com/golang/mock/gomock"
|
||||||
@@ -41,7 +41,7 @@ func Test_Provider_GetConnection(t *testing.T) {
|
|||||||
},
|
},
|
||||||
"default OpenVPN TCP port": {
|
"default OpenVPN TCP port": {
|
||||||
filteredServers: []models.Server{
|
filteredServers: []models.Server{
|
||||||
{IPs: []net.IP{net.IPv4(1, 1, 1, 1)}},
|
{IPs: []netip.Addr{netip.AddrFrom4([4]byte{1, 1, 1, 1})}},
|
||||||
},
|
},
|
||||||
selection: settings.ServerSelection{
|
selection: settings.ServerSelection{
|
||||||
OpenVPN: settings.OpenVPNSelection{
|
OpenVPN: settings.OpenVPNSelection{
|
||||||
@@ -50,14 +50,14 @@ func Test_Provider_GetConnection(t *testing.T) {
|
|||||||
}.WithDefaults(provider),
|
}.WithDefaults(provider),
|
||||||
connection: models.Connection{
|
connection: models.Connection{
|
||||||
Type: vpn.OpenVPN,
|
Type: vpn.OpenVPN,
|
||||||
IP: net.IPv4(1, 1, 1, 1),
|
IP: netip.AddrFrom4([4]byte{1, 1, 1, 1}),
|
||||||
Port: 443,
|
Port: 443,
|
||||||
Protocol: constants.TCP,
|
Protocol: constants.TCP,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"default OpenVPN UDP port": {
|
"default OpenVPN UDP port": {
|
||||||
filteredServers: []models.Server{
|
filteredServers: []models.Server{
|
||||||
{IPs: []net.IP{net.IPv4(1, 1, 1, 1)}},
|
{IPs: []netip.Addr{netip.AddrFrom4([4]byte{1, 1, 1, 1})}},
|
||||||
},
|
},
|
||||||
selection: settings.ServerSelection{
|
selection: settings.ServerSelection{
|
||||||
OpenVPN: settings.OpenVPNSelection{
|
OpenVPN: settings.OpenVPNSelection{
|
||||||
@@ -66,21 +66,21 @@ func Test_Provider_GetConnection(t *testing.T) {
|
|||||||
}.WithDefaults(provider),
|
}.WithDefaults(provider),
|
||||||
connection: models.Connection{
|
connection: models.Connection{
|
||||||
Type: vpn.OpenVPN,
|
Type: vpn.OpenVPN,
|
||||||
IP: net.IPv4(1, 1, 1, 1),
|
IP: netip.AddrFrom4([4]byte{1, 1, 1, 1}),
|
||||||
Port: 1194,
|
Port: 1194,
|
||||||
Protocol: constants.UDP,
|
Protocol: constants.UDP,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"default Wireguard port": {
|
"default Wireguard port": {
|
||||||
filteredServers: []models.Server{
|
filteredServers: []models.Server{
|
||||||
{IPs: []net.IP{net.IPv4(1, 1, 1, 1)}, WgPubKey: "x"},
|
{IPs: []netip.Addr{netip.AddrFrom4([4]byte{1, 1, 1, 1})}, WgPubKey: "x"},
|
||||||
},
|
},
|
||||||
selection: settings.ServerSelection{
|
selection: settings.ServerSelection{
|
||||||
VPN: vpn.Wireguard,
|
VPN: vpn.Wireguard,
|
||||||
}.WithDefaults(provider),
|
}.WithDefaults(provider),
|
||||||
connection: models.Connection{
|
connection: models.Connection{
|
||||||
Type: vpn.Wireguard,
|
Type: vpn.Wireguard,
|
||||||
IP: net.IPv4(1, 1, 1, 1),
|
IP: netip.AddrFrom4([4]byte{1, 1, 1, 1}),
|
||||||
Port: 51820,
|
Port: 51820,
|
||||||
Protocol: constants.UDP,
|
Protocol: constants.UDP,
|
||||||
PubKey: "x",
|
PubKey: "x",
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package updater
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net/netip"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/constants/vpn"
|
"github.com/qdm12/gluetun/internal/constants/vpn"
|
||||||
@@ -14,8 +14,8 @@ type hostToServer map[string]models.Server
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
ErrNoIP = errors.New("no IP address for VPN server")
|
ErrNoIP = errors.New("no IP address for VPN server")
|
||||||
ErrParseIPv4 = errors.New("cannot parse IPv4 address")
|
ErrIPIsNotV4 = errors.New("IP address is not IPv4")
|
||||||
ErrParseIPv6 = errors.New("cannot parse IPv6 address")
|
ErrIPIsNotV6 = errors.New("IP address is not IPv6")
|
||||||
ErrVPNTypeNotSupported = errors.New("VPN type not supported")
|
ErrVPNTypeNotSupported = errors.New("VPN type not supported")
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -48,17 +48,21 @@ func (hts hostToServer) add(data serverData) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if data.IPv4 != "" {
|
if data.IPv4 != "" {
|
||||||
ipv4 := net.ParseIP(data.IPv4)
|
ipv4, err := netip.ParseAddr(data.IPv4)
|
||||||
if ipv4 == nil || ipv4.To4() == nil {
|
if err != nil {
|
||||||
return fmt.Errorf("%w: %s", ErrParseIPv4, data.IPv4)
|
return fmt.Errorf("parsing IPv4 address: %w", err)
|
||||||
|
} else if !ipv4.Is4() {
|
||||||
|
return fmt.Errorf("%w: %s", ErrIPIsNotV4, data.IPv4)
|
||||||
}
|
}
|
||||||
server.IPs = append(server.IPs, ipv4)
|
server.IPs = append(server.IPs, ipv4)
|
||||||
}
|
}
|
||||||
|
|
||||||
if data.IPv6 != "" {
|
if data.IPv6 != "" {
|
||||||
ipv6 := net.ParseIP(data.IPv6)
|
ipv6, err := netip.ParseAddr(data.IPv6)
|
||||||
if ipv6 == nil || ipv6.To4() != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("%w: %s", ErrParseIPv6, data.IPv6)
|
return fmt.Errorf("parsing IPv6 address: %w", err)
|
||||||
|
} else if !ipv6.Is6() {
|
||||||
|
return fmt.Errorf("%w: %s", ErrIPIsNotV6, data.IPv6)
|
||||||
}
|
}
|
||||||
server.IPs = append(server.IPs, ipv6)
|
server.IPs = append(server.IPs, ipv6)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,29 +1,31 @@
|
|||||||
package updater
|
package updater
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"net/netip"
|
||||||
"net"
|
|
||||||
"sort"
|
"sort"
|
||||||
)
|
)
|
||||||
|
|
||||||
func uniqueSortedIPs(ips []net.IP) []net.IP {
|
func uniqueSortedIPs(ips []netip.Addr) []netip.Addr {
|
||||||
uniqueIPs := make(map[string]struct{}, len(ips))
|
uniqueIPs := make(map[string]struct{}, len(ips))
|
||||||
for _, ip := range ips {
|
for _, ip := range ips {
|
||||||
key := ip.String()
|
key := ip.String()
|
||||||
uniqueIPs[key] = struct{}{}
|
uniqueIPs[key] = struct{}{}
|
||||||
}
|
}
|
||||||
|
|
||||||
ips = make([]net.IP, 0, len(uniqueIPs))
|
ips = make([]netip.Addr, 0, len(uniqueIPs))
|
||||||
for key := range uniqueIPs {
|
for key := range uniqueIPs {
|
||||||
ip := net.ParseIP(key)
|
ip, err := netip.ParseAddr(key)
|
||||||
if ipv4 := ip.To4(); ipv4 != nil {
|
if err != nil {
|
||||||
ip = ipv4
|
panic(err)
|
||||||
|
}
|
||||||
|
if ip.Is4In6() {
|
||||||
|
ip = netip.AddrFrom4(ip.As4())
|
||||||
}
|
}
|
||||||
ips = append(ips, ip)
|
ips = append(ips, ip)
|
||||||
}
|
}
|
||||||
|
|
||||||
sort.Slice(ips, func(i, j int) bool {
|
sort.Slice(ips, func(i, j int) bool {
|
||||||
return bytes.Compare(ips[i], ips[j]) < 0
|
return ips[i].Compare(ips[j]) < 0
|
||||||
})
|
})
|
||||||
|
|
||||||
return ips
|
return ips
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package updater
|
package updater
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net/netip"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@@ -10,24 +10,24 @@ import (
|
|||||||
func Test_uniqueSortedIPs(t *testing.T) {
|
func Test_uniqueSortedIPs(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
testCases := map[string]struct {
|
testCases := map[string]struct {
|
||||||
inputIPs []net.IP
|
inputIPs []netip.Addr
|
||||||
outputIPs []net.IP
|
outputIPs []netip.Addr
|
||||||
}{
|
}{
|
||||||
"nil": {
|
"nil": {
|
||||||
inputIPs: nil,
|
inputIPs: nil,
|
||||||
outputIPs: []net.IP{},
|
outputIPs: []netip.Addr{},
|
||||||
},
|
},
|
||||||
"empty": {
|
"empty": {
|
||||||
inputIPs: []net.IP{},
|
inputIPs: []netip.Addr{},
|
||||||
outputIPs: []net.IP{},
|
outputIPs: []netip.Addr{},
|
||||||
},
|
},
|
||||||
"single IPv4": {
|
"single IPv4": {
|
||||||
inputIPs: []net.IP{{1, 1, 1, 1}},
|
inputIPs: []netip.Addr{netip.AddrFrom4([4]byte{1, 1, 1, 1})},
|
||||||
outputIPs: []net.IP{{1, 1, 1, 1}},
|
outputIPs: []netip.Addr{netip.AddrFrom4([4]byte{1, 1, 1, 1})},
|
||||||
},
|
},
|
||||||
"two IPv4s": {
|
"two IPv4s": {
|
||||||
inputIPs: []net.IP{{1, 1, 2, 1}, {1, 1, 1, 1}},
|
inputIPs: []netip.Addr{netip.AddrFrom4([4]byte{1, 1, 2, 1}), netip.AddrFrom4([4]byte{1, 1, 1, 1})},
|
||||||
outputIPs: []net.IP{{1, 1, 1, 1}, {1, 1, 2, 1}},
|
outputIPs: []netip.Addr{netip.AddrFrom4([4]byte{1, 1, 1, 1}), netip.AddrFrom4([4]byte{1, 1, 2, 1})},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for name, testCase := range testCases {
|
for name, testCase := range testCases {
|
||||||
|
|||||||
@@ -2,15 +2,16 @@ package updater
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net/netip"
|
||||||
)
|
)
|
||||||
|
|
||||||
func parseIPv4(s string) (ipv4 net.IP, err error) {
|
func parseIPv4(s string) (ipv4 netip.Addr, err error) {
|
||||||
ip := net.ParseIP(s)
|
ipv4, err = netip.ParseAddr(s)
|
||||||
if ip == nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%w: %q", ErrParseIP, s)
|
return ipv4, err
|
||||||
} else if ip.To4() == nil {
|
|
||||||
return nil, fmt.Errorf("%w: %s", ErrNotIPv4, ip)
|
|
||||||
}
|
}
|
||||||
return ip, nil
|
if !ipv4.Is4() {
|
||||||
|
return ipv4, fmt.Errorf("%w: %s", ErrNotIPv4, ipv4)
|
||||||
|
}
|
||||||
|
return ipv4, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net/netip"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/constants/vpn"
|
"github.com/qdm12/gluetun/internal/constants/vpn"
|
||||||
@@ -13,7 +13,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrParseIP = errors.New("cannot parse IP address")
|
|
||||||
ErrNotIPv4 = errors.New("IP address is not IPv4")
|
ErrNotIPv4 = errors.New("IP address is not IPv4")
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -47,7 +46,7 @@ func (u *Updater) FetchServers(ctx context.Context, minServers int) (
|
|||||||
Region: jsonServer.Country,
|
Region: jsonServer.Country,
|
||||||
Hostname: jsonServer.Domain,
|
Hostname: jsonServer.Domain,
|
||||||
Number: number,
|
Number: number,
|
||||||
IPs: []net.IP{ip},
|
IPs: []netip.Addr{ip},
|
||||||
TCP: jsonServer.Features.TCP,
|
TCP: jsonServer.Features.TCP,
|
||||||
UDP: jsonServer.Features.UDP,
|
UDP: jsonServer.Features.UDP,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package updater
|
package updater
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net/netip"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/constants/vpn"
|
"github.com/qdm12/gluetun/internal/constants/vpn"
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
|
|
||||||
type cityToServer map[string]models.Server
|
type cityToServer map[string]models.Server
|
||||||
|
|
||||||
func (cts cityToServer) add(city string, ips []net.IP) {
|
func (cts cityToServer) add(city string, ips []netip.Addr) {
|
||||||
server, ok := cts[city]
|
server, ok := cts[city]
|
||||||
if !ok {
|
if !ok {
|
||||||
server.VPN = vpn.OpenVPN
|
server.VPN = vpn.OpenVPN
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package updater
|
package updater
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net/netip"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/constants/vpn"
|
"github.com/qdm12/gluetun/internal/constants/vpn"
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
@@ -28,7 +28,7 @@ func (hts hostToServer) toHostsSlice() (hosts []string) {
|
|||||||
return hosts
|
return hosts
|
||||||
}
|
}
|
||||||
|
|
||||||
func (hts hostToServer) adaptWithIPs(hostToIPs map[string][]net.IP) {
|
func (hts hostToServer) adaptWithIPs(hostToIPs map[string][]netip.Addr) {
|
||||||
for host, IPs := range hostToIPs {
|
for host, IPs := range hostToIPs {
|
||||||
server := hts[host]
|
server := hts[host]
|
||||||
server.IPs = IPs
|
server.IPs = IPs
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package updater
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"net"
|
"net/netip"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
"github.com/qdm12/gluetun/internal/provider/common"
|
"github.com/qdm12/gluetun/internal/provider/common"
|
||||||
@@ -10,7 +10,7 @@ import (
|
|||||||
|
|
||||||
func setLocationInfo(ctx context.Context, fetcher common.IPFetcher, servers []models.Server) (err error) {
|
func setLocationInfo(ctx context.Context, fetcher common.IPFetcher, servers []models.Server) (err error) {
|
||||||
// Get public IP address information
|
// Get public IP address information
|
||||||
ipsToGetInfo := make([]net.IP, 0, len(servers))
|
ipsToGetInfo := make([]netip.Addr, 0, len(servers))
|
||||||
for _, server := range servers {
|
for _, server := range servers {
|
||||||
ipsToGetInfo = append(ipsToGetInfo, server.IPs...)
|
ipsToGetInfo = append(ipsToGetInfo, server.IPs...)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/netip"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -21,14 +22,14 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrServerNameNotFound = errors.New("server name not found in servers")
|
ErrServerNameNotFound = errors.New("server name not found in servers")
|
||||||
ErrGatewayIPIsNil = errors.New("gateway IP address is nil")
|
ErrGatewayIPIsNotValid = errors.New("gateway IP address is not valid")
|
||||||
ErrServerNameEmpty = errors.New("server name is empty")
|
ErrServerNameEmpty = errors.New("server name is empty")
|
||||||
)
|
)
|
||||||
|
|
||||||
// PortForward obtains a VPN server side port forwarded from PIA.
|
// PortForward obtains a VPN server side port forwarded from PIA.
|
||||||
func (p *Provider) PortForward(ctx context.Context, client *http.Client,
|
func (p *Provider) PortForward(ctx context.Context, client *http.Client,
|
||||||
logger utils.Logger, gateway net.IP, serverName string) (
|
logger utils.Logger, gateway netip.Addr, serverName string) (
|
||||||
port uint16, err error) {
|
port uint16, err error) {
|
||||||
server, ok := p.storage.GetServerByName(providers.PrivateInternetAccess, serverName)
|
server, ok := p.storage.GetServerByName(providers.PrivateInternetAccess, serverName)
|
||||||
if !ok {
|
if !ok {
|
||||||
@@ -40,8 +41,8 @@ func (p *Provider) PortForward(ctx context.Context, client *http.Client,
|
|||||||
" (region " + server.Region + ") does not support port forwarding")
|
" (region " + server.Region + ") does not support port forwarding")
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
if gateway == nil {
|
if !gateway.IsValid() {
|
||||||
return 0, ErrGatewayIPIsNil
|
return 0, fmt.Errorf("%w: %s", ErrGatewayIPIsNotValid, gateway)
|
||||||
} else if serverName == "" {
|
} else if serverName == "" {
|
||||||
return 0, ErrServerNameEmpty
|
return 0, ErrServerNameEmpty
|
||||||
}
|
}
|
||||||
@@ -91,7 +92,7 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (p *Provider) KeepPortForward(ctx context.Context,
|
func (p *Provider) KeepPortForward(ctx context.Context,
|
||||||
gateway net.IP, serverName string) (err error) {
|
gateway netip.Addr, serverName string) (err error) {
|
||||||
privateIPClient, err := newHTTPClient(serverName)
|
privateIPClient, err := newHTTPClient(serverName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("creating custom HTTP client: %w", err)
|
return fmt.Errorf("creating custom HTTP client: %w", err)
|
||||||
@@ -132,7 +133,7 @@ func (p *Provider) KeepPortForward(ctx context.Context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func refreshPIAPortForwardData(ctx context.Context, client, privateIPClient *http.Client,
|
func refreshPIAPortForwardData(ctx context.Context, client, privateIPClient *http.Client,
|
||||||
gateway net.IP, portForwardPath, authFilePath string) (data piaPortForwardData, err error) {
|
gateway netip.Addr, portForwardPath, authFilePath string) (data piaPortForwardData, err error) {
|
||||||
data.Token, err = fetchToken(ctx, client, authFilePath)
|
data.Token, err = fetchToken(ctx, client, authFilePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return data, fmt.Errorf("fetching token: %w", err)
|
return data, fmt.Errorf("fetching token: %w", err)
|
||||||
@@ -314,7 +315,7 @@ func getOpenvpnCredentials(authFilePath string) (
|
|||||||
return username, password, nil
|
return username, password, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func fetchPortForwardData(ctx context.Context, client *http.Client, gateway net.IP, token string) (
|
func fetchPortForwardData(ctx context.Context, client *http.Client, gateway netip.Addr, token string) (
|
||||||
port uint16, signature string, expiration time.Time, err error) {
|
port uint16, signature string, expiration time.Time, err error) {
|
||||||
errSubstitutions := map[string]string{url.QueryEscape(token): "<token>"}
|
errSubstitutions := map[string]string{url.QueryEscape(token): "<token>"}
|
||||||
|
|
||||||
@@ -368,7 +369,7 @@ var (
|
|||||||
ErrBadResponse = errors.New("bad response received")
|
ErrBadResponse = errors.New("bad response received")
|
||||||
)
|
)
|
||||||
|
|
||||||
func bindPort(ctx context.Context, client *http.Client, gateway net.IP, data piaPortForwardData) (err error) {
|
func bindPort(ctx context.Context, client *http.Client, gateway netip.Addr, data piaPortForwardData) (err error) {
|
||||||
payload, err := packPayload(data.Port, data.Token, data.Expiration)
|
payload, err := packPayload(data.Port, data.Token, data.Expiration)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("serializing payload: %w", err)
|
return fmt.Errorf("serializing payload: %w", err)
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/netip"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -31,8 +31,8 @@ type regionData struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type serverData struct {
|
type serverData struct {
|
||||||
IP net.IP `json:"ip"`
|
IP netip.Addr `json:"ip"`
|
||||||
CN string `json:"cn"`
|
CN string `json:"cn"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func fetchAPI(ctx context.Context, client *http.Client) (
|
func fetchAPI(ctx context.Context, client *http.Client) (
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package updater
|
package updater
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net/netip"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/constants/vpn"
|
"github.com/qdm12/gluetun/internal/constants/vpn"
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
@@ -10,7 +10,7 @@ import (
|
|||||||
type nameToServer map[string]models.Server
|
type nameToServer map[string]models.Server
|
||||||
|
|
||||||
func (nts nameToServer) add(name, hostname, region string,
|
func (nts nameToServer) add(name, hostname, region string,
|
||||||
tcp, udp, portForward bool, ip net.IP) (change bool) {
|
tcp, udp, portForward bool, ip netip.Addr) (change bool) {
|
||||||
server, ok := nts[name]
|
server, ok := nts[name]
|
||||||
if !ok {
|
if !ok {
|
||||||
change = true
|
change = true
|
||||||
@@ -32,7 +32,7 @@ func (nts nameToServer) add(name, hostname, region string,
|
|||||||
|
|
||||||
ipFound := false
|
ipFound := false
|
||||||
for _, existingIP := range server.IPs {
|
for _, existingIP := range server.IPs {
|
||||||
if ip.Equal(existingIP) {
|
if ip == existingIP {
|
||||||
ipFound = true
|
ipFound = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package updater
|
package updater
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net/netip"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/constants/vpn"
|
"github.com/qdm12/gluetun/internal/constants/vpn"
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
@@ -32,7 +32,7 @@ func (hts hostToServer) toHostsSlice() (hosts []string) {
|
|||||||
return hosts
|
return hosts
|
||||||
}
|
}
|
||||||
|
|
||||||
func (hts hostToServer) adaptWithIPs(hostToIPs map[string][]net.IP) {
|
func (hts hostToServer) adaptWithIPs(hostToIPs map[string][]netip.Addr) {
|
||||||
for host, IPs := range hostToIPs {
|
for host, IPs := range hostToIPs {
|
||||||
server := hts[host]
|
server := hts[host]
|
||||||
server.IPs = IPs
|
server.IPs = IPs
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/netip"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -26,8 +26,8 @@ type logicalServer struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type physicalServer struct {
|
type physicalServer struct {
|
||||||
EntryIP net.IP
|
EntryIP netip.Addr
|
||||||
ExitIP net.IP
|
ExitIP netip.Addr
|
||||||
Domain string
|
Domain string
|
||||||
Status uint8
|
Status uint8
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package updater
|
package updater
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net/netip"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/constants/vpn"
|
"github.com/qdm12/gluetun/internal/constants/vpn"
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
@@ -10,7 +10,7 @@ import (
|
|||||||
type ipToServer map[string]models.Server
|
type ipToServer map[string]models.Server
|
||||||
|
|
||||||
func (its ipToServer) add(country, region, city, name, hostname string,
|
func (its ipToServer) add(country, region, city, name, hostname string,
|
||||||
free bool, entryIP net.IP) {
|
free bool, entryIP netip.Addr) {
|
||||||
key := entryIP.String()
|
key := entryIP.String()
|
||||||
|
|
||||||
server, ok := its[key]
|
server, ok := its[key]
|
||||||
@@ -27,7 +27,7 @@ func (its ipToServer) add(country, region, city, name, hostname string,
|
|||||||
server.Free = free
|
server.Free = free
|
||||||
server.UDP = true
|
server.UDP = true
|
||||||
server.TCP = true
|
server.TCP = true
|
||||||
server.IPs = []net.IP{entryIP}
|
server.IPs = []netip.Addr{entryIP}
|
||||||
its[key] = server
|
its[key] = server
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ package provider
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"net"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/netip"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/configuration/settings"
|
"github.com/qdm12/gluetun/internal/configuration/settings"
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
@@ -22,8 +22,8 @@ type Provider interface {
|
|||||||
|
|
||||||
type PortForwarder interface {
|
type PortForwarder interface {
|
||||||
PortForward(ctx context.Context, client *http.Client,
|
PortForward(ctx context.Context, client *http.Client,
|
||||||
logger utils.Logger, gateway net.IP, serverName string) (
|
logger utils.Logger, gateway netip.Addr, serverName string) (
|
||||||
port uint16, err error)
|
port uint16, err error)
|
||||||
KeepPortForward(ctx context.Context, gateway net.IP,
|
KeepPortForward(ctx context.Context, gateway netip.Addr,
|
||||||
serverName string) (err error)
|
serverName string) (err error)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package updater
|
package updater
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net/netip"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/constants/vpn"
|
"github.com/qdm12/gluetun/internal/constants/vpn"
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
@@ -32,7 +32,7 @@ func (hts hostToServer) toHostsSlice() (hosts []string) {
|
|||||||
return hosts
|
return hosts
|
||||||
}
|
}
|
||||||
|
|
||||||
func (hts hostToServer) adaptWithIPs(hostToIPs map[string][]net.IP) {
|
func (hts hostToServer) adaptWithIPs(hostToIPs map[string][]netip.Addr) {
|
||||||
for host, IPs := range hostToIPs {
|
for host, IPs := range hostToIPs {
|
||||||
server := hts[host]
|
server := hts[host]
|
||||||
server.IPs = IPs
|
server.IPs = IPs
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package updater
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net/netip"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -76,7 +76,7 @@ func (u *Updater) FetchServers(ctx context.Context, minServers int) (
|
|||||||
servers = hts.toServersSlice()
|
servers = hts.toServersSlice()
|
||||||
|
|
||||||
// Get public IP address information
|
// Get public IP address information
|
||||||
ipsToGetInfo := make([]net.IP, len(servers))
|
ipsToGetInfo := make([]netip.Addr, len(servers))
|
||||||
for i := range servers {
|
for i := range servers {
|
||||||
ipsToGetInfo[i] = servers[i].IPs[0]
|
ipsToGetInfo[i] = servers[i].IPs[0]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package updater
|
package updater
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net/netip"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/constants/vpn"
|
"github.com/qdm12/gluetun/internal/constants/vpn"
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
@@ -75,7 +75,7 @@ func (hts hostToServers) toHostsSlice() (hosts []string) {
|
|||||||
return hosts
|
return hosts
|
||||||
}
|
}
|
||||||
|
|
||||||
func (hts hostToServers) adaptWithIPs(hostToIPs map[string][]net.IP) {
|
func (hts hostToServers) adaptWithIPs(hostToIPs map[string][]netip.Addr) {
|
||||||
for host, IPs := range hostToIPs {
|
for host, IPs := range hostToIPs {
|
||||||
servers := hts[host]
|
servers := hts[host]
|
||||||
for i := range servers {
|
for i := range servers {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package updater
|
package updater
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net/netip"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/constants/vpn"
|
"github.com/qdm12/gluetun/internal/constants/vpn"
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
@@ -10,7 +10,7 @@ import (
|
|||||||
type hostToServer map[string]models.Server
|
type hostToServer map[string]models.Server
|
||||||
|
|
||||||
func (hts hostToServer) add(host, country, city string,
|
func (hts hostToServer) add(host, country, city string,
|
||||||
tcp, udp bool, ips []net.IP) {
|
tcp, udp bool, ips []netip.Addr) {
|
||||||
server, ok := hts[host]
|
server, ok := hts[host]
|
||||||
if !ok {
|
if !ok {
|
||||||
server.VPN = vpn.OpenVPN
|
server.VPN = vpn.OpenVPN
|
||||||
@@ -39,7 +39,7 @@ func (hts hostToServer) toHostsSlice() (hosts []string) {
|
|||||||
return hosts
|
return hosts
|
||||||
}
|
}
|
||||||
|
|
||||||
func (hts hostToServer) adaptWithIPs(hostToIPs map[string][]net.IP) {
|
func (hts hostToServer) adaptWithIPs(hostToIPs map[string][]netip.Addr) {
|
||||||
for host, IPs := range hostToIPs {
|
for host, IPs := range hostToIPs {
|
||||||
server := hts[host]
|
server := hts[host]
|
||||||
server.IPs = IPs
|
server.IPs = IPs
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ func GetConnection(provider string,
|
|||||||
connections := make([]models.Connection, 0, len(servers))
|
connections := make([]models.Connection, 0, len(servers))
|
||||||
for _, server := range servers {
|
for _, server := range servers {
|
||||||
for _, ip := range server.IPs {
|
for _, ip := range server.IPs {
|
||||||
if !ipv6Supported && ip.To4() == nil {
|
if !ipv6Supported && ip.Is6() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package utils
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net"
|
"net/netip"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/golang/mock/gomock"
|
"github.com/golang/mock/gomock"
|
||||||
@@ -58,7 +58,7 @@ func Test_GetConnection(t *testing.T) {
|
|||||||
{
|
{
|
||||||
VPN: vpn.OpenVPN,
|
VPN: vpn.OpenVPN,
|
||||||
UDP: true,
|
UDP: true,
|
||||||
IPs: []net.IP{net.IPv4(1, 1, 1, 1)},
|
IPs: []netip.Addr{netip.AddrFrom4([4]byte{1, 1, 1, 1})},
|
||||||
Hostname: "name",
|
Hostname: "name",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -68,7 +68,7 @@ func Test_GetConnection(t *testing.T) {
|
|||||||
randSource: rand.NewSource(0),
|
randSource: rand.NewSource(0),
|
||||||
connection: models.Connection{
|
connection: models.Connection{
|
||||||
Type: vpn.OpenVPN,
|
Type: vpn.OpenVPN,
|
||||||
IP: net.IPv4(1, 1, 1, 1),
|
IP: netip.AddrFrom4([4]byte{1, 1, 1, 1}),
|
||||||
Protocol: constants.UDP,
|
Protocol: constants.UDP,
|
||||||
Port: 1194,
|
Port: 1194,
|
||||||
Hostname: "name",
|
Hostname: "name",
|
||||||
@@ -79,7 +79,7 @@ func Test_GetConnection(t *testing.T) {
|
|||||||
{
|
{
|
||||||
VPN: vpn.OpenVPN,
|
VPN: vpn.OpenVPN,
|
||||||
UDP: true,
|
UDP: true,
|
||||||
IPs: []net.IP{net.IPv4(1, 1, 1, 1)},
|
IPs: []netip.Addr{netip.AddrFrom4([4]byte{1, 1, 1, 1})},
|
||||||
Hostname: "hostname",
|
Hostname: "hostname",
|
||||||
OvpnX509: "x509",
|
OvpnX509: "x509",
|
||||||
},
|
},
|
||||||
@@ -90,7 +90,7 @@ func Test_GetConnection(t *testing.T) {
|
|||||||
randSource: rand.NewSource(0),
|
randSource: rand.NewSource(0),
|
||||||
connection: models.Connection{
|
connection: models.Connection{
|
||||||
Type: vpn.OpenVPN,
|
Type: vpn.OpenVPN,
|
||||||
IP: net.IPv4(1, 1, 1, 1),
|
IP: netip.AddrFrom4([4]byte{1, 1, 1, 1}),
|
||||||
Protocol: constants.UDP,
|
Protocol: constants.UDP,
|
||||||
Port: 1194,
|
Port: 1194,
|
||||||
Hostname: "x509",
|
Hostname: "x509",
|
||||||
@@ -101,14 +101,14 @@ func Test_GetConnection(t *testing.T) {
|
|||||||
{
|
{
|
||||||
VPN: vpn.OpenVPN,
|
VPN: vpn.OpenVPN,
|
||||||
UDP: true,
|
UDP: true,
|
||||||
IPs: []net.IP{
|
IPs: []netip.Addr{
|
||||||
net.IPv4(1, 1, 1, 1),
|
netip.AddrFrom4([4]byte{1, 1, 1, 1}),
|
||||||
// All IPv6 is ignored
|
// All IPv6 is ignored
|
||||||
net.IPv6zero,
|
netip.IPv6Unspecified(),
|
||||||
net.IPv6zero,
|
netip.IPv6Unspecified(),
|
||||||
net.IPv6zero,
|
netip.IPv6Unspecified(),
|
||||||
net.IPv6zero,
|
netip.IPv6Unspecified(),
|
||||||
net.IPv6zero,
|
netip.IPv6Unspecified(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -118,7 +118,7 @@ func Test_GetConnection(t *testing.T) {
|
|||||||
randSource: rand.NewSource(0),
|
randSource: rand.NewSource(0),
|
||||||
connection: models.Connection{
|
connection: models.Connection{
|
||||||
Type: vpn.OpenVPN,
|
Type: vpn.OpenVPN,
|
||||||
IP: net.IPv4(1, 1, 1, 1),
|
IP: netip.AddrFrom4([4]byte{1, 1, 1, 1}),
|
||||||
Protocol: constants.UDP,
|
Protocol: constants.UDP,
|
||||||
Port: 1194,
|
Port: 1194,
|
||||||
},
|
},
|
||||||
@@ -128,9 +128,9 @@ func Test_GetConnection(t *testing.T) {
|
|||||||
{
|
{
|
||||||
VPN: vpn.OpenVPN,
|
VPN: vpn.OpenVPN,
|
||||||
UDP: true,
|
UDP: true,
|
||||||
IPs: []net.IP{
|
IPs: []netip.Addr{
|
||||||
net.IPv6zero,
|
netip.IPv6Unspecified(),
|
||||||
net.IPv4(1, 1, 1, 1),
|
netip.AddrFrom4([4]byte{1, 1, 1, 1}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -141,7 +141,7 @@ func Test_GetConnection(t *testing.T) {
|
|||||||
randSource: rand.NewSource(0),
|
randSource: rand.NewSource(0),
|
||||||
connection: models.Connection{
|
connection: models.Connection{
|
||||||
Type: vpn.OpenVPN,
|
Type: vpn.OpenVPN,
|
||||||
IP: net.IPv6zero,
|
IP: netip.IPv6Unspecified(),
|
||||||
Protocol: constants.UDP,
|
Protocol: constants.UDP,
|
||||||
Port: 1194,
|
Port: 1194,
|
||||||
},
|
},
|
||||||
@@ -151,21 +151,21 @@ func Test_GetConnection(t *testing.T) {
|
|||||||
{
|
{
|
||||||
VPN: vpn.OpenVPN,
|
VPN: vpn.OpenVPN,
|
||||||
UDP: true,
|
UDP: true,
|
||||||
IPs: []net.IP{net.IPv4(1, 1, 1, 1)},
|
IPs: []netip.Addr{netip.AddrFrom4([4]byte{1, 1, 1, 1})},
|
||||||
OvpnX509: "ovpnx509",
|
OvpnX509: "ovpnx509",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
VPN: vpn.Wireguard,
|
VPN: vpn.Wireguard,
|
||||||
UDP: true,
|
UDP: true,
|
||||||
IPs: []net.IP{net.IPv4(2, 2, 2, 2)},
|
IPs: []netip.Addr{netip.AddrFrom4([4]byte{2, 2, 2, 2})},
|
||||||
OvpnX509: "ovpnx509",
|
OvpnX509: "ovpnx509",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
VPN: vpn.OpenVPN,
|
VPN: vpn.OpenVPN,
|
||||||
UDP: true,
|
UDP: true,
|
||||||
IPs: []net.IP{
|
IPs: []netip.Addr{
|
||||||
net.IPv4(3, 3, 3, 3),
|
netip.AddrFrom4([4]byte{3, 3, 3, 3}),
|
||||||
{1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, // ipv6 ignored
|
netip.AddrFrom16([16]byte{1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}), // ipv6 ignored
|
||||||
},
|
},
|
||||||
Hostname: "hostname",
|
Hostname: "hostname",
|
||||||
},
|
},
|
||||||
@@ -176,7 +176,7 @@ func Test_GetConnection(t *testing.T) {
|
|||||||
randSource: rand.NewSource(0),
|
randSource: rand.NewSource(0),
|
||||||
connection: models.Connection{
|
connection: models.Connection{
|
||||||
Type: vpn.OpenVPN,
|
Type: vpn.OpenVPN,
|
||||||
IP: net.IPv4(1, 1, 1, 1),
|
IP: netip.AddrFrom4([4]byte{1, 1, 1, 1}),
|
||||||
Protocol: constants.UDP,
|
Protocol: constants.UDP,
|
||||||
Port: 1194,
|
Port: 1194,
|
||||||
Hostname: "ovpnx509",
|
Hostname: "ovpnx509",
|
||||||
|
|||||||
@@ -4,15 +4,15 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/netip"
|
||||||
)
|
)
|
||||||
|
|
||||||
type NoPortForwarder interface {
|
type NoPortForwarder interface {
|
||||||
PortForward(ctx context.Context, client *http.Client,
|
PortForward(ctx context.Context, client *http.Client,
|
||||||
logger Logger, gateway net.IP, serverName string) (
|
logger Logger, gateway netip.Addr, serverName string) (
|
||||||
port uint16, err error)
|
port uint16, err error)
|
||||||
KeepPortForward(ctx context.Context, gateway net.IP,
|
KeepPortForward(ctx context.Context, gateway netip.Addr,
|
||||||
serverName string) (err error)
|
serverName string) (err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,10 +29,10 @@ func NewNoPortForwarding(providerName string) *NoPortForwarding {
|
|||||||
var ErrPortForwardingNotSupported = errors.New("custom port forwarding obtention is not supported")
|
var ErrPortForwardingNotSupported = errors.New("custom port forwarding obtention is not supported")
|
||||||
|
|
||||||
func (n *NoPortForwarding) PortForward(context.Context, *http.Client,
|
func (n *NoPortForwarding) PortForward(context.Context, *http.Client,
|
||||||
Logger, net.IP, string) (port uint16, err error) {
|
Logger, netip.Addr, string) (port uint16, err error) {
|
||||||
return 0, fmt.Errorf("%w: for %s", ErrPortForwardingNotSupported, n.providerName)
|
return 0, fmt.Errorf("%w: for %s", ErrPortForwardingNotSupported, n.providerName)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *NoPortForwarding) KeepPortForward(context.Context, net.IP, string) (err error) {
|
func (n *NoPortForwarding) KeepPortForward(context.Context, netip.Addr, string) (err error) {
|
||||||
return fmt.Errorf("%w: for %s", ErrPortForwardingNotSupported, n.providerName)
|
return fmt.Errorf("%w: for %s", ErrPortForwardingNotSupported, n.providerName)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net"
|
"net/netip"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/configuration/settings"
|
"github.com/qdm12/gluetun/internal/configuration/settings"
|
||||||
"github.com/qdm12/gluetun/internal/constants/vpn"
|
"github.com/qdm12/gluetun/internal/constants/vpn"
|
||||||
@@ -25,13 +25,15 @@ func pickConnection(connections []models.Connection,
|
|||||||
return connection, ErrNoConnectionToPickFrom
|
return connection, ErrNoConnectionToPickFrom
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(selection.TargetIP) > 0 && selection.VPN == vpn.Wireguard {
|
targetIPSet := selection.TargetIP.IsValid() && !selection.TargetIP.IsUnspecified()
|
||||||
|
|
||||||
|
if targetIPSet && selection.VPN == vpn.Wireguard {
|
||||||
// we need the right public key
|
// we need the right public key
|
||||||
return getTargetIPConnection(connections, selection.TargetIP)
|
return getTargetIPConnection(connections, selection.TargetIP)
|
||||||
}
|
}
|
||||||
|
|
||||||
connection = pickRandomConnection(connections, randSource)
|
connection = pickRandomConnection(connections, randSource)
|
||||||
if len(selection.TargetIP) > 0 {
|
if targetIPSet {
|
||||||
connection.IP = selection.TargetIP
|
connection.IP = selection.TargetIP
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,9 +48,9 @@ func pickRandomConnection(connections []models.Connection,
|
|||||||
var errTargetIPNotFound = errors.New("target IP address not found")
|
var errTargetIPNotFound = errors.New("target IP address not found")
|
||||||
|
|
||||||
func getTargetIPConnection(connections []models.Connection,
|
func getTargetIPConnection(connections []models.Connection,
|
||||||
targetIP net.IP) (connection models.Connection, err error) {
|
targetIP netip.Addr) (connection models.Connection, err error) {
|
||||||
for _, connection := range connections {
|
for _, connection := range connections {
|
||||||
if targetIP.Equal(connection.IP) {
|
if targetIP == connection.IP {
|
||||||
return connection, nil
|
return connection, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,8 +22,7 @@ func BuildWireguardSettings(connection models.Connection,
|
|||||||
settings.RulePriority = rulePriority
|
settings.RulePriority = rulePriority
|
||||||
|
|
||||||
settings.Endpoint = new(net.UDPAddr)
|
settings.Endpoint = new(net.UDPAddr)
|
||||||
settings.Endpoint.IP = make(net.IP, len(connection.IP))
|
settings.Endpoint.IP = connection.IP.AsSlice()
|
||||||
copy(settings.Endpoint.IP, connection.IP)
|
|
||||||
settings.Endpoint.Port = int(connection.Port)
|
settings.Endpoint.Port = int(connection.Port)
|
||||||
|
|
||||||
settings.Addresses = make([]netip.Prefix, 0, len(userSettings.Addresses))
|
settings.Addresses = make([]netip.Prefix, 0, len(userSettings.Addresses))
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ func Test_BuildWireguardSettings(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
"some settings": {
|
"some settings": {
|
||||||
connection: models.Connection{
|
connection: models.Connection{
|
||||||
IP: net.IPv4(1, 2, 3, 4),
|
IP: netip.AddrFrom4([4]byte{1, 2, 3, 4}),
|
||||||
Port: 51821,
|
Port: 51821,
|
||||||
PubKey: "public",
|
PubKey: "public",
|
||||||
},
|
},
|
||||||
@@ -44,7 +44,7 @@ func Test_BuildWireguardSettings(t *testing.T) {
|
|||||||
PublicKey: "public",
|
PublicKey: "public",
|
||||||
PreSharedKey: "pre-shared",
|
PreSharedKey: "pre-shared",
|
||||||
Endpoint: &net.UDPAddr{
|
Endpoint: &net.UDPAddr{
|
||||||
IP: net.IPv4(1, 2, 3, 4),
|
IP: net.IP{1, 2, 3, 4},
|
||||||
Port: 51821,
|
Port: 51821,
|
||||||
},
|
},
|
||||||
Addresses: []netip.Prefix{
|
Addresses: []netip.Prefix{
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package updater
|
package updater
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net/netip"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
)
|
)
|
||||||
@@ -16,7 +16,7 @@ func (hts hostToServer) toHostsSlice() (hosts []string) {
|
|||||||
return hosts
|
return hosts
|
||||||
}
|
}
|
||||||
|
|
||||||
func (hts hostToServer) adaptWithIPs(hostToIPs map[string][]net.IP) {
|
func (hts hostToServer) adaptWithIPs(hostToIPs map[string][]netip.Addr) {
|
||||||
for host, IPs := range hostToIPs {
|
for host, IPs := range hostToIPs {
|
||||||
server := hts[host]
|
server := hts[host]
|
||||||
server.IPs = IPs
|
server.IPs = IPs
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package updater
|
package updater
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net/netip"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
)
|
)
|
||||||
@@ -16,7 +16,7 @@ func (hts hostToServer) toHostsSlice() (hosts []string) {
|
|||||||
return hosts
|
return hosts
|
||||||
}
|
}
|
||||||
|
|
||||||
func (hts hostToServer) adaptWithIPs(hostToIPs map[string][]net.IP) {
|
func (hts hostToServer) adaptWithIPs(hostToIPs map[string][]netip.Addr) {
|
||||||
for host, IPs := range hostToIPs {
|
for host, IPs := range hostToIPs {
|
||||||
server := hts[host]
|
server := hts[host]
|
||||||
server.IPs = IPs
|
server.IPs = IPs
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package updater
|
package updater
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net/netip"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/constants/vpn"
|
"github.com/qdm12/gluetun/internal/constants/vpn"
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
@@ -33,7 +33,7 @@ func (hts hostToServer) toHostsSlice() (hosts []string) {
|
|||||||
return hosts
|
return hosts
|
||||||
}
|
}
|
||||||
|
|
||||||
func (hts hostToServer) adaptWithIPs(hostToIPs map[string][]net.IP) {
|
func (hts hostToServer) adaptWithIPs(hostToIPs map[string][]netip.Addr) {
|
||||||
for host, IPs := range hostToIPs {
|
for host, IPs := range hostToIPs {
|
||||||
server := hts[host]
|
server := hts[host]
|
||||||
server.IPs = IPs
|
server.IPs = IPs
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package wevpn
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net"
|
"net/netip"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/golang/mock/gomock"
|
"github.com/golang/mock/gomock"
|
||||||
@@ -41,7 +41,7 @@ func Test_Provider_GetConnection(t *testing.T) {
|
|||||||
},
|
},
|
||||||
"default OpenVPN TCP port": {
|
"default OpenVPN TCP port": {
|
||||||
filteredServers: []models.Server{
|
filteredServers: []models.Server{
|
||||||
{IPs: []net.IP{net.IPv4(1, 1, 1, 1)}},
|
{IPs: []netip.Addr{netip.AddrFrom4([4]byte{1, 1, 1, 1})}},
|
||||||
},
|
},
|
||||||
selection: settings.ServerSelection{
|
selection: settings.ServerSelection{
|
||||||
OpenVPN: settings.OpenVPNSelection{
|
OpenVPN: settings.OpenVPNSelection{
|
||||||
@@ -50,14 +50,14 @@ func Test_Provider_GetConnection(t *testing.T) {
|
|||||||
}.WithDefaults(provider),
|
}.WithDefaults(provider),
|
||||||
connection: models.Connection{
|
connection: models.Connection{
|
||||||
Type: vpn.OpenVPN,
|
Type: vpn.OpenVPN,
|
||||||
IP: net.IPv4(1, 1, 1, 1),
|
IP: netip.AddrFrom4([4]byte{1, 1, 1, 1}),
|
||||||
Port: 1195,
|
Port: 1195,
|
||||||
Protocol: constants.TCP,
|
Protocol: constants.TCP,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"default OpenVPN UDP port": {
|
"default OpenVPN UDP port": {
|
||||||
filteredServers: []models.Server{
|
filteredServers: []models.Server{
|
||||||
{IPs: []net.IP{net.IPv4(1, 1, 1, 1)}},
|
{IPs: []netip.Addr{netip.AddrFrom4([4]byte{1, 1, 1, 1})}},
|
||||||
},
|
},
|
||||||
selection: settings.ServerSelection{
|
selection: settings.ServerSelection{
|
||||||
OpenVPN: settings.OpenVPNSelection{
|
OpenVPN: settings.OpenVPNSelection{
|
||||||
@@ -66,14 +66,14 @@ func Test_Provider_GetConnection(t *testing.T) {
|
|||||||
}.WithDefaults(provider),
|
}.WithDefaults(provider),
|
||||||
connection: models.Connection{
|
connection: models.Connection{
|
||||||
Type: vpn.OpenVPN,
|
Type: vpn.OpenVPN,
|
||||||
IP: net.IPv4(1, 1, 1, 1),
|
IP: netip.AddrFrom4([4]byte{1, 1, 1, 1}),
|
||||||
Port: 1194,
|
Port: 1194,
|
||||||
Protocol: constants.UDP,
|
Protocol: constants.UDP,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"default Wireguard port": {
|
"default Wireguard port": {
|
||||||
filteredServers: []models.Server{
|
filteredServers: []models.Server{
|
||||||
{IPs: []net.IP{net.IPv4(1, 1, 1, 1)}, WgPubKey: "x"},
|
{IPs: []netip.Addr{netip.AddrFrom4([4]byte{1, 1, 1, 1})}, WgPubKey: "x"},
|
||||||
},
|
},
|
||||||
selection: settings.ServerSelection{
|
selection: settings.ServerSelection{
|
||||||
VPN: vpn.Wireguard,
|
VPN: vpn.Wireguard,
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ package windscribe
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/netip"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/golang/mock/gomock"
|
"github.com/golang/mock/gomock"
|
||||||
@@ -42,7 +42,7 @@ func Test_Provider_GetConnection(t *testing.T) {
|
|||||||
},
|
},
|
||||||
"default OpenVPN TCP port": {
|
"default OpenVPN TCP port": {
|
||||||
filteredServers: []models.Server{
|
filteredServers: []models.Server{
|
||||||
{IPs: []net.IP{net.IPv4(1, 1, 1, 1)}},
|
{IPs: []netip.Addr{netip.AddrFrom4([4]byte{1, 1, 1, 1})}},
|
||||||
},
|
},
|
||||||
selection: settings.ServerSelection{
|
selection: settings.ServerSelection{
|
||||||
OpenVPN: settings.OpenVPNSelection{
|
OpenVPN: settings.OpenVPNSelection{
|
||||||
@@ -51,14 +51,14 @@ func Test_Provider_GetConnection(t *testing.T) {
|
|||||||
}.WithDefaults(provider),
|
}.WithDefaults(provider),
|
||||||
connection: models.Connection{
|
connection: models.Connection{
|
||||||
Type: vpn.OpenVPN,
|
Type: vpn.OpenVPN,
|
||||||
IP: net.IPv4(1, 1, 1, 1),
|
IP: netip.AddrFrom4([4]byte{1, 1, 1, 1}),
|
||||||
Port: 443,
|
Port: 443,
|
||||||
Protocol: constants.TCP,
|
Protocol: constants.TCP,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"default OpenVPN UDP port": {
|
"default OpenVPN UDP port": {
|
||||||
filteredServers: []models.Server{
|
filteredServers: []models.Server{
|
||||||
{IPs: []net.IP{net.IPv4(1, 1, 1, 1)}},
|
{IPs: []netip.Addr{netip.AddrFrom4([4]byte{1, 1, 1, 1})}},
|
||||||
},
|
},
|
||||||
selection: settings.ServerSelection{
|
selection: settings.ServerSelection{
|
||||||
OpenVPN: settings.OpenVPNSelection{
|
OpenVPN: settings.OpenVPNSelection{
|
||||||
@@ -67,21 +67,21 @@ func Test_Provider_GetConnection(t *testing.T) {
|
|||||||
}.WithDefaults(provider),
|
}.WithDefaults(provider),
|
||||||
connection: models.Connection{
|
connection: models.Connection{
|
||||||
Type: vpn.OpenVPN,
|
Type: vpn.OpenVPN,
|
||||||
IP: net.IPv4(1, 1, 1, 1),
|
IP: netip.AddrFrom4([4]byte{1, 1, 1, 1}),
|
||||||
Port: 1194,
|
Port: 1194,
|
||||||
Protocol: constants.UDP,
|
Protocol: constants.UDP,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"default Wireguard port": {
|
"default Wireguard port": {
|
||||||
filteredServers: []models.Server{
|
filteredServers: []models.Server{
|
||||||
{IPs: []net.IP{net.IPv4(1, 1, 1, 1)}, WgPubKey: "x"},
|
{IPs: []netip.Addr{netip.AddrFrom4([4]byte{1, 1, 1, 1})}, WgPubKey: "x"},
|
||||||
},
|
},
|
||||||
selection: settings.ServerSelection{
|
selection: settings.ServerSelection{
|
||||||
VPN: vpn.Wireguard,
|
VPN: vpn.Wireguard,
|
||||||
}.WithDefaults(provider),
|
}.WithDefaults(provider),
|
||||||
connection: models.Connection{
|
connection: models.Connection{
|
||||||
Type: vpn.Wireguard,
|
Type: vpn.Wireguard,
|
||||||
IP: net.IPv4(1, 1, 1, 1),
|
IP: netip.AddrFrom4([4]byte{1, 1, 1, 1}),
|
||||||
Port: 1194,
|
Port: 1194,
|
||||||
Protocol: constants.UDP,
|
Protocol: constants.UDP,
|
||||||
PubKey: "x",
|
PubKey: "x",
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/netip"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@@ -32,10 +32,10 @@ type groupData struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type serverData struct {
|
type serverData struct {
|
||||||
Hostname string `json:"hostname"`
|
Hostname string `json:"hostname"`
|
||||||
IP net.IP `json:"ip"`
|
IP netip.Addr `json:"ip"`
|
||||||
IP2 net.IP `json:"ip2"`
|
IP2 netip.Addr `json:"ip2"`
|
||||||
IP3 net.IP `json:"ip3"`
|
IP3 netip.Addr `json:"ip3"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func fetchAPI(ctx context.Context, client *http.Client) (
|
func fetchAPI(ctx context.Context, client *http.Client) (
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net/netip"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/constants/vpn"
|
"github.com/qdm12/gluetun/internal/constants/vpn"
|
||||||
@@ -30,11 +30,11 @@ func (u *Updater) FetchServers(ctx context.Context, minServers int) (
|
|||||||
x5090Name := group.OvpnX509
|
x5090Name := group.OvpnX509
|
||||||
wgPubKey := group.WgPubKey
|
wgPubKey := group.WgPubKey
|
||||||
for _, node := range group.Nodes {
|
for _, node := range group.Nodes {
|
||||||
ips := make([]net.IP, 0, 2) //nolint:gomnd
|
ips := make([]netip.Addr, 0, 2) //nolint:gomnd
|
||||||
if node.IP != nil {
|
if node.IP.IsValid() {
|
||||||
ips = append(ips, node.IP)
|
ips = append(ips, node.IP)
|
||||||
}
|
}
|
||||||
if node.IP2 != nil {
|
if node.IP2.IsValid() {
|
||||||
ips = append(ips, node.IP2)
|
ips = append(ips, node.IP2)
|
||||||
}
|
}
|
||||||
server := models.Server{
|
server := models.Server{
|
||||||
@@ -49,7 +49,7 @@ func (u *Updater) FetchServers(ctx context.Context, minServers int) (
|
|||||||
}
|
}
|
||||||
servers = append(servers, server)
|
servers = append(servers, server)
|
||||||
|
|
||||||
if node.IP3 == nil { // Wireguard + Stealth
|
if !node.IP3.IsValid() { // Wireguard + Stealth
|
||||||
continue
|
continue
|
||||||
} else if wgPubKey == "" {
|
} else if wgPubKey == "" {
|
||||||
return nil, fmt.Errorf("%w: for node %s", ErrNoWireguardKey, node.Hostname)
|
return nil, fmt.Errorf("%w: for node %s", ErrNoWireguardKey, node.Hostname)
|
||||||
@@ -60,7 +60,7 @@ func (u *Updater) FetchServers(ctx context.Context, minServers int) (
|
|||||||
server.TCP = false
|
server.TCP = false
|
||||||
server.OvpnX509 = ""
|
server.OvpnX509 = ""
|
||||||
server.WgPubKey = wgPubKey
|
server.WgPubKey = wgPubKey
|
||||||
server.IPs = []net.IP{node.IP3}
|
server.IPs = []netip.Addr{node.IP3}
|
||||||
servers = append(servers, server)
|
servers = append(servers, server)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,12 +2,12 @@ package publicip
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"net"
|
"net/netip"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/publicip/ipinfo"
|
"github.com/qdm12/gluetun/internal/publicip/ipinfo"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Fetcher interface {
|
type Fetcher interface {
|
||||||
FetchInfo(ctx context.Context, ip net.IP) (
|
FetchInfo(ctx context.Context, ip netip.Addr) (
|
||||||
result ipinfo.Response, err error)
|
result ipinfo.Response, err error)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/netip"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/constants"
|
"github.com/qdm12/gluetun/internal/constants"
|
||||||
@@ -28,13 +28,13 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// FetchInfo obtains information on the ip address provided
|
// FetchInfo obtains information on the ip address provided
|
||||||
// using the ipinfo.io API. If the ip is nil, the public IP address
|
// using the ipinfo.io API. If the ip is the zero value, the public IP address
|
||||||
// of the machine is used as the IP.
|
// of the machine is used as the IP.
|
||||||
func (f *Fetch) FetchInfo(ctx context.Context, ip net.IP) (
|
func (f *Fetch) FetchInfo(ctx context.Context, ip netip.Addr) (
|
||||||
result Response, err error) {
|
result Response, err error) {
|
||||||
const baseURL = "https://ipinfo.io/"
|
const baseURL = "https://ipinfo.io/"
|
||||||
url := baseURL
|
url := baseURL
|
||||||
if ip != nil {
|
if ip.IsValid() {
|
||||||
url += ip.String()
|
url += ip.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,26 +1,26 @@
|
|||||||
package ipinfo
|
package ipinfo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net/netip"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Response struct {
|
type Response struct {
|
||||||
IP net.IP `json:"ip,omitempty"`
|
IP netip.Addr `json:"ip,omitempty"`
|
||||||
Region string `json:"region,omitempty"`
|
Region string `json:"region,omitempty"`
|
||||||
Country string `json:"country,omitempty"`
|
Country string `json:"country,omitempty"`
|
||||||
City string `json:"city,omitempty"`
|
City string `json:"city,omitempty"`
|
||||||
Hostname string `json:"hostname,omitempty"`
|
Hostname string `json:"hostname,omitempty"`
|
||||||
Loc string `json:"loc,omitempty"`
|
Loc string `json:"loc,omitempty"`
|
||||||
Org string `json:"org,omitempty"`
|
Org string `json:"org,omitempty"`
|
||||||
Postal string `json:"postal,omitempty"`
|
Postal string `json:"postal,omitempty"`
|
||||||
Timezone string `json:"timezone,omitempty"`
|
Timezone string `json:"timezone,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Response) ToPublicIPModel() (model models.PublicIP) {
|
func (r *Response) ToPublicIPModel() (model models.PublicIP) {
|
||||||
model = models.PublicIP{
|
return models.PublicIP{
|
||||||
IP: make(net.IP, len(r.IP)),
|
IP: r.IP,
|
||||||
Region: r.Region,
|
Region: r.Region,
|
||||||
Country: r.Country,
|
Country: r.Country,
|
||||||
City: r.City,
|
City: r.City,
|
||||||
@@ -30,6 +30,4 @@ func (r *Response) ToPublicIPModel() (model models.PublicIP) {
|
|||||||
PostalCode: r.Postal,
|
PostalCode: r.Postal,
|
||||||
Timezone: r.Timezone,
|
Timezone: r.Timezone,
|
||||||
}
|
}
|
||||||
copy(model.IP, r.IP)
|
|
||||||
return model
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package ipinfo
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"net"
|
"net/netip"
|
||||||
)
|
)
|
||||||
|
|
||||||
// FetchMultiInfo obtains the public IP address information for every IP
|
// FetchMultiInfo obtains the public IP address information for every IP
|
||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
// If an error is encountered, all the operations are canceled and
|
// If an error is encountered, all the operations are canceled and
|
||||||
// an error is returned, so the results returned should be considered
|
// an error is returned, so the results returned should be considered
|
||||||
// incomplete in this case.
|
// incomplete in this case.
|
||||||
func (f *Fetch) FetchMultiInfo(ctx context.Context, ips []net.IP) (
|
func (f *Fetch) FetchMultiInfo(ctx context.Context, ips []netip.Addr) (
|
||||||
results []Response, err error) {
|
results []Response, err error) {
|
||||||
ctx, cancel := context.WithCancel(ctx)
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@ func (f *Fetch) FetchMultiInfo(ctx context.Context, ips []net.IP) (
|
|||||||
resultsCh := make(chan asyncResult)
|
resultsCh := make(chan asyncResult)
|
||||||
|
|
||||||
for i, ip := range ips {
|
for i, ip := range ips {
|
||||||
go func(index int, ip net.IP) {
|
go func(index int, ip netip.Addr) {
|
||||||
aResult := asyncResult{
|
aResult := asyncResult{
|
||||||
index: index,
|
index: index,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package publicip
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
"net/netip"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/constants"
|
"github.com/qdm12/gluetun/internal/constants"
|
||||||
@@ -26,7 +27,7 @@ func (l *Loop) Run(ctx context.Context, done chan<- struct{}) {
|
|||||||
resultCh := make(chan models.PublicIP)
|
resultCh := make(chan models.PublicIP)
|
||||||
errorCh := make(chan error)
|
errorCh := make(chan error)
|
||||||
go func() {
|
go func() {
|
||||||
result, err := l.fetcher.FetchInfo(getCtx, nil)
|
result, err := l.fetcher.FetchInfo(getCtx, netip.Addr{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if getCtx.Err() == nil {
|
if getCtx.Err() == nil {
|
||||||
errorCh <- err
|
errorCh <- err
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package routing
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net/netip"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/netlink"
|
"github.com/qdm12/gluetun/internal/netlink"
|
||||||
)
|
)
|
||||||
@@ -14,8 +14,8 @@ var (
|
|||||||
|
|
||||||
type DefaultRoute struct {
|
type DefaultRoute struct {
|
||||||
NetInterface string
|
NetInterface string
|
||||||
Gateway net.IP
|
Gateway netip.Addr
|
||||||
AssignedIP net.IP
|
AssignedIP netip.Addr
|
||||||
Family int
|
Family int
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,7 +35,7 @@ func (r *Routing) DefaultRoutes() (defaultRoutes []DefaultRoute, err error) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
defaultRoute := DefaultRoute{
|
defaultRoute := DefaultRoute{
|
||||||
Gateway: route.Gw,
|
Gateway: netIPToNetipAddress(route.Gw),
|
||||||
Family: route.Family,
|
Family: route.Family,
|
||||||
}
|
}
|
||||||
linkIndex := route.LinkIndex
|
linkIndex := route.LinkIndex
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ func (r *Routing) unrouteInboundFromDefault(defaultRoutes []DefaultRoute) (err e
|
|||||||
|
|
||||||
func (r *Routing) addRuleInboundFromDefault(table int, defaultRoutes []DefaultRoute) (err error) {
|
func (r *Routing) addRuleInboundFromDefault(table int, defaultRoutes []DefaultRoute) (err error) {
|
||||||
for _, defaultRoute := range defaultRoutes {
|
for _, defaultRoute := range defaultRoutes {
|
||||||
assignedIP := netIPToNetipAddress(defaultRoute.AssignedIP)
|
assignedIP := defaultRoute.AssignedIP
|
||||||
bits := 32
|
bits := 32
|
||||||
if assignedIP.Is6() {
|
if assignedIP.Is6() {
|
||||||
bits = 128
|
bits = 128
|
||||||
@@ -82,7 +82,7 @@ func (r *Routing) addRuleInboundFromDefault(table int, defaultRoutes []DefaultRo
|
|||||||
|
|
||||||
func (r *Routing) delRuleInboundFromDefault(table int, defaultRoutes []DefaultRoute) (err error) {
|
func (r *Routing) delRuleInboundFromDefault(table int, defaultRoutes []DefaultRoute) (err error) {
|
||||||
for _, defaultRoute := range defaultRoutes {
|
for _, defaultRoute := range defaultRoutes {
|
||||||
assignedIP := netIPToNetipAddress(defaultRoute.AssignedIP)
|
assignedIP := defaultRoute.AssignedIP
|
||||||
bits := 32
|
bits := 32
|
||||||
if assignedIP.Is6() {
|
if assignedIP.Is6() {
|
||||||
bits = 128
|
bits = 128
|
||||||
|
|||||||
@@ -4,11 +4,12 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"net/netip"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/netlink"
|
"github.com/qdm12/gluetun/internal/netlink"
|
||||||
)
|
)
|
||||||
|
|
||||||
func IPIsPrivate(ip net.IP) bool {
|
func IPIsPrivate(ip netip.Addr) bool {
|
||||||
return ip.IsPrivate() || ip.IsLoopback() ||
|
return ip.IsPrivate() || ip.IsLoopback() ||
|
||||||
ip.IsLinkLocalUnicast() || ip.IsLinkLocalMulticast()
|
ip.IsLinkLocalUnicast() || ip.IsLinkLocalMulticast()
|
||||||
}
|
}
|
||||||
@@ -17,38 +18,26 @@ var (
|
|||||||
errInterfaceIPNotFound = errors.New("IP address not found for interface")
|
errInterfaceIPNotFound = errors.New("IP address not found for interface")
|
||||||
)
|
)
|
||||||
|
|
||||||
func ipMatchesFamily(ip net.IP, family int) bool {
|
func ipMatchesFamily(ip netip.Addr, family int) bool {
|
||||||
return (family == netlink.FAMILY_V6 && ip.To4() == nil) ||
|
return (family == netlink.FAMILY_V6 && ip.Is6()) ||
|
||||||
(family == netlink.FAMILY_V4 && ip.To4() != nil)
|
(family == netlink.FAMILY_V4 && (ip.Is4() || ip.Is4In6()))
|
||||||
}
|
}
|
||||||
|
|
||||||
func ensureNoIPv6WrappedIPv4(candidateIP net.IP) (resultIP net.IP) {
|
func (r *Routing) assignedIP(interfaceName string, family int) (ip netip.Addr, err error) {
|
||||||
const ipv4Size = 4
|
|
||||||
if candidateIP.To4() == nil || len(candidateIP) == ipv4Size { // ipv6 or ipv4
|
|
||||||
return candidateIP
|
|
||||||
}
|
|
||||||
|
|
||||||
// ipv6-wrapped ipv4
|
|
||||||
resultIP = make(net.IP, ipv4Size)
|
|
||||||
copy(resultIP, candidateIP[12:16])
|
|
||||||
return resultIP
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Routing) assignedIP(interfaceName string, family int) (ip net.IP, err error) {
|
|
||||||
iface, err := net.InterfaceByName(interfaceName)
|
iface, err := net.InterfaceByName(interfaceName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("network interface %s not found: %w", interfaceName, err)
|
return ip, fmt.Errorf("network interface %s not found: %w", interfaceName, err)
|
||||||
}
|
}
|
||||||
addresses, err := iface.Addrs()
|
addresses, err := iface.Addrs()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("listing interface %s addresses: %w", interfaceName, err)
|
return ip, fmt.Errorf("listing interface %s addresses: %w", interfaceName, err)
|
||||||
}
|
}
|
||||||
for _, address := range addresses {
|
for _, address := range addresses {
|
||||||
switch value := address.(type) {
|
switch value := address.(type) {
|
||||||
case *net.IPAddr:
|
case *net.IPAddr:
|
||||||
ip = value.IP
|
ip = netIPToNetipAddress(value.IP)
|
||||||
case *net.IPNet:
|
case *net.IPNet:
|
||||||
ip = value.IP
|
ip = netIPToNetipAddress(value.IP)
|
||||||
default:
|
default:
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -60,9 +49,8 @@ func (r *Routing) assignedIP(interfaceName string, family int) (ip net.IP, err e
|
|||||||
// Ensure we don't return an IPv6-wrapped IPv4 address
|
// Ensure we don't return an IPv6-wrapped IPv4 address
|
||||||
// since netip.Address String method works differently than
|
// since netip.Address String method works differently than
|
||||||
// net.IP String method for this kind of addresses.
|
// net.IP String method for this kind of addresses.
|
||||||
ip = ensureNoIPv6WrappedIPv4(ip)
|
return ip.Unmap(), nil
|
||||||
return ip, nil
|
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("%w: interface %s in %d addresses",
|
return ip, fmt.Errorf("%w: interface %s in %d addresses",
|
||||||
errInterfaceIPNotFound, interfaceName, len(addresses))
|
errInterfaceIPNotFound, interfaceName, len(addresses))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package routing
|
package routing
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net/netip"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@@ -87,8 +87,8 @@ func Test_IPIsPrivate(t *testing.T) {
|
|||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
ip := net.ParseIP(testCase.ipString)
|
ip, err := netip.ParseAddr(testCase.ipString)
|
||||||
require.NotNil(t, ip)
|
require.NoError(t, err)
|
||||||
|
|
||||||
isPrivate := IPIsPrivate(ip)
|
isPrivate := IPIsPrivate(ip)
|
||||||
|
|
||||||
@@ -96,35 +96,3 @@ func Test_IPIsPrivate(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_ensureNoIPv6WrappedIPv4(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
testCases := map[string]struct {
|
|
||||||
candidateIP net.IP
|
|
||||||
resultIP net.IP
|
|
||||||
}{
|
|
||||||
"nil": {},
|
|
||||||
"ipv6": {
|
|
||||||
candidateIP: net.IPv6loopback,
|
|
||||||
resultIP: net.IPv6loopback,
|
|
||||||
},
|
|
||||||
"ipv4": {
|
|
||||||
candidateIP: net.IP{1, 2, 3, 4},
|
|
||||||
resultIP: net.IP{1, 2, 3, 4},
|
|
||||||
},
|
|
||||||
"ipv6_wrapped_ipv4": {
|
|
||||||
candidateIP: net.IPv4(1, 2, 3, 4),
|
|
||||||
resultIP: net.IP{1, 2, 3, 4},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for name, testCase := range testCases {
|
|
||||||
testCase := testCase
|
|
||||||
t.Run(name, func(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
resultIP := ensureNoIPv6WrappedIPv4(testCase.candidateIP)
|
|
||||||
assert.Equal(t, testCase.resultIP, resultIP)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package routing
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
|
||||||
"net/netip"
|
"net/netip"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/netlink"
|
"github.com/qdm12/gluetun/internal/netlink"
|
||||||
@@ -18,7 +17,7 @@ var (
|
|||||||
type LocalNetwork struct {
|
type LocalNetwork struct {
|
||||||
IPNet netip.Prefix
|
IPNet netip.Prefix
|
||||||
InterfaceName string
|
InterfaceName string
|
||||||
IP net.IP
|
IP netip.Addr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Routing) LocalNetworks() (localNetworks []LocalNetwork, err error) {
|
func (r *Routing) LocalNetworks() (localNetworks []LocalNetwork, err error) {
|
||||||
|
|||||||
@@ -2,14 +2,13 @@ package routing
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/netlink"
|
"github.com/qdm12/gluetun/internal/netlink"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (r *Routing) addRouteVia(destination netip.Prefix, gateway net.IP,
|
func (r *Routing) addRouteVia(destination netip.Prefix, gateway netip.Addr,
|
||||||
iface string, table int) error {
|
iface string, table int) error {
|
||||||
destinationStr := destination.String()
|
destinationStr := destination.String()
|
||||||
r.logger.Info("adding route for " + destinationStr)
|
r.logger.Info("adding route for " + destinationStr)
|
||||||
@@ -25,7 +24,7 @@ func (r *Routing) addRouteVia(destination netip.Prefix, gateway net.IP,
|
|||||||
|
|
||||||
route := netlink.Route{
|
route := netlink.Route{
|
||||||
Dst: NetipPrefixToIPNet(&destination),
|
Dst: NetipPrefixToIPNet(&destination),
|
||||||
Gw: gateway,
|
Gw: gateway.AsSlice(),
|
||||||
LinkIndex: link.Attrs().Index,
|
LinkIndex: link.Attrs().Index,
|
||||||
Table: table,
|
Table: table,
|
||||||
}
|
}
|
||||||
@@ -37,7 +36,7 @@ func (r *Routing) addRouteVia(destination netip.Prefix, gateway net.IP,
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Routing) deleteRouteVia(destination netip.Prefix, gateway net.IP,
|
func (r *Routing) deleteRouteVia(destination netip.Prefix, gateway netip.Addr,
|
||||||
iface string, table int) (err error) {
|
iface string, table int) (err error) {
|
||||||
destinationStr := destination.String()
|
destinationStr := destination.String()
|
||||||
r.logger.Info("deleting route for " + destinationStr)
|
r.logger.Info("deleting route for " + destinationStr)
|
||||||
@@ -53,7 +52,7 @@ func (r *Routing) deleteRouteVia(destination netip.Prefix, gateway net.IP,
|
|||||||
|
|
||||||
route := netlink.Route{
|
route := netlink.Route{
|
||||||
Dst: NetipPrefixToIPNet(&destination),
|
Dst: NetipPrefixToIPNet(&destination),
|
||||||
Gw: gateway,
|
Gw: gateway.AsSlice(),
|
||||||
LinkIndex: link.Attrs().Index,
|
LinkIndex: link.Attrs().Index,
|
||||||
Table: table,
|
Table: table,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"net/netip"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/netlink"
|
"github.com/qdm12/gluetun/internal/netlink"
|
||||||
)
|
)
|
||||||
@@ -14,10 +15,10 @@ var (
|
|||||||
ErrVPNLocalGatewayIPNotFound = errors.New("VPN local gateway IP address not found")
|
ErrVPNLocalGatewayIPNotFound = errors.New("VPN local gateway IP address not found")
|
||||||
)
|
)
|
||||||
|
|
||||||
func (r *Routing) VPNDestinationIP() (ip net.IP, err error) {
|
func (r *Routing) VPNDestinationIP() (ip netip.Addr, err error) {
|
||||||
routes, err := r.netLinker.RouteList(nil, netlink.FAMILY_ALL)
|
routes, err := r.netLinker.RouteList(nil, netlink.FAMILY_ALL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("listing routes: %w", err)
|
return ip, fmt.Errorf("listing routes: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultLinkIndex := -1
|
defaultLinkIndex := -1
|
||||||
@@ -28,36 +29,36 @@ func (r *Routing) VPNDestinationIP() (ip net.IP, err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if defaultLinkIndex == -1 {
|
if defaultLinkIndex == -1 {
|
||||||
return nil, fmt.Errorf("%w: in %d route(s)", ErrLinkDefaultNotFound, len(routes))
|
return ip, fmt.Errorf("%w: in %d route(s)", ErrLinkDefaultNotFound, len(routes))
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, route := range routes {
|
for _, route := range routes {
|
||||||
if route.LinkIndex == defaultLinkIndex &&
|
if route.LinkIndex == defaultLinkIndex &&
|
||||||
route.Dst != nil &&
|
route.Dst != nil &&
|
||||||
!IPIsPrivate(route.Dst.IP) &&
|
!IPIsPrivate(netIPToNetipAddress(route.Dst.IP)) &&
|
||||||
bytes.Equal(route.Dst.Mask, net.IPMask{255, 255, 255, 255}) {
|
bytes.Equal(route.Dst.Mask, net.IPMask{255, 255, 255, 255}) {
|
||||||
return route.Dst.IP, nil
|
return netIPToNetipAddress(route.Dst.IP), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("%w: in %d routes", ErrVPNDestinationIPNotFound, len(routes))
|
return ip, fmt.Errorf("%w: in %d routes", ErrVPNDestinationIPNotFound, len(routes))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Routing) VPNLocalGatewayIP(vpnIntf string) (ip net.IP, err error) {
|
func (r *Routing) VPNLocalGatewayIP(vpnIntf string) (ip netip.Addr, err error) {
|
||||||
routes, err := r.netLinker.RouteList(nil, netlink.FAMILY_ALL)
|
routes, err := r.netLinker.RouteList(nil, netlink.FAMILY_ALL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("listing routes: %w", err)
|
return ip, fmt.Errorf("listing routes: %w", err)
|
||||||
}
|
}
|
||||||
for _, route := range routes {
|
for _, route := range routes {
|
||||||
link, err := r.netLinker.LinkByIndex(route.LinkIndex)
|
link, err := r.netLinker.LinkByIndex(route.LinkIndex)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("finding link at index %d: %w", route.LinkIndex, err)
|
return ip, fmt.Errorf("finding link at index %d: %w", route.LinkIndex, err)
|
||||||
}
|
}
|
||||||
interfaceName := link.Attrs().Name
|
interfaceName := link.Attrs().Name
|
||||||
if interfaceName == vpnIntf &&
|
if interfaceName == vpnIntf &&
|
||||||
route.Dst != nil &&
|
route.Dst != nil &&
|
||||||
route.Dst.IP.Equal(net.IP{0, 0, 0, 0}) {
|
route.Dst.IP.Equal(net.IP{0, 0, 0, 0}) {
|
||||||
return route.Gw, nil
|
return netIPToNetipAddress(route.Gw), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("%w: in %d routes", ErrVPNLocalGatewayIPNotFound, len(routes))
|
return ip, fmt.Errorf("%w: in %d routes", ErrVPNLocalGatewayIPNotFound, len(routes))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package storage
|
package storage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net/netip"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
)
|
)
|
||||||
@@ -12,21 +12,12 @@ func copyServer(server models.Server) (serverCopy models.Server) {
|
|||||||
return serverCopy
|
return serverCopy
|
||||||
}
|
}
|
||||||
|
|
||||||
func copyIPs(toCopy []net.IP) (copied []net.IP) {
|
func copyIPs(toCopy []netip.Addr) (copied []netip.Addr) {
|
||||||
if toCopy == nil {
|
if toCopy == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
copied = make([]net.IP, len(toCopy))
|
copied = make([]netip.Addr, len(toCopy))
|
||||||
for i := range toCopy {
|
|
||||||
copied[i] = copyIP(toCopy[i])
|
|
||||||
}
|
|
||||||
|
|
||||||
return copied
|
|
||||||
}
|
|
||||||
|
|
||||||
func copyIP(toCopy net.IP) (copied net.IP) {
|
|
||||||
copied = make(net.IP, len(toCopy))
|
|
||||||
copy(copied, toCopy)
|
copy(copied, toCopy)
|
||||||
return copied
|
return copied
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
package storage
|
package storage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net/netip"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_copyServer(t *testing.T) {
|
func Test_copyServer(t *testing.T) {
|
||||||
@@ -14,14 +13,14 @@ func Test_copyServer(t *testing.T) {
|
|||||||
|
|
||||||
server := models.Server{
|
server := models.Server{
|
||||||
Country: "a",
|
Country: "a",
|
||||||
IPs: []net.IP{{1, 2, 3, 4}},
|
IPs: []netip.Addr{netip.AddrFrom4([4]byte{1, 2, 3, 4})},
|
||||||
}
|
}
|
||||||
|
|
||||||
serverCopy := copyServer(server)
|
serverCopy := copyServer(server)
|
||||||
|
|
||||||
assert.Equal(t, server, serverCopy)
|
assert.Equal(t, server, serverCopy)
|
||||||
// Check for mutation
|
// Check for mutation
|
||||||
serverCopy.IPs[0][0] = 9
|
serverCopy.IPs[0] = netip.AddrFrom4([4]byte{9, 9, 9, 9})
|
||||||
assert.NotEqual(t, server, serverCopy)
|
assert.NotEqual(t, server, serverCopy)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,21 +28,21 @@ func Test_copyIPs(t *testing.T) {
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
testCases := map[string]struct {
|
testCases := map[string]struct {
|
||||||
toCopy []net.IP
|
toCopy []netip.Addr
|
||||||
copied []net.IP
|
copied []netip.Addr
|
||||||
}{
|
}{
|
||||||
"nil": {},
|
"nil": {},
|
||||||
"empty": {
|
"empty": {
|
||||||
toCopy: []net.IP{},
|
toCopy: []netip.Addr{},
|
||||||
copied: []net.IP{},
|
copied: []netip.Addr{},
|
||||||
},
|
},
|
||||||
"single IP": {
|
"single IP": {
|
||||||
toCopy: []net.IP{{1, 1, 1, 1}},
|
toCopy: []netip.Addr{netip.AddrFrom4([4]byte{1, 1, 1, 1})},
|
||||||
copied: []net.IP{{1, 1, 1, 1}},
|
copied: []netip.Addr{netip.AddrFrom4([4]byte{1, 1, 1, 1})},
|
||||||
},
|
},
|
||||||
"two IPs": {
|
"two IPs": {
|
||||||
toCopy: []net.IP{{1, 1, 1, 1}, {2, 2, 2, 2}},
|
toCopy: []netip.Addr{netip.AddrFrom4([4]byte{1, 1, 1, 1}), netip.AddrFrom4([4]byte{2, 2, 2, 2})},
|
||||||
copied: []net.IP{{1, 1, 1, 1}, {2, 2, 2, 2}},
|
copied: []netip.Addr{netip.AddrFrom4([4]byte{1, 1, 1, 1}), netip.AddrFrom4([4]byte{2, 2, 2, 2})},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,23 +51,13 @@ func Test_copyIPs(t *testing.T) {
|
|||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Reserver leading 9 for copy modifications below
|
|
||||||
for _, ipToCopy := range testCase.toCopy {
|
|
||||||
require.NotEqual(t, 9, ipToCopy[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
copied := copyIPs(testCase.toCopy)
|
copied := copyIPs(testCase.toCopy)
|
||||||
|
|
||||||
assert.Equal(t, testCase.copied, copied)
|
assert.Equal(t, testCase.copied, copied)
|
||||||
|
|
||||||
if len(copied) > 0 {
|
if len(copied) > 0 {
|
||||||
original := testCase.toCopy[0][0]
|
testCase.toCopy[0] = netip.AddrFrom4([4]byte{9, 9, 9, 9})
|
||||||
testCase.toCopy[0][0] = 9
|
assert.NotEqual(t, testCase.toCopy[0], testCase.copied[0])
|
||||||
assert.NotEqual(t, 9, copied[0][0])
|
|
||||||
testCase.toCopy[0][0] = original
|
|
||||||
|
|
||||||
copied[0][0] = 9
|
|
||||||
assert.NotEqual(t, 9, testCase.toCopy[0][0])
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package openvpn
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net/netip"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
@@ -54,7 +54,7 @@ func ExtractHost(b []byte) (host, warning string, err error) {
|
|||||||
return hosts[0], warning, nil
|
return hosts[0], warning, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExtractIPs(b []byte) (ips []net.IP, err error) {
|
func ExtractIPs(b []byte) (ips []netip.Addr, err error) {
|
||||||
const rejectIP, rejectDomain = false, true
|
const rejectIP, rejectDomain = false, true
|
||||||
ipStrings := extractRemoteHosts(b, rejectIP, rejectDomain)
|
ipStrings := extractRemoteHosts(b, rejectIP, rejectDomain)
|
||||||
if len(ipStrings) == 0 {
|
if len(ipStrings) == 0 {
|
||||||
@@ -65,9 +65,12 @@ func ExtractIPs(b []byte) (ips []net.IP, err error) {
|
|||||||
return ipStrings[i] < ipStrings[j]
|
return ipStrings[i] < ipStrings[j]
|
||||||
})
|
})
|
||||||
|
|
||||||
ips = make([]net.IP, len(ipStrings))
|
ips = make([]netip.Addr, len(ipStrings))
|
||||||
for i := range ipStrings {
|
for i := range ipStrings {
|
||||||
ips[i] = net.ParseIP(ipStrings[i])
|
ips[i], err = netip.ParseAddr(ipStrings[i])
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("parsing IP address: %w", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ips, nil
|
return ips, nil
|
||||||
@@ -85,9 +88,9 @@ func extractRemoteHosts(content []byte, rejectIP, rejectDomain bool) (hosts []st
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
host := fields[1]
|
host := fields[1]
|
||||||
parsedIP := net.ParseIP(host)
|
_, err := netip.ParseAddr(host)
|
||||||
if (rejectIP && parsedIP != nil) ||
|
if (rejectIP && err == nil) ||
|
||||||
(rejectDomain && parsedIP == nil) {
|
(rejectDomain && err != nil) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
hosts = append(hosts, host)
|
hosts = append(hosts, host)
|
||||||
|
|||||||
@@ -1,15 +1,20 @@
|
|||||||
package resolver
|
package resolver
|
||||||
|
|
||||||
import "net"
|
import (
|
||||||
|
"net/netip"
|
||||||
|
)
|
||||||
|
|
||||||
func uniqueIPsToSlice(uniqueIPs map[string]struct{}) (ips []net.IP) {
|
func uniqueIPsToSlice(uniqueIPs map[string]struct{}) (ips []netip.Addr) {
|
||||||
ips = make([]net.IP, 0, len(uniqueIPs))
|
ips = make([]netip.Addr, 0, len(uniqueIPs))
|
||||||
for key := range uniqueIPs {
|
for key := range uniqueIPs {
|
||||||
IP := net.ParseIP(key)
|
ip, err := netip.ParseAddr(key)
|
||||||
if IPv4 := IP.To4(); IPv4 != nil {
|
if err != nil {
|
||||||
IP = IPv4
|
panic(err)
|
||||||
}
|
}
|
||||||
ips = append(ips, IP)
|
if ip.Is4In6() {
|
||||||
|
ip = netip.AddrFrom4(ip.As4())
|
||||||
|
}
|
||||||
|
ips = append(ips, ip)
|
||||||
}
|
}
|
||||||
return ips
|
return ips
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package resolver
|
package resolver
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net/netip"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@@ -11,23 +11,23 @@ func Test_uniqueIPsToSlice(t *testing.T) {
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
testCases := map[string]struct {
|
testCases := map[string]struct {
|
||||||
inputIPs map[string]struct{}
|
inputIPs map[string]struct{}
|
||||||
outputIPs []net.IP
|
outputIPs []netip.Addr
|
||||||
}{
|
}{
|
||||||
"nil": {
|
"nil": {
|
||||||
inputIPs: nil,
|
inputIPs: nil,
|
||||||
outputIPs: []net.IP{},
|
outputIPs: []netip.Addr{},
|
||||||
},
|
},
|
||||||
"empty": {
|
"empty": {
|
||||||
inputIPs: map[string]struct{}{},
|
inputIPs: map[string]struct{}{},
|
||||||
outputIPs: []net.IP{},
|
outputIPs: []netip.Addr{},
|
||||||
},
|
},
|
||||||
"single IPv4": {
|
"single IPv4": {
|
||||||
inputIPs: map[string]struct{}{"1.1.1.1": {}},
|
inputIPs: map[string]struct{}{"1.1.1.1": {}},
|
||||||
outputIPs: []net.IP{{1, 1, 1, 1}},
|
outputIPs: []netip.Addr{netip.AddrFrom4([4]byte{1, 1, 1, 1})},
|
||||||
},
|
},
|
||||||
"two IPv4s": {
|
"two IPv4s": {
|
||||||
inputIPs: map[string]struct{}{"1.1.1.1": {}, "1.1.2.1": {}},
|
inputIPs: map[string]struct{}{"1.1.1.1": {}, "1.1.2.1": {}},
|
||||||
outputIPs: []net.IP{{1, 1, 1, 1}, {1, 1, 2, 1}},
|
outputIPs: []netip.Addr{netip.AddrFrom4([4]byte{1, 1, 1, 1}), netip.AddrFrom4([4]byte{1, 1, 2, 1})},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for name, testCase := range testCases {
|
for name, testCase := range testCases {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net/netip"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Parallel struct {
|
type Parallel struct {
|
||||||
@@ -31,7 +31,7 @@ type ParallelSettings struct {
|
|||||||
|
|
||||||
type parallelResult struct {
|
type parallelResult struct {
|
||||||
host string
|
host string
|
||||||
IPs []net.IP
|
IPs []netip.Addr
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -40,7 +40,7 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (pr *Parallel) Resolve(ctx context.Context, settings ParallelSettings) (
|
func (pr *Parallel) Resolve(ctx context.Context, settings ParallelSettings) (
|
||||||
hostToIPs map[string][]net.IP, warnings []string, err error) {
|
hostToIPs map[string][]netip.Addr, warnings []string, err error) {
|
||||||
ctx, cancel := context.WithCancel(ctx)
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
@@ -53,7 +53,7 @@ func (pr *Parallel) Resolve(ctx context.Context, settings ParallelSettings) (
|
|||||||
go pr.resolveAsync(ctx, host, settings.Repeat, results, errors)
|
go pr.resolveAsync(ctx, host, settings.Repeat, results, errors)
|
||||||
}
|
}
|
||||||
|
|
||||||
hostToIPs = make(map[string][]net.IP, len(settings.Hosts))
|
hostToIPs = make(map[string][]netip.Addr, len(settings.Hosts))
|
||||||
maxFails := int(settings.MaxFailRatio * float64(len(settings.Hosts)))
|
maxFails := int(settings.MaxFailRatio * float64(len(settings.Hosts)))
|
||||||
|
|
||||||
for range settings.Hosts {
|
for range settings.Hosts {
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
package resolver
|
package resolver
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"net/netip"
|
||||||
"sort"
|
"sort"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@@ -31,7 +31,7 @@ type RepeatSettings struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *Repeat) Resolve(ctx context.Context, host string, settings RepeatSettings) (
|
func (r *Repeat) Resolve(ctx context.Context, host string, settings RepeatSettings) (
|
||||||
ips []net.IP, err error) {
|
ips []netip.Addr, err error) {
|
||||||
timedCtx, cancel := context.WithTimeout(ctx, settings.MaxDuration)
|
timedCtx, cancel := context.WithTimeout(ctx, settings.MaxDuration)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
@@ -54,7 +54,7 @@ func (r *Repeat) Resolve(ctx context.Context, host string, settings RepeatSettin
|
|||||||
|
|
||||||
if settings.SortIPs {
|
if settings.SortIPs {
|
||||||
sort.Slice(ips, func(i, j int) bool {
|
sort.Slice(ips, func(i, j int) bool {
|
||||||
return bytes.Compare(ips[i], ips[j]) < 1
|
return ips[i].Compare(ips[j]) < 1
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,15 +121,15 @@ func (r *Repeat) resolveOnce(ctx, timedCtx context.Context, host string,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Repeat) lookupIPs(ctx context.Context, host string) (ips []net.IP, err error) {
|
func (r *Repeat) lookupIPs(ctx context.Context, host string) (ips []netip.Addr, err error) {
|
||||||
addresses, err := r.resolver.LookupIPAddr(ctx, host)
|
addresses, err := r.resolver.LookupIPAddr(ctx, host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
ips = make([]net.IP, 0, len(addresses))
|
ips = make([]netip.Addr, 0, len(addresses))
|
||||||
for i := range addresses {
|
for i := range addresses {
|
||||||
ip := addresses[i].IP
|
ip, ok := netip.AddrFromSlice(addresses[i].IP)
|
||||||
if ip == nil {
|
if !ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
ips = append(ips, ip)
|
ips = append(ips, ip)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package vpn
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"net"
|
"net/netip"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/configuration/settings"
|
"github.com/qdm12/gluetun/internal/configuration/settings"
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
@@ -18,7 +18,7 @@ type Firewall interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Routing interface {
|
type Routing interface {
|
||||||
VPNLocalGatewayIP(vpnInterface string) (gateway net.IP, err error)
|
VPNLocalGatewayIP(vpnInterface string) (gateway netip.Addr, err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type PortForward interface {
|
type PortForward interface {
|
||||||
|
|||||||
Reference in New Issue
Block a user