diff --git a/go.mod b/go.mod index 018d7ee01..b71ac9372 100644 --- a/go.mod +++ b/go.mod @@ -109,6 +109,7 @@ require ( github.com/go-stack/stack v1.8.0 // indirect github.com/goki/freetype v0.0.0-20181231101311-fa8a33aabaff // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/google/btree v1.0.1 // indirect github.com/google/s2a-go v0.1.4 // indirect github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect github.com/googleapis/gax-go/v2 v2.10.0 // indirect @@ -154,6 +155,7 @@ require ( gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gopkg.in/tomb.v2 v2.0.0-20161208151619-d5d1b5820637 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect + gvisor.dev/gvisor v0.0.0-20221203005347-703fd9b7fbc0 // indirect honnef.co/go/tools v0.2.2 // indirect k8s.io/apimachinery v0.23.5 // indirect ) diff --git a/iface/iface_nonandroid.go b/iface/iface_nonandroid.go index da4ef13fd..98fb38978 100644 --- a/iface/iface_nonandroid.go +++ b/iface/iface_nonandroid.go @@ -20,10 +20,10 @@ func NewWGIFace(iFaceName string, address string, mtu int, tunAdapter TunAdapter return wgIFace, err } - wgIFace.tun = newTunDevice(iFaceName, wgAddress, mtu, transportNet) - - wgIFace.configurer = newWGConfigurer(iFaceName) - wgIFace.userspaceBind = !WireGuardModuleIsLoaded() + tun := newTunDevice(iFaceName, wgAddress, mtu, transportNet) + wgIFace.tun = tun + wgIFace.configurer = newWGConfigurer(tun) + wgIFace.userspaceBind = true return wgIFace, nil } diff --git a/iface/ipc_parser_android.go b/iface/ipc_parser.go similarity index 100% rename from iface/ipc_parser_android.go rename to iface/ipc_parser.go diff --git a/iface/tun_linux.go b/iface/tun_linux.go index 1a3537394..1debd5698 100644 --- a/iface/tun_linux.go +++ b/iface/tun_linux.go @@ -3,7 +3,6 @@ package iface import ( - "fmt" "os" log "github.com/sirupsen/logrus" @@ -11,14 +10,6 @@ import ( ) func (c *tunDevice) Create() error { - if WireGuardModuleIsLoaded() { - log.Infof("create tun interface with kernel WireGuard support: %s", c.DeviceName()) - return c.createWithKernel() - } - - if !tunModuleIsLoaded() { - return fmt.Errorf("couldn't check or load tun module") - } log.Infof("create tun interface with userspace WireGuard support: %s", c.DeviceName()) var err error c.netInterface, err = c.createWithUserspace() @@ -27,7 +18,6 @@ func (c *tunDevice) Create() error { } return c.assignAddr() - } // createWithKernel Creates a new WireGuard interface using kernel WireGuard module. @@ -90,34 +80,7 @@ func (c *tunDevice) createWithKernel() error { // assignAddr Adds IP address to the tunnel interface func (c *tunDevice) assignAddr() error { - link := newWGLink(c.name) - - //delete existing addresses - list, err := netlink.AddrList(link, 0) - if err != nil { - return err - } - if len(list) > 0 { - for _, a := range list { - addr := a - err = netlink.AddrDel(link, &addr) - if err != nil { - return err - } - } - } - - log.Debugf("adding address %s to interface: %s", c.address.String(), c.name) - addr, _ := netlink.ParseAddr(c.address.String()) - err = netlink.AddrAdd(link, addr) - if os.IsExist(err) { - log.Infof("interface %s already has the address: %s", c.name, c.address.String()) - } else if err != nil { - return err - } - // On linux, the link must be brought up - err = netlink.LinkSetUp(link) - return err + return nil } type wgLink struct { diff --git a/iface/tun_unix.go b/iface/tun_unix.go index f923362a4..8a8feea64 100644 --- a/iface/tun_unix.go +++ b/iface/tun_unix.go @@ -4,16 +4,17 @@ package iface import ( "net" + "net/netip" "os" "github.com/pion/transport/v2" "golang.zx2c4.com/wireguard/ipc" + "golang.zx2c4.com/wireguard/tun/netstack" "github.com/netbirdio/netbird/iface/bind" log "github.com/sirupsen/logrus" "golang.zx2c4.com/wireguard/device" - "golang.zx2c4.com/wireguard/tun" ) type tunDevice struct { @@ -25,6 +26,7 @@ type tunDevice struct { uapi net.Listener wrapper *DeviceWrapper close chan struct{} + tunDevice *device.Device } func newTunDevice(name string, address WGAddress, mtu int, transportNet transport.Net) *tunDevice { @@ -46,6 +48,10 @@ func (c *tunDevice) WgAddress() WGAddress { return c.address } +func (t *tunDevice) Device() *device.Device { + return t.tunDevice +} + func (c *tunDevice) DeviceName() string { return c.name } @@ -87,8 +93,12 @@ func (c *tunDevice) Close() error { // createWithUserspace Creates a new Wireguard interface, using wireguard-go userspace implementation func (c *tunDevice) createWithUserspace() (NetInterface, error) { - tunIface, err := tun.CreateTUN(c.name, c.mtu) + tunIface, _, err := netstack.CreateNetTUN( + []netip.Addr{netip.MustParseAddr(c.address.IP.String())}, + []netip.Addr{netip.MustParseAddr("8.8.8.8")}, + 1420) if err != nil { + log.Debugf("createWithUserspace failed with error: %v", err) return nil, err } c.wrapper = newDeviceWrapper(tunIface) @@ -101,37 +111,12 @@ func (c *tunDevice) createWithUserspace() (NetInterface, error) { ) err = tunDev.Up() if err != nil { + log.Debugf("tunDev.Up() failed with error: %v", err) _ = tunIface.Close() return nil, err } - c.uapi, err = c.getUAPI(c.name) - if err != nil { - _ = tunIface.Close() - return nil, err - } - - go func() { - for { - select { - case <-c.close: - log.Debugf("exit uapi.Accept()") - return - default: - } - uapiConn, uapiErr := c.uapi.Accept() - if uapiErr != nil { - log.Traceln("uapi Accept failed with error: ", uapiErr) - continue - } - go func() { - tunDev.IpcHandle(uapiConn) - log.Debugf("exit tunDevice.IpcHandle") - }() - } - }() - - log.Debugln("UAPI listener started") + c.tunDevice = tunDev return tunIface, nil } diff --git a/iface/wg_configurer_android.go b/iface/wg_configurer.go similarity index 100% rename from iface/wg_configurer_android.go rename to iface/wg_configurer.go diff --git a/iface/wg_configurer_nonandroid.go b/iface/wg_configurer_nonandroid.go deleted file mode 100644 index 3d9aff7a9..000000000 --- a/iface/wg_configurer_nonandroid.go +++ /dev/null @@ -1,205 +0,0 @@ -//go:build !android - -package iface - -import ( - "fmt" - "net" - "time" - - log "github.com/sirupsen/logrus" - "golang.zx2c4.com/wireguard/wgctrl" - "golang.zx2c4.com/wireguard/wgctrl/wgtypes" -) - -type wGConfigurer struct { - deviceName string -} - -func newWGConfigurer(deviceName string) wGConfigurer { - return wGConfigurer{ - deviceName: deviceName, - } -} - -func (c *wGConfigurer) configureInterface(privateKey string, port int) error { - log.Debugf("adding Wireguard private key") - key, err := wgtypes.ParseKey(privateKey) - if err != nil { - return err - } - fwmark := 0 - config := wgtypes.Config{ - PrivateKey: &key, - ReplacePeers: true, - FirewallMark: &fwmark, - ListenPort: &port, - } - - err = c.configure(config) - if err != nil { - return fmt.Errorf(`received error "%w" while configuring interface %s with port %d`, err, c.deviceName, port) - } - return nil -} - -func (c *wGConfigurer) updatePeer(peerKey string, allowedIps string, keepAlive time.Duration, endpoint *net.UDPAddr, preSharedKey *wgtypes.Key) error { - //parse allowed ips - _, ipNet, err := net.ParseCIDR(allowedIps) - if err != nil { - return err - } - - peerKeyParsed, err := wgtypes.ParseKey(peerKey) - if err != nil { - return err - } - peer := wgtypes.PeerConfig{ - PublicKey: peerKeyParsed, - ReplaceAllowedIPs: true, - AllowedIPs: []net.IPNet{*ipNet}, - PersistentKeepaliveInterval: &keepAlive, - PresharedKey: preSharedKey, - Endpoint: endpoint, - } - - config := wgtypes.Config{ - Peers: []wgtypes.PeerConfig{peer}, - } - err = c.configure(config) - if err != nil { - return fmt.Errorf(`received error "%w" while updating peer on interface %s with settings: allowed ips %s, endpoint %s`, err, c.deviceName, allowedIps, endpoint.String()) - } - return nil -} - -func (c *wGConfigurer) removePeer(peerKey string) error { - peerKeyParsed, err := wgtypes.ParseKey(peerKey) - if err != nil { - return err - } - - peer := wgtypes.PeerConfig{ - PublicKey: peerKeyParsed, - Remove: true, - } - - config := wgtypes.Config{ - Peers: []wgtypes.PeerConfig{peer}, - } - err = c.configure(config) - if err != nil { - return fmt.Errorf(`received error "%w" while removing peer %s from interface %s`, err, peerKey, c.deviceName) - } - return nil -} - -func (c *wGConfigurer) addAllowedIP(peerKey string, allowedIP string) error { - _, ipNet, err := net.ParseCIDR(allowedIP) - if err != nil { - return err - } - - peerKeyParsed, err := wgtypes.ParseKey(peerKey) - if err != nil { - return err - } - peer := wgtypes.PeerConfig{ - PublicKey: peerKeyParsed, - UpdateOnly: true, - ReplaceAllowedIPs: false, - AllowedIPs: []net.IPNet{*ipNet}, - } - - config := wgtypes.Config{ - Peers: []wgtypes.PeerConfig{peer}, - } - err = c.configure(config) - if err != nil { - return fmt.Errorf(`received error "%w" while adding allowed Ip to peer on interface %s with settings: allowed ips %s`, err, c.deviceName, allowedIP) - } - return nil -} - -func (c *wGConfigurer) removeAllowedIP(peerKey string, allowedIP string) error { - _, ipNet, err := net.ParseCIDR(allowedIP) - if err != nil { - return err - } - - peerKeyParsed, err := wgtypes.ParseKey(peerKey) - if err != nil { - return err - } - - existingPeer, err := c.getPeer(c.deviceName, peerKey) - if err != nil { - return err - } - - newAllowedIPs := existingPeer.AllowedIPs - - for i, existingAllowedIP := range existingPeer.AllowedIPs { - if existingAllowedIP.String() == ipNet.String() { - newAllowedIPs = append(existingPeer.AllowedIPs[:i], existingPeer.AllowedIPs[i+1:]...) //nolint:gocritic - break - } - } - - peer := wgtypes.PeerConfig{ - PublicKey: peerKeyParsed, - UpdateOnly: true, - ReplaceAllowedIPs: true, - AllowedIPs: newAllowedIPs, - } - - config := wgtypes.Config{ - Peers: []wgtypes.PeerConfig{peer}, - } - err = c.configure(config) - if err != nil { - return fmt.Errorf(`received error "%w" while removing allowed IP from peer on interface %s with settings: allowed ips %s`, err, c.deviceName, allowedIP) - } - return nil -} - -func (c *wGConfigurer) getPeer(ifaceName, peerPubKey string) (wgtypes.Peer, error) { - wg, err := wgctrl.New() - if err != nil { - return wgtypes.Peer{}, err - } - defer func() { - err = wg.Close() - if err != nil { - log.Errorf("got error while closing wgctl: %v", err) - } - }() - - wgDevice, err := wg.Device(ifaceName) - if err != nil { - return wgtypes.Peer{}, err - } - for _, peer := range wgDevice.Peers { - if peer.PublicKey.String() == peerPubKey { - return peer, nil - } - } - return wgtypes.Peer{}, fmt.Errorf("peer not found") -} - -func (c *wGConfigurer) configure(config wgtypes.Config) error { - wg, err := wgctrl.New() - if err != nil { - return err - } - defer wg.Close() - - // validate if device with name exists - _, err = wg.Device(c.deviceName) - if err != nil { - return err - } - log.Tracef("got Wireguard device %s", c.deviceName) - - return wg.ConfigureDevice(c.deviceName, config) -}