Add uid and android user rules support in tun routing

This commit is contained in:
世界 2022-08-15 00:25:49 +08:00
parent c8399a297e
commit 3157593b6b
No known key found for this signature in database
GPG Key ID: CD109927C34A63C4
10 changed files with 176 additions and 90 deletions

View File

@ -3,18 +3,15 @@ linters:
enable:
- gofumpt
- govet
- gci
# - gci
- staticcheck
- paralleltest
issues:
fix: true
linters-settings:
gci:
sections:
- standard
- prefix(github.com/sagernet/)
- default
# gci:
# sections:
# - standard
# - prefix(github.com/sagernet/)
# - default
staticcheck:
go: '1.19'

View File

@ -1,7 +1,7 @@
NAME = sing-box
COMMIT = $(shell git rev-parse --short HEAD)
TAGS ?= with_quic,with_clash_api
PARAMS = -trimpath -tags '$(TAGS)' -ldflags \
PARAMS = -v -trimpath -tags '$(TAGS)' -ldflags \
'-X "github.com/sagernet/sing-box/constant.Commit=$(COMMIT)" \
-w -s -buildid='
MAIN = ./cmd/sing-box
@ -11,26 +11,17 @@ MAIN = ./cmd/sing-box
build:
go build $(PARAMS) $(MAIN)
action_version: build
echo "::set-output name=VERSION::`./sing-box version -n`"
install:
go install $(PARAMS) $(MAIN)
release:
goreleaser release --snapshot --rm-dist
fmt_install:
go install -v mvdan.cc/gofumpt@latest
go install -v github.com/daixiang0/gci@v0.4.0
fmt:
@gofumpt -l -w .
@gofmt -s -w .
@gci write -s "standard,prefix(github.com/sagernet/),default" .
lint_install:
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
fmt_install:
go install -v mvdan.cc/gofumpt@latest
go install -v github.com/daixiang0/gci@v0.4.0
lint:
GOOS=linux golangci-lint run ./...
@ -38,6 +29,9 @@ lint:
GOOS=darwin golangci-lint run ./...
GOOS=freebsd golangci-lint run ./...
lint_install:
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
test:
@go test -v . && \
@pushd test && \

View File

@ -1,3 +1,11 @@
#### 2022/08/15
* Add uid and android user rules support in [Tun](/configuration/inbound/tun) routing.
#### 2022/08/13
* Fix dns concurrent write
#### 2022/08/12
* Performance improvements

View File

@ -19,6 +19,26 @@
"endpoint_independent_nat": false,
"udp_timeout": 300,
"stack": "gvisor",
"include_uid": [
0
],
"include_uid_range": [
[
1000,
99999
]
],
"include_android_user": [
0,
10
],
"exclude_uid": [
1000
],
"exclude_uid_range": [
1000,
99999
],
"sniff": true,
"sniff_override_destination": false,
@ -28,9 +48,13 @@
}
```
!!! note ""
You can ignore the JSON Array [] tag when the content is only one item
!!! warning ""
If tun is running in non-privileged mode, the address and MTU will not be configured automatically, please make sure the settings are accurate.
If tun is running in non-privileged mode, addresses and MTU will not be configured automatically, please make sure the settings are accurate.
### Tun Fields
@ -83,6 +107,39 @@ TCP/IP stack.
The LWIP stack is not included by default, see [Installation](/#Installation).
#### include_uid
!!! error ""
UID and android user rules are only supported on Linux and require auto_route.
Limit users in route. Not limited by default.
#### include_uid_range
Limit users in route, but in range.
#### include_android_user
!!! warning ""
Only supported on Android
Limit android users in route.
| Common user | ID |
|--------------|-----|
| Main | 0 |
| Work Profile | 10 |
#### exclude_uid
Exclude users in route.
#### exclude_uid_range
Exclude users in route, but in range.
### Listen Fields
#### sniff

6
go.mod
View File

@ -15,17 +15,17 @@ require (
github.com/logrusorgru/aurora v2.0.3+incompatible
github.com/lucas-clemente/quic-go v0.28.1
github.com/oschwald/maxminddb-golang v1.10.0
github.com/sagernet/sing v0.0.0-20220813024838-eb2fad956aa8
github.com/sagernet/sing v0.0.0-20220814164830-4f2b872a8cbf
github.com/sagernet/sing-dns v0.0.0-20220813025814-e656c9dbf3ae
github.com/sagernet/sing-shadowsocks v0.0.0-20220812082714-484a11603b48
github.com/sagernet/sing-tun v0.0.0-20220808133432-d378b6ca536d
github.com/sagernet/sing-tun v0.0.0-20220815014658-b828f0164333
github.com/sagernet/sing-vmess v0.0.0-20220811135656-4f3f07acf9c4
github.com/sagernet/smux v0.0.0-20220812084127-e2d085ee3939
github.com/spf13/cobra v1.5.0
github.com/stretchr/testify v1.8.0
go.uber.org/atomic v1.10.0
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa
golang.org/x/net v0.0.0-20220811182439-13a9a731de15
golang.org/x/net v0.0.0-20220812174116-3211cb980234
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab
)

12
go.sum
View File

@ -153,14 +153,14 @@ github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD
github.com/sagernet/netlink v0.0.0-20220803045538-bdac49abf805 h1:hE+vtsjBCCPmxkRz9jZA+CicHgVkDT6H+Av5ZzskVxs=
github.com/sagernet/netlink v0.0.0-20220803045538-bdac49abf805/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM=
github.com/sagernet/sing v0.0.0-20220812082120-05f9836bff8f/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
github.com/sagernet/sing v0.0.0-20220813024838-eb2fad956aa8 h1:zTuJbqzZgBh+iGPV41d8ZarKxXPgTq/+PGk1kMhPV8I=
github.com/sagernet/sing v0.0.0-20220813024838-eb2fad956aa8/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
github.com/sagernet/sing v0.0.0-20220814164830-4f2b872a8cbf h1:JYnx6N1H2KeFKM7YSH5+qfhvvcy6gpqSpewkp1RLRSg=
github.com/sagernet/sing v0.0.0-20220814164830-4f2b872a8cbf/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
github.com/sagernet/sing-dns v0.0.0-20220813025814-e656c9dbf3ae h1:xOpbvgizvIbKKrrcl/CK3RjGY2u7rC+SBXlgqzEZOU4=
github.com/sagernet/sing-dns v0.0.0-20220813025814-e656c9dbf3ae/go.mod h1:T77zZdE2Cm6VqnFumrpwsq+kxYsbq+vWDhmjtdSl/oM=
github.com/sagernet/sing-shadowsocks v0.0.0-20220812082714-484a11603b48 h1:NlcTFKldteZvYBDyr+V9MjZEI0rAWCSFCyLgPvc5n/Y=
github.com/sagernet/sing-shadowsocks v0.0.0-20220812082714-484a11603b48/go.mod h1:EX3RbZvrwAkPI2nuGa78T2iQXmrkT+/VQtskjou42xM=
github.com/sagernet/sing-tun v0.0.0-20220808133432-d378b6ca536d h1:AQpkoUiF8FxYVI1lf2W9Rbkk914eHjVH9M8y+F/0+Nw=
github.com/sagernet/sing-tun v0.0.0-20220808133432-d378b6ca536d/go.mod h1:gWwYd53AqXl+Y+q6WlXUc6PkqU28sfu5VTQhyeEIFbw=
github.com/sagernet/sing-tun v0.0.0-20220815014658-b828f0164333 h1:fJj7jCPkGkbhY/UNwebi7kKq8Yxc6qeD3Jzh9Wk9tPw=
github.com/sagernet/sing-tun v0.0.0-20220815014658-b828f0164333/go.mod h1:+JztVFWrBR8bbf1fWPCyc4KJ/a1bPejmmoEBj9rI6HQ=
github.com/sagernet/sing-vmess v0.0.0-20220811135656-4f3f07acf9c4 h1:2hLETh97+S4WnfMR27XyC7QVU1SH7FTNoCznP229YJU=
github.com/sagernet/sing-vmess v0.0.0-20220811135656-4f3f07acf9c4/go.mod h1:82O6gzbxLha/W/jxSVQbsqf2lVdRTjMIgyLug0lpJps=
github.com/sagernet/smux v0.0.0-20220812084127-e2d085ee3939 h1:pB1Dh1NbwVrLhQhotr4O4Hs3yhiBzmg3AvnUyYjL4x4=
@ -248,8 +248,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20220811182439-13a9a731de15 h1:cik0bxZUSJVDyaHf1hZPSDsU8SZHGQZQMeueXCE7yBQ=
golang.org/x/net v0.0.0-20220811182439-13a9a731de15/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
golang.org/x/net v0.0.0-20220812174116-3211cb980234 h1:RDqmgfe7SvlMWoqC3xwQ2blLO3fcWcxMa3eBLRdRW7E=
golang.org/x/net v0.0.0-20220812174116-3211cb980234/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=

View File

@ -3,7 +3,6 @@ package inbound
import (
"context"
"net"
"net/netip"
"strconv"
"strings"
"time"
@ -17,9 +16,9 @@ import (
"github.com/sagernet/sing-tun"
"github.com/sagernet/sing/common"
E "github.com/sagernet/sing/common/exceptions"
F "github.com/sagernet/sing/common/format"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
"github.com/sagernet/sing/common/ranges"
)
var _ adapter.Inbound = (*Tun)(nil)
@ -30,11 +29,7 @@ type Tun struct {
router adapter.Router
logger log.ContextLogger
inboundOptions option.InboundOptions
tunName string
tunMTU uint32
inet4Address netip.Prefix
inet6Address netip.Prefix
autoRoute bool
tunOptions tun.Options
endpointIndependentNat bool
udpTimeout int64
stack string
@ -45,7 +40,7 @@ type Tun struct {
func NewTun(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.TunInboundOptions) (*Tun, error) {
tunName := options.InterfaceName
if tunName == "" {
tunName = mkInterfaceName()
tunName = tun.DefaultInterfaceName()
}
tunMTU := options.MTU
if tunMTU == 0 {
@ -57,23 +52,76 @@ func NewTun(ctx context.Context, router adapter.Router, logger log.ContextLogger
} else {
udpTimeout = int64(C.UDPTimeout.Seconds())
}
includeUID := uidToRange(options.IncludeUID)
if len(options.IncludeUIDRange) > 0 {
var err error
includeUID, err = parseRange(includeUID, options.IncludeUIDRange)
if err != nil {
return nil, E.Cause(err, "parse include_uid_range")
}
}
excludeUID := uidToRange(options.ExcludeUID)
if len(options.ExcludeUIDRange) > 0 {
var err error
excludeUID, err = parseRange(excludeUID, options.ExcludeUIDRange)
if err != nil {
return nil, E.Cause(err, "parse exclude_uid_range")
}
}
return &Tun{
tag: tag,
ctx: ctx,
router: router,
logger: logger,
inboundOptions: options.InboundOptions,
tunName: tunName,
tunMTU: tunMTU,
inet4Address: options.Inet4Address.Build(),
inet6Address: options.Inet6Address.Build(),
autoRoute: options.AutoRoute,
tunOptions: tun.Options{
Name: tunName,
MTU: tunMTU,
Inet4Address: options.Inet4Address.Build(),
Inet6Address: options.Inet6Address.Build(),
AutoRoute: options.AutoRoute,
IncludeUID: includeUID,
IncludeAndroidUser: options.IncludeAndroidUser,
ExcludeUID: excludeUID,
},
endpointIndependentNat: options.EndpointIndependentNat,
udpTimeout: udpTimeout,
stack: options.Stack,
}, nil
}
func uidToRange(uidList option.Listable[uint32]) []ranges.Range[uint32] {
return common.Map(uidList, func(uid uint32) ranges.Range[uint32] {
return ranges.NewSingle(uid)
})
}
func parseRange(uidRanges []ranges.Range[uint32], rangeList []string) ([]ranges.Range[uint32], error) {
for _, uidRange := range rangeList {
if !strings.Contains(uidRange, ":") {
return nil, E.New("missing ':' in range: ", uidRange)
}
subIndex := strings.Index(uidRange, ":")
if subIndex == 0 {
return nil, E.New("missing range start: ", uidRange)
} else if subIndex == len(uidRange)-1 {
return nil, E.New("missing range end: ", uidRange)
}
var start, end uint64
var err error
start, err = strconv.ParseUint(uidRange[:subIndex], 10, 32)
if err != nil {
return nil, E.Cause(err, "parse range start")
}
end, err = strconv.ParseUint(uidRange[subIndex+1:], 10, 32)
if err != nil {
return nil, E.Cause(err, "parse range end")
}
uidRanges = append(uidRanges, ranges.New(uint32(start), uint32(end)))
}
return uidRanges, nil
}
func (t *Tun) Type() string {
return C.TypeTun
}
@ -83,12 +131,12 @@ func (t *Tun) Tag() string {
}
func (t *Tun) Start() error {
tunIf, err := tun.Open(t.tunName, t.inet4Address, t.inet6Address, t.tunMTU, t.autoRoute)
tunIf, err := tun.Open(t.tunOptions)
if err != nil {
return E.Cause(err, "configure tun interface")
}
t.tunIf = tunIf
t.tunStack, err = tun.NewStack(t.ctx, t.stack, tunIf, t.tunMTU, t.endpointIndependentNat, t.udpTimeout, t)
t.tunStack, err = tun.NewStack(t.ctx, t.stack, tunIf, t.tunOptions.MTU, t.endpointIndependentNat, t.udpTimeout, t)
if err != nil {
return err
}
@ -96,7 +144,7 @@ func (t *Tun) Start() error {
if err != nil {
return err
}
t.logger.Info("started at ", t.tunName)
t.logger.Info("started at ", t.tunOptions.Name)
return nil
}
@ -153,26 +201,3 @@ func (t *Tun) NewPacketConnection(ctx context.Context, conn N.PacketConn, upstre
func (t *Tun) NewError(ctx context.Context, err error) {
NewError(t.logger, ctx, err)
}
func mkInterfaceName() (tunName string) {
if C.IsDarwin {
tunName = "utun"
} else {
tunName = "tun"
}
interfaces, err := net.Interfaces()
if err != nil {
return
}
var tunIndex int
for _, netInterface := range interfaces {
if strings.HasPrefix(netInterface.Name, tunName) {
index, parseErr := strconv.ParseInt(netInterface.Name[len(tunName):], 10, 16)
if parseErr == nil {
tunIndex = int(index) + 1
}
}
}
tunName = F.ToString(tunName, tunIndex)
return
}

View File

@ -6,6 +6,11 @@ type TunInboundOptions struct {
Inet4Address *ListenPrefix `json:"inet4_address,omitempty"`
Inet6Address *ListenPrefix `json:"inet6_address,omitempty"`
AutoRoute bool `json:"auto_route,omitempty"`
IncludeUID Listable[uint32] `json:"include_uid,omitempty"`
IncludeUIDRange Listable[string] `json:"include_uid_range,omitempty"`
ExcludeUID Listable[uint32] `json:"exclude_uid,omitempty"`
ExcludeUIDRange Listable[string] `json:"exclude_uid_range,omitempty"`
IncludeAndroidUser Listable[int] `json:"android_user,omitempty"`
EndpointIndependentNat bool `json:"endpoint_independent_nat,omitempty"`
UDPTimeout int64 `json:"udp_timeout,omitempty"`
Stack string `json:"stack,omitempty"`

View File

@ -10,7 +10,7 @@ require (
github.com/docker/docker v20.10.17+incompatible
github.com/docker/go-connections v0.4.0
github.com/gofrs/uuid v4.2.0+incompatible
github.com/sagernet/sing v0.0.0-20220813024838-eb2fad956aa8
github.com/sagernet/sing v0.0.0-20220814164830-4f2b872a8cbf
github.com/sagernet/sing-shadowsocks v0.0.0-20220812082714-484a11603b48
github.com/spyzhov/ajson v0.7.1
github.com/stretchr/testify v1.8.0
@ -54,7 +54,7 @@ require (
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/sagernet/netlink v0.0.0-20220803045538-bdac49abf805 // indirect
github.com/sagernet/sing-dns v0.0.0-20220813025814-e656c9dbf3ae // indirect
github.com/sagernet/sing-tun v0.0.0-20220808133432-d378b6ca536d // indirect
github.com/sagernet/sing-tun v0.0.0-20220815014658-b828f0164333 // indirect
github.com/sagernet/sing-vmess v0.0.0-20220811135656-4f3f07acf9c4 // indirect
github.com/sagernet/smux v0.0.0-20220812084127-e2d085ee3939 // indirect
github.com/sirupsen/logrus v1.8.1 // indirect

View File

@ -175,14 +175,14 @@ github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR
github.com/sagernet/netlink v0.0.0-20220803045538-bdac49abf805 h1:hE+vtsjBCCPmxkRz9jZA+CicHgVkDT6H+Av5ZzskVxs=
github.com/sagernet/netlink v0.0.0-20220803045538-bdac49abf805/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM=
github.com/sagernet/sing v0.0.0-20220812082120-05f9836bff8f/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
github.com/sagernet/sing v0.0.0-20220813024838-eb2fad956aa8 h1:zTuJbqzZgBh+iGPV41d8ZarKxXPgTq/+PGk1kMhPV8I=
github.com/sagernet/sing v0.0.0-20220813024838-eb2fad956aa8/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
github.com/sagernet/sing v0.0.0-20220814164830-4f2b872a8cbf h1:JYnx6N1H2KeFKM7YSH5+qfhvvcy6gpqSpewkp1RLRSg=
github.com/sagernet/sing v0.0.0-20220814164830-4f2b872a8cbf/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
github.com/sagernet/sing-dns v0.0.0-20220813025814-e656c9dbf3ae h1:xOpbvgizvIbKKrrcl/CK3RjGY2u7rC+SBXlgqzEZOU4=
github.com/sagernet/sing-dns v0.0.0-20220813025814-e656c9dbf3ae/go.mod h1:T77zZdE2Cm6VqnFumrpwsq+kxYsbq+vWDhmjtdSl/oM=
github.com/sagernet/sing-shadowsocks v0.0.0-20220812082714-484a11603b48 h1:NlcTFKldteZvYBDyr+V9MjZEI0rAWCSFCyLgPvc5n/Y=
github.com/sagernet/sing-shadowsocks v0.0.0-20220812082714-484a11603b48/go.mod h1:EX3RbZvrwAkPI2nuGa78T2iQXmrkT+/VQtskjou42xM=
github.com/sagernet/sing-tun v0.0.0-20220808133432-d378b6ca536d h1:AQpkoUiF8FxYVI1lf2W9Rbkk914eHjVH9M8y+F/0+Nw=
github.com/sagernet/sing-tun v0.0.0-20220808133432-d378b6ca536d/go.mod h1:gWwYd53AqXl+Y+q6WlXUc6PkqU28sfu5VTQhyeEIFbw=
github.com/sagernet/sing-tun v0.0.0-20220815014658-b828f0164333 h1:fJj7jCPkGkbhY/UNwebi7kKq8Yxc6qeD3Jzh9Wk9tPw=
github.com/sagernet/sing-tun v0.0.0-20220815014658-b828f0164333/go.mod h1:+JztVFWrBR8bbf1fWPCyc4KJ/a1bPejmmoEBj9rI6HQ=
github.com/sagernet/sing-vmess v0.0.0-20220811135656-4f3f07acf9c4 h1:2hLETh97+S4WnfMR27XyC7QVU1SH7FTNoCznP229YJU=
github.com/sagernet/sing-vmess v0.0.0-20220811135656-4f3f07acf9c4/go.mod h1:82O6gzbxLha/W/jxSVQbsqf2lVdRTjMIgyLug0lpJps=
github.com/sagernet/smux v0.0.0-20220812084127-e2d085ee3939 h1:pB1Dh1NbwVrLhQhotr4O4Hs3yhiBzmg3AvnUyYjL4x4=