Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
144 changes: 144 additions & 0 deletions redirect_nftables_rules.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
package tun

import (
"net"
"net/netip"
_ "unsafe"

Expand Down Expand Up @@ -375,6 +376,149 @@ func (r *autoRedirect) nftablesCreateExcludeRules(nft *nftables.Conn, table *nft
})
}
}
if len(r.tunOptions.IncludeMACAddress) > 0 {
nft.AddRule(&nftables.Rule{
Table: table,
Chain: chain,
Exprs: []expr.Any{
&expr.Meta{Key: expr.MetaKeyIIFTYPE, Register: 1},
&expr.Cmp{
Op: expr.CmpOpNeq,
Register: 1,
Data: binaryutil.NativeEndian.PutUint16(unix.ARPHRD_ETHER),
},
&expr.Counter{},
&expr.Verdict{
Kind: expr.VerdictReturn,
},
},
})
if len(r.tunOptions.IncludeMACAddress) > 1 {
includeMACSet := &nftables.Set{
Table: table,
Anonymous: true,
Constant: true,
KeyType: nftables.TypeEtherAddr,
}
err := nft.AddSet(includeMACSet, common.Map(r.tunOptions.IncludeMACAddress, func(it net.HardwareAddr) nftables.SetElement {
return nftables.SetElement{
Key: []byte(it),
}
}))
if err != nil {
return err
}
nft.AddRule(&nftables.Rule{
Table: table,
Chain: chain,
Exprs: []expr.Any{
&expr.Payload{
OperationType: expr.PayloadLoad,
DestRegister: 1,
Base: expr.PayloadBaseLLHeader,
Offset: 6,
Len: 6,
},
&expr.Lookup{
SourceRegister: 1,
SetID: includeMACSet.ID,
SetName: includeMACSet.Name,
Invert: true,
},
&expr.Counter{},
&expr.Verdict{
Kind: expr.VerdictReturn,
},
},
})
} else {
nft.AddRule(&nftables.Rule{
Table: table,
Chain: chain,
Exprs: []expr.Any{
&expr.Payload{
OperationType: expr.PayloadLoad,
DestRegister: 1,
Base: expr.PayloadBaseLLHeader,
Offset: 6,
Len: 6,
},
&expr.Cmp{
Op: expr.CmpOpNeq,
Register: 1,
Data: []byte(r.tunOptions.IncludeMACAddress[0]),
},
&expr.Counter{},
&expr.Verdict{
Kind: expr.VerdictReturn,
},
},
})
}
}
if len(r.tunOptions.ExcludeMACAddress) > 0 {
if len(r.tunOptions.ExcludeMACAddress) > 1 {
excludeMACSet := &nftables.Set{
Table: table,
Anonymous: true,
Constant: true,
KeyType: nftables.TypeEtherAddr,
}
err := nft.AddSet(excludeMACSet, common.Map(r.tunOptions.ExcludeMACAddress, func(it net.HardwareAddr) nftables.SetElement {
return nftables.SetElement{
Key: []byte(it),
}
}))
if err != nil {
return err
}
nft.AddRule(&nftables.Rule{
Table: table,
Chain: chain,
Exprs: []expr.Any{
&expr.Payload{
OperationType: expr.PayloadLoad,
DestRegister: 1,
Base: expr.PayloadBaseLLHeader,
Offset: 6,
Len: 6,
},
&expr.Lookup{
SourceRegister: 1,
SetID: excludeMACSet.ID,
SetName: excludeMACSet.Name,
},
&expr.Counter{},
&expr.Verdict{
Kind: expr.VerdictReturn,
},
},
})
} else {
nft.AddRule(&nftables.Rule{
Table: table,
Chain: chain,
Exprs: []expr.Any{
&expr.Payload{
OperationType: expr.PayloadLoad,
DestRegister: 1,
Base: expr.PayloadBaseLLHeader,
Offset: 6,
Len: 6,
},
&expr.Cmp{
Op: expr.CmpOpEq,
Register: 1,
Data: []byte(r.tunOptions.ExcludeMACAddress[0]),
},
&expr.Counter{},
&expr.Verdict{
Kind: expr.VerdictReturn,
},
},
})
}
}
} else {
if len(r.tunOptions.IncludeUID) > 0 {
if len(r.tunOptions.IncludeUID) > 1 || r.tunOptions.IncludeUID[0].Start != r.tunOptions.IncludeUID[0].End {
Expand Down
4 changes: 4 additions & 0 deletions tun.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,13 @@ type Options struct {
ExcludeInterface []string
IncludeUID []ranges.Range[uint32]
ExcludeUID []ranges.Range[uint32]
ExcludeSrcPort []ranges.Range[uint16]
ExcludeDstPort []ranges.Range[uint16]
IncludeAndroidUser []int
IncludePackage []string
ExcludePackage []string
IncludeMACAddress []net.HardwareAddr
ExcludeMACAddress []net.HardwareAddr
InterfaceFinder control.InterfaceFinder
InterfaceMonitor DefaultInterfaceMonitor
FileDescriptor int
Expand Down
38 changes: 37 additions & 1 deletion tun_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -655,6 +655,42 @@ func (t *NativeTun) rules() []*netlink.Rule {
}

nopPriority := ruleStart + 10
for _, excludePort := range t.options.ExcludeSrcPort {
if p4 {
it = netlink.NewRule()
it.Priority = priority
it.Sport = netlink.NewRulePortRange(excludePort.Start, excludePort.End)
it.Goto = nopPriority
it.Family = unix.AF_INET
rules = append(rules, it)
}
if p6 {
it = netlink.NewRule()
it.Priority = priority6
it.Sport = netlink.NewRulePortRange(excludePort.Start, excludePort.End)
it.Goto = nopPriority
it.Family = unix.AF_INET6
rules = append(rules, it)
}
}
for _, excludePort := range t.options.ExcludeDstPort {
if p4 {
it = netlink.NewRule()
it.Priority = priority
it.Dport = netlink.NewRulePortRange(excludePort.Start, excludePort.End)
it.Goto = nopPriority
it.Family = unix.AF_INET
rules = append(rules, it)
}
if p6 {
it = netlink.NewRule()
it.Priority = priority6
it.Dport = netlink.NewRulePortRange(excludePort.Start, excludePort.End)
it.Goto = nopPriority
it.Family = unix.AF_INET6
rules = append(rules, it)
}
}
for _, excludeRange := range excludeRanges {
if p4 {
it = netlink.NewRule()
Expand All @@ -673,7 +709,7 @@ func (t *NativeTun) rules() []*netlink.Rule {
rules = append(rules, it)
}
}
if len(excludeRanges) > 0 {
if len(t.options.ExcludeSrcPort) > 0 || len(t.options.ExcludeDstPort) > 0 || len(excludeRanges) > 0 {
if p4 {
priority++
}
Expand Down