@@ -19,29 +19,28 @@ import (
1919)
2020
2121const (
22- nfqueueNum = 100
22+ nfqueueDefaultQueueNum = 100
2323 nfqueueMaxPacketLen = 0xFFFF
2424 nfqueueDefaultQueueSize = 128
2525
26- nfqueueConnMarkAccept = 1001
27- nfqueueConnMarkDrop = 1002
26+ nfqueueDefaultConnMarkAccept = 1001
2827
29- nftFamily = "inet"
30- nftTable = "opengfw"
28+ nftFamily = "inet"
29+ nftDefaultTable = "opengfw"
3130)
3231
33- func generateNftRules ( local , rst bool ) (* nftTableSpec , error ) {
34- if local && rst {
32+ func ( n * nfqueuePacketIO ) generateNftRules ( ) (* nftTableSpec , error ) {
33+ if n . local && n . rst {
3534 return nil , errors .New ("tcp rst is not supported in local mode" )
3635 }
3736 table := & nftTableSpec {
3837 Family : nftFamily ,
39- Table : nftTable ,
38+ Table : n . table ,
4039 }
41- table .Defines = append (table .Defines , fmt .Sprintf ("define ACCEPT_CTMARK=%d" , nfqueueConnMarkAccept ))
42- table .Defines = append (table .Defines , fmt .Sprintf ("define DROP_CTMARK=%d" , nfqueueConnMarkDrop ))
43- table .Defines = append (table .Defines , fmt .Sprintf ("define QUEUE_NUM=%d" , nfqueueNum ))
44- if local {
40+ table .Defines = append (table .Defines , fmt .Sprintf ("define ACCEPT_CTMARK=%d" , n . connMarkAccept ))
41+ table .Defines = append (table .Defines , fmt .Sprintf ("define DROP_CTMARK=%d" , n . connMarkDrop ))
42+ table .Defines = append (table .Defines , fmt .Sprintf ("define QUEUE_NUM=%d" , n . queueNum ))
43+ if n . local {
4544 table .Chains = []nftChainSpec {
4645 {Chain : "INPUT" , Header : "type filter hook input priority filter; policy accept;" },
4746 {Chain : "OUTPUT" , Header : "type filter hook output priority filter; policy accept;" },
@@ -55,7 +54,7 @@ func generateNftRules(local, rst bool) (*nftTableSpec, error) {
5554 c := & table .Chains [i ]
5655 c .Rules = append (c .Rules , "meta mark $ACCEPT_CTMARK ct mark set $ACCEPT_CTMARK" ) // Bypass protected connections
5756 c .Rules = append (c .Rules , "ct mark $ACCEPT_CTMARK counter accept" )
58- if rst {
57+ if n . rst {
5958 c .Rules = append (c .Rules , "ip protocol tcp ct mark $DROP_CTMARK counter reject with tcp reset" )
6059 }
6160 c .Rules = append (c .Rules , "ct mark $DROP_CTMARK counter drop" )
@@ -64,26 +63,26 @@ func generateNftRules(local, rst bool) (*nftTableSpec, error) {
6463 return table , nil
6564}
6665
67- func generateIptRules ( local , rst bool ) ([]iptRule , error ) {
68- if local && rst {
66+ func ( n * nfqueuePacketIO ) generateIptRules ( ) ([]iptRule , error ) {
67+ if n . local && n . rst {
6968 return nil , errors .New ("tcp rst is not supported in local mode" )
7069 }
7170 var chains []string
72- if local {
71+ if n . local {
7372 chains = []string {"INPUT" , "OUTPUT" }
7473 } else {
7574 chains = []string {"FORWARD" }
7675 }
7776 rules := make ([]iptRule , 0 , 4 * len (chains ))
7877 for _ , chain := range chains {
7978 // Bypass protected connections
80- rules = append (rules , iptRule {"filter" , chain , []string {"-m" , "mark" , "--mark" , strconv .Itoa (nfqueueConnMarkAccept ), "-j" , "CONNMARK" , "--set-mark" , strconv .Itoa (nfqueueConnMarkAccept )}})
81- rules = append (rules , iptRule {"filter" , chain , []string {"-m" , "connmark" , "--mark" , strconv .Itoa (nfqueueConnMarkAccept ), "-j" , "ACCEPT" }})
82- if rst {
83- rules = append (rules , iptRule {"filter" , chain , []string {"-p" , "tcp" , "-m" , "connmark" , "--mark" , strconv .Itoa (nfqueueConnMarkDrop ), "-j" , "REJECT" , "--reject-with" , "tcp-reset" }})
79+ rules = append (rules , iptRule {"filter" , chain , []string {"-m" , "mark" , "--mark" , strconv .Itoa (n . connMarkAccept ), "-j" , "CONNMARK" , "--set-mark" , strconv .Itoa (n . connMarkAccept )}})
80+ rules = append (rules , iptRule {"filter" , chain , []string {"-m" , "connmark" , "--mark" , strconv .Itoa (n . connMarkAccept ), "-j" , "ACCEPT" }})
81+ if n . rst {
82+ rules = append (rules , iptRule {"filter" , chain , []string {"-p" , "tcp" , "-m" , "connmark" , "--mark" , strconv .Itoa (n . connMarkDrop ), "-j" , "REJECT" , "--reject-with" , "tcp-reset" }})
8483 }
85- rules = append (rules , iptRule {"filter" , chain , []string {"-m" , "connmark" , "--mark" , strconv .Itoa (nfqueueConnMarkDrop ), "-j" , "DROP" }})
86- rules = append (rules , iptRule {"filter" , chain , []string {"-j" , "NFQUEUE" , "--queue-num" , strconv .Itoa (nfqueueNum ), "--queue-bypass" }})
84+ rules = append (rules , iptRule {"filter" , chain , []string {"-m" , "connmark" , "--mark" , strconv .Itoa (n . connMarkDrop ), "-j" , "DROP" }})
85+ rules = append (rules , iptRule {"filter" , chain , []string {"-j" , "NFQUEUE" , "--queue-num" , strconv .Itoa (n . queueNum ), "--queue-bypass" }})
8786 }
8887
8988 return rules , nil
@@ -94,10 +93,14 @@ var _ PacketIO = (*nfqueuePacketIO)(nil)
9493var errNotNFQueuePacket = errors .New ("not an NFQueue packet" )
9594
9695type nfqueuePacketIO struct {
97- n * nfqueue.Nfqueue
98- local bool
99- rst bool
100- rSet bool // whether the nftables/iptables rules have been set
96+ n * nfqueue.Nfqueue
97+ local bool
98+ rst bool
99+ rSet bool // whether the nftables/iptables rules have been set
100+ queueNum int
101+ table string // nftable name
102+ connMarkAccept int
103+ connMarkDrop int
101104
102105 // iptables not nil = use iptables instead of nftables
103106 ipt4 * iptables.IPTables
@@ -107,7 +110,12 @@ type nfqueuePacketIO struct {
107110}
108111
109112type NFQueuePacketIOConfig struct {
110- QueueSize uint32
113+ QueueSize uint32
114+ QueueNum * uint16
115+ Table string
116+ ConnMarkAccept uint32
117+ ConnMarkDrop uint32
118+
111119 ReadBuffer int
112120 WriteBuffer int
113121 Local bool
@@ -118,6 +126,26 @@ func NewNFQueuePacketIO(config NFQueuePacketIOConfig) (PacketIO, error) {
118126 if config .QueueSize == 0 {
119127 config .QueueSize = nfqueueDefaultQueueSize
120128 }
129+ if config .QueueNum == nil {
130+ queueNum := uint16 (nfqueueDefaultQueueNum )
131+ config .QueueNum = & queueNum
132+ }
133+ if config .Table == "" {
134+ config .Table = nftDefaultTable
135+ }
136+ if config .ConnMarkAccept == 0 {
137+ config .ConnMarkAccept = nfqueueDefaultConnMarkAccept
138+ }
139+ if config .ConnMarkDrop == 0 {
140+ config .ConnMarkDrop = config .ConnMarkAccept + 1
141+ if config .ConnMarkDrop == 0 {
142+ // Overflow
143+ config .ConnMarkDrop = 1
144+ }
145+ }
146+ if config .ConnMarkAccept == config .ConnMarkDrop {
147+ return nil , errors .New ("connMarkAccept and connMarkDrop cannot be the same" )
148+ }
121149 var ipt4 , ipt6 * iptables.IPTables
122150 var err error
123151 if nftCheck () != nil {
@@ -132,7 +160,7 @@ func NewNFQueuePacketIO(config NFQueuePacketIOConfig) (PacketIO, error) {
132160 }
133161 }
134162 n , err := nfqueue .Open (& nfqueue.Config {
135- NfQueue : nfqueueNum ,
163+ NfQueue : * config . QueueNum ,
136164 MaxPacketLen : nfqueueMaxPacketLen ,
137165 MaxQueueLen : config .QueueSize ,
138166 Copymode : nfqueue .NfQnlCopyPacket ,
@@ -156,16 +184,20 @@ func NewNFQueuePacketIO(config NFQueuePacketIOConfig) (PacketIO, error) {
156184 }
157185 }
158186 return & nfqueuePacketIO {
159- n : n ,
160- local : config .Local ,
161- rst : config .RST ,
162- ipt4 : ipt4 ,
163- ipt6 : ipt6 ,
187+ n : n ,
188+ local : config .Local ,
189+ rst : config .RST ,
190+ queueNum : int (* config .QueueNum ),
191+ table : config .Table ,
192+ connMarkAccept : int (config .ConnMarkAccept ),
193+ connMarkDrop : int (config .ConnMarkDrop ),
194+ ipt4 : ipt4 ,
195+ ipt6 : ipt6 ,
164196 protectedDialer : & net.Dialer {
165197 Control : func (network , address string , c syscall.RawConn ) error {
166198 var err error
167199 cErr := c .Control (func (fd uintptr ) {
168- err = syscall .SetsockoptInt (int (fd ), syscall .SOL_SOCKET , syscall .SO_MARK , nfqueueConnMarkAccept )
200+ err = syscall .SetsockoptInt (int (fd ), syscall .SOL_SOCKET , syscall .SO_MARK , int ( config . ConnMarkAccept ) )
169201 })
170202 if cErr != nil {
171203 return cErr
@@ -212,9 +244,9 @@ func (n *nfqueuePacketIO) Register(ctx context.Context, cb PacketCallback) error
212244 }
213245 if ! n .rSet {
214246 if n .ipt4 != nil {
215- err = n .setupIpt (n . local , n . rst , false )
247+ err = n .setupIpt (false )
216248 } else {
217- err = n .setupNft (n . local , n . rst , false )
249+ err = n .setupNft (false )
218250 }
219251 if err != nil {
220252 return err
@@ -254,11 +286,11 @@ func (n *nfqueuePacketIO) SetVerdict(p Packet, v Verdict, newPacket []byte) erro
254286 case VerdictAcceptModify :
255287 return n .n .SetVerdictModPacket (nP .id , nfqueue .NfAccept , newPacket )
256288 case VerdictAcceptStream :
257- return n .n .SetVerdictWithConnMark (nP .id , nfqueue .NfAccept , nfqueueConnMarkAccept )
289+ return n .n .SetVerdictWithConnMark (nP .id , nfqueue .NfAccept , n . connMarkAccept )
258290 case VerdictDrop :
259291 return n .n .SetVerdict (nP .id , nfqueue .NfDrop )
260292 case VerdictDropStream :
261- return n .n .SetVerdictWithConnMark (nP .id , nfqueue .NfDrop , nfqueueConnMarkDrop )
293+ return n .n .SetVerdictWithConnMark (nP .id , nfqueue .NfDrop , n . connMarkDrop )
262294 default :
263295 // Invalid verdict, ignore for now
264296 return nil
@@ -272,9 +304,9 @@ func (n *nfqueuePacketIO) ProtectedDialContext(ctx context.Context, network, add
272304func (n * nfqueuePacketIO ) Close () error {
273305 if n .rSet {
274306 if n .ipt4 != nil {
275- _ = n .setupIpt (n . local , n . rst , true )
307+ _ = n .setupIpt (true )
276308 } else {
277- _ = n .setupNft (n . local , n . rst , true )
309+ _ = n .setupNft (true )
278310 }
279311 n .rSet = false
280312 }
@@ -286,17 +318,17 @@ func (n *nfqueuePacketIO) SetCancelFunc(cancelFunc context.CancelFunc) error {
286318 return nil
287319}
288320
289- func (n * nfqueuePacketIO ) setupNft (local , rst , remove bool ) error {
290- rules , err := generateNftRules (local , rst )
321+ func (n * nfqueuePacketIO ) setupNft (remove bool ) error {
322+ rules , err := n . generateNftRules ()
291323 if err != nil {
292324 return err
293325 }
294326 rulesText := rules .String ()
295327 if remove {
296- err = nftDelete (nftFamily , nftTable )
328+ err = nftDelete (nftFamily , n . table )
297329 } else {
298330 // Delete first to make sure no leftover rules
299- _ = nftDelete (nftFamily , nftTable )
331+ _ = nftDelete (nftFamily , n . table )
300332 err = nftAdd (rulesText )
301333 }
302334 if err != nil {
@@ -305,8 +337,8 @@ func (n *nfqueuePacketIO) setupNft(local, rst, remove bool) error {
305337 return nil
306338}
307339
308- func (n * nfqueuePacketIO ) setupIpt (local , rst , remove bool ) error {
309- rules , err := generateIptRules (local , rst )
340+ func (n * nfqueuePacketIO ) setupIpt (remove bool ) error {
341+ rules , err := n . generateIptRules ()
310342 if err != nil {
311343 return err
312344 }
0 commit comments