Skip to content

Commit e090833

Browse files
intercept packets only with the SYN flag set
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.
1 parent 481574f commit e090833

File tree

2 files changed

+62
-4
lines changed

2 files changed

+62
-4
lines changed

daemon/firewall/nftables/monitor.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,16 @@ func (n *Nft) AreRulesLoaded() bool {
3333
return false
3434
}
3535
nRules++
36-
if c.Table.Name == exprs.NFT_CHAIN_MANGLE && rdx+1 != len(rules) {
37-
log.Warning("nfables queue rule is not the latest of the list, reloading")
36+
if c.Table.Name == exprs.NFT_CHAIN_MANGLE && rdx < len(rules)-2 {
37+
log.Warning("nfables queue rule is not the latest of the list (%d/%d), reloading", rdx, len(rules))
3838
return false
3939
}
4040
}
4141
}
4242
}
43-
// we expect to have exactly 2 rules (queue and dns). If there're less or more, then we
43+
// we expect to have exactly 3 rules (2 queue and dns). If there're less or more, then we
4444
// need to reload them.
45-
if nRules != 2 {
45+
if nRules != 3 {
4646
log.Warning("nfables filter rules not loaded: %d", nRules)
4747
return false
4848
}

daemon/firewall/nftables/rules.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,12 @@ func (n *Nft) QueueConnections(enable bool, logError bool) (error, error) {
9696
Table: table,
9797
Chain: chain,
9898
Exprs: []expr.Any{
99+
&expr.Meta{Key: expr.MetaKeyL4PROTO, Register: 1},
100+
&expr.Cmp{
101+
Op: expr.CmpOpNeq,
102+
Register: 1,
103+
Data: []byte{unix.IPPROTO_TCP},
104+
},
99105
&expr.Ct{Register: 1, SourceRegister: false, Key: expr.CtKeySTATE},
100106
&expr.Bitwise{
101107
SourceRegister: 1,
@@ -113,6 +119,58 @@ func (n *Nft) QueueConnections(enable bool, logError bool) (error, error) {
113119
// rule key, to allow get it later by key
114120
UserData: []byte(InterceptionRuleKey),
115121
})
122+
123+
/* nft --debug=netlink add rule inet mangle output tcp flags '& (fin|syn|rst|ack) == syn' queue bypass num 0
124+
[ meta load l4proto => reg 1 ]
125+
[ cmp eq reg 1 0x00000006 ]
126+
[ payload load 1b @ transport header + 13 => reg 1 ]
127+
[ bitwise reg 1 = ( reg 1 & 0x00000002 ) ^ 0x00000000 ]
128+
[ cmp neq reg 1 0x00000000 ]
129+
[ queue num 0 bypass ]
130+
131+
Intercept packets *only* with the SYN flag set.
132+
Using 'ct state NEW' causes to intercept packets with other flags set, which
133+
sometimes means that we receive outbound connections not in the expected order:
134+
443:1.1.1.1 -> 192.168.123:12345 (bits ACK, ACK+PSH or SYN+ACK set)
135+
*/
136+
n.Conn.AddRule(&nftables.Rule{
137+
Position: 0,
138+
Table: table,
139+
Chain: chain,
140+
Exprs: []expr.Any{
141+
&expr.Meta{Key: expr.MetaKeyL4PROTO, Register: 1},
142+
&expr.Cmp{
143+
Op: expr.CmpOpEq,
144+
Register: 1,
145+
Data: []byte{unix.IPPROTO_TCP},
146+
},
147+
&expr.Payload{
148+
DestRegister: 1,
149+
Base: expr.PayloadBaseTransportHeader,
150+
Offset: 13,
151+
Len: 1,
152+
},
153+
&expr.Bitwise{
154+
DestRegister: 1,
155+
SourceRegister: 1,
156+
Len: 1,
157+
Mask: []byte{0x17},
158+
Xor: []byte{0x00},
159+
},
160+
&expr.Cmp{
161+
Op: expr.CmpOpEq,
162+
Register: 1,
163+
Data: []byte{0x02},
164+
},
165+
&expr.Queue{
166+
Num: n.QueueNum,
167+
Flag: expr.QueueFlagBypass,
168+
},
169+
},
170+
// rule key, to allow get it later by key
171+
UserData: []byte(InterceptionRuleKey),
172+
})
173+
116174
// apply changes
117175
if !n.Commit() {
118176
return fmt.Errorf("Error adding interception rule "), nil

0 commit comments

Comments
 (0)