@@ -27,59 +27,60 @@ const (
27
27
nftTable = "opengfw"
28
28
)
29
29
30
- var nftRulesForward = fmt .Sprintf (`
31
- define ACCEPT_CTMARK=%d
32
- define DROP_CTMARK=%d
33
- define QUEUE_NUM=%d
34
-
35
- table %s %s {
36
- chain FORWARD {
37
- type filter hook forward priority filter; policy accept;
38
-
39
- ct mark $ACCEPT_CTMARK counter accept
40
- ct mark $DROP_CTMARK counter drop
41
- counter queue num $QUEUE_NUM bypass
42
- }
43
- }
44
- ` , nfqueueConnMarkAccept , nfqueueConnMarkDrop , nfqueueNum , nftFamily , nftTable )
45
-
46
- var nftRulesLocal = fmt .Sprintf (`
47
- define ACCEPT_CTMARK=%d
48
- define DROP_CTMARK=%d
49
- define QUEUE_NUM=%d
50
-
51
- table %s %s {
52
- chain INPUT {
53
- type filter hook input priority filter; policy accept;
54
-
55
- ct mark $ACCEPT_CTMARK counter accept
56
- ct mark $DROP_CTMARK counter drop
57
- counter queue num $QUEUE_NUM bypass
58
- }
59
- chain OUTPUT {
60
- type filter hook output priority filter; policy accept;
61
-
62
- ct mark $ACCEPT_CTMARK counter accept
63
- ct mark $DROP_CTMARK counter drop
64
- counter queue num $QUEUE_NUM bypass
65
- }
66
- }
67
- ` , nfqueueConnMarkAccept , nfqueueConnMarkDrop , nfqueueNum , nftFamily , nftTable )
68
-
69
- var iptRulesForward = []iptRule {
70
- {"filter" , "FORWARD" , []string {"-m" , "connmark" , "--mark" , strconv .Itoa (nfqueueConnMarkAccept ), "-j" , "ACCEPT" }},
71
- {"filter" , "FORWARD" , []string {"-m" , "connmark" , "--mark" , strconv .Itoa (nfqueueConnMarkDrop ), "-j" , "DROP" }},
72
- {"filter" , "FORWARD" , []string {"-j" , "NFQUEUE" , "--queue-num" , strconv .Itoa (nfqueueNum ), "--queue-bypass" }},
30
+ func generateNftRules (local , rst bool ) (* nftTableSpec , error ) {
31
+ if local && rst {
32
+ return nil , errors .New ("tcp rst is not supported in local mode" )
33
+ }
34
+ table := & nftTableSpec {
35
+ Family : nftFamily ,
36
+ Table : nftTable ,
37
+ }
38
+ table .Defines = append (table .Defines , fmt .Sprintf ("define ACCEPT_CTMARK=%d" , nfqueueConnMarkAccept ))
39
+ table .Defines = append (table .Defines , fmt .Sprintf ("define DROP_CTMARK=%d" , nfqueueConnMarkDrop ))
40
+ table .Defines = append (table .Defines , fmt .Sprintf ("define QUEUE_NUM=%d" , nfqueueNum ))
41
+ if local {
42
+ table .Chains = []nftChainSpec {
43
+ {Chain : "INPUT" , Header : "type filter hook input priority filter; policy accept;" },
44
+ {Chain : "OUTPUT" , Header : "type filter hook output priority filter; policy accept;" },
45
+ }
46
+ } else {
47
+ table .Chains = []nftChainSpec {
48
+ {Chain : "FORWARD" , Header : "type filter hook forward priority filter; policy accept;" },
49
+ }
50
+ }
51
+ for i := range table .Chains {
52
+ c := & table .Chains [i ]
53
+ c .Rules = append (c .Rules , "ct mark $ACCEPT_CTMARK counter accept" )
54
+ if rst {
55
+ c .Rules = append (c .Rules , "ip protocol tcp ct mark $DROP_CTMARK counter reject with tcp reset" )
56
+ }
57
+ c .Rules = append (c .Rules , "ct mark $DROP_CTMARK counter drop" )
58
+ c .Rules = append (c .Rules , "counter queue num $QUEUE_NUM bypass" )
59
+ }
60
+ return table , nil
73
61
}
74
62
75
- var iptRulesLocal = []iptRule {
76
- {"filter" , "INPUT" , []string {"-m" , "connmark" , "--mark" , strconv .Itoa (nfqueueConnMarkAccept ), "-j" , "ACCEPT" }},
77
- {"filter" , "INPUT" , []string {"-m" , "connmark" , "--mark" , strconv .Itoa (nfqueueConnMarkDrop ), "-j" , "DROP" }},
78
- {"filter" , "INPUT" , []string {"-j" , "NFQUEUE" , "--queue-num" , strconv .Itoa (nfqueueNum ), "--queue-bypass" }},
63
+ func generateIptRules (local , rst bool ) ([]iptRule , error ) {
64
+ if local && rst {
65
+ return nil , errors .New ("tcp rst is not supported in local mode" )
66
+ }
67
+ var chains []string
68
+ if local {
69
+ chains = []string {"INPUT" , "OUTPUT" }
70
+ } else {
71
+ chains = []string {"FORWARD" }
72
+ }
73
+ rules := make ([]iptRule , 0 , 4 * len (chains ))
74
+ for _ , chain := range chains {
75
+ rules = append (rules , iptRule {"filter" , chain , []string {"-m" , "connmark" , "--mark" , strconv .Itoa (nfqueueConnMarkAccept ), "-j" , "ACCEPT" }})
76
+ if rst {
77
+ rules = append (rules , iptRule {"filter" , chain , []string {"-p" , "tcp" , "-m" , "connmark" , "--mark" , strconv .Itoa (nfqueueConnMarkDrop ), "-j" , "REJECT" , "--reject-with" , "tcp-reset" }})
78
+ }
79
+ rules = append (rules , iptRule {"filter" , chain , []string {"-m" , "connmark" , "--mark" , strconv .Itoa (nfqueueConnMarkDrop ), "-j" , "DROP" }})
80
+ rules = append (rules , iptRule {"filter" , chain , []string {"-j" , "NFQUEUE" , "--queue-num" , strconv .Itoa (nfqueueNum ), "--queue-bypass" }})
81
+ }
79
82
80
- {"filter" , "OUTPUT" , []string {"-m" , "connmark" , "--mark" , strconv .Itoa (nfqueueConnMarkAccept ), "-j" , "ACCEPT" }},
81
- {"filter" , "OUTPUT" , []string {"-m" , "connmark" , "--mark" , strconv .Itoa (nfqueueConnMarkDrop ), "-j" , "DROP" }},
82
- {"filter" , "OUTPUT" , []string {"-j" , "NFQUEUE" , "--queue-num" , strconv .Itoa (nfqueueNum ), "--queue-bypass" }},
83
+ return rules , nil
83
84
}
84
85
85
86
var _ PacketIO = (* nfqueuePacketIO )(nil )
@@ -89,6 +90,7 @@ var errNotNFQueuePacket = errors.New("not an NFQueue packet")
89
90
type nfqueuePacketIO struct {
90
91
n * nfqueue.Nfqueue
91
92
local bool
93
+ rst bool
92
94
rSet bool // whether the nftables/iptables rules have been set
93
95
94
96
// iptables not nil = use iptables instead of nftables
@@ -101,6 +103,7 @@ type NFQueuePacketIOConfig struct {
101
103
ReadBuffer int
102
104
WriteBuffer int
103
105
Local bool
106
+ RST bool
104
107
}
105
108
106
109
func NewNFQueuePacketIO (config NFQueuePacketIOConfig ) (PacketIO , error ) {
@@ -147,6 +150,7 @@ func NewNFQueuePacketIO(config NFQueuePacketIOConfig) (PacketIO, error) {
147
150
return & nfqueuePacketIO {
148
151
n : n ,
149
152
local : config .Local ,
153
+ rst : config .RST ,
150
154
ipt4 : ipt4 ,
151
155
ipt6 : ipt6 ,
152
156
}, nil
@@ -182,9 +186,9 @@ func (n *nfqueuePacketIO) Register(ctx context.Context, cb PacketCallback) error
182
186
}
183
187
if ! n .rSet {
184
188
if n .ipt4 != nil {
185
- err = n .setupIpt (n .local , false )
189
+ err = n .setupIpt (n .local , n . rst , false )
186
190
} else {
187
- err = n .setupNft (n .local , false )
191
+ err = n .setupNft (n .local , n . rst , false )
188
192
}
189
193
if err != nil {
190
194
return err
@@ -238,44 +242,39 @@ func (n *nfqueuePacketIO) SetVerdict(p Packet, v Verdict, newPacket []byte) erro
238
242
func (n * nfqueuePacketIO ) Close () error {
239
243
if n .rSet {
240
244
if n .ipt4 != nil {
241
- _ = n .setupIpt (n .local , true )
245
+ _ = n .setupIpt (n .local , n . rst , true )
242
246
} else {
243
- _ = n .setupNft (n .local , true )
247
+ _ = n .setupNft (n .local , n . rst , true )
244
248
}
245
249
n .rSet = false
246
250
}
247
251
return n .n .Close ()
248
252
}
249
253
250
- func (n * nfqueuePacketIO ) setupNft (local , remove bool ) error {
251
- var rules string
252
- if local {
253
- rules = nftRulesLocal
254
- } else {
255
- rules = nftRulesForward
254
+ func (n * nfqueuePacketIO ) setupNft (local , rst , remove bool ) error {
255
+ rules , err := generateNftRules (local , rst )
256
+ if err != nil {
257
+ return err
256
258
}
257
- var err error
259
+ rulesText := rules . String ()
258
260
if remove {
259
261
err = nftDelete (nftFamily , nftTable )
260
262
} else {
261
263
// Delete first to make sure no leftover rules
262
264
_ = nftDelete (nftFamily , nftTable )
263
- err = nftAdd (rules )
265
+ err = nftAdd (rulesText )
264
266
}
265
267
if err != nil {
266
268
return err
267
269
}
268
270
return nil
269
271
}
270
272
271
- func (n * nfqueuePacketIO ) setupIpt (local , remove bool ) error {
272
- var rules []iptRule
273
- if local {
274
- rules = iptRulesLocal
275
- } else {
276
- rules = iptRulesForward
273
+ func (n * nfqueuePacketIO ) setupIpt (local , rst , remove bool ) error {
274
+ rules , err := generateIptRules (local , rst )
275
+ if err != nil {
276
+ return err
277
277
}
278
- var err error
279
278
if remove {
280
279
err = iptsBatchDeleteIfExists ([]* iptables.IPTables {n .ipt4 , n .ipt6 }, rules )
281
280
} else {
@@ -330,6 +329,42 @@ func nftDelete(family, table string) error {
330
329
return cmd .Run ()
331
330
}
332
331
332
+ type nftTableSpec struct {
333
+ Defines []string
334
+ Family , Table string
335
+ Chains []nftChainSpec
336
+ }
337
+
338
+ func (t * nftTableSpec ) String () string {
339
+ chains := make ([]string , 0 , len (t .Chains ))
340
+ for _ , c := range t .Chains {
341
+ chains = append (chains , c .String ())
342
+ }
343
+
344
+ return fmt .Sprintf (`
345
+ %s
346
+
347
+ table %s %s {
348
+ %s
349
+ }
350
+ ` , strings .Join (t .Defines , "\n " ), t .Family , t .Table , strings .Join (chains , "" ))
351
+ }
352
+
353
+ type nftChainSpec struct {
354
+ Chain string
355
+ Header string
356
+ Rules []string
357
+ }
358
+
359
+ func (c * nftChainSpec ) String () string {
360
+ return fmt .Sprintf (`
361
+ chain %s {
362
+ %s
363
+ %s
364
+ }
365
+ ` , c .Chain , c .Header , strings .Join (c .Rules , "\n \x20 \x20 \x20 \x20 " ))
366
+ }
367
+
333
368
type iptRule struct {
334
369
Table , Chain string
335
370
RuleSpec []string
0 commit comments