Skip to content

Commit

Permalink
intercept packets only with the SYN flag set
Browse files Browse the repository at this point in the history
Using "ct state NEW" to intercept packets causes some undesired effects:
  We intercept packets that not only have the SYN flag set, like ACK,
  ACK+PSH or SYN+ACK. Mainly response packets.

  This means that the IPs are not always in the expected order:
  443:1.1.1.1 -> 192.168.1.123:12345
  which causes sometimes not to obtain the process of the connection,
  because the connection in the system appears as
  12345:192.168.1.123 -> 1.1.1.1:443

Intercepting packets with *only* the SYN flag set seems to resolve
this problem.
  • Loading branch information
gustavo-iniguez-goya committed Jul 23, 2023
1 parent 481574f commit e090833
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 4 deletions.
8 changes: 4 additions & 4 deletions daemon/firewall/nftables/monitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,16 @@ func (n *Nft) AreRulesLoaded() bool {
return false
}
nRules++
if c.Table.Name == exprs.NFT_CHAIN_MANGLE && rdx+1 != len(rules) {
log.Warning("nfables queue rule is not the latest of the list, reloading")
if c.Table.Name == exprs.NFT_CHAIN_MANGLE && rdx < len(rules)-2 {
log.Warning("nfables queue rule is not the latest of the list (%d/%d), reloading", rdx, len(rules))
return false
}
}
}
}
// we expect to have exactly 2 rules (queue and dns). If there're less or more, then we
// we expect to have exactly 3 rules (2 queue and dns). If there're less or more, then we
// need to reload them.
if nRules != 2 {
if nRules != 3 {
log.Warning("nfables filter rules not loaded: %d", nRules)
return false
}
Expand Down
58 changes: 58 additions & 0 deletions daemon/firewall/nftables/rules.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,12 @@ func (n *Nft) QueueConnections(enable bool, logError bool) (error, error) {
Table: table,
Chain: chain,
Exprs: []expr.Any{
&expr.Meta{Key: expr.MetaKeyL4PROTO, Register: 1},
&expr.Cmp{
Op: expr.CmpOpNeq,
Register: 1,
Data: []byte{unix.IPPROTO_TCP},
},
&expr.Ct{Register: 1, SourceRegister: false, Key: expr.CtKeySTATE},
&expr.Bitwise{
SourceRegister: 1,
Expand All @@ -113,6 +119,58 @@ func (n *Nft) QueueConnections(enable bool, logError bool) (error, error) {
// rule key, to allow get it later by key
UserData: []byte(InterceptionRuleKey),
})

/* nft --debug=netlink add rule inet mangle output tcp flags '& (fin|syn|rst|ack) == syn' queue bypass num 0
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x00000006 ]
[ payload load 1b @ transport header + 13 => reg 1 ]
[ bitwise reg 1 = ( reg 1 & 0x00000002 ) ^ 0x00000000 ]
[ cmp neq reg 1 0x00000000 ]
[ queue num 0 bypass ]
Intercept packets *only* with the SYN flag set.
Using 'ct state NEW' causes to intercept packets with other flags set, which
sometimes means that we receive outbound connections not in the expected order:
443:1.1.1.1 -> 192.168.123:12345 (bits ACK, ACK+PSH or SYN+ACK set)
*/
n.Conn.AddRule(&nftables.Rule{
Position: 0,
Table: table,
Chain: chain,
Exprs: []expr.Any{
&expr.Meta{Key: expr.MetaKeyL4PROTO, Register: 1},
&expr.Cmp{
Op: expr.CmpOpEq,
Register: 1,
Data: []byte{unix.IPPROTO_TCP},
},
&expr.Payload{
DestRegister: 1,
Base: expr.PayloadBaseTransportHeader,
Offset: 13,
Len: 1,
},
&expr.Bitwise{
DestRegister: 1,
SourceRegister: 1,
Len: 1,
Mask: []byte{0x17},
Xor: []byte{0x00},
},
&expr.Cmp{
Op: expr.CmpOpEq,
Register: 1,
Data: []byte{0x02},
},
&expr.Queue{
Num: n.QueueNum,
Flag: expr.QueueFlagBypass,
},
},
// rule key, to allow get it later by key
UserData: []byte(InterceptionRuleKey),
})

// apply changes
if !n.Commit() {
return fmt.Errorf("Error adding interception rule "), nil
Expand Down

0 comments on commit e090833

Please sign in to comment.