diff --git a/client/internal/connection.go b/client/internal/connection.go index 0790f57760b..ee68a094dcf 100644 --- a/client/internal/connection.go +++ b/client/internal/connection.go @@ -188,11 +188,19 @@ func (conn *Connection) Open(timeout time.Duration) error { } // in case the remote peer is in the local network or one of the peers has public static IP -> no need for a Wireguard proxy, direct communication is possible. if !useProxy(pair) { - log.Debugf("it is possible to establish a direct connection (without proxy) to peer %s - my addr: %s, remote addr: %s", conn.Config.RemoteWgKey.String(), pair.Local.Address(), pair.Remote.Address()) - err = conn.wgProxy.StartLocal(fmt.Sprintf("%s:%d", pair.Remote.Address(), iface.WgPort)) + log.Debugf("it is possible to establish a direct connection (without proxy) to peer %s - my addr: %s, remote addr: %s", conn.Config.RemoteWgKey.String(), pair.Local, pair.Remote) + var endpoint string + if isPublicIP(net.ParseIP(pair.Local.Address())) { + //skip endpoint because we are public - it will be discovered by Wireguard automatically + endpoint = "" + } else { + endpoint = fmt.Sprintf("%s:%d", pair.Remote.Address(), iface.WgPort) + } + err = conn.wgProxy.StartLocal(endpoint) if err != nil { return err } + } else { log.Infof("establishing secure tunnel to peer %s via selected candidate pair %s", conn.Config.RemoteWgKey.String(), pair) err = conn.wgProxy.Start(remoteConn) @@ -239,23 +247,31 @@ func isPublicIP(ip net.IP) bool { } //useProxy determines whether a direct connection (without a go proxy) is possible -//There are 2 cases: one of the peers has a public IP or both peers are in teh same private network. +//There are 3 cases: one of the peers has a public IP or both peers are in the same private network //Please note, that this check happens when peers were already able to ping each other with ICE layer. func useProxy(pair *ice.CandidatePair) bool { remoteIP := net.ParseIP(pair.Remote.Address()) myIp := net.ParseIP(pair.Local.Address()) + remoteIsPublic := isPublicIP(remoteIP) + myIsPublic := isPublicIP(myIp) if pair.Local.Type() == ice.CandidateTypeHost && pair.Remote.Type() == ice.CandidateTypeHost { - if isPublicIP(remoteIP) || isPublicIP(myIp) { + if remoteIsPublic || myIsPublic { //one of the hosts has a public IP return false } - if !isPublicIP(remoteIP) && !isPublicIP(myIp) { + if !remoteIsPublic && !myIsPublic { //both hosts are in the same private network return false } } + if (pair.Local.Type() == ice.CandidateTypeHost && myIsPublic) && pair.Remote.Type() == ice.CandidateTypePeerReflexive { + // same as the case when either host is public but adds additional case when remote is peer reflexive + // remote is peer reflexive and we are public -> no proxy needed + return false + } + return true }