From d30cf8706ae197eed2b65bfd287c73c9395db0c2 Mon Sep 17 00:00:00 2001 From: Viktor Liu Date: Fri, 12 Apr 2024 16:53:11 +0200 Subject: [PATCH] Allow disabling custom routing (#1840) --- client/internal/routemanager/manager.go | 25 +++++++++++++------ .../internal/routemanager/systemops_linux.go | 2 +- client/internal/wgproxy/proxy_ebpf.go | 2 +- iface/wg_configurer_kernel.go | 4 +-- iface/wg_configurer_usp.go | 2 +- util/net/dialer_generic.go | 12 +++++++++ util/net/listener_generic.go | 11 +++++++- util/net/net.go | 12 ++++++++- util/net/net_linux.go | 10 +++++++- 9 files changed, 64 insertions(+), 16 deletions(-) diff --git a/client/internal/routemanager/manager.go b/client/internal/routemanager/manager.go index 36a37f02c50..0dfc0f7e008 100644 --- a/client/internal/routemanager/manager.go +++ b/client/internal/routemanager/manager.go @@ -16,6 +16,7 @@ import ( "github.com/netbirdio/netbird/client/internal/peer" "github.com/netbirdio/netbird/iface" "github.com/netbirdio/netbird/route" + nbnet "github.com/netbirdio/netbird/util/net" "github.com/netbirdio/netbird/version" ) @@ -68,6 +69,10 @@ func NewManager(ctx context.Context, pubKey string, wgInterface *iface.WGIface, // Init sets up the routing func (m *DefaultManager) Init() (peer.BeforeAddPeerHookFunc, peer.AfterRemovePeerHookFunc, error) { + if nbnet.CustomRoutingDisabled() { + return nil, nil, nil + } + if err := cleanupRouting(); err != nil { log.Warnf("Failed cleaning up routing: %v", err) } @@ -99,11 +104,15 @@ func (m *DefaultManager) Stop() { if m.serverRouter != nil { m.serverRouter.cleanUp() } - if err := cleanupRouting(); err != nil { - log.Errorf("Error cleaning up routing: %v", err) - } else { - log.Info("Routing cleanup complete") + + if !nbnet.CustomRoutingDisabled() { + if err := cleanupRouting(); err != nil { + log.Errorf("Error cleaning up routing: %v", err) + } else { + log.Info("Routing cleanup complete") + } } + m.ctx = nil } @@ -210,9 +219,11 @@ func (m *DefaultManager) clientRoutes(initialRoutes []*route.Route) []*route.Rou } func isPrefixSupported(prefix netip.Prefix) bool { - switch runtime.GOOS { - case "linux", "windows", "darwin": - return true + if !nbnet.CustomRoutingDisabled() { + switch runtime.GOOS { + case "linux", "windows", "darwin": + return true + } } // If prefix is too small, lets assume it is a possible default prefix which is not yet supported diff --git a/client/internal/routemanager/systemops_linux.go b/client/internal/routemanager/systemops_linux.go index 2dfde31a222..a0f55131df4 100644 --- a/client/internal/routemanager/systemops_linux.go +++ b/client/internal/routemanager/systemops_linux.go @@ -36,7 +36,7 @@ const ( var ErrTableIDExists = errors.New("ID exists with different name") var routeManager = &RouteManager{} -var isLegacy = os.Getenv("NB_USE_LEGACY_ROUTING") == "true" +var isLegacy = os.Getenv("NB_USE_LEGACY_ROUTING") == "true" || nbnet.CustomRoutingDisabled() type ruleParams struct { priority int diff --git a/client/internal/wgproxy/proxy_ebpf.go b/client/internal/wgproxy/proxy_ebpf.go index 2235c5d2bdf..22d3273762b 100644 --- a/client/internal/wgproxy/proxy_ebpf.go +++ b/client/internal/wgproxy/proxy_ebpf.go @@ -230,7 +230,7 @@ func (p *WGEBPFProxy) prepareSenderRawSocket() (net.PacketConn, error) { } // Set the fwmark on the socket. - err = syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_MARK, nbnet.NetbirdFwmark) + err = nbnet.SetSocketOpt(fd) if err != nil { return nil, fmt.Errorf("setting fwmark failed: %w", err) } diff --git a/iface/wg_configurer_kernel.go b/iface/wg_configurer_kernel.go index 9fe987cee21..67bfb716d0f 100644 --- a/iface/wg_configurer_kernel.go +++ b/iface/wg_configurer_kernel.go @@ -10,8 +10,6 @@ import ( log "github.com/sirupsen/logrus" "golang.zx2c4.com/wireguard/wgctrl" "golang.zx2c4.com/wireguard/wgctrl/wgtypes" - - nbnet "github.com/netbirdio/netbird/util/net" ) type wgKernelConfigurer struct { @@ -31,7 +29,7 @@ func (c *wgKernelConfigurer) configureInterface(privateKey string, port int) err if err != nil { return err } - fwmark := nbnet.NetbirdFwmark + fwmark := getFwmark() config := wgtypes.Config{ PrivateKey: &key, ReplacePeers: true, diff --git a/iface/wg_configurer_usp.go b/iface/wg_configurer_usp.go index 24dfadf1408..c15bc1448fc 100644 --- a/iface/wg_configurer_usp.go +++ b/iface/wg_configurer_usp.go @@ -349,7 +349,7 @@ func toWgUserspaceString(wgCfg wgtypes.Config) string { } func getFwmark() int { - if runtime.GOOS == "linux" { + if runtime.GOOS == "linux" && !nbnet.CustomRoutingDisabled() { return nbnet.NetbirdFwmark } return 0 diff --git a/util/net/dialer_generic.go b/util/net/dialer_generic.go index 4eda710ac40..1e217da1369 100644 --- a/util/net/dialer_generic.go +++ b/util/net/dialer_generic.go @@ -49,6 +49,10 @@ func RemoveDialerHooks() { // DialContext wraps the net.Dialer's DialContext method to use the custom connection func (d *Dialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) { + if CustomRoutingDisabled() { + return d.Dialer.DialContext(ctx, network, address) + } + var resolver *net.Resolver if d.Resolver != nil { resolver = d.Resolver @@ -123,6 +127,10 @@ func callDialerHooks(ctx context.Context, connID ConnectionID, address string, r } func DialUDP(network string, laddr, raddr *net.UDPAddr) (*net.UDPConn, error) { + if CustomRoutingDisabled() { + return net.DialUDP(network, laddr, raddr) + } + dialer := NewDialer() dialer.LocalAddr = laddr @@ -143,6 +151,10 @@ func DialUDP(network string, laddr, raddr *net.UDPAddr) (*net.UDPConn, error) { } func DialTCP(network string, laddr, raddr *net.TCPAddr) (*net.TCPConn, error) { + if CustomRoutingDisabled() { + return net.DialTCP(network, laddr, raddr) + } + dialer := NewDialer() dialer.LocalAddr = laddr diff --git a/util/net/listener_generic.go b/util/net/listener_generic.go index 451279e9d25..7847a29c737 100644 --- a/util/net/listener_generic.go +++ b/util/net/listener_generic.go @@ -8,6 +8,7 @@ import ( "net" "sync" + "github.com/pion/transport/v3" log "github.com/sirupsen/logrus" ) @@ -52,6 +53,10 @@ func RemoveListenerHooks() { // ListenPacket listens on the network address and returns a PacketConn // which includes support for write hooks. func (l *ListenerConfig) ListenPacket(ctx context.Context, network, address string) (net.PacketConn, error) { + if CustomRoutingDisabled() { + return l.ListenConfig.ListenPacket(ctx, network, address) + } + pc, err := l.ListenConfig.ListenPacket(ctx, network, address) if err != nil { return nil, fmt.Errorf("listen packet: %w", err) @@ -144,7 +149,11 @@ func closeConn(id ConnectionID, conn net.PacketConn) error { // ListenUDP listens on the network address and returns a transport.UDPConn // which includes support for write and close hooks. -func ListenUDP(network string, laddr *net.UDPAddr) (*UDPConn, error) { +func ListenUDP(network string, laddr *net.UDPAddr) (transport.UDPConn, error) { + if CustomRoutingDisabled() { + return net.ListenUDP(network, laddr) + } + conn, err := NewListener().ListenPacket(context.Background(), network, laddr.String()) if err != nil { return nil, fmt.Errorf("listen UDP: %w", err) diff --git a/util/net/net.go b/util/net/net.go index 9ea7ae80340..3856911b1b7 100644 --- a/util/net/net.go +++ b/util/net/net.go @@ -1,10 +1,16 @@ package net -import "github.com/google/uuid" +import ( + "os" + + "github.com/google/uuid" +) const ( // NetbirdFwmark is the fwmark value used by Netbird via wireguard NetbirdFwmark = 0x1BD00 + + envDisableCustomRouting = "NB_DISABLE_CUSTOM_ROUTING" ) // ConnectionID provides a globally unique identifier for network connections. @@ -15,3 +21,7 @@ type ConnectionID string func GenerateConnID() ConnectionID { return ConnectionID(uuid.NewString()) } + +func CustomRoutingDisabled() bool { + return os.Getenv(envDisableCustomRouting) == "true" +} diff --git a/util/net/net_linux.go b/util/net/net_linux.go index 82141750029..954545eb556 100644 --- a/util/net/net_linux.go +++ b/util/net/net_linux.go @@ -21,7 +21,7 @@ func SetRawSocketMark(conn syscall.RawConn) error { var setErr error err := conn.Control(func(fd uintptr) { - setErr = syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_MARK, NetbirdFwmark) + setErr = SetSocketOpt(int(fd)) }) if err != nil { return fmt.Errorf("control: %w", err) @@ -33,3 +33,11 @@ func SetRawSocketMark(conn syscall.RawConn) error { return nil } + +func SetSocketOpt(fd int) error { + if CustomRoutingDisabled() { + return nil + } + + return syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_MARK, NetbirdFwmark) +}