diff --git a/client/internal/engine.go b/client/internal/engine.go index af9a13f0f..e7f1c6a32 100644 --- a/client/internal/engine.go +++ b/client/internal/engine.go @@ -18,7 +18,6 @@ import ( "github.com/netbirdio/netbird/client/internal/dns" "github.com/netbirdio/netbird/client/internal/peer" - "github.com/netbirdio/netbird/client/internal/proxy" "github.com/netbirdio/netbird/client/internal/routemanager" "github.com/netbirdio/netbird/client/internal/stdnet" nbssh "github.com/netbirdio/netbird/client/ssh" @@ -809,14 +808,6 @@ func (e Engine) createPeerConn(pubKey string, allowedIPs string) (*peer.Conn, er stunTurn = append(stunTurn, e.STUNs...) stunTurn = append(stunTurn, e.TURNs...) - proxyConfig := proxy.Config{ - RemoteKey: pubKey, - WgListenAddr: fmt.Sprintf("127.0.0.1:%d", e.config.WgPort), - WgInterface: e.wgInterface, - AllowedIps: allowedIPs, - PreSharedKey: e.config.PreSharedKey, - } - // randomize connection timeout timeout := time.Duration(rand.Intn(PeerConnectionTimeoutMax-PeerConnectionTimeoutMin)+PeerConnectionTimeoutMin) * time.Millisecond config := peer.ConnConfig{ @@ -828,13 +819,12 @@ func (e Engine) createPeerConn(pubKey string, allowedIPs string) (*peer.Conn, er Timeout: timeout, UDPMux: e.udpMux, UDPMuxSrflx: e.udpMuxSrflx, - ProxyConfig: proxyConfig, LocalWgPort: e.config.WgPort, NATExternalIPs: e.parseNATExternalIPMappings(), - UserspaceBind: e.wgInterface.IsUserspaceBind(), + AllowedIPs: allowedIPs, } - peerConn, err := peer.NewConn(config, e.statusRecorder, e.config.TunAdapter, e.config.IFaceDiscover) + peerConn, err := peer.NewConn(config, e.wgInterface, e.statusRecorder, e.config.TunAdapter, e.config.IFaceDiscover) if err != nil { return nil, err } diff --git a/client/internal/peer/conn.go b/client/internal/peer/conn.go index eb7ff9db4..9c4a306a7 100644 --- a/client/internal/peer/conn.go +++ b/client/internal/peer/conn.go @@ -37,8 +37,6 @@ type ConnConfig struct { Timeout time.Duration - ProxyConfig proxy.Config - UDPMux ice.UDPMux UDPMuxSrflx ice.UniversalUDPMux @@ -46,8 +44,7 @@ type ConnConfig struct { NATExternalIPs []string - // UsesBind indicates whether the WireGuard interface is userspace and uses bind.ICEBind - UserspaceBind bool + AllowedIPs string } // OfferAnswer represents a session establishment offer or answer @@ -96,6 +93,7 @@ type Conn struct { remoteModeCh chan ModeMessage meta meta + wgIface *iface.WGIface adapter iface.TunAdapter iFaceDiscover stdnet.ExternalIFaceDiscover } @@ -123,7 +121,7 @@ func (conn *Conn) UpdateConf(conf ConnConfig) { // NewConn creates a new not opened Conn to the remote peer. // To establish a connection run Conn.Open -func NewConn(config ConnConfig, statusRecorder *Status, adapter iface.TunAdapter, iFaceDiscover stdnet.ExternalIFaceDiscover) (*Conn, error) { +func NewConn(config ConnConfig, wgIface *iface.WGIface, statusRecorder *Status, adapter iface.TunAdapter, iFaceDiscover stdnet.ExternalIFaceDiscover) (*Conn, error) { return &Conn{ config: config, mu: sync.Mutex{}, @@ -135,6 +133,7 @@ func NewConn(config ConnConfig, statusRecorder *Status, adapter iface.TunAdapter remoteModeCh: make(chan ModeMessage, 1), adapter: adapter, iFaceDiscover: iFaceDiscover, + wgIface: wgIface, }, nil } @@ -198,7 +197,7 @@ func (conn *Conn) Open() error { peerState := State{PubKey: conn.config.Key} - peerState.IP = strings.Split(conn.config.ProxyConfig.AllowedIps, "/")[0] + peerState.IP = strings.Split(conn.config.AllowedIPs, "/")[0] peerState.ConnStatusUpdate = time.Now() peerState.ConnStatus = conn.status @@ -430,7 +429,7 @@ func (conn *Conn) startProxy(remoteConn net.Conn, remoteWgPort int) error { } func (conn *Conn) getProxyWithMessageExchange(pair *ice.CandidatePair, remoteWgPort int) proxy.Proxy { - useProxy := shouldUseProxy(pair, conn.config.UserspaceBind) + useProxy := shouldUseProxy(pair, conn.wgIface.IsUserspaceBind()) localDirectMode := !useProxy remoteDirectMode := localDirectMode @@ -440,12 +439,13 @@ func (conn *Conn) getProxyWithMessageExchange(pair *ice.CandidatePair, remoteWgP remoteDirectMode = conn.receiveRemoteDirectMode() } - if conn.config.UserspaceBind && localDirectMode { + if conn.wgIface.IsUserspaceBind() && localDirectMode { return proxy.NewNoProxy(conn.config.ProxyConfig) } if localDirectMode && remoteDirectMode { - return proxy.NewDirectNoProxy(conn.config.ProxyConfig, remoteWgPort) + //wgInterface *iface.WGIface, remoteKey string, allowedIps string, preSharedKey *wgtypes.Key, remoteWgPort int) + return proxy.NewDirectNoProxy(conn.wgIface, conn.config.Key, conn.config.AllowedIPs, remoteWgPort) } log.Debugf("falling back to local proxy mode with peer %s", conn.config.Key) diff --git a/client/internal/proxy/direct.go b/client/internal/proxy/direct.go index 58603a831..765e43ae4 100644 --- a/client/internal/proxy/direct.go +++ b/client/internal/proxy/direct.go @@ -1,8 +1,11 @@ package proxy import ( - log "github.com/sirupsen/logrus" "net" + + log "github.com/sirupsen/logrus" + + "github.com/netbirdio/netbird/iface" ) // DirectNoProxy is used when there is no need for a proxy between ICE and WireGuard. @@ -12,20 +15,28 @@ import ( // DirectNoProxy will just update remote peer with a remote host and fixed WireGuard port (r.g. 51820). // In order DirectNoProxy to work, WireGuard port has to be fixed for the time being. type DirectNoProxy struct { - config Config + wgInterface *iface.WGIface + + remoteKey string + allowedIps string + // RemoteWgListenPort is a WireGuard port of a remote peer. // It is used instead of the hardcoded 51820 port. - RemoteWgListenPort int + remoteWgListenPort int } // NewDirectNoProxy creates a new DirectNoProxy with a provided config and remote peer's WireGuard listen port -func NewDirectNoProxy(config Config, remoteWgPort int) *DirectNoProxy { - return &DirectNoProxy{config: config, RemoteWgListenPort: remoteWgPort} +func NewDirectNoProxy(wgInterface *iface.WGIface, remoteKey string, allowedIps string, remoteWgPort int) *DirectNoProxy { + return &DirectNoProxy{ + wgInterface: wgInterface, + remoteKey: remoteKey, + allowedIps: allowedIps, + remoteWgListenPort: remoteWgPort} } // Close removes peer from the WireGuard interface func (p *DirectNoProxy) Close() error { - err := p.config.WgInterface.RemovePeer(p.config.RemoteKey) + err := p.wgInterface.RemovePeer(p.remoteKey) if err != nil { return err } @@ -35,14 +46,13 @@ func (p *DirectNoProxy) Close() error { // Start just updates WireGuard peer with the remote IP and default WireGuard port func (p *DirectNoProxy) Start(remoteConn net.Conn) error { - log.Debugf("using DirectNoProxy while connecting to peer %s", p.config.RemoteKey) + log.Debugf("using DirectNoProxy while connecting to peer %s", p.remoteKey) addr, err := net.ResolveUDPAddr("udp", remoteConn.RemoteAddr().String()) if err != nil { return err } - addr.Port = p.RemoteWgListenPort - err = p.config.WgInterface.UpdatePeer(p.config.RemoteKey, p.config.AllowedIps, DefaultWgKeepAlive, - addr, p.config.PreSharedKey) + addr.Port = p.remoteWgListenPort + err = p.wgInterface.UpdatePeer(p.remoteKey, p.allowedIps, addr) if err != nil { return err diff --git a/client/internal/proxy/proxy.go b/client/internal/proxy/proxy.go index a0b9e98a1..67ec606e9 100644 --- a/client/internal/proxy/proxy.go +++ b/client/internal/proxy/proxy.go @@ -1,15 +1,10 @@ package proxy import ( - "github.com/netbirdio/netbird/iface" - "golang.zx2c4.com/wireguard/wgctrl/wgtypes" "io" "net" - "time" ) -const DefaultWgKeepAlive = 25 * time.Second - type Type string const ( @@ -19,14 +14,6 @@ const ( TypeNoProxy Type = "NoProxy" ) -type Config struct { - WgListenAddr string - RemoteKey string - WgInterface *iface.WGIface - AllowedIps string - PreSharedKey *wgtypes.Key -} - type Proxy interface { io.Closer // Start creates a local remoteConn and starts proxying data from/to remoteConn diff --git a/iface/iface.go b/iface/iface.go index 26d86d296..96eb9fc77 100644 --- a/iface/iface.go +++ b/iface/iface.go @@ -1,18 +1,20 @@ package iface import ( - "github.com/netbirdio/netbird/iface/bind" "net" "sync" "time" + "github.com/netbirdio/netbird/iface/bind" + log "github.com/sirupsen/logrus" - "golang.zx2c4.com/wireguard/wgctrl/wgtypes" ) const ( DefaultMTU = 1280 DefaultWgPort = 51820 + + defaultWgKeepAlive = 25 * time.Second ) // WGIface represents a interface instance @@ -76,12 +78,12 @@ func (w *WGIface) UpdateAddr(newAddr string) error { // UpdatePeer updates existing Wireguard Peer or creates a new one if doesn't exist // Endpoint is optional -func (w *WGIface) UpdatePeer(peerKey string, allowedIps string, keepAlive time.Duration, endpoint *net.UDPAddr, preSharedKey *wgtypes.Key) error { +func (w *WGIface) UpdatePeer(peerKey string, allowedIps string, endpoint *net.UDPAddr) error { w.mu.Lock() defer w.mu.Unlock() log.Debugf("updating interface %s peer %s: endpoint %s ", w.tun.DeviceName(), peerKey, endpoint) - return w.configurer.updatePeer(peerKey, allowedIps, keepAlive, endpoint, preSharedKey) + return w.configurer.updatePeer(peerKey, allowedIps, endpoint) } // RemovePeer removes a Wireguard Peer from the interface iface diff --git a/iface/iface_android.go b/iface/iface_android.go index fb57f0762..9fe73100b 100644 --- a/iface/iface_android.go +++ b/iface/iface_android.go @@ -1,12 +1,13 @@ package iface import ( - "github.com/pion/transport/v2" "sync" + + "github.com/pion/transport/v2" ) // NewWGIFace Creates a new WireGuard interface instance -func NewWGIFace(iFaceName string, address string, mtu int, tunAdapter TunAdapter, transportNet transport.Net) (*WGIface, error) { +func NewWGIFace(iFaceName string, address string, mtu int, preSharedKey *wgtypes.Key, tunAdapter TunAdapter, transportNet transport.Net) (*WGIface, error) { wgIFace := &WGIface{ mu: sync.Mutex{}, } @@ -19,7 +20,7 @@ func NewWGIFace(iFaceName string, address string, mtu int, tunAdapter TunAdapter tun := newTunDevice(wgAddress, mtu, tunAdapter, transportNet) wgIFace.tun = tun - wgIFace.configurer = newWGConfigurer(tun) + wgIFace.configurer = newWGConfigurer(tun, preSharedKey) wgIFace.userspaceBind = !WireGuardModuleIsLoaded() diff --git a/iface/iface_nonandroid.go b/iface/iface_nonandroid.go index 7168eea40..636b2a778 100644 --- a/iface/iface_nonandroid.go +++ b/iface/iface_nonandroid.go @@ -4,11 +4,13 @@ package iface import ( "github.com/pion/transport/v2" + "golang.zx2c4.com/wireguard/wgctrl/wgtypes" + "sync" ) // NewWGIFace Creates a new WireGuard interface instance -func NewWGIFace(iFaceName string, address string, mtu int, tunAdapter TunAdapter, transportNet transport.Net) (*WGIface, error) { +func NewWGIFace(iFaceName string, address string, mtu int, preSharedKey *wgtypes.Key, tunAdapter TunAdapter, transportNet transport.Net) (*WGIface, error) { wgIFace := &WGIface{ mu: sync.Mutex{}, } @@ -20,7 +22,7 @@ func NewWGIFace(iFaceName string, address string, mtu int, tunAdapter TunAdapter wgIFace.tun = newTunDevice(iFaceName, wgAddress, mtu, transportNet) - wgIFace.configurer = newWGConfigurer(iFaceName) + wgIFace.configurer = newWGConfigurer(iFaceName, preSharedKey) wgIFace.userspaceBind = !WireGuardModuleIsLoaded() return wgIFace, nil } diff --git a/iface/wg_configurer_android.go b/iface/wg_configurer_android.go index 9328467a6..4bef1b470 100644 --- a/iface/wg_configurer_android.go +++ b/iface/wg_configurer_android.go @@ -3,7 +3,6 @@ package iface import ( "errors" "net" - "time" log "github.com/sirupsen/logrus" @@ -15,12 +14,14 @@ var ( ) type wGConfigurer struct { - tunDevice *tunDevice + tunDevice *tunDevice + preSharedKey *wgtypes.Key } -func newWGConfigurer(tunDevice *tunDevice) wGConfigurer { +func newWGConfigurer(tunDevice *tunDevice, preSharedKey *wgtypes.Key) wGConfigurer { return wGConfigurer{ - tunDevice: tunDevice, + tunDevice: tunDevice, + preSharedKey: preSharedKey, } } @@ -41,7 +42,7 @@ func (c *wGConfigurer) configureInterface(privateKey string, port int) error { return c.tunDevice.Device().IpcSet(toWgUserspaceString(config)) } -func (c *wGConfigurer) updatePeer(peerKey string, allowedIps string, keepAlive time.Duration, endpoint *net.UDPAddr, preSharedKey *wgtypes.Key) error { +func (c *wGConfigurer) updatePeer(peerKey string, allowedIps string, endpoint *net.UDPAddr) error { //parse allowed ips _, ipNet, err := net.ParseCIDR(allowedIps) if err != nil { @@ -52,12 +53,13 @@ func (c *wGConfigurer) updatePeer(peerKey string, allowedIps string, keepAlive t if err != nil { return err } + keepalive := defaultWgKeepAlive peer := wgtypes.PeerConfig{ PublicKey: peerKeyParsed, ReplaceAllowedIPs: true, AllowedIPs: []net.IPNet{*ipNet}, PersistentKeepaliveInterval: &keepAlive, - PresharedKey: preSharedKey, + PresharedKey: c.preSharedKey, Endpoint: endpoint, } diff --git a/iface/wg_configurer_nonandroid.go b/iface/wg_configurer_nonandroid.go index 5a2a70ea3..6eaa7dd93 100644 --- a/iface/wg_configurer_nonandroid.go +++ b/iface/wg_configurer_nonandroid.go @@ -5,7 +5,6 @@ package iface import ( "fmt" "net" - "time" log "github.com/sirupsen/logrus" "golang.zx2c4.com/wireguard/wgctrl" @@ -13,12 +12,14 @@ import ( ) type wGConfigurer struct { - deviceName string + deviceName string + preSharedKey *wgtypes.Key } -func newWGConfigurer(deviceName string) wGConfigurer { +func newWGConfigurer(deviceName string, preSharedKey *wgtypes.Key) wGConfigurer { return wGConfigurer{ - deviceName: deviceName, + deviceName: deviceName, + preSharedKey: preSharedKey, } } @@ -43,7 +44,7 @@ func (c *wGConfigurer) configureInterface(privateKey string, port int) error { return nil } -func (c *wGConfigurer) updatePeer(peerKey string, allowedIps string, keepAlive time.Duration, endpoint *net.UDPAddr, preSharedKey *wgtypes.Key) error { +func (c *wGConfigurer) updatePeer(peerKey string, allowedIps string, endpoint *net.UDPAddr) error { //parse allowed ips _, ipNet, err := net.ParseCIDR(allowedIps) if err != nil { @@ -54,12 +55,13 @@ func (c *wGConfigurer) updatePeer(peerKey string, allowedIps string, keepAlive t if err != nil { return err } + keepalive := defaultWgKeepAlive peer := wgtypes.PeerConfig{ PublicKey: peerKeyParsed, ReplaceAllowedIPs: true, AllowedIPs: []net.IPNet{*ipNet}, - PersistentKeepaliveInterval: &keepAlive, - PresharedKey: preSharedKey, + PersistentKeepaliveInterval: &keepalive, + PresharedKey: c.preSharedKey, Endpoint: endpoint, }