Compare commits

...

9 Commits

Author SHA1 Message Date
世界
49977c4d84 Update workflows 2024-09-14 14:46:32 +08:00
世界
db923a2c7c Fix linter configuration 2024-09-14 14:43:00 +08:00
世界
aaaacba916 auto-redirect: Fix uid rules 2024-09-14 14:32:17 +08:00
世界
2f8200267b monitor: Do not select disconnected interface 2024-09-14 09:27:10 +08:00
世界
5d440412ba auto-redirect: Fix nftables available check 2024-07-04 13:18:26 +08:00
世界
60a8276dc4 auto-redirect: Fix iptables rules 2024-07-04 00:25:07 +08:00
世界
7c4975c412 Use new fswatcher to udpate android packages 2024-06-26 11:02:47 +08:00
世界
c01b403a44 Avoid hijack DNS requests send to loopback 2024-06-24 19:36:41 +08:00
wwqgtxx
625ac412bb Using netipx.IPSet safely 2024-06-22 13:01:06 +08:00
15 changed files with 305 additions and 231 deletions

View File

@@ -1,4 +1,4 @@
name: Lint
name: lint
on:
push:
@@ -24,16 +24,16 @@ jobs:
with:
fetch-depth: 0
- name: Setup Go
uses: actions/setup-go@v4
uses: actions/setup-go@v5
with:
go-version: ^1.22
go-version: ^1.23
- name: Cache go module
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: |
~/go/pkg/mod
key: go-${{ hashFiles('**/go.sum') }}
- name: golangci-lint
uses: golangci/golangci-lint-action@v3
uses: golangci/golangci-lint-action@v6
with:
version: latest

View File

@@ -1,4 +1,4 @@
name: Debug build
name: test
on:
push:
@@ -16,7 +16,7 @@ on:
jobs:
build:
name: Linux Debug build
name: Linux
runs-on: ubuntu-latest
steps:
- name: Checkout
@@ -24,14 +24,14 @@ jobs:
with:
fetch-depth: 0
- name: Setup Go
uses: actions/setup-go@v4
uses: actions/setup-go@v5
with:
go-version: ^1.22
go-version: ^1.23
- name: Build
run: |
make test
build_go120:
name: Linux Debug build (Go 1.20)
name: Linux (Go 1.20)
runs-on: ubuntu-latest
steps:
- name: Checkout
@@ -39,7 +39,7 @@ jobs:
with:
fetch-depth: 0
- name: Setup Go
uses: actions/setup-go@v4
uses: actions/setup-go@v5
with:
go-version: ~1.20
continue-on-error: true
@@ -47,7 +47,7 @@ jobs:
run: |
make test
build_go121:
name: Linux Debug build (Go 1.21)
name: Linux (Go 1.21)
runs-on: ubuntu-latest
steps:
- name: Checkout
@@ -55,15 +55,31 @@ jobs:
with:
fetch-depth: 0
- name: Setup Go
uses: actions/setup-go@v4
uses: actions/setup-go@v5
with:
go-version: ~1.21
continue-on-error: true
- name: Build
run: |
make test
build__windows:
name: Windows Debug build
build_go122:
name: Linux (Go 1.22)
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: ~1.22
continue-on-error: true
- name: Build
run: |
make test
build_windows:
name: Windows
runs-on: windows-latest
steps:
- name: Checkout
@@ -71,15 +87,15 @@ jobs:
with:
fetch-depth: 0
- name: Setup Go
uses: actions/setup-go@v4
uses: actions/setup-go@v5
with:
go-version: ^1.22
go-version: ^1.23
continue-on-error: true
- name: Build
run: |
make test
build_darwin:
name: macOS Debug build
name: macOS
runs-on: macos-latest
steps:
- name: Checkout
@@ -87,9 +103,9 @@ jobs:
with:
fetch-depth: 0
- name: Setup Go
uses: actions/setup-go@v4
uses: actions/setup-go@v5
with:
go-version: ^1.22
go-version: ^1.23
continue-on-error: true
- name: Build
run: |

View File

@@ -3,18 +3,22 @@ linters:
enable:
- gofumpt
- govet
# - gci
- gci
- staticcheck
- paralleltest
- ineffassign
issues:
exclude-dirs:
- internal
linters-settings:
# gci:
# sections:
# - standard
# - prefix(github.com/sagernet/sing)
# - default
staticcheck:
go: '1.19'
gci:
custom-order: true
sections:
- standard
- prefix(github.com/sagernet/)
- default
run:
go: "1.23"

View File

@@ -27,4 +27,5 @@ lint_install:
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
test:
go test -v .
go build -v .
#go test -v .

5
go.mod
View File

@@ -3,12 +3,12 @@ module github.com/sagernet/sing-tun
go 1.20
require (
github.com/fsnotify/fsnotify v1.7.0
github.com/go-ole/go-ole v1.3.0
github.com/sagernet/fswatch v0.1.1
github.com/sagernet/gvisor v0.0.0-20240428053021-e691de28565f
github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a
github.com/sagernet/nftables v0.3.0-beta.4
github.com/sagernet/sing v0.5.0-alpha.10
github.com/sagernet/sing v0.5.0-alpha.11.0.20240625144910-6bd878184516
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8
golang.org/x/net v0.26.0
@@ -16,6 +16,7 @@ require (
)
require (
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/google/btree v1.1.2 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/josharian/native v1.1.0 // indirect

6
go.sum
View File

@@ -14,14 +14,16 @@ github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU
github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U=
github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/sagernet/fswatch v0.1.1 h1:YqID+93B7VRfqIH3PArW/XpJv5H4OLEVWDfProGoRQs=
github.com/sagernet/fswatch v0.1.1/go.mod h1:nz85laH0mkQqJfaOrqPpkwtU1znMFNVTpT/5oRsVz/o=
github.com/sagernet/gvisor v0.0.0-20240428053021-e691de28565f h1:NkhuupzH5ch7b/Y/6ZHJWrnNLoiNnSJaow6DPb8VW2I=
github.com/sagernet/gvisor v0.0.0-20240428053021-e691de28565f/go.mod h1:KXmw+ouSJNOsuRpg4wgwwCQuunrGz4yoAqQjsLjc6N0=
github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a h1:ObwtHN2VpqE0ZNjr6sGeT00J8uU7JF4cNUdb44/Duis=
github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM=
github.com/sagernet/nftables v0.3.0-beta.4 h1:kbULlAwAC3jvdGAC1P5Fa3GSxVwQJibNenDW2zaXr8I=
github.com/sagernet/nftables v0.3.0-beta.4/go.mod h1:OQXAjvjNGGFxaTgVCSTRIhYB5/llyVDeapVoENYBDS8=
github.com/sagernet/sing v0.5.0-alpha.10 h1:kuHl10gpjbKQAdQfyogQU3u0CVnpqC3wrAHe/+BFaXc=
github.com/sagernet/sing v0.5.0-alpha.10/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
github.com/sagernet/sing v0.5.0-alpha.11.0.20240625144910-6bd878184516 h1:C5NYqSEQC2CcILDFhT31iZe5Kp5hFNEtdS9mnNWyW5c=
github.com/sagernet/sing v0.5.0-alpha.11.0.20240625144910-6bd878184516/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8=
github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=

View File

@@ -78,12 +78,16 @@ func (m *defaultInterfaceMonitor) checkUpdate() error {
continue
}
if ifrow.Type == winipcfg.IfTypePropVirtual || ifrow.Type == winipcfg.IfTypeSoftwareLoopback {
continue
}
iface, err := row.InterfaceLUID.IPInterface(windows.AF_INET)
if err != nil {
continue
}
if ifrow.Type == winipcfg.IfTypePropVirtual || ifrow.Type == winipcfg.IfTypeSoftwareLoopback {
if !iface.Connected {
continue
}

View File

@@ -1,6 +1,6 @@
package tun
import E "github.com/sagernet/sing/common/exceptions"
import "github.com/sagernet/sing/common/logger"
type PackageManager interface {
Start() error
@@ -11,7 +11,14 @@ type PackageManager interface {
SharedPackageByID(id uint32) (string, bool)
}
type PackageManagerOptions struct {
Callback PackageManagerCallback
// Logger is the logger to log errors
// optional
Logger logger.Logger
}
type PackageManagerCallback interface {
OnPackagesUpdated(packages int, sharedUsers int)
E.Handler
}

View File

@@ -2,30 +2,33 @@ package tun
import (
"bytes"
"context"
"encoding/xml"
"io"
"os"
"strconv"
"github.com/sagernet/fswatch"
"github.com/sagernet/sing/common"
"github.com/sagernet/sing/common/abx"
E "github.com/sagernet/sing/common/exceptions"
"github.com/fsnotify/fsnotify"
"github.com/sagernet/sing/common/logger"
)
type packageManager struct {
callback PackageManagerCallback
watcher *fsnotify.Watcher
logger logger.Logger
watcher *fswatch.Watcher
idByPackage map[string]uint32
sharedByPackage map[string]uint32
packageById map[uint32]string
sharedById map[uint32]string
}
func NewPackageManager(callback PackageManagerCallback) (PackageManager, error) {
return &packageManager{callback: callback}, nil
func NewPackageManager(options PackageManagerOptions) (PackageManager, error) {
return &packageManager{
callback: options.Callback,
logger: options.Logger,
}, nil
}
func (m *packageManager) Start() error {
@@ -35,42 +38,33 @@ func (m *packageManager) Start() error {
}
err = m.startWatcher()
if err != nil {
m.callback.NewError(context.Background(), E.Cause(err, "create fsnotify watcher"))
m.logger.Error(E.Cause(err, "create watcher for packages list"))
}
return nil
}
func (m *packageManager) startWatcher() error {
watcher, err := fsnotify.NewWatcher()
watcher, err := fswatch.NewWatcher(fswatch.Options{
Path: []string{"/data/system/packages.xml"},
Direct: true,
Callback: m.packagesUpdated,
Logger: m.logger,
})
if err != nil {
return err
}
err = watcher.Add("/data/system/packages.xml")
err = watcher.Start()
if err != nil {
return err
}
m.watcher = watcher
go m.loopUpdate()
return nil
}
func (m *packageManager) loopUpdate() {
for {
select {
case _, ok := <-m.watcher.Events:
if !ok {
return
}
err := m.updatePackages()
if err != nil {
m.callback.NewError(context.Background(), E.Cause(err, "update packages"))
}
case err, ok := <-m.watcher.Errors:
if !ok {
return
}
m.callback.NewError(context.Background(), E.Cause(err, "fsnotify error"))
}
func (m *packageManager) packagesUpdated(path string) {
err := m.updatePackages()
if err != nil {
m.logger.Error(E.Cause(err, "update packages"))
}
}

View File

@@ -4,6 +4,6 @@ package tun
import "os"
func NewPackageManager(callback PackageManagerCallback) (PackageManager, error) {
func NewPackageManager(options PackageManagerOptions) (PackageManager, error) {
return nil, os.ErrInvalid
}

View File

@@ -68,7 +68,7 @@ func (r *autoRedirect) setupIPTablesForFamily(iptablesPath string) error {
if err != nil {
return err
}
err = r.runShell(iptablesPath, "-I FORWARD -j", tableNameInput)
err = r.runShell(iptablesPath, "-I INPUT -j", tableNameInput)
if err != nil {
return err
}
@@ -235,18 +235,26 @@ func (r *autoRedirect) cleanupIPTables() {
}
func (r *autoRedirect) cleanupIPTablesForFamily(iptablesPath string) {
tableNameInput := r.tableName + "-input"
tableNameOutput := r.tableName + "-output"
tableNameForward := r.tableName + "-forward"
tableNamePreRouteing := r.tableName + "-prerouting"
_ = r.runShell(iptablesPath, "-t nat -D OUTPUT -j", tableNameOutput)
_ = r.runShell(iptablesPath, "-t nat -F", tableNameOutput)
_ = r.runShell(iptablesPath, "-t nat -X", tableNameOutput)
if runtime.GOOS == "android" {
return
}
_ = r.runShell(iptablesPath, "-D INPUT -j", tableNameInput)
_ = r.runShell(iptablesPath, "-F", tableNameInput)
_ = r.runShell(iptablesPath, "-X", tableNameInput)
_ = r.runShell(iptablesPath, "-D FORWARD -j", tableNameForward)
_ = r.runShell(iptablesPath, "-F", tableNameForward)
_ = r.runShell(iptablesPath, "-X", tableNameForward)
_ = r.runShell(iptablesPath, "-t nat -D PREROUTING -j", tableNamePreRouteing)
_ = r.runShell(iptablesPath, "-t nat -F", tableNamePreRouteing)
_ = r.runShell(iptablesPath, "-t nat -X", tableNamePreRouteing)

View File

@@ -6,7 +6,6 @@ import (
"os"
"os/exec"
"runtime"
"time"
"github.com/sagernet/nftables"
"github.com/sagernet/sing/common"
@@ -81,7 +80,8 @@ func NewAutoRedirect(options AutoRedirectOptions) (AutoRedirect, error) {
if r.useNFTables {
err = r.initializeNFTables()
if err != nil && err != os.ErrInvalid {
r.logger.Debug("device has no nftables support: ", err)
r.useNFTables = false
r.logger.Debug("missing nftables support: ", err)
}
}
if len(r.tunOptions.Inet4Address) > 0 {
@@ -131,7 +131,6 @@ func (r *autoRedirect) Start() error {
}
r.redirectServer = server
}
startAt := time.Now()
var err error
if r.useNFTables {
r.cleanupNFTables()
@@ -140,11 +139,7 @@ func (r *autoRedirect) Start() error {
r.cleanupIPTables()
err = r.setupIPTables()
}
if err != nil {
return err
}
r.logger.Debug("auto-redirect configured in ", time.Since(startAt))
return nil
return err
}
func (r *autoRedirect) Close() error {

View File

@@ -4,7 +4,6 @@ package tun
import (
"net/netip"
"unsafe"
"github.com/sagernet/nftables"
"github.com/sagernet/nftables/expr"
@@ -77,42 +76,34 @@ func nftablesCreateIPSet(
id uint32, name string, family nftables.TableFamily,
setList []*netipx.IPSet, prefixList []netip.Prefix, appendDefault bool, update bool,
) (*nftables.Set, error) {
if len(prefixList) > 0 {
var builder netipx.IPSetBuilder
for _, prefix := range prefixList {
builder.AddPrefix(prefix)
}
ipSet, err := builder.IPSet()
if err != nil {
return nil, err
}
setList = append(setList, ipSet)
var builder netipx.IPSetBuilder
for _, prefix := range prefixList {
builder.AddPrefix(prefix)
}
ipSets := make([]*myIPSet, 0, len(setList))
var rangeLen int
for _, set := range setList {
mySet := (*myIPSet)(unsafe.Pointer(set))
ipSets = append(ipSets, mySet)
rangeLen += len(mySet.rr)
builder.AddSet(set)
}
setElements := make([]nftables.SetElement, 0, rangeLen)
for _, mySet := range ipSets {
for _, rr := range mySet.rr {
if (family == nftables.TableFamilyIPv4) != rr.from.Is4() {
continue
}
endAddr := rr.to.Next()
if !endAddr.IsValid() {
endAddr = rr.from
}
setElements = append(setElements, nftables.SetElement{
Key: rr.from.AsSlice(),
})
setElements = append(setElements, nftables.SetElement{
Key: endAddr.AsSlice(),
IntervalEnd: true,
})
ipSet, err := builder.IPSet()
if err != nil {
return nil, err
}
ipRanges := ipSet.Ranges()
setElements := make([]nftables.SetElement, 0, len(ipRanges))
for _, rr := range ipRanges {
if (family == nftables.TableFamilyIPv4) != rr.From().Is4() {
continue
}
endAddr := rr.To().Next()
if !endAddr.IsValid() {
endAddr = rr.From()
}
setElements = append(setElements, nftables.SetElement{
Key: rr.From().AsSlice(),
})
setElements = append(setElements, nftables.SetElement{
Key: endAddr.AsSlice(),
IntervalEnd: true,
})
}
if len(prefixList) == 0 && appendDefault {
if family == nftables.TableFamilyIPv4 {
@@ -179,12 +170,3 @@ func nftablesCreateIPSet(
}
return mySet, nil
}
type myIPSet struct {
rr []myIPRange
}
type myIPRange struct {
from netip.Addr
to netip.Addr
}

View File

@@ -9,6 +9,7 @@ import (
"github.com/sagernet/nftables"
"github.com/sagernet/nftables/binaryutil"
"github.com/sagernet/nftables/expr"
"github.com/sagernet/nftables/userdata"
"github.com/sagernet/sing/common"
"github.com/sagernet/sing/common/ranges"
@@ -245,84 +246,124 @@ func (r *autoRedirect) nftablesCreateExcludeRules(nft *nftables.Conn, table *nft
}
} else {
if len(r.tunOptions.IncludeUID) > 0 {
includeUID := &nftables.Set{
Table: table,
Anonymous: true,
Constant: true,
Interval: true,
KeyType: nftables.TypeUID,
}
err := nft.AddSet(includeUID, common.FlatMap(r.tunOptions.IncludeUID, func(it ranges.Range[uint32]) []nftables.SetElement {
return []nftables.SetElement{
{
Key: binaryutil.BigEndian.PutUint32(it.Start),
},
{
Key: binaryutil.BigEndian.PutUint32(it.End + 1),
IntervalEnd: true,
},
if len(r.tunOptions.IncludeUID) > 1 || r.tunOptions.IncludeUID[0].Start != r.tunOptions.IncludeUID[0].End {
includeUID := &nftables.Set{
Table: table,
Anonymous: true,
Constant: true,
Interval: true,
KeyType: nftables.TypeUID,
}
}))
if err != nil {
return err
err := nft.AddSet(includeUID, common.FlatMap(r.tunOptions.IncludeUID, func(it ranges.Range[uint32]) []nftables.SetElement {
return []nftables.SetElement{
{
Key: binaryutil.NativeEndian.PutUint32(it.Start),
},
{
Key: binaryutil.NativeEndian.PutUint32(it.End + 1),
IntervalEnd: true,
},
}
}))
if err != nil {
return err
}
nft.AddRule(&nftables.Rule{
Table: table,
Chain: chain,
Exprs: []expr.Any{
&expr.Meta{Key: expr.MetaKeySKUID, Register: 1},
&expr.Lookup{
SourceRegister: 1,
SetID: includeUID.ID,
SetName: includeUID.Name,
Invert: true,
},
&expr.Counter{},
&expr.Verdict{
Kind: expr.VerdictReturn,
},
},
UserData: userdata.AppendString(nil, userdata.TypeComment, "not a bug :("),
})
} else {
nft.AddRule(&nftables.Rule{
Table: table,
Chain: chain,
Exprs: []expr.Any{
&expr.Meta{Key: expr.MetaKeySKUID, Register: 1},
&expr.Cmp{
Op: expr.CmpOpNeq,
Register: 1,
Data: binaryutil.BigEndian.PutUint32(r.tunOptions.IncludeUID[0].Start),
},
&expr.Counter{},
&expr.Verdict{
Kind: expr.VerdictReturn,
},
},
})
}
nft.AddRule(&nftables.Rule{
Table: table,
Chain: chain,
Exprs: []expr.Any{
&expr.Meta{Key: expr.MetaKeySKUID, Register: 1},
&expr.Lookup{
SourceRegister: 1,
SetID: includeUID.ID,
SetName: includeUID.Name,
Invert: true,
},
&expr.Counter{},
&expr.Verdict{
Kind: expr.VerdictReturn,
},
},
})
}
if len(r.tunOptions.ExcludeUID) > 0 {
excludeUID := &nftables.Set{
Table: table,
Anonymous: true,
Constant: true,
Interval: true,
KeyType: nftables.TypeUID,
}
err := nft.AddSet(excludeUID, common.FlatMap(r.tunOptions.ExcludeUID, func(it ranges.Range[uint32]) []nftables.SetElement {
return []nftables.SetElement{
{
Key: binaryutil.BigEndian.PutUint32(it.Start),
},
{
Key: binaryutil.BigEndian.PutUint32(it.End + 1),
IntervalEnd: true,
},
if len(r.tunOptions.ExcludeUID) > 1 || r.tunOptions.ExcludeUID[0].Start != r.tunOptions.ExcludeUID[0].End {
excludeUID := &nftables.Set{
Table: table,
Anonymous: true,
Constant: true,
Interval: true,
KeyType: nftables.TypeUID,
}
}))
if err != nil {
return err
err := nft.AddSet(excludeUID, common.FlatMap(r.tunOptions.ExcludeUID, func(it ranges.Range[uint32]) []nftables.SetElement {
return []nftables.SetElement{
{
Key: binaryutil.NativeEndian.PutUint32(it.Start),
},
{
Key: binaryutil.NativeEndian.PutUint32(it.End + 1),
IntervalEnd: true,
},
}
}))
if err != nil {
return err
}
nft.AddRule(&nftables.Rule{
Table: table,
Chain: chain,
Exprs: []expr.Any{
&expr.Meta{Key: expr.MetaKeySKUID, Register: 1},
&expr.Lookup{
SourceRegister: 1,
SetID: excludeUID.ID,
SetName: excludeUID.Name,
},
&expr.Counter{},
&expr.Verdict{
Kind: expr.VerdictReturn,
},
},
UserData: userdata.AppendString(nil, userdata.TypeComment, "not a bug :("),
})
} else {
nft.AddRule(&nftables.Rule{
Table: table,
Chain: chain,
Exprs: []expr.Any{
&expr.Meta{Key: expr.MetaKeySKUID, Register: 1},
&expr.Cmp{
Op: expr.CmpOpEq,
Register: 1,
Data: binaryutil.NativeEndian.PutUint32(r.tunOptions.ExcludeUID[0].Start),
},
&expr.Counter{},
&expr.Verdict{
Kind: expr.VerdictReturn,
},
},
})
}
nft.AddRule(&nftables.Rule{
Table: table,
Chain: chain,
Exprs: []expr.Any{
&expr.Meta{Key: expr.MetaKeySKUID, Register: 1},
&expr.Lookup{
SourceRegister: 1,
SetID: excludeUID.ID,
SetName: excludeUID.Name,
},
&expr.Counter{},
&expr.Verdict{
Kind: expr.VerdictReturn,
},
},
})
}
}
@@ -537,51 +578,70 @@ func (r *autoRedirect) nftablesCreateDNSHijackRulesForFamily(
dnsServer = r.tunOptions.Inet6Address[0].Addr().Next()
}
}
exprs := []expr.Any{
&expr.Meta{
Key: expr.MetaKeyNFPROTO,
Register: 1,
},
&expr.Cmp{
Op: expr.CmpOpEq,
Register: 1,
Data: []byte{uint8(family)},
},
}
if chain.Hooknum == nftables.ChainHookOutput {
// It looks like we can't hijack DNS requests sent to loopback.
// https://serverfault.com/questions/363899/iptables-dnat-from-loopback
// and tproxy is not available in output
exprs = append(exprs,
&expr.Meta{
Key: expr.MetaKeyOIFNAME,
Register: 1,
},
&expr.Cmp{
Op: expr.CmpOpNeq,
Register: 1,
Data: nftablesIfname("lo"),
},
)
}
exprs = append(exprs,
&expr.Meta{
Key: expr.MetaKeyL4PROTO,
Register: 1,
},
&expr.Lookup{
SourceRegister: 1,
SetID: ipProto.ID,
SetName: ipProto.Name,
},
&expr.Payload{
OperationType: expr.PayloadLoad,
DestRegister: 1,
Base: expr.PayloadBaseTransportHeader,
Offset: 2,
Len: 2,
},
&expr.Cmp{
Op: expr.CmpOpEq,
Register: 1,
Data: binaryutil.BigEndian.PutUint16(53),
},
&expr.Immediate{
Register: 1,
Data: dnsServer.AsSlice(),
},
&expr.NAT{
Type: expr.NATTypeDestNAT,
Family: uint32(family),
RegAddrMin: 1,
},
&expr.Counter{},
)
nft.AddRule(&nftables.Rule{
Table: table,
Chain: chain,
Exprs: []expr.Any{
&expr.Meta{
Key: expr.MetaKeyNFPROTO,
Register: 1,
},
&expr.Cmp{
Op: expr.CmpOpEq,
Register: 1,
Data: []byte{uint8(family)},
},
&expr.Meta{
Key: expr.MetaKeyL4PROTO,
Register: 1,
},
&expr.Lookup{
SourceRegister: 1,
SetID: ipProto.ID,
SetName: ipProto.Name,
},
&expr.Payload{
OperationType: expr.PayloadLoad,
DestRegister: 1,
Base: expr.PayloadBaseTransportHeader,
Offset: 2,
Len: 2,
},
&expr.Cmp{
Op: expr.CmpOpEq,
Register: 1,
Data: binaryutil.BigEndian.PutUint16(53),
},
&expr.Counter{},
&expr.Immediate{
Register: 1,
Data: dnsServer.AsSlice(),
},
&expr.NAT{
Type: expr.NATTypeDestNAT,
Family: uint32(family),
RegAddrMin: 1,
},
},
Exprs: exprs,
})
return nil
}

View File

@@ -182,7 +182,7 @@ var controlPath string
func init() {
const defaultTunPath = "/dev/net/tun"
const androidTunPath = "/dev/tun"
if rw.FileExists(androidTunPath) {
if rw.IsFile(androidTunPath) {
controlPath = androidTunPath
} else {
controlPath = defaultTunPath
@@ -712,7 +712,7 @@ func (t *NativeTun) rules() []*netlink.Rule {
it.Family = unix.AF_INET
rules = append(rules, it)
}
priority++
// priority++
}
if p6 {
it = netlink.NewRule()
@@ -755,7 +755,7 @@ func (t *NativeTun) rules() []*netlink.Rule {
it.Table = t.options.IPRoute2TableIndex
it.Family = unix.AF_INET6
rules = append(rules, it)
priority6++
// priority6++
}
if p4 {
it = netlink.NewRule()