diff --git a/client/firewall/iptables/router_linux.go b/client/firewall/iptables/router_linux.go index 5b1b162ef..9a310b1a2 100644 --- a/client/firewall/iptables/router_linux.go +++ b/client/firewall/iptables/router_linux.go @@ -114,6 +114,10 @@ func (r *router) init(stateManager *statemanager.Manager) error { log.Errorf("failed to clean up rules from FORWARD chain: %s", err) } + if err := r.setupConntrackZones(); err != nil { + log.Errorf("failed to setup conntrack zones: %v", err) + } + if err := r.createContainers(); err != nil { return fmt.Errorf("create containers: %w", err) } @@ -396,10 +400,6 @@ func (r *router) cleanUpDefaultForwardRules() error { } func (r *router) createContainers() error { - if err := r.setupConntrackZones(); err != nil { - log.Errorf("failed to setup conntrack zones: %v", err) - } - for _, chainInfo := range []struct { chain string table string diff --git a/client/firewall/nftables/router_linux.go b/client/firewall/nftables/router_linux.go index 6def30bf0..f7488945d 100644 --- a/client/firewall/nftables/router_linux.go +++ b/client/firewall/nftables/router_linux.go @@ -21,6 +21,7 @@ import ( nberrors "github.com/netbirdio/netbird/client/errors" firewall "github.com/netbirdio/netbird/client/firewall/manager" nbid "github.com/netbirdio/netbird/client/internal/acl/id" + nftypes "github.com/netbirdio/netbird/client/internal/netflow/types" "github.com/netbirdio/netbird/client/internal/routemanager/ipfwdstate" "github.com/netbirdio/netbird/client/internal/routemanager/refcounter" nbnet "github.com/netbirdio/netbird/util/net" @@ -33,6 +34,7 @@ const ( chainNameRoutingNat = "netbird-rt-postrouting" chainNameRoutingRdr = "netbird-rt-redirect" chainNameForward = "FORWARD" + chainNameRaw = "netbird-raw" userDataAcceptForwardRuleIif = "frwacceptiif" userDataAcceptForwardRuleOif = "frwacceptoif" @@ -96,6 +98,10 @@ func (r *router) init(workTable *nftables.Table) error { log.Errorf("failed to clean up rules from FORWARD chain: %s", err) } + if err := r.setupConntrackZones(); err != nil { + log.Errorf("failed to setup conntrack zones: %v", err) + } + if err := r.createContainers(); err != nil { return fmt.Errorf("create containers: %w", err) } @@ -226,6 +232,49 @@ func (r *router) createContainers() error { return nil } +// setupConntrackZones configures the connection tracking zones for the NetBird interface +func (r *router) setupConntrackZones() error { + rawChain := r.conn.AddChain(&nftables.Chain{ + Name: chainNameRaw, + Table: r.workTable, + Type: nftables.ChainTypeFilter, + Hooknum: nftables.ChainHookPrerouting, + Priority: nftables.ChainPriorityRaw, + }) + + exprs := []expr.Any{ + &expr.Meta{ + Key: expr.MetaKeyIIFNAME, + Register: 1, + }, + &expr.Cmp{ + Op: expr.CmpOpEq, + Register: 1, + Data: ifname(r.wgIface.Name()), + }, + &expr.Immediate{ + Register: 1, + Data: binaryutil.NativeEndian.PutUint32(nftypes.ZoneID), + }, + &expr.Ct{ + Key: expr.CtKeyZONE, + Register: 1, + SourceRegister: true, + }, + } + + r.conn.AddRule(&nftables.Rule{ + Table: r.workTable, + Chain: rawChain, + Exprs: exprs, + }) + + if err := r.conn.Flush(); err != nil { + return fmt.Errorf("nftables: flush conntrack zone: %w", err) + } + return nil +} + // AddRouteFiltering appends a nftables rule to the routing chain func (r *router) AddRouteFiltering( id []byte, diff --git a/client/internal/netflow/conntrack/conntrack.go b/client/internal/netflow/conntrack/conntrack.go index 63fb84aa8..a7471d10c 100644 --- a/client/internal/netflow/conntrack/conntrack.go +++ b/client/internal/netflow/conntrack/conntrack.go @@ -225,16 +225,14 @@ func (c *ConnTrack) handleEvent(event nfct.Event) { // relevantFlow checks if the flow is related to the specified interface func (c *ConnTrack) relevantFlow(zone uint16, srcIP, dstIP netip.Addr) bool { + // This currently only covers inbound. + // TODO: handle outbound flows based on interface for site2site traffic if zone == nftypes.ZoneID { return true } wgnet := c.iface.Address().Network - if !wgnet.Contains(srcIP.AsSlice()) && !wgnet.Contains(dstIP.AsSlice()) { - return false - } - - return true + return wgnet.Contains(srcIP.AsSlice()) || wgnet.Contains(dstIP.AsSlice()) } // mapRxPackets maps packet counts to RX based on flow direction