From 4bd5029e7b5660ef2d34f0582cb9dadb3b669bbb Mon Sep 17 00:00:00 2001 From: Genteure Date: Wed, 23 Nov 2022 18:03:29 +0800 Subject: [PATCH] Enable IPv6 address discovery (#578) Agents will use IPv6 when available for ICE negotiation --- client/internal/config.go | 26 ++++++++++++++------------ client/internal/connect.go | 13 +++++++------ client/internal/engine.go | 31 +++++++++++++++++++------------ client/internal/peer/conn.go | 16 ++++++++++++---- 4 files changed, 52 insertions(+), 34 deletions(-) diff --git a/client/internal/config.go b/client/internal/config.go index 1ba0389ce..6420eb1de 100644 --- a/client/internal/config.go +++ b/client/internal/config.go @@ -33,13 +33,14 @@ func init() { // Config Configuration type type Config struct { // Wireguard private key of local peer - PrivateKey string - PreSharedKey string - ManagementURL *url.URL - AdminURL *url.URL - WgIface string - WgPort int - IFaceBlackList []string + PrivateKey string + PreSharedKey string + ManagementURL *url.URL + AdminURL *url.URL + WgIface string + WgPort int + IFaceBlackList []string + DisableIPv6Discovery bool // SSHKey is a private SSH key in a PEM format SSHKey string @@ -69,11 +70,12 @@ func createNewConfig(managementURL, adminURL, configPath, preSharedKey string) ( return nil, err } config := &Config{ - SSHKey: string(pem), - PrivateKey: wgKey, - WgIface: iface.WgInterfaceDefault, - WgPort: iface.DefaultWgPort, - IFaceBlackList: []string{}, + SSHKey: string(pem), + PrivateKey: wgKey, + WgIface: iface.WgInterfaceDefault, + WgPort: iface.DefaultWgPort, + IFaceBlackList: []string{}, + DisableIPv6Discovery: false, } if managementURL != "" { URL, err := ParseURL("Management URL", managementURL) diff --git a/client/internal/connect.go b/client/internal/connect.go index d9ddf5d26..c8d10026a 100644 --- a/client/internal/connect.go +++ b/client/internal/connect.go @@ -185,12 +185,13 @@ func RunClient(ctx context.Context, config *Config, statusRecorder *nbStatus.Sta func createEngineConfig(key wgtypes.Key, config *Config, peerConfig *mgmProto.PeerConfig) (*EngineConfig, error) { engineConf := &EngineConfig{ - WgIfaceName: config.WgIface, - WgAddr: peerConfig.Address, - IFaceBlackList: config.IFaceBlackList, - WgPrivateKey: key, - WgPort: config.WgPort, - SSHKey: []byte(config.SSHKey), + WgIfaceName: config.WgIface, + WgAddr: peerConfig.Address, + IFaceBlackList: config.IFaceBlackList, + DisableIPv6Discovery: config.DisableIPv6Discovery, + WgPrivateKey: key, + WgPort: config.WgPort, + SSHKey: []byte(config.SSHKey), NATExternalIPs: config.NATExternalIPs, } diff --git a/client/internal/engine.go b/client/internal/engine.go index 9099d6908..82425e62a 100644 --- a/client/internal/engine.go +++ b/client/internal/engine.go @@ -55,7 +55,8 @@ type EngineConfig struct { WgPrivateKey wgtypes.Key // IFaceBlackList is a list of network interfaces to ignore when discovering connection candidates (ICE related) - IFaceBlackList []string + IFaceBlackList []string + DisableIPv6Discovery bool PreSharedKey *wgtypes.Key @@ -226,13 +227,18 @@ func (e *Engine) Start() error { return err } - e.udpMuxConn, err = net.ListenUDP("udp4", &net.UDPAddr{Port: e.config.UDPMuxPort}) + networkName := "udp" + if e.config.DisableIPv6Discovery { + networkName = "udp4" + } + + e.udpMuxConn, err = net.ListenUDP(networkName, &net.UDPAddr{Port: e.config.UDPMuxPort}) if err != nil { log.Errorf("failed listening on UDP port %d: [%s]", e.config.UDPMuxPort, err.Error()) return err } - e.udpMuxConnSrflx, err = net.ListenUDP("udp4", &net.UDPAddr{Port: e.config.UDPMuxSrflxPort}) + e.udpMuxConnSrflx, err = net.ListenUDP(networkName, &net.UDPAddr{Port: e.config.UDPMuxSrflxPort}) if err != nil { log.Errorf("failed listening on UDP port %d: [%s]", e.config.UDPMuxSrflxPort, err.Error()) return err @@ -819,15 +825,16 @@ func (e Engine) createPeerConn(pubKey string, allowedIPs string) (*peer.Conn, er // randomize connection timeout timeout := time.Duration(rand.Intn(PeerConnectionTimeoutMax-PeerConnectionTimeoutMin)+PeerConnectionTimeoutMin) * time.Millisecond config := peer.ConnConfig{ - Key: pubKey, - LocalKey: e.config.WgPrivateKey.PublicKey().String(), - StunTurn: stunTurn, - InterfaceBlackList: e.config.IFaceBlackList, - Timeout: timeout, - UDPMux: e.udpMux, - UDPMuxSrflx: e.udpMuxSrflx, - ProxyConfig: proxyConfig, - LocalWgPort: e.config.WgPort, + Key: pubKey, + LocalKey: e.config.WgPrivateKey.PublicKey().String(), + StunTurn: stunTurn, + InterfaceBlackList: e.config.IFaceBlackList, + DisableIPv6Discovery: e.config.DisableIPv6Discovery, + Timeout: timeout, + UDPMux: e.udpMux, + UDPMuxSrflx: e.udpMuxSrflx, + ProxyConfig: proxyConfig, + LocalWgPort: e.config.WgPort, NATExternalIPs: e.parseNATExternalIPMappings(), } diff --git a/client/internal/peer/conn.go b/client/internal/peer/conn.go index 2f097c156..4489797ec 100644 --- a/client/internal/peer/conn.go +++ b/client/internal/peer/conn.go @@ -29,7 +29,8 @@ type ConnConfig struct { // InterfaceBlackList is a list of machine interfaces that should be filtered out by ICE Candidate gathering // (e.g. if eth0 is in the list, host candidate of this interface won't be used) - InterfaceBlackList []string + InterfaceBlackList []string + DisableIPv6Discovery bool Timeout time.Duration @@ -145,9 +146,9 @@ func (conn *Conn) reCreateAgent() error { failedTimeout := 6 * time.Second var err error - conn.agent, err = ice.NewAgent(&ice.AgentConfig{ + agentConfig := &ice.AgentConfig{ MulticastDNSMode: ice.MulticastDNSModeDisabled, - NetworkTypes: []ice.NetworkType{ice.NetworkTypeUDP4}, + NetworkTypes: []ice.NetworkType{ice.NetworkTypeUDP4, ice.NetworkTypeUDP6}, Urls: conn.config.StunTurn, CandidateTypes: []ice.CandidateType{ice.CandidateTypeHost, ice.CandidateTypeServerReflexive, ice.CandidateTypeRelay}, FailedTimeout: &failedTimeout, @@ -155,7 +156,14 @@ func (conn *Conn) reCreateAgent() error { UDPMux: conn.config.UDPMux, UDPMuxSrflx: conn.config.UDPMuxSrflx, NAT1To1IPs: conn.config.NATExternalIPs, - }) + } + + if conn.config.DisableIPv6Discovery { + agentConfig.NetworkTypes = []ice.NetworkType{ice.NetworkTypeUDP4} + } + + conn.agent, err = ice.NewAgent(agentConfig) + if err != nil { return err }