forked from SagerNet/sing-tun
-
Notifications
You must be signed in to change notification settings - Fork 21
/
redirect_nftables_rules_openwrt.go
103 lines (99 loc) · 2.09 KB
/
redirect_nftables_rules_openwrt.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
//go:build linux
package tun
import (
"github.com/sagernet/nftables"
"github.com/sagernet/nftables/expr"
"golang.org/x/exp/slices"
)
func (r *autoRedirect) configureOpenWRTFirewall4(nft *nftables.Conn, cleanup bool) error {
tableFW4, err := nft.ListTableOfFamily("fw4", nftables.TableFamilyINet)
if err != nil {
return nil
}
if !cleanup {
ruleIif := &nftables.Rule{
Table: tableFW4,
Exprs: []expr.Any{
&expr.Meta{
Key: expr.MetaKeyIIFNAME,
Register: 1,
},
&expr.Cmp{
Op: expr.CmpOpEq,
Register: 1,
Data: nftablesIfname(r.tunOptions.Name),
},
&expr.Counter{},
&expr.Verdict{
Kind: expr.VerdictAccept,
},
},
}
ruleOif := &nftables.Rule{
Table: tableFW4,
Exprs: []expr.Any{
&expr.Meta{
Key: expr.MetaKeyOIFNAME,
Register: 1,
},
&expr.Cmp{
Op: expr.CmpOpEq,
Register: 1,
Data: nftablesIfname(r.tunOptions.Name),
},
&expr.Counter{},
&expr.Verdict{
Kind: expr.VerdictAccept,
},
},
}
chainForward := &nftables.Chain{
Name: "forward",
}
ruleIif.Chain = chainForward
ruleOif.Chain = chainForward
nft.InsertRule(ruleOif)
nft.InsertRule(ruleIif)
chainInput := &nftables.Chain{
Name: "input",
}
ruleIif.Chain = chainInput
ruleOif.Chain = chainInput
nft.InsertRule(ruleOif)
nft.InsertRule(ruleIif)
return nil
}
for _, chainName := range []string{"input", "forward"} {
var rules []*nftables.Rule
rules, err = nft.GetRules(tableFW4, &nftables.Chain{
Name: chainName,
})
if err != nil {
return err
}
for _, rule := range rules {
if len(rule.Exprs) != 4 {
continue
}
exprMeta, isMeta := rule.Exprs[0].(*expr.Meta)
if !isMeta {
continue
}
if exprMeta.Key != expr.MetaKeyIIFNAME && exprMeta.Key != expr.MetaKeyOIFNAME {
continue
}
exprCmp, isCmp := rule.Exprs[1].(*expr.Cmp)
if !isCmp {
continue
}
if !slices.Equal(exprCmp.Data, nftablesIfname(r.tunOptions.Name)) {
continue
}
err = nft.DelRule(rule)
if err != nil {
return err
}
}
}
return nil
}