Compare commits

..

11 Commits

Author SHA1 Message Date
世界
02862cbc6a documentation: Bump version 2024-02-09 19:20:10 +08:00
世界
fef9c4f606 documentation: Add description for client_subnet options 2024-02-09 19:20:10 +08:00
世界
5ffae06bf2 Add support for client-subnet DNS options 2024-02-09 18:50:47 +08:00
世界
36c89165f2 documentation: Add description for address filter DNS rules 2024-02-09 18:36:29 +08:00
世界
57fcea326b Update dependencies 2024-02-09 13:58:15 +08:00
世界
de4e9553b1 Fixed order for Clash modes 2024-02-09 13:58:15 +08:00
世界
8fc2e1e7ea Add address filter support for DNS rules 2024-02-09 13:58:14 +08:00
世界
c65db38379 Fix timezone for Android and iOS 2024-02-09 13:58:13 +08:00
世界
76dd983a45 Improve domain suffix match behavior
For historical reasons, sing-box's `domain_suffix` rule matches literal prefixes instead of the same as other projects.

This change modifies the behavior of `domain_suffix`: If the rule value is prefixed with `.`,
the behavior is unchanged, otherwise it matches `(domain|.+\.domain)` instead.
2024-02-09 13:58:13 +08:00
世界
16cae78411 Remove PROCESS_NAME_NATIVE dwFlag in process query output
The `process_path` rule of sing-box is inherited from Clash,
the original code uses the local system's path format (e.g. `\Device\HarddiskVolume1\folder\program.exe`),
but when the device has multiple disks, the HarddiskVolume serial number is not stable.

This change make QueryFullProcessImageNameW output a Win32 path (such as `C:\folder\program.exe`),
which will disrupt the existing `process_path` use cases in Windows.
2024-02-09 13:58:13 +08:00
世界
bd0ccafd40 badtls: Support uTLS and TLS ECH for read waiter 2024-02-09 13:58:12 +08:00
117 changed files with 1228 additions and 1003 deletions

View File

@@ -65,12 +65,6 @@ body:
For Apple platform clients, please check `Settings - View Service Log` for crash logs.
For the Android client, please check the `/sdcard/Android/data/io.nekohasekai.sfa/files/stderr.log` file for crash logs.
render: shell
- type: checkboxes
id: supporter
attributes:
label: Supporter
options:
- label: I am a [sponsor](https://github.com/sponsors/nekohasekai/)
- type: checkboxes
attributes:
label: Integrity requirements

View File

@@ -65,12 +65,6 @@ body:
对于 Apple 平台图形客户端程序,请检查 `Settings - View Service Log` 以导出崩溃日志。
对于 Android 图形客户端程序,请检查 `/sdcard/Android/data/io.nekohasekai.sfa/files/stderr.log` 文件以导出崩溃日志。
render: shell
- type: checkboxes
id: supporter
attributes:
label: 支持我们
options:
- label: 我已经 [赞助](https://github.com/sponsors/nekohasekai/)
- type: checkboxes
attributes:
label: 完整性要求

View File

@@ -1,14 +0,0 @@
#!/usr/bin/env bash
PROJECTS=$(dirname "$0")/../..
function updateClient() {
pushd clients/$1
git fetch
git reset FETCH_HEAD --hard
popd
git add clients/$1
}
updateClient "apple"
updateClient "android"

View File

@@ -72,7 +72,7 @@ jobs:
~/go/pkg/mod
key: go120-${{ hashFiles('**/go.sum') }}
- name: Run Test
run: make ci_build_go120
run: make ci_build
build_go121:
name: Debug build (Go 1.21)
runs-on: ubuntu-latest

View File

@@ -3,7 +3,7 @@ name: Build Docker Images
on:
release:
types:
- released
- published
jobs:
build:

View File

@@ -26,11 +26,15 @@ jobs:
with:
fetch-depth: 0
- name: Setup Go
uses: actions/setup-go@v5
uses: actions/setup-go@v4
with:
go-version: ^1.22
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: ${{ steps.version.outputs.go_version }}
- name: golangci-lint
uses: golangci/golangci-lint-action@v4
uses: golangci/golangci-lint-action@v3
with:
version: latest
args: --timeout=30m

View File

@@ -1,37 +0,0 @@
name: Release to Linux repository
on:
release:
types:
- published
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
with:
fetch-depth: 0
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: ^1.22
- name: Extract signing key
run: |-
mkdir -p $HOME/.gnupg
cat > $HOME/.gnupg/sagernet.key <<EOF
${{ secrets.GPG_KEY }}
EOF
- name: Publish release
uses: goreleaser/goreleaser-action@v5
with:
distribution: goreleaser-pro
version: latest
args: release -f .goreleaser.fury.yaml --clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }}
FURY_TOKEN: ${{ secrets.FURY_TOKEN }}
NFPM_KEY_PATH: ${{ env.Home }}/.gnupg/sagernet.key
NFPM_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}

6
.gitmodules vendored
View File

@@ -1,6 +0,0 @@
[submodule "clients/apple"]
path = clients/apple
url = https://github.com/SagerNet/sing-box-for-apple.git
[submodule "clients/android"]
path = clients/android
url = https://github.com/SagerNet/sing-box-for-android.git

View File

@@ -1,87 +0,0 @@
project_name: sing-box
builds:
- id: main
main: ./cmd/sing-box
flags:
- -v
- -trimpath
ldflags:
- -X github.com/sagernet/sing-box/constant.Version={{ .Version }} -s -w -buildid=
tags:
- with_gvisor
- with_quic
- with_dhcp
- with_wireguard
- with_ech
- with_utls
- with_reality_server
- with_acme
- with_clash_api
env:
- CGO_ENABLED=0
targets:
- linux_386
- linux_amd64_v1
- linux_arm64
- linux_arm_7
- linux_s390x
- linux_riscv64
mod_timestamp: '{{ .CommitTimestamp }}'
snapshot:
name_template: "{{ .Version }}.{{ .ShortCommit }}"
nfpms:
- &template
id: package
package_name: sing-box
file_name_template: '{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ with .Arm }}v{{ . }}{{ end }}{{ with .Mips }}_{{ . }}{{ end }}{{ if not (eq .Amd64 "v1") }}{{ .Amd64 }}{{ end }}'
builds:
- main
vendor: sagernet
homepage: https://sing-box.sagernet.org/
maintainer: nekohasekai <contact-git@sekai.icu>
description: The universal proxy platform.
license: GPLv3 or later
formats:
- deb
- rpm
priority: extra
contents:
- src: release/config/config.json
dst: /etc/sing-box/config.json
type: config
- src: release/config/sing-box.service
dst: /usr/lib/systemd/system/sing-box.service
- src: release/config/sing-box@.service
dst: /usr/lib/systemd/system/sing-box@.service
- src: LICENSE
dst: /usr/share/licenses/sing-box/LICENSE
deb:
signature:
key_file: "{{ .Env.NFPM_KEY_PATH }}"
fields:
Bugs: https://github.com/SagerNet/sing-box/issues
rpm:
signature:
key_file: "{{ .Env.NFPM_KEY_PATH }}"
conflicts:
- sing-box-beta
- id: package_beta
<<: *template
package_name: sing-box-beta
file_name_template: '{{ .ProjectName }}-beta_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ with .Arm }}v{{ . }}{{ end }}{{ with .Mips }}_{{ . }}{{ end }}{{ if not (eq .Amd64 "v1") }}{{ .Amd64 }}{{ end }}'
formats:
- deb
- rpm
conflicts:
- sing-box
release:
disable: true
furies:
- account: sagernet
ids:
- package
disable: "{{ not (not .Prerelease) }}"
- account: sagernet
ids:
- package_beta
disable: "{{ not .Prerelease }}"

View File

@@ -1,11 +1,14 @@
project_name: sing-box
builds:
- &template
id: main
- id: main
main: ./cmd/sing-box
flags:
- -v
- -trimpath
asmflags:
- all=-trimpath={{.Env.GOPATH}}
gcflags:
- all=-trimpath={{.Env.GOPATH}}
ldflags:
- -X github.com/sagernet/sing-box/constant.Version={{ .Version }} -s -w -buildid=
tags:
@@ -27,35 +30,65 @@ builds:
- linux_arm64
- linux_arm_7
- linux_s390x
- linux_riscv64
- windows_amd64_v1
- windows_amd64_v3
- windows_386
- windows_arm64
- darwin_amd64_v1
- darwin_amd64_v3
- darwin_arm64
mod_timestamp: '{{ .CommitTimestamp }}'
- id: legacy
<<: *template
main: ./cmd/sing-box
flags:
- -v
- -trimpath
asmflags:
- all=-trimpath={{.Env.GOPATH}}
gcflags:
- all=-trimpath={{.Env.GOPATH}}
ldflags:
- -X github.com/sagernet/sing-box/constant.Version={{ .Version }} -s -w -buildid=
tags:
- with_gvisor
- with_quic
- with_dhcp
- with_wireguard
- with_ech
- with_utls
- with_reality_server
- with_acme
- with_clash_api
env:
- CGO_ENABLED=0
- GOROOT={{ .Env.GOPATH }}/go1.20.14
gobinary: "{{ .Env.GOPATH }}/go1.20.14/bin/go"
- GOROOT=/nix/store/kg6i737jjqs923jcijnm003h68c1dghj-go-1.20.11/share/go
gobinary: /nix/store/kg6i737jjqs923jcijnm003h68c1dghj-go-1.20.11/bin/go
targets:
- windows_amd64_v1
- windows_386
- darwin_amd64_v1
mod_timestamp: '{{ .CommitTimestamp }}'
- id: android
<<: *template
main: ./cmd/sing-box
flags:
- -v
- -trimpath
asmflags:
- all=-trimpath={{.Env.GOPATH}}
gcflags:
- all=-trimpath={{.Env.GOPATH}}
ldflags:
- -X github.com/sagernet/sing-box/constant.Version={{ .Version }} -s -w -buildid=
tags:
- with_gvisor
- with_quic
- with_dhcp
- with_wireguard
- with_ech
- with_utls
- with_reality_server
- with_acme
- with_clash_api
env:
- CGO_ENABLED=1
overrides:
@@ -63,8 +96,8 @@ builds:
goarch: arm
goarm: 7
env:
- CC=armv7a-linux-androideabi21-clang
- CXX=armv7a-linux-androideabi21-clang++
- CC=armv7a-linux-androideabi19-clang
- CXX=armv7a-linux-androideabi19-clang++
- goos: android
goarch: arm64
env:
@@ -73,8 +106,8 @@ builds:
- goos: android
goarch: 386
env:
- CC=i686-linux-android21-clang
- CXX=i686-linux-android21-clang++
- CC=i686-linux-android19-clang
- CXX=i686-linux-android19-clang++
- goos: android
goarch: amd64
goamd64: v1
@@ -86,11 +119,11 @@ builds:
- android_arm64
- android_386
- android_amd64
mod_timestamp: '{{ .CommitTimestamp }}'
snapshot:
name_template: "{{ .Version }}.{{ .ShortCommit }}"
archives:
- &template
id: archive
- id: archive
builds:
- main
- android
@@ -103,16 +136,20 @@ archives:
- LICENSE
name_template: '{{ .ProjectName }}-{{ .Version }}-{{ .Os }}-{{ .Arch }}{{ with .Arm }}v{{ . }}{{ end }}{{ with .Mips }}_{{ . }}{{ end }}{{ if not (eq .Amd64 "v1") }}{{ .Amd64 }}{{ end }}'
- id: archive-legacy
<<: *template
builds:
- legacy
format: tar.gz
format_overrides:
- goos: windows
format: zip
wrap_in_directory: true
files:
- LICENSE
name_template: '{{ .ProjectName }}-{{ .Version }}-{{ .Os }}-{{ .Arch }}-legacy'
nfpms:
- id: package
package_name: sing-box
file_name_template: '{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ with .Arm }}v{{ . }}{{ end }}{{ with .Mips }}_{{ . }}{{ end }}{{ if not (eq .Amd64 "v1") }}{{ .Amd64 }}{{ end }}'
builds:
- main
vendor: sagernet
homepage: https://sing-box.sagernet.org/
maintainer: nekohasekai <contact-git@sekai.icu>
@@ -128,27 +165,11 @@ nfpms:
dst: /etc/sing-box/config.json
type: config
- src: release/config/sing-box.service
dst: /usr/lib/systemd/system/sing-box.service
dst: /etc/systemd/system/sing-box.service
- src: release/config/sing-box@.service
dst: /usr/lib/systemd/system/sing-box@.service
dst: /etc/systemd/system/sing-box@.service
- src: LICENSE
dst: /usr/share/licenses/sing-box/LICENSE
deb:
signature:
key_file: "{{ .Env.NFPM_KEY_PATH }}"
fields:
Bugs: https://github.com/SagerNet/sing-box/issues
rpm:
signature:
key_file: "{{ .Env.NFPM_KEY_PATH }}"
overrides:
deb:
conflicts:
- sing-box-beta
rpm:
conflicts:
- sing-box-beta
source:
enabled: false
name_template: '{{ .ProjectName }}-{{ .Version }}.source'
@@ -162,10 +183,6 @@ release:
github:
owner: SagerNet
name: sing-box
name_template: '{{ if .IsSnapshot }}{{ nightly }}{{ else }}{{ .Version }}{{ end }}'
draft: true
prerelease: auto
mode: replace
ids:
- archive
- package
skip_upload: true
mode: replace

View File

@@ -1,4 +1,4 @@
FROM --platform=$BUILDPLATFORM golang:1.22-alpine AS builder
FROM --platform=$BUILDPLATFORM golang:1.21-alpine AS builder
LABEL maintainer="nekohasekai <contact-git@sekai.icu>"
COPY . /go/src/github.com/sagernet/sing-box
WORKDIR /go/src/github.com/sagernet/sing-box

View File

@@ -1,9 +1,8 @@
NAME = sing-box
COMMIT = $(shell git rev-parse --short HEAD)
TAGS_GO118 = with_gvisor,with_dhcp,with_wireguard,with_reality_server,with_clash_api
TAGS_GO120 = with_quic,with_utls
TAGS_GO121 = with_ech
TAGS ?= $(TAGS_GO118),$(TAGS_GO120),$(TAGS_GO121)
TAGS_GO120 = with_quic,with_ech,with_utls
TAGS ?= $(TAGS_GO118),$(TAGS_GO120)
TAGS_TEST ?= with_gvisor,with_quic,with_wireguard,with_grpc,with_ech,with_utls,with_reality_server
GOHOSTOS = $(shell go env GOHOSTOS)
@@ -15,7 +14,7 @@ MAIN_PARAMS = $(PARAMS) -tags $(TAGS)
MAIN = ./cmd/sing-box
PREFIX ?= $(shell go env GOPATH)
.PHONY: test release docs build
.PHONY: test release docs
build:
go build $(MAIN_PARAMS) $(MAIN)
@@ -24,10 +23,6 @@ ci_build_go118:
go build $(PARAMS) $(MAIN)
go build $(PARAMS) -tags "$(TAGS_GO118)" $(MAIN)
ci_build_go120:
go build $(PARAMS) $(MAIN)
go build $(PARAMS) -tags "$(TAGS_GO118),$(TAGS_GO120)" $(MAIN)
ci_build:
go build $(PARAMS) $(MAIN)
go build $(MAIN_PARAMS) $(MAIN)
@@ -64,35 +59,25 @@ proto_install:
go install -v google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
release:
go run ./cmd/internal/build goreleaser release --clean --skip publish
go run ./cmd/internal/build goreleaser release --clean --skip-publish || exit 1
mkdir dist/release
mv dist/*.tar.gz \
dist/*.zip \
dist/*.deb \
dist/*.rpm \
dist/*_amd64.pkg.tar.zst \
dist/*_amd64v3.pkg.tar.zst \
dist/*_arm64.pkg.tar.zst \
dist/release
mv dist/*.tar.gz dist/*.zip dist/*.deb dist/*.rpm dist/*.pkg.tar.zst dist/release
ghr --replace --draft --prerelease -p 3 "v${VERSION}" dist/release
rm -r dist/release
release_repo:
go run ./cmd/internal/build goreleaser release -f .goreleaser.fury.yaml --clean
release_install:
go install -v github.com/goreleaser/goreleaser@latest
go install -v github.com/tcnksm/ghr@latest
update_android_version:
go run ./cmd/internal/update_android_version
build_android:
cd ../sing-box-for-android && ./gradlew :app:clean :app:assemblePlayRelease :app:assembleOtherRelease && ./gradlew --stop
cd ../sing-box-for-android && ./gradlew :app:assemblePlayRelease && ./gradlew --stop
upload_android:
mkdir -p dist/release_android
cp ../sing-box-for-android/app/build/outputs/apk/play/release/*.apk dist/release_android
cp ../sing-box-for-android/app/build/outputs/apk/other/release/*-universal.apk dist/release_android
ghr --replace --draft --prerelease -p 3 "v${VERSION}" dist/release_android
rm -rf dist/release_android
@@ -193,8 +178,8 @@ lib:
go run ./cmd/internal/build_libbox -target ios
lib_install:
go install -v github.com/sagernet/gomobile/cmd/gomobile@v0.1.3
go install -v github.com/sagernet/gomobile/cmd/gobind@v0.1.3
go install -v github.com/sagernet/gomobile/cmd/gomobile@v0.1.1
go install -v github.com/sagernet/gomobile/cmd/gobind@v0.1.1
docs:
mkdocs serve

View File

@@ -51,11 +51,13 @@ type InboundContext struct {
// rule cache
IPCIDRMatchSource bool
SourceAddressMatch bool
SourcePortMatch bool
DestinationAddressMatch bool
DestinationPortMatch bool
IPCIDRMatchSource bool
SourceAddressMatch bool
SourcePortMatch bool
DestinationAddressMatch bool
DestinationPortMatch bool
DidMatch bool
IgnoreDestinationIPCIDRMatch bool
}
func (c *InboundContext) ResetRuleCache() {

View File

@@ -33,8 +33,6 @@ type Router interface {
RuleSet(tag string) (RuleSet, bool)
NeedWIFIState() bool
Exchange(ctx context.Context, message *mdns.Msg) (*mdns.Msg, error)
Lookup(ctx context.Context, domain string, strategy dns.DomainStrategy) ([]netip.Addr, error)
LookupDefault(ctx context.Context, domain string) ([]netip.Addr, error)
@@ -86,6 +84,9 @@ type DNSRule interface {
Rule
DisableCache() bool
RewriteTTL() *uint32
ClientSubnet() *netip.Addr
WithAddressLimit() bool
MatchAddressLimit(metadata *InboundContext) bool
}
type RuleSet interface {
@@ -99,6 +100,7 @@ type RuleSet interface {
type RuleSetMetadata struct {
ContainsProcessRule bool
ContainsWIFIRule bool
ContainsIPCIDRRule bool
}
type RuleSetStartContext interface {

4
box.go
View File

@@ -235,7 +235,7 @@ func (s *Box) Start() error {
}
func (s *Box) preStart() error {
monitor := taskmonitor.New(s.logger, C.StartTimeout)
monitor := taskmonitor.New(s.logger, C.DefaultStartTimeout)
monitor.Start("start logger")
err := s.logFactory.Start()
monitor.Finish()
@@ -331,7 +331,7 @@ func (s *Box) Close() error {
default:
close(s.done)
}
monitor := taskmonitor.New(s.logger, C.StopTimeout)
monitor := taskmonitor.New(s.logger, C.DefaultStopTimeout)
var errors error
for serviceName, service := range s.postServices {
monitor.Start("close ", serviceName)

View File

@@ -12,7 +12,7 @@ import (
)
func (s *Box) startOutbounds() error {
monitor := taskmonitor.New(s.logger, C.StartTimeout)
monitor := taskmonitor.New(s.logger, C.DefaultStartTimeout)
outboundTags := make(map[adapter.Outbound]string)
outbounds := make(map[string]adapter.Outbound)
for i, outboundToStart := range s.outbounds {

Submodule clients/android deleted from 288a6f34db

Submodule clients/apple deleted from 1c5bc23a25

View File

@@ -46,13 +46,13 @@ var (
func init() {
sharedFlags = append(sharedFlags, "-trimpath")
sharedFlags = append(sharedFlags, "-buildvcs=false")
sharedFlags = append(sharedFlags, "-ldflags")
currentTag, err := build_shared.ReadTag()
if err != nil {
currentTag = "unknown"
}
sharedFlags = append(sharedFlags, "-ldflags", "-X github.com/sagernet/sing-box/constant.Version="+currentTag+" -s -w -buildid=")
debugFlags = append(debugFlags, "-ldflags", "-X github.com/sagernet/sing-box/constant.Version="+currentTag)
sharedFlags = append(sharedFlags, "-X github.com/sagernet/sing-box/constant.Version="+currentTag+" -s -w -buildid=")
debugFlags = append(debugFlags, "-X github.com/sagernet/sing-box/constant.Version="+currentTag)
sharedTags = append(sharedTags, "with_gvisor", "with_quic", "with_wireguard", "with_ech", "with_utls", "with_clash_api")
iosTags = append(iosTags, "with_dhcp", "with_low_memory", "with_conntrack")

View File

@@ -11,9 +11,7 @@ import (
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing/common"
E "github.com/sagernet/sing/common/exceptions"
"github.com/sagernet/sing/common/rw"
"github.com/sagernet/sing/common/shell"
)
var (
@@ -30,7 +28,7 @@ func FindSDK() {
}
for _, path := range searchPath {
path = os.ExpandEnv(path)
if rw.FileExists(filepath.Join(path, "licenses", "android-sdk-license")) {
if rw.FileExists(path + "/licenses/android-sdk-license") {
androidSDKPath = path
break
}
@@ -42,14 +40,6 @@ func FindSDK() {
log.Fatal("android NDK not found")
}
javaVersion, err := shell.Exec("java", "--version").ReadOutput()
if err != nil {
log.Fatal(E.Cause(err, "check java version"))
}
if !strings.Contains(javaVersion, "openjdk 17") {
log.Fatal("java version should be openjdk 17")
}
os.Setenv("ANDROID_HOME", androidSDKPath)
os.Setenv("ANDROID_SDK_HOME", androidSDKPath)
os.Setenv("ANDROID_NDK_HOME", androidNDKPath)
@@ -58,13 +48,11 @@ func FindSDK() {
}
func findNDK() bool {
const fixedVersion = "26.2.11394342"
const versionFile = "source.properties"
if fixedPath := filepath.Join(androidSDKPath, "ndk", fixedVersion); rw.FileExists(filepath.Join(fixedPath, versionFile)) {
androidNDKPath = fixedPath
if rw.FileExists(androidSDKPath + "/ndk/25.1.8937393") {
androidNDKPath = androidSDKPath + "/ndk/25.1.8937393"
return true
}
ndkVersions, err := os.ReadDir(filepath.Join(androidSDKPath, "ndk"))
ndkVersions, err := os.ReadDir(androidSDKPath + "/ndk")
if err != nil {
return false
}
@@ -85,10 +73,8 @@ func findNDK() bool {
return true
})
for _, versionName := range versionNames {
currentNDKPath := filepath.Join(androidSDKPath, "ndk", versionName)
if rw.FileExists(filepath.Join(androidSDKPath, versionFile)) {
androidNDKPath = currentNDKPath
log.Warn("reproducibility warning: using NDK version " + versionName + " instead of " + fixedVersion)
if rw.FileExists(androidSDKPath + "/ndk/" + versionName) {
androidNDKPath = androidSDKPath + "/ndk/" + versionName
return true
}
}
@@ -99,12 +85,13 @@ var GoBinPath string
func FindMobile() {
goBin := filepath.Join(build.Default.GOPATH, "bin")
if runtime.GOOS == "windows" {
if !rw.FileExists(filepath.Join(goBin, "gobind.exe")) {
log.Fatal("missing gomobile installation")
if !rw.FileExists(goBin + "/" + "gobind.exe") {
log.Fatal("missing gomobile.exe installation")
}
} else {
if !rw.FileExists(filepath.Join(goBin, "gobind")) {
if !rw.FileExists(goBin + "/" + "gobind") {
log.Fatal("missing gomobile installation")
}
}

View File

@@ -3,7 +3,6 @@ package main
import (
"os"
"path/filepath"
"runtime"
"strconv"
"strings"
@@ -19,46 +18,34 @@ func main() {
log.Fatal(err)
}
common.Must(os.Chdir(androidPath))
localProps := common.Must1(os.ReadFile("version.properties"))
localProps := common.Must1(os.ReadFile("local.properties"))
var propsList [][]string
for _, propLine := range strings.Split(string(localProps), "\n") {
propsList = append(propsList, strings.Split(propLine, "="))
}
var (
versionUpdated bool
goVersionUpdated bool
)
for _, propPair := range propsList {
switch propPair[0] {
case "VERSION_NAME":
if propPair[1] != newVersion.String() {
versionUpdated = true
propPair[1] = newVersion.String()
log.Info("updated version to ", newVersion.String())
}
case "GO_VERSION":
if propPair[1] != runtime.Version() {
goVersionUpdated = true
propPair[1] = runtime.Version()
log.Info("updated Go version to ", runtime.Version())
if propPair[0] == "VERSION_NAME" {
if propPair[1] == newVersion.String() {
log.Info("version not changed")
return
}
propPair[1] = newVersion.String()
log.Info("updated version to ", newVersion.String())
}
}
if !(versionUpdated || goVersionUpdated) {
log.Info("version not changed")
return
}
for _, propPair := range propsList {
switch propPair[0] {
case "VERSION_CODE":
versionCode := common.Must1(strconv.ParseInt(propPair[1], 10, 64))
propPair[1] = strconv.Itoa(int(versionCode + 1))
log.Info("updated version code to ", propPair[1])
case "RELEASE_NOTES":
propPair[1] = "sing-box " + newVersion.String()
}
}
var newProps []string
for _, propPair := range propsList {
newProps = append(newProps, strings.Join(propPair, "="))
}
common.Must(os.WriteFile("version.properties", []byte(strings.Join(newProps, "\n")), 0o644))
common.Must(os.WriteFile("local.properties", []byte(strings.Join(newProps, "\n")), 0o644))
}

View File

@@ -199,7 +199,7 @@ func run() error {
}
func closeMonitor(ctx context.Context) {
time.Sleep(C.FatalStopTimeout)
time.Sleep(C.DefaultStopFatalTimeout)
select {
case <-ctx.Done():
return

View File

@@ -4,6 +4,8 @@ package badtls
import (
"bytes"
"context"
"net"
"os"
"reflect"
"sync"
@@ -18,20 +20,32 @@ import (
var _ N.ReadWaiter = (*ReadWaitConn)(nil)
type ReadWaitConn struct {
*tls.STDConn
halfAccess *sync.Mutex
rawInput *bytes.Buffer
input *bytes.Reader
hand *bytes.Buffer
readWaitOptions N.ReadWaitOptions
tls.Conn
halfAccess *sync.Mutex
rawInput *bytes.Buffer
input *bytes.Reader
hand *bytes.Buffer
readWaitOptions N.ReadWaitOptions
tlsReadRecord func() error
tlsHandlePostHandshakeMessage func() error
}
func NewReadWaitConn(conn tls.Conn) (tls.Conn, error) {
stdConn, isSTDConn := conn.(*tls.STDConn)
if !isSTDConn {
var (
loaded bool
tlsReadRecord func() error
tlsHandlePostHandshakeMessage func() error
)
for _, tlsCreator := range tlsRegistry {
loaded, tlsReadRecord, tlsHandlePostHandshakeMessage = tlsCreator(conn)
if loaded {
break
}
}
if !loaded {
return nil, os.ErrInvalid
}
rawConn := reflect.Indirect(reflect.ValueOf(stdConn))
rawConn := reflect.Indirect(reflect.ValueOf(conn))
rawHalfConn := rawConn.FieldByName("in")
if !rawHalfConn.IsValid() || rawHalfConn.Kind() != reflect.Struct {
return nil, E.New("badtls: invalid half conn")
@@ -57,11 +71,13 @@ func NewReadWaitConn(conn tls.Conn) (tls.Conn, error) {
}
hand := (*bytes.Buffer)(unsafe.Pointer(rawHand.UnsafeAddr()))
return &ReadWaitConn{
STDConn: stdConn,
halfAccess: halfAccess,
rawInput: rawInput,
input: input,
hand: hand,
Conn: conn,
halfAccess: halfAccess,
rawInput: rawInput,
input: input,
hand: hand,
tlsReadRecord: tlsReadRecord,
tlsHandlePostHandshakeMessage: tlsHandlePostHandshakeMessage,
}, nil
}
@@ -71,19 +87,19 @@ func (c *ReadWaitConn) InitializeReadWaiter(options N.ReadWaitOptions) (needCopy
}
func (c *ReadWaitConn) WaitReadBuffer() (buffer *buf.Buffer, err error) {
err = c.Handshake()
err = c.HandshakeContext(context.Background())
if err != nil {
return
}
c.halfAccess.Lock()
defer c.halfAccess.Unlock()
for c.input.Len() == 0 {
err = tlsReadRecord(c.STDConn)
err = c.tlsReadRecord()
if err != nil {
return
}
for c.hand.Len() > 0 {
err = tlsHandlePostHandshakeMessage(c.STDConn)
err = c.tlsHandlePostHandshakeMessage()
if err != nil {
return
}
@@ -100,7 +116,7 @@ func (c *ReadWaitConn) WaitReadBuffer() (buffer *buf.Buffer, err error) {
if n != 0 && c.input.Len() == 0 && c.rawInput.Len() > 0 &&
// recordType(c.rawInput.Bytes()[0]) == recordTypeAlert {
c.rawInput.Bytes()[0] == 21 {
_ = tlsReadRecord(c.STDConn)
_ = c.tlsReadRecord()
// return n, err // will be io.EOF on closeNotify
}
@@ -109,11 +125,27 @@ func (c *ReadWaitConn) WaitReadBuffer() (buffer *buf.Buffer, err error) {
}
func (c *ReadWaitConn) Upstream() any {
return c.STDConn
return c.Conn
}
//go:linkname tlsReadRecord crypto/tls.(*Conn).readRecord
func tlsReadRecord(c *tls.STDConn) error
var tlsRegistry []func(conn net.Conn) (loaded bool, tlsReadRecord func() error, tlsHandlePostHandshakeMessage func() error)
//go:linkname tlsHandlePostHandshakeMessage crypto/tls.(*Conn).handlePostHandshakeMessage
func tlsHandlePostHandshakeMessage(c *tls.STDConn) error
func init() {
tlsRegistry = append(tlsRegistry, func(conn net.Conn) (loaded bool, tlsReadRecord func() error, tlsHandlePostHandshakeMessage func() error) {
tlsConn, loaded := conn.(*tls.STDConn)
if !loaded {
return
}
return true, func() error {
return stdTLSReadRecord(tlsConn)
}, func() error {
return stdTLSHandlePostHandshakeMessage(tlsConn)
}
})
}
//go:linkname stdTLSReadRecord crypto/tls.(*Conn).readRecord
func stdTLSReadRecord(c *tls.STDConn) error
//go:linkname stdTLSHandlePostHandshakeMessage crypto/tls.(*Conn).handlePostHandshakeMessage
func stdTLSHandlePostHandshakeMessage(c *tls.STDConn) error

View File

@@ -0,0 +1,31 @@
//go:build go1.21 && !without_badtls && with_ech
package badtls
import (
"net"
_ "unsafe"
"github.com/sagernet/cloudflare-tls"
"github.com/sagernet/sing/common"
)
func init() {
tlsRegistry = append(tlsRegistry, func(conn net.Conn) (loaded bool, tlsReadRecord func() error, tlsHandlePostHandshakeMessage func() error) {
tlsConn, loaded := common.Cast[*tls.Conn](conn)
if !loaded {
return
}
return true, func() error {
return echReadRecord(tlsConn)
}, func() error {
return echHandlePostHandshakeMessage(tlsConn)
}
})
}
//go:linkname echReadRecord github.com/sagernet/cloudflare-tls.(*Conn).readRecord
func echReadRecord(c *tls.Conn) error
//go:linkname echHandlePostHandshakeMessage github.com/sagernet/cloudflare-tls.(*Conn).handlePostHandshakeMessage
func echHandlePostHandshakeMessage(c *tls.Conn) error

View File

@@ -0,0 +1,31 @@
//go:build go1.21 && !without_badtls && with_utls
package badtls
import (
"net"
_ "unsafe"
"github.com/sagernet/sing/common"
"github.com/sagernet/utls"
)
func init() {
tlsRegistry = append(tlsRegistry, func(conn net.Conn) (loaded bool, tlsReadRecord func() error, tlsHandlePostHandshakeMessage func() error) {
tlsConn, loaded := common.Cast[*tls.UConn](conn)
if !loaded {
return
}
return true, func() error {
return utlsReadRecord(tlsConn.Conn)
}, func() error {
return utlsHandlePostHandshakeMessage(tlsConn.Conn)
}
})
}
//go:linkname utlsReadRecord github.com/sagernet/utls.(*Conn).readRecord
func utlsReadRecord(c *tls.Conn) error
//go:linkname utlsHandlePostHandshakeMessage github.com/sagernet/utls.(*Conn).handlePostHandshakeMessage
func utlsHandlePostHandshakeMessage(c *tls.Conn) error

View File

@@ -223,7 +223,7 @@ func getExecPathFromPID(pid uint32) (string, error) {
r1, _, err := syscall.SyscallN(
procQueryFullProcessImageNameW.Addr(),
uintptr(h),
uintptr(1),
uintptr(0),
uintptr(unsafe.Pointer(&buf[0])),
uintptr(unsafe.Pointer(&size)),
)

5
constant/quic.go Normal file
View File

@@ -0,0 +1,5 @@
//go:build with_quic
package constant
const WithQUIC = true

5
constant/quic_stub.go Normal file
View File

@@ -0,0 +1,5 @@
//go:build !with_quic
package constant
const WithQUIC = false

View File

@@ -3,16 +3,15 @@ package constant
import "time"
const (
TCPTimeout = 5 * time.Second
ReadPayloadTimeout = 300 * time.Millisecond
DNSTimeout = 10 * time.Second
QUICTimeout = 30 * time.Second
STUNTimeout = 15 * time.Second
UDPTimeout = 5 * time.Minute
DefaultURLTestInterval = 3 * time.Minute
DefaultURLTestIdleTimeout = 30 * time.Minute
StartTimeout = 10 * time.Second
StopTimeout = 5 * time.Second
FatalStopTimeout = 10 * time.Second
FakeIPMetadataSaveInterval = 10 * time.Second
TCPTimeout = 5 * time.Second
ReadPayloadTimeout = 300 * time.Millisecond
DNSTimeout = 10 * time.Second
QUICTimeout = 30 * time.Second
STUNTimeout = 15 * time.Second
UDPTimeout = 5 * time.Minute
DefaultURLTestInterval = 3 * time.Minute
DefaultURLTestIdleTimeout = 30 * time.Minute
DefaultStartTimeout = 10 * time.Second
DefaultStopTimeout = 5 * time.Second
DefaultStopFatalTimeout = 10 * time.Second
)

View File

@@ -2,39 +2,40 @@
icon: material/alert-decagram
---
#### 1.8.12
#### 1.9.0-alpha.2
* Now we have official APT and DNF repositories **1**
* Fix packet MTU for QUIC protocols
* Add support for `client-subnet` DNS options **1**
* Fixes and improvements
**1**:
Including stable and beta versions, see https://sing-box.sagernet.org/installation/package-manager/
See [DNS](/configuration/dns), [DNS Server](/configuration/dns/server) and [DNS Rules](/configuration/dns/rule).
#### 1.8.11
Since this feature makes the scenario mentioned in `alpha.1` no longer leak DNS requests,
the [Client example](/manual/proxy/client#traffic-bypass-usage-for-chinese-users) has been updated.
* Fixes and improvements
#### 1.9.0-alpha.1
#### 1.8.10
* `domain_suffix` behavior update **1**
* `process_path` format update on Windows **2**
* Add address filter DNS rule items **3**
* Fixes and improvements
**1**:
#### 1.8.9
See [Migration](/migration/#domain_suffix-behavior-update).
* Fixes and improvements
**2**:
#### 1.8.8
See [Migration](/migration/#process_path-format-update-on-windows).
* Fixes and improvements
**3**:
#### 1.8.7
The new DNS feature allows you to more precisely bypass Chinese websites via **DNS leaks**. Do not use plain local DNS
if using this method.
* Fixes and improvements
See [Address Filter Fields](/configuration/dns/rule#address-filter-fields).
#### 1.8.6
* Fixes and improvements
[Client example](/manual/proxy/client#traffic-bypass-usage-for-chinese-users) updated.
#### 1.8.5

View File

@@ -16,7 +16,6 @@ platform-specific function implementation, such as TUN transparent proxy impleme
* [Play Store](https://play.google.com/store/apps/details?id=io.nekohasekai.sfa)
* [Play Store (Beta)](https://play.google.com/apps/testing/io.nekohasekai.sfa)
* [GitHub Releases](https://github.com/SagerNet/sing-box/releases)
* [F-Droid](https://f-droid.org/packages/io.nekohasekai.sfa/) (Unified signature via reproducible builds)
## :material-source-repository: Source code

View File

@@ -6,9 +6,3 @@ icon: material/security
sing-box and official graphics clients do not collect or share personal data,
and the data generated by the software is always on your device.
## Android
If your configuration contains `wifi_ssid` or `wifi_bssid` routing rules,
sing-box uses the location permission in the background
to get information about the connected Wi-Fi network to make them work.

View File

@@ -1,3 +1,11 @@
---
icon: material/new-box
---
!!! quote "Changes in sing-box 1.9.0"
:material-plus: [client_subnet](#client_subnet)
# DNS
### Structure
@@ -13,6 +21,7 @@
"disable_expire": false,
"independent_cache": false,
"reverse_mapping": false,
"client_subnet": "",
"fakeip": {}
}
}
@@ -21,8 +30,8 @@
### Fields
| Key | Format |
|----------|--------------------------------|
| Key | Format |
|----------|---------------------------------|
| `server` | List of [DNS Server](./server/) |
| `rules` | List of [DNS Rule](./rule/) |
| `fakeip` | [FakeIP](./fakeip/) |
@@ -60,6 +69,10 @@ Stores a reverse mapping of IP addresses after responding to a DNS query in orde
Since this process relies on the act of resolving domain names by an application before making a request, it can be
problematic in environments such as macOS, where DNS is proxied and cached by the system.
#### fakeip
#### client_subnet
[FakeIP](./fakeip/) settings.
!!! question "Since sing-box 1.9.0"
Append a `edns0-subnet` OPT extra record with the specified IP address to every query by default.
Can be overrides by `servers.[].client_subnet` or `rules.[].client_subnet`.

View File

@@ -1,3 +1,11 @@
---
icon: material/new-box
---
!!! quote "sing-box 1.9.0 中的更改"
:material-plus: [client_subnet](#client_subnet)
# DNS
### 结构
@@ -13,6 +21,7 @@
"disable_expire": false,
"independent_cache": false,
"reverse_mapping": false,
"client_subnet": "",
"fakeip": {}
}
}
@@ -58,6 +67,14 @@
由于此过程依赖于应用程序在发出请求之前解析域名的行为,因此在 macOS 等 DNS 由系统代理和缓存的环境中可能会出现问题。
#### client_subnet
!!! question "自 sing-box 1.9.0 起"
默认情况下,将带有指定 IP 地址的 `edns0-subnet` OPT 附加记录附加到每个查询。
可以被 `servers.[].client_subnet``rules.[].client_subnet` 覆盖。
#### fakeip
[FakeIP](./fakeip/) 设置。

View File

@@ -1,7 +1,14 @@
---
icon: material/alert-decagram
icon: material/new-box
---
!!! quote "Changes in sing-box 1.9.0"
:material-plus: [geoip](#geoip)
:material-plus: [ip_cidr](#ip_cidr)
:material-plus: [ip_is_private](#ip_is_private)
:material-plus: [client_subnet](#client_subnet)
!!! quote "Changes in sing-box 1.8.0"
:material-plus: [rule_set](#rule_set)
@@ -53,11 +60,19 @@ icon: material/alert-decagram
"source_geoip": [
"private"
],
"geoip": [
"cn"
],
"source_ip_cidr": [
"10.0.0.0/24",
"192.168.0.1"
],
"source_ip_is_private": false,
"ip_cidr": [
"10.0.0.0/24",
"192.168.0.1"
],
"ip_is_private": false,
"source_port": [
12345
],
@@ -107,7 +122,8 @@ icon: material/alert-decagram
],
"server": "local",
"disable_cache": false,
"rewrite_ttl": 100
"rewrite_ttl": 100,
"client_subnet": "127.0.0.1"
},
{
"type": "logical",
@@ -115,7 +131,8 @@ icon: material/alert-decagram
"rules": [],
"server": "local",
"disable_cache": false,
"rewrite_ttl": 100
"rewrite_ttl": 100,
"client_subnet": "127.0.0.1"
}
]
}
@@ -266,8 +283,6 @@ Match Clash mode.
#### wifi_ssid
<!-- md:version 1.7.0-beta.4 -->
!!! quote ""
Only supported in graphical clients on Android and iOS.
@@ -312,6 +327,40 @@ Disable cache and save cache in this query.
Rewrite TTL in DNS responses.
#### client_subnet
!!! question "Since sing-box 1.9.0"
Append a `edns0-subnet` OPT extra record with the specified IP address to every query by default.
Will overrides `dns.client_subnet` and `servers.[].client_subnet`.
### Address Filter Fields
Only takes effect for IP address requests. When the query results do not match the address filtering rule items, the current rule will be skipped.
!!! note ""
`ip_cidr` items in included rule sets also takes effect as an address filtering field.
#### geoip
!!! question "Since sing-box 1.9.0"
Match GeoIP with query response.
#### ip_cidr
!!! question "Since sing-box 1.9.0"
Match IP CIDR with query response.
#### ip_is_private
!!! question "Since sing-box 1.9.0"
Match private IP with query response.
### Logical Fields
#### type

View File

@@ -1,7 +1,14 @@
---
icon: material/alert-decagram
icon: material/new-box
---
!!! quote "sing-box 1.9.0 中的更改"
:material-plus: [geoip](#geoip)
:material-plus: [ip_cidr](#ip_cidr)
:material-plus: [ip_is_private](#ip_is_private)
:material-plus: [client_subnet](#client_subnet)
!!! quote "sing-box 1.8.0 中的更改"
:material-plus: [rule_set](#rule_set)
@@ -53,10 +60,19 @@ icon: material/alert-decagram
"source_geoip": [
"private"
],
"geoip": [
"cn"
],
"source_ip_cidr": [
"10.0.0.0/24"
"10.0.0.0/24",
"192.168.0.1"
],
"source_ip_is_private": false,
"ip_cidr": [
"10.0.0.0/24",
"192.168.0.1"
],
"ip_is_private": false,
"source_port": [
12345
],
@@ -105,14 +121,16 @@ icon: material/alert-decagram
"direct"
],
"server": "local",
"disable_cache": false
"disable_cache": false,
"client_subnet": "127.0.0.1"
},
{
"type": "logical",
"mode": "and",
"rules": [],
"server": "local",
"disable_cache": false
"disable_cache": false,
"client_subnet": "127.0.0.1"
}
]
}
@@ -307,6 +325,40 @@ DNS 查询类型。值可以为整数或者类型名称字符串。
重写 DNS 回应中的 TTL。
#### client_subnet
!!! question "自 sing-box 1.9.0 起"
默认情况下,将带有指定 IP 地址的 `edns0-subnet` OPT 附加记录附加到每个查询。
将覆盖 `dns.client_subnet``servers.[].client_subnet`
### 地址筛选字段
仅对IP地址请求生效。 当查询结果与地址筛选规则项不匹配时,将跳过当前规则。
!!! note ""
引用的规则集中的 `ip_cidr` 项也作为地址筛选字段生效。
#### geoip
!!! question "自 sing-box 1.8.0 起"
与查询响应匹配 GeoIP。
#### ip_cidr
!!! question "自 sing-box 1.8.0 起"
与查询相应匹配 IP CIDR。
#### ip_is_private
!!! question "自 sing-box 1.8.0 起"
与查询响应匹配非公开 IP。
### 逻辑字段
#### type

View File

@@ -1,3 +1,11 @@
---
icon: material/new-box
---
!!! quote "Changes in sing-box 1.9.0"
:material-plus: [client_subnet](#client_subnet)
### Structure
```json
@@ -5,17 +13,17 @@
"dns": {
"servers": [
{
"tag": "google",
"address": "tls://dns.google",
"address_resolver": "local",
"address_strategy": "prefer_ipv4",
"strategy": "ipv4_only",
"detour": "direct"
"tag": "",
"address": "",
"address_resolver": "",
"address_strategy": "",
"strategy": "",
"detour": "",
"client_subnet": ""
}
]
}
}
```
### Fields
@@ -80,10 +88,20 @@ Default domain strategy for resolving the domain names.
One of `prefer_ipv4` `prefer_ipv6` `ipv4_only` `ipv6_only`.
Take no effect if override by other settings.
Take no effect if overridden by other settings.
#### detour
Tag of an outbound for connecting to the dns server.
Default outbound will be used if empty.
#### client_subnet
!!! question "Since sing-box 1.9.0"
Append a `edns0-subnet` OPT extra record with the specified IP address to every query by default.
Can be overrides by `rules.[].client_subnet`.
Will overrides `dns.client_subnet`.

View File

@@ -1,3 +1,11 @@
---
icon: material/new-box
---
!!! quote "sing-box 1.9.0 中的更改"
:material-plus: [client_subnet](#client_subnet)
### 结构
```json
@@ -5,17 +13,17 @@
"dns": {
"servers": [
{
"tag": "google",
"address": "tls://dns.google",
"address_resolver": "local",
"address_strategy": "prefer_ipv4",
"strategy": "ipv4_only",
"detour": "direct"
"tag": "",
"address": "",
"address_resolver": "",
"address_strategy": "",
"strategy": "",
"detour": "",
"client_subnet": ""
}
]
}
}
```
### 字段
@@ -87,3 +95,13 @@ DNS 服务器的地址。
用于连接到 DNS 服务器的出站的标签。
如果为空,将使用默认出站。
#### client_subnet
!!! question "自 sing-box 1.9.0 起"
默认情况下,将带有指定 IP 地址的 `edns0-subnet` OPT 附加记录附加到每个查询。
可以被 `rules.[].client_subnet` 覆盖。
将覆盖 `dns.client_subnet`

View File

@@ -1,7 +1,3 @@
---
icon: material/new-box
---
!!! question "Since sing-box 1.8.0"
### Structure

View File

@@ -1,7 +1,3 @@
---
icon: material/new-box
---
!!! question "自 sing-box 1.8.0 起"
### 结构

View File

@@ -1,7 +1,3 @@
---
icon: material/alert-decagram
---
!!! quote "Changes in sing-box 1.8.0"
:material-delete-alert: [store_mode](#store_mode)

View File

@@ -1,7 +1,3 @@
---
icon: material/alert-decagram
---
!!! quote "sing-box 1.8.0 中的更改"
:material-delete-alert: [store_mode](#store_mode)

View File

@@ -1,7 +1,3 @@
---
icon: material/alert-decagram
---
# Experimental
!!! quote "Changes in sing-box 1.8.0"

View File

@@ -1,7 +1,3 @@
---
icon: material/alert-decagram
---
# 实验性
!!! quote "sing-box 1.8.0 中的更改"

View File

@@ -1,7 +1,3 @@
---
icon: material/alert-decagram
---
!!! quote "Changes in sing-box 1.8.0"
:material-plus: [gso](#gso)

View File

@@ -1,7 +1,3 @@
---
icon: material/alert-decagram
---
!!! quote "sing-box 1.8.0 中的更改"
:material-plus: [gso](#gso)

View File

@@ -1,7 +1,3 @@
---
icon: material/new-box
---
!!! quote "Changes in sing-box 1.8.0"
:material-plus: [gso](#gso)

View File

@@ -1,7 +1,3 @@
---
icon: material/new-box
---
!!! quote "sing-box 1.8.0 中的更改"
:material-plus: [gso](#gso)

View File

@@ -1,7 +1,3 @@
---
icon: material/alert-decagram
---
# Route
!!! quote "Changes in sing-box 1.8.0"

View File

@@ -1,7 +1,3 @@
---
icon: material/alert-decagram
---
# 路由
!!! quote "sing-box 1.8.0 中的更改"

View File

@@ -1,7 +1,3 @@
---
icon: material/alert-decagram
---
!!! quote "Changes in sing-box 1.8.0"
:material-plus: [rule_set](#rule_set)

View File

@@ -1,7 +1,3 @@
---
icon: material/alert-decagram
---
!!! quote "sing-box 1.8.0 中的更改"
:material-plus: [rule_set](#rule_set)

View File

@@ -1,7 +1,3 @@
---
icon: material/new-box
---
### Structure
!!! question "Since sing-box 1.8.0"

View File

@@ -1,7 +1,3 @@
---
icon: material/new-box
---
# Rule Set
!!! question "Since sing-box 1.8.0"

View File

@@ -1,7 +1,3 @@
---
icon: material/new-box
---
# Source Format
!!! question "Since sing-box 1.8.0"

View File

@@ -1,8 +1,3 @@
---
icon: material/alert-decagram
---
!!! quote "Changes in sing-box 1.8.0"
:material-alert-decagram: [utls](#utls)

View File

@@ -1,7 +1,3 @@
---
icon: material/alert-decagram
---
!!! quote "sing-box 1.8.0 中的更改"
:material-alert-decagram: [utls](#utls)

View File

@@ -32,6 +32,8 @@ suffers from a number of problems, including lack of maintenance, inaccurate rul
sing-box 1.8.0 introduces [Rule Set](/configuration/rule-set/), which can completely replace Geosite,
check [Migration](/migration/#migrate-geosite-to-rule-sets).
Geosite即由 V2Ray 维护的 domain-list-community 项目,作为早期流量绕过解决方案,存在着大量问题,包括缺少维护、规则不准确、管理困难。
## 1.6.0
The following features will be marked deprecated in 1.5.0 and removed entirely in 1.6.0.

View File

@@ -23,8 +23,7 @@ Since sing-box 1.5.0:
Since sing-box 1.8.0:
* Go 1.18.5 - ~
* Go 1.20.0 - ~ with tag `with_quic`, or `with_utls` enabled
* Go 1.21.0 - ~ with tag `with_ech` enabled
* Go 1.20.0 - ~ with tag `with_quic`, `with_ech`, or `with_utls` enabled
You can download and install Go from: https://go.dev/doc/install, latest version is recommended.

View File

@@ -23,8 +23,7 @@ sing-box 1.4.0 前:
从 sing-box 1.8.0:
* Go 1.18.5 - ~
* Go 1.20.0 - ~ 如果启用构建标记 `with_quic``with_utls`
* Go 1.20.1 - ~ 如果启用构建标记 `with_ech`
* Go 1.20.0 - ~ 如果启用构建标记 `with_quic``with_ech``with_utls`
您可以从 https://go.dev/doc/install 下载并安装 Go推荐使用最新版本。

View File

@@ -4,35 +4,6 @@ icon: material/package
# Package Manager
## :material-tram: Repository Installation
=== ":material-debian: Debian / APT"
```bash
sudo curl -fsSL https://sing-box.app/gpg.key -o /etc/apt/keyrings/sagernet.asc
sudo chmod a+r /etc/apt/keyrings/sagernet.asc
echo "deb [arch=`dpkg --print-architecture` signed-by=/etc/apt/keyrings/sagernet.asc] https://deb.sagernet.org/ * *" | \
sudo tee /etc/apt/sources.list.d/sagernet.list > /dev/null
sudo apt-get update
sudo apt-get install sing-box # or sing-box-beta
```
=== ":material-redhat: Redhat / DNF"
```bash
sudo dnf -y install dnf-plugins-core
sudo dnf config-manager --add-repo https://sing-box.app/sing-box.repo
sudo dnf install sing-box # or sing-box-beta
```
=== ":material-redhat: CentOS / YUM"
```bash
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://sing-box.app/sing-box.repo
sudo yum install sing-box # or sing-box-beta
```
## :material-download-box: Manual Installation
=== ":material-debian: Debian / DEB"

View File

@@ -4,35 +4,6 @@ icon: material/package
# 包管理器
## :material-tram: 仓库安装
=== ":material-debian: Debian / APT"
```bash
sudo curl -fsSL https://sing-box.app/gpg.key -o /etc/apt/keyrings/sagernet.asc
sudo chmod a+r /etc/apt/keyrings/sagernet.asc
echo "deb [arch=`dpkg --print-architecture` signed-by=/etc/apt/keyrings/sagernet.asc] https://deb.sagernet.org/ * *" | \
sudo tee /etc/apt/sources.list.d/sagernet.list > /dev/null
sudo apt-get update
sudo apt-get install sing-box # or sing-box-beta
```
=== ":material-redhat: Redhat / DNF"
```bash
sudo dnf -y install dnf-plugins-core
sudo dnf config-manager --add-repo https://sing-box.app/sing-box.repo
sudo dnf install sing-box # or sing-box-beta
```
=== ":material-redhat: CentOS / YUM"
```bash
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://sing-box.app/sing-box.repo
sudo yum install sing-box # or sing-box-beta
```
## :material-download-box: 手动安装
=== ":material-debian: Debian / DEB"

View File

@@ -1,8 +0,0 @@
[sing-box]
name=sing-box
baseurl=https://rpm.sagernet.org/
metalink=https://sing-box.app/sing-box.repo
enabled=1
repo_gpgcheck=1
gpgcheck=1
gpgkey=https://sing-box.app/gpg.key

View File

@@ -290,52 +290,6 @@ flowchart TB
=== ":material-dns: DNS rules"
!!! info
DNS rules are optional if FakeIP is used.
```json
{
"dns": {
"servers": [
{
"tag": "google",
"address": "tls://8.8.8.8"
},
{
"tag": "local",
"address": "223.5.5.5",
"detour": "direct"
}
],
"rules": [
{
"outbound": "any",
"server": "local"
},
{
"clash_mode": "Direct",
"server": "local"
},
{
"clash_mode": "Global",
"server": "google"
},
{
"geosite": "geolocation-cn",
"server": "local"
}
]
}
}
```
=== ":material-dns: DNS rules (1.8.0+)"
!!! info
DNS rules are optional if FakeIP is used.
```json
{
"dns": {
@@ -382,74 +336,144 @@ flowchart TB
}
```
=== ":material-router-network: Route rules"
=== ":material-dns: DNS rules (1.9.0+)"
```json
{
"outbounds": [
=== ":material-shield-off: With DNS Leaks"
```json
{
"type": "direct",
"tag": "direct"
},
{
"type": "block",
"tag": "block"
}
],
"route": {
"rules": [
{
"type": "logical",
"mode": "or",
"rules": [
"dns": {
"servers": [
{
"protocol": "dns"
"tag": "google",
"address": "tls://8.8.8.8"
},
{
"port": 53
"tag": "local",
"address": "https://223.5.5.5/dns-query",
"detour": "direct"
}
],
"outbound": "dns"
},
{
"geoip": "private",
"outbound": "direct"
},
{
"clash_mode": "Direct",
"outbound": "direct"
},
{
"clash_mode": "Global",
"outbound": "default"
},
{
"type": "logical",
"mode": "or",
"rules": [
{
"port": 853
"outbound": "any",
"server": "local"
},
{
"network": "udp",
"port": 443
"clash_mode": "Direct",
"server": "local"
},
{
"protocol": "stun"
"clash_mode": "Global",
"server": "google"
},
{
"rule_set": "geosite-geolocation-cn",
"server": "local"
},
{
"clash_mode": "Default",
"server": "google"
},
{
"rule_set": "geoip-cn",
"server": "local"
}
],
"outbound": "block"
]
},
{
"geosite": "geolocation-cn",
"outbound": "direct"
"route": {
"rule_set": [
{
"type": "remote",
"tag": "geosite-geolocation-cn",
"format": "binary",
"url": "https://raw.githubusercontent.com/SagerNet/sing-geosite/rule-set/geosite-geolocation-cn.srs"
},
{
"type": "remote",
"tag": "geoip-cn",
"format": "binary",
"url": "https://raw.githubusercontent.com/SagerNet/sing-geoip/rule-set/geoip-cn.srs"
}
]
},
"experimental": {
"clash_api": {
"default_mode": "Leak"
}
}
]
}
}
```
}
```
=== ":material-router-network: Route rules (1.8.0+)"
=== ":material-security: Without DNS Leaks (1.9.0-alpha.2+)"
```json
{
"dns": {
"servers": [
{
"tag": "google",
"address": "tls://8.8.8.8"
},
{
"tag": "local",
"address": "https://223.5.5.5/dns-query",
"detour": "direct"
}
],
"rules": [
{
"outbound": "any",
"server": "local"
},
{
"clash_mode": "Direct",
"server": "local"
},
{
"clash_mode": "Global",
"server": "google"
},
{
"rule_set": "geosite-geolocation-cn",
"server": "local"
},
{
"clash_mode": "Default",
"server": "google"
},
{
"rule_set": "geoip-cn",
"server": "google",
"client_subnet": "114.114.114.114" // Any China client IP address
}
]
},
"route": {
"rule_set": [
{
"type": "remote",
"tag": "geosite-geolocation-cn",
"format": "binary",
"url": "https://raw.githubusercontent.com/SagerNet/sing-geosite/rule-set/geosite-geolocation-cn.srs"
},
{
"type": "remote",
"tag": "geoip-cn",
"format": "binary",
"url": "https://raw.githubusercontent.com/SagerNet/sing-geoip/rule-set/geoip-cn.srs"
}
]
},
"experimental": {
"clash_api": {
"default_mode": "Leak"
}
}
}
```
=== ":material-router-network: Route rules"
```json
{

View File

@@ -2,6 +2,28 @@
icon: material/arrange-bring-forward
---
## 1.9.0
!!! warning "Unstable"
This version is still under development, and the following migration guide may be changed in the future.
### `domain_suffix` behavior update
For historical reasons, sing-box's `domain_suffix` rule matches literal prefixes instead of the same as other projects.
sing-box 1.9.0 modifies the behavior of `domain_suffix`: If the rule value is prefixed with `.`,
the behavior is unchanged, otherwise it matches `(domain|.+\.domain)` instead.
### `process_path` format update on Windows
The `process_path` rule of sing-box is inherited from Clash,
the original code uses the local system's path format (e.g. `\Device\HarddiskVolume1\folder\program.exe`),
but when the device has multiple disks, the HarddiskVolume serial number is not stable.
sing-box 1.9.0 make QueryFullProcessImageNameW output a Win32 path (such as `C:\folder\program.exe`),
which will disrupt the existing `process_path` use cases in Windows.
## 1.8.0
### :material-close-box: Migrate cache file from Clash API to independent options

View File

@@ -2,6 +2,27 @@
icon: material/arrange-bring-forward
---
## 1.9.0
!!! warning "不稳定的"
该版本仍在开发中,迁移指南可能将在未来更改。
### `domain_suffix` 行为更新
由于历史原因sing-box 的 `domain_suffix` 规则匹配字面前缀,而不与其他项目相同。
sing-box 1.9.0 修改了 `domain_suffix` 的行为:如果规则值以 `.` 为前缀则行为不变,否则改为匹配 `(domain|.+\.domain)`
### 对 Windows 上 `process_path` 格式的更新
sing-box 的 `process_path` 规则继承自Clash
原始代码使用本地系统的路径格式(例如 `\Device\HarddiskVolume1\folder\program.exe`
但是当设备有多个硬盘时,该 HarddiskVolume 系列号并不稳定。
sing-box 1.9.0 使 QueryFullProcessImageNameW 输出 Win32 路径(如 `C:\folder\program.exe`
这将会破坏现有的 Windows `process_path` 用例。
## 1.8.0
### :material-close-box: 将缓存文件从 Clash API 迁移到独立选项

View File

@@ -7,7 +7,6 @@ import (
"github.com/sagernet/bbolt"
"github.com/sagernet/sing-box/adapter"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing/common/logger"
M "github.com/sagernet/sing/common/metadata"
)
@@ -59,13 +58,12 @@ func (c *CacheFile) FakeIPSaveMetadata(metadata *adapter.FakeIPMetadata) error {
}
func (c *CacheFile) FakeIPSaveMetadataAsync(metadata *adapter.FakeIPMetadata) {
if c.saveMetadataTimer == nil {
c.saveMetadataTimer = time.AfterFunc(C.FakeIPMetadataSaveInterval, func() {
_ = c.FakeIPSaveMetadata(metadata)
})
} else {
c.saveMetadataTimer.Reset(C.FakeIPMetadataSaveInterval)
if timer := c.saveMetadataTimer; timer != nil {
timer.Stop()
}
c.saveMetadataTimer = time.AfterFunc(10*time.Second, func() {
_ = c.FakeIPSaveMetadata(metadata)
})
}
func (c *CacheFile) FakeIPStore(address netip.Addr, domain string) error {

View File

@@ -3,6 +3,7 @@ package experimental
import (
"context"
"os"
"sort"
"github.com/sagernet/sing-box/adapter"
C "github.com/sagernet/sing-box/constant"
@@ -27,11 +28,26 @@ func NewClashServer(ctx context.Context, router adapter.Router, logFactory log.O
}
func CalculateClashModeList(options option.Options) []string {
var clashMode []string
clashMode = append(clashMode, extraClashModeFromRule(common.PtrValueOrDefault(options.Route).Rules)...)
clashMode = append(clashMode, extraClashModeFromDNSRule(common.PtrValueOrDefault(options.DNS).Rules)...)
clashMode = common.FilterNotDefault(common.Uniq(clashMode))
return clashMode
var clashModes []string
clashModes = append(clashModes, extraClashModeFromRule(common.PtrValueOrDefault(options.Route).Rules)...)
clashModes = append(clashModes, extraClashModeFromDNSRule(common.PtrValueOrDefault(options.DNS).Rules)...)
clashModes = common.FilterNotDefault(common.Uniq(clashModes))
predefinedOrder := []string{
"Rule", "Global", "Direct",
}
var newClashModes []string
for _, mode := range clashModes {
if !common.Contains(predefinedOrder, mode) {
newClashModes = append(newClashModes, mode)
}
}
sort.Strings(newClashModes)
for _, mode := range predefinedOrder {
if common.Contains(clashModes, mode) {
newClashModes = append(newClashModes, mode)
}
}
return newClashModes
}
func extraClashModeFromRule(rules []option.Rule) []string {

View File

@@ -4,7 +4,6 @@ const (
CommandLog int32 = iota
CommandStatus
CommandServiceReload
CommandServiceClose
CommandCloseConnections
CommandGroup
CommandSelectOutbound

View File

@@ -30,6 +30,7 @@ func (c *CommandClient) SetClashMode(newMode string) error {
}
func (s *CommandServer) handleSetClashMode(conn net.Conn) error {
defer conn.Close()
newMode, err := rw.ReadVString(conn)
if err != nil {
return err
@@ -60,6 +61,7 @@ func (c *CommandClient) handleModeConn(conn net.Conn) {
}
func (s *CommandServer) handleModeConn(conn net.Conn) error {
defer conn.Close()
ctx := connKeepAlive(conn)
for s.service == nil {
select {
@@ -71,6 +73,7 @@ func (s *CommandServer) handleModeConn(conn net.Conn) error {
}
clashServer := s.service.instance.Router().ClashServer()
if clashServer == nil {
defer conn.Close()
return binary.Write(conn, binary.BigEndian, uint16(0))
}
err := writeClashModeList(conn, clashServer)

View File

@@ -58,13 +58,7 @@ func (c *CommandClient) handleGroupConn(conn net.Conn) {
}
func (s *CommandServer) handleGroupConn(conn net.Conn) error {
var interval int64
err := binary.Read(conn, binary.BigEndian, &interval)
if err != nil {
return E.Cause(err, "read interval")
}
ticker := time.NewTicker(time.Duration(interval))
defer ticker.Stop()
defer conn.Close()
ctx := connKeepAlive(conn)
for {
service := s.service
@@ -82,7 +76,7 @@ func (s *CommandServer) handleGroupConn(conn net.Conn) error {
select {
case <-ctx.Done():
return ctx.Err()
case <-ticker.C:
case <-time.After(2 * time.Second):
}
select {
case <-ctx.Done():
@@ -280,6 +274,7 @@ func (c *CommandClient) SetGroupExpand(groupTag string, isExpand bool) error {
}
func (s *CommandServer) handleSetGroupExpand(conn net.Conn) error {
defer conn.Close()
groupTag, err := rw.ReadVString(conn)
if err != nil {
return err

View File

@@ -44,41 +44,3 @@ func (s *CommandServer) handleServiceReload(conn net.Conn) error {
}
return nil
}
func (c *CommandClient) ServiceClose() error {
conn, err := c.directConnect()
if err != nil {
return err
}
defer conn.Close()
err = binary.Write(conn, binary.BigEndian, uint8(CommandServiceClose))
if err != nil {
return err
}
var hasError bool
err = binary.Read(conn, binary.BigEndian, &hasError)
if err != nil {
return nil
}
if hasError {
errorMessage, err := rw.ReadVString(conn)
if err != nil {
return nil
}
return E.New(errorMessage)
}
return nil
}
func (s *CommandServer) handleServiceClose(conn net.Conn) error {
rErr := s.service.Close()
s.handler.PostServiceClose()
err := binary.Write(conn, binary.BigEndian, rErr != nil)
if err != nil {
return err
}
if rErr != nil {
return rw.WriteVString(conn, rErr.Error())
}
return nil
}

View File

@@ -31,6 +31,7 @@ func (c *CommandClient) SelectOutbound(groupTag string, outboundTag string) erro
}
func (s *CommandServer) handleSelectOutbound(conn net.Conn) error {
defer conn.Close()
groupTag, err := rw.ReadVString(conn)
if err != nil {
return err

View File

@@ -37,7 +37,6 @@ type CommandServer struct {
type CommandServerHandler interface {
ServiceReload() error
PostServiceClose()
GetSystemProxyStatus() *SystemProxyStatus
SetSystemProxyEnabled(isEnabled bool) error
}
@@ -59,19 +58,16 @@ func (s *CommandServer) SetService(newService *BoxService) {
if newService != nil {
service.PtrFromContext[urltest.HistoryStorage](newService.ctx).SetHook(s.urlTestUpdate)
newService.instance.Router().ClashServer().(*clashapi.Server).SetModeUpdateHook(s.modeUpdate)
s.savedLines.Init()
select {
case s.logReset <- struct{}{}:
default:
}
}
s.service = newService
s.notifyURLTestUpdate()
}
func (s *CommandServer) ResetLog() {
s.savedLines.Init()
select {
case s.logReset <- struct{}{}:
default:
}
}
func (s *CommandServer) notifyURLTestUpdate() {
select {
case s.urlTestUpdate <- struct{}{}:
@@ -156,8 +152,6 @@ func (s *CommandServer) handleConnection(conn net.Conn) error {
return s.handleStatusConn(conn)
case CommandServiceReload:
return s.handleServiceReload(conn)
case CommandServiceClose:
return s.handleServiceClose(conn)
case CommandCloseConnections:
return s.handleCloseConnections(conn)
case CommandGroup:

View File

@@ -35,6 +35,7 @@ func (c *CommandClient) GetSystemProxyStatus() (*SystemProxyStatus, error) {
}
func (s *CommandServer) handleGetSystemProxyStatus(conn net.Conn) error {
defer conn.Close()
status := s.handler.GetSystemProxyStatus()
err := binary.Write(conn, binary.BigEndian, status.Available)
if err != nil {
@@ -67,6 +68,7 @@ func (c *CommandClient) SetSystemProxyEnabled(isEnabled bool) error {
}
func (s *CommandServer) handleSetSystemProxyEnabled(conn net.Conn) error {
defer conn.Close()
var isEnabled bool
err := binary.Read(conn, binary.BigEndian, &isEnabled)
if err != nil {

View File

@@ -33,6 +33,7 @@ func (c *CommandClient) URLTest(groupTag string) error {
}
func (s *CommandServer) handleURLTest(conn net.Conn) error {
defer conn.Close()
groupTag, err := rw.ReadVString(conn)
if err != nil {
return err

View File

@@ -9,9 +9,7 @@ import (
"github.com/sagernet/sing-dns"
"github.com/sagernet/sing/common"
E "github.com/sagernet/sing/common/exceptions"
"github.com/sagernet/sing/common/logger"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
"github.com/sagernet/sing/common/task"
mDNS "github.com/miekg/dns"
@@ -25,9 +23,11 @@ type LocalDNSTransport interface {
func RegisterLocalDNSTransport(transport LocalDNSTransport) {
if transport == nil {
dns.RegisterTransport([]string{"local"}, dns.CreateLocalTransport)
dns.RegisterTransport([]string{"local"}, func(options dns.TransportOptions) (dns.Transport, error) {
return dns.NewLocalTransport(options), nil
})
} else {
dns.RegisterTransport([]string{"local"}, func(name string, ctx context.Context, logger logger.ContextLogger, dialer N.Dialer, link string) (dns.Transport, error) {
dns.RegisterTransport([]string{"local"}, func(options dns.TransportOptions) (dns.Transport, error) {
return &platformLocalDNSTransport{
iif: transport,
}, nil

View File

@@ -3,17 +3,14 @@ package libbox
import (
"context"
"net/netip"
"os"
"runtime"
runtimeDebug "runtime/debug"
"syscall"
"time"
"github.com/sagernet/sing-box"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/common/process"
"github.com/sagernet/sing-box/common/urltest"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/experimental/libbox/internal/procfs"
"github.com/sagernet/sing-box/experimental/libbox/platform"
"github.com/sagernet/sing-box/log"
@@ -75,25 +72,11 @@ func (s *BoxService) Start() error {
}
func (s *BoxService) Close() error {
done := make(chan struct{})
defer close(done)
go func() {
select {
case <-done:
return
case <-time.After(C.FatalStopTimeout):
os.Exit(1)
}
}()
s.cancel()
s.urlTestHistoryStorage.Close()
return s.instance.Close()
}
func (s *BoxService) NeedWIFIState() bool {
return s.instance.Router().NeedWIFIState()
}
var (
_ platform.Interface = (*platformInterfaceWrapper)(nil)
_ log.PlatformWriter = (*platformInterfaceWrapper)(nil)

View File

@@ -3,6 +3,8 @@ package libbox
import (
"sync"
"time"
"github.com/sagernet/sing-box/log"
)
type servicePauseFields struct {
@@ -13,28 +15,38 @@ type servicePauseFields struct {
func (s *BoxService) Pause() {
s.pauseAccess.Lock()
defer s.pauseAccess.Unlock()
if s.pauseTimer != nil {
s.pauseTimer.Stop()
log.Debug("pause() reconfigured")
}
s.pauseTimer = time.AfterFunc(time.Minute, s.pause)
}
func (s *BoxService) pause() {
s.pauseAccess.Lock()
defer s.pauseAccess.Unlock()
s.pauseManager.DevicePause()
_ = s.instance.Router().ResetNetwork()
s.pauseTimer = nil
log.Debug("pause()")
}
func (s *BoxService) Wake() {
_ = s.instance.Router().ResetNetwork()
s.pauseAccess.Lock()
defer s.pauseAccess.Unlock()
if s.pauseTimer != nil {
s.pauseTimer.Stop()
s.pauseTimer = nil
log.Debug("pause() ignored")
return
}
s.pauseManager.DeviceWake()
_ = s.instance.Router().ResetNetwork()
log.Debug("wake()")
}

View File

@@ -7,6 +7,7 @@ import (
"github.com/sagernet/sing-box/common/humanize"
C "github.com/sagernet/sing-box/constant"
_ "github.com/sagernet/sing-box/include"
)
var (

47
go.mod
View File

@@ -8,32 +8,32 @@ require (
github.com/cloudflare/circl v1.3.7
github.com/cretz/bine v0.2.0
github.com/fsnotify/fsnotify v1.7.0
github.com/go-chi/chi/v5 v5.0.12
github.com/go-chi/chi/v5 v5.0.11
github.com/go-chi/cors v1.2.1
github.com/go-chi/render v1.0.3
github.com/gofrs/uuid/v5 v5.1.0
github.com/insomniacslk/dhcp v0.0.0-20231206064809-8c70d406f6d2
github.com/gofrs/uuid/v5 v5.0.0
github.com/insomniacslk/dhcp v0.0.0-20240204152450-ca2dc33955c1
github.com/libdns/alidns v1.0.3
github.com/libdns/cloudflare v0.1.1
github.com/libdns/cloudflare v0.1.0
github.com/logrusorgru/aurora v2.0.3+incompatible
github.com/mholt/acmez v1.2.0
github.com/miekg/dns v1.1.59
github.com/miekg/dns v1.1.58
github.com/ooni/go-libtor v1.1.8
github.com/oschwald/maxminddb-golang v1.12.0
github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a
github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1
github.com/sagernet/gomobile v0.1.3
github.com/sagernet/gomobile v0.1.1
github.com/sagernet/gvisor v0.0.0-20231209105102-8d27a30e436e
github.com/sagernet/quic-go v0.40.1
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691
github.com/sagernet/sing v0.3.8
github.com/sagernet/sing-dns v0.1.14
github.com/sagernet/sing v0.3.1-0.20240105061852-782bc05c5573
github.com/sagernet/sing-dns v0.1.13-0.20240209104932-6a377c9272fb
github.com/sagernet/sing-mux v0.2.0
github.com/sagernet/sing-quic v0.1.12
github.com/sagernet/sing-quic v0.1.8
github.com/sagernet/sing-shadowsocks v0.2.6
github.com/sagernet/sing-shadowsocks2 v0.2.0
github.com/sagernet/sing-shadowtls v0.1.4
github.com/sagernet/sing-tun v0.2.6
github.com/sagernet/sing-tun v0.2.1
github.com/sagernet/sing-vmess v0.1.8
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7
github.com/sagernet/tfo-go v0.0.0-20231209031829-7b5343ac1dc6
@@ -41,15 +41,15 @@ require (
github.com/sagernet/wireguard-go v0.0.0-20231215174105-89dec3b2f3e8
github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854
github.com/spf13/cobra v1.8.0
github.com/stretchr/testify v1.9.0
go.uber.org/zap v1.27.0
github.com/stretchr/testify v1.8.4
go.uber.org/zap v1.26.0
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
golang.org/x/crypto v0.22.0
golang.org/x/net v0.24.0
golang.org/x/sys v0.19.0
golang.org/x/crypto v0.19.0
golang.org/x/net v0.21.0
golang.org/x/sys v0.17.0
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6
google.golang.org/grpc v1.63.2
google.golang.org/protobuf v1.33.0
google.golang.org/grpc v1.61.0
google.golang.org/protobuf v1.32.0
howett.net/plist v1.0.1
)
@@ -64,6 +64,7 @@ require (
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/gobwas/httphead v0.1.0 // indirect
github.com/gobwas/pool v0.2.1 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/btree v1.1.2 // indirect
github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a // indirect
github.com/hashicorp/yamux v0.1.1 // indirect
@@ -71,7 +72,7 @@ require (
github.com/josharian/native v1.1.0 // indirect
github.com/klauspost/compress v1.17.4 // indirect
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
github.com/libdns/libdns v0.2.2 // indirect
github.com/libdns/libdns v0.2.1 // indirect
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
github.com/onsi/ginkgo/v2 v2.9.7 // indirect
github.com/pierrec/lz4/v4 v4.1.14 // indirect
@@ -79,18 +80,18 @@ require (
github.com/quic-go/qpack v0.4.0 // indirect
github.com/quic-go/qtls-go1-20 v0.4.1 // indirect
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 // indirect
github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 // indirect
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect
github.com/zeebo/blake3 v0.2.3 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f // indirect
golang.org/x/mod v0.17.0 // indirect
golang.org/x/sync v0.7.0 // indirect
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect
golang.org/x/mod v0.14.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/time v0.5.0 // indirect
golang.org/x/tools v0.20.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect
golang.org/x/tools v0.17.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20231106174013-bbf56f31fb17 // indirect
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
lukechampine.com/blake3 v1.2.1 // indirect

105
go.sum
View File

@@ -19,8 +19,8 @@ github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nos
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/gaukas/godicttls v0.0.4 h1:NlRaXb3J6hAnTmWdsEKb9bcSBD6BvcIjdGdeb0zfXbk=
github.com/gaukas/godicttls v0.0.4/go.mod h1:l6EenT4TLWgTdwslVb4sEMOCf7Bv0JAK67deKr9/NCI=
github.com/go-chi/chi/v5 v5.0.12 h1:9euLV5sTrTNTRUU9POmDUvfxyj6LAABLUcEWO+JJb4s=
github.com/go-chi/chi/v5 v5.0.12/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/go-chi/chi/v5 v5.0.11 h1:BnpYbFZ3T3S1WMpD79r7R5ThWX40TaFB7L31Y8xqSwA=
github.com/go-chi/chi/v5 v5.0.11/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4=
github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
github.com/go-chi/render v1.0.3 h1:AsXqd2a1/INaIfUSKq3G5uA8weYx20FOsM7uSoCyyt4=
@@ -34,11 +34,14 @@ github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=
github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
github.com/gofrs/uuid/v5 v5.1.0 h1:S5rqVKIigghZTCBKPCw0Y+bXkn26K3TB5mvQq2Ix8dk=
github.com/gofrs/uuid/v5 v5.1.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/gofrs/uuid/v5 v5.0.0 h1:p544++a97kEL+svbcFbCQVM9KFu0Yo25UoISXGNNH9M=
github.com/gofrs/uuid/v5 v5.0.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=
github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a h1:fEBsGL/sjAuJrgah5XqmmYsTLzJp/TO9Lhy39gkverk=
github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
@@ -46,8 +49,8 @@ github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE
github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/insomniacslk/dhcp v0.0.0-20231206064809-8c70d406f6d2 h1:9K06NfxkBh25x56yVhWWlKFE8YpicaSfHwoV8SFbueA=
github.com/insomniacslk/dhcp v0.0.0-20231206064809-8c70d406f6d2/go.mod h1:3A9PQ1cunSDF/1rbTq99Ts4pVnycWg+vlPkfeD2NLFI=
github.com/insomniacslk/dhcp v0.0.0-20240204152450-ca2dc33955c1 h1:L3pm9Kf2G6gJVYawz2SrI5QnV1wzHYbqmKnSHHXJAb8=
github.com/insomniacslk/dhcp v0.0.0-20240204152450-ca2dc33955c1/go.mod h1:izxuNQZeFrbx2nK2fAyN5iNUB34Fe9j0nK4PwLzAkKw=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/josharian/native v1.0.1-0.20221213033349-c1e37c09b531/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA=
@@ -62,17 +65,17 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/libdns/alidns v1.0.3 h1:LFHuGnbseq5+HCeGa1aW8awyX/4M2psB9962fdD2+yQ=
github.com/libdns/alidns v1.0.3/go.mod h1:e18uAG6GanfRhcJj6/tps2rCMzQJaYVcGKT+ELjdjGE=
github.com/libdns/cloudflare v0.1.1 h1:FVPfWwP8zZCqj268LZjmkDleXlHPlFU9KC4OJ3yn054=
github.com/libdns/cloudflare v0.1.1/go.mod h1:9VK91idpOjg6v7/WbjkEW49bSCxj00ALesIFDhJ8PBU=
github.com/libdns/cloudflare v0.1.0 h1:93WkJaGaiXCe353LHEP36kAWCUw0YjFqwhkBkU2/iic=
github.com/libdns/cloudflare v0.1.0/go.mod h1:a44IP6J1YH6nvcNl1PverfJviADgXUnsozR3a7vBKN8=
github.com/libdns/libdns v0.2.0/go.mod h1:yQCXzk1lEZmmCPa857bnk4TsOiqYasqpyOEeSObbb40=
github.com/libdns/libdns v0.2.2 h1:O6ws7bAfRPaBsgAYt8MDe2HcNBGC29hkZ9MX2eUSX3s=
github.com/libdns/libdns v0.2.2/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ=
github.com/libdns/libdns v0.2.1 h1:Wu59T7wSHRgtA0cfxC+n1c/e+O3upJGWytknkmFEDis=
github.com/libdns/libdns v0.2.1/go.mod h1:yQCXzk1lEZmmCPa857bnk4TsOiqYasqpyOEeSObbb40=
github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8=
github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
github.com/mholt/acmez v1.2.0 h1:1hhLxSgY5FvH5HCnGUuwbKY2VQVo8IU7rxXKSnZ7F30=
github.com/mholt/acmez v1.2.0/go.mod h1:VT9YwH1xgNX1kmYY89gY8xPJC84BFAisjo8Egigt4kE=
github.com/miekg/dns v1.1.59 h1:C9EXc/UToRwKLhK5wKU/I4QVsBUc8kE6MkHBkeypWZs=
github.com/miekg/dns v1.1.59/go.mod h1:nZpewl5p6IvctfgrckopVx2OlSEHPRO/U4SYkRklrEk=
github.com/miekg/dns v1.1.58 h1:ca2Hdkz+cDg/7eNF6V56jjzuZ4aCAE+DbVkILdQWG/4=
github.com/miekg/dns v1.1.58/go.mod h1:Ypv+3b/KadlvW9vJfXOTf300O4UqaHFzFCuHz+rPkBY=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/onsi/ginkgo/v2 v2.9.7 h1:06xGQy5www2oN160RtEZoTvnP2sPhEfePYmCDc2szss=
@@ -95,8 +98,8 @@ github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a h1:+NkI2670SQpQWvkk
github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a/go.mod h1:63s7jpZqcDAIpj8oI/1v4Izok+npJOHACFCU6+huCkM=
github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1 h1:YbmpqPQEMdlk9oFSKYWRqVuu9qzNiOayIonKmv1gCXY=
github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1/go.mod h1:J2yAxTFPDjrDPhuAi9aWFz2L3ox9it4qAluBBbN0H5k=
github.com/sagernet/gomobile v0.1.3 h1:ohjIb1Ou2+1558PnZour3od69suSuvkdSVOlO1tC4B8=
github.com/sagernet/gomobile v0.1.3/go.mod h1:Pqq2+ZVvs10U7xK+UwJgwYWUykewi8H6vlslAO73n9E=
github.com/sagernet/gomobile v0.1.1 h1:3vihRGyUfFTToHMeeak0UK6/ldt2MV2bcWKFi2VyECU=
github.com/sagernet/gomobile v0.1.1/go.mod h1:Pqq2+ZVvs10U7xK+UwJgwYWUykewi8H6vlslAO73n9E=
github.com/sagernet/gvisor v0.0.0-20231209105102-8d27a30e436e h1:DOkjByVeAR56dkszjnMZke4wr7yM/1xHaJF3G9olkEE=
github.com/sagernet/gvisor v0.0.0-20231209105102-8d27a30e436e/go.mod h1:fLxq/gtp0qzkaEwywlRRiGmjOK5ES/xUzyIKIFP2Asw=
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 h1:iL5gZI3uFp0X6EslacyapiRz7LLSJyr4RajF/BhMVyE=
@@ -106,22 +109,22 @@ github.com/sagernet/quic-go v0.40.1/go.mod h1:CcKTpzTAISxrM4PA5M20/wYuz9Tj6Tx4Dw
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 h1:5Th31OC6yj8byLGkEnIYp6grlXfo1QYUfiYFGjewIdc=
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691/go.mod h1:B8lp4WkQ1PwNnrVMM6KyuFR20pU8jYBD+A4EhJovEXU=
github.com/sagernet/sing v0.2.18/go.mod h1:OL6k2F0vHmEzXz2KW19qQzu172FDgSbUSODylighuVo=
github.com/sagernet/sing v0.3.8 h1:gm4JKalPhydMYX2zFOTnnd4TXtM/16WFRqSjMepYQQk=
github.com/sagernet/sing v0.3.8/go.mod h1:+60H3Cm91RnL9dpVGWDPHt0zTQImO9Vfqt9a4rSambI=
github.com/sagernet/sing-dns v0.1.14 h1:kxE/Ik3jMXmD3sXsdt9MgrNzLFWt64mghV+MQqzyf40=
github.com/sagernet/sing-dns v0.1.14/go.mod h1:AA+vZMNovuPN5i/sPnfF6756Nq94nzb5nXodMWbta5w=
github.com/sagernet/sing v0.3.1-0.20240105061852-782bc05c5573 h1:1wGN3eNanp8r+Y3bNBys3ZnAVF5gdtDoDwtosMZEbgA=
github.com/sagernet/sing v0.3.1-0.20240105061852-782bc05c5573/go.mod h1:9pfuAH6mZfgnz/YjP6xu5sxx882rfyjpcrTdUpd6w3g=
github.com/sagernet/sing-dns v0.1.13-0.20240209104932-6a377c9272fb h1:jjlaJ9GMjTB4OoS8taQ1gh0oMBnWke72qSteaMzecPU=
github.com/sagernet/sing-dns v0.1.13-0.20240209104932-6a377c9272fb/go.mod h1:IxOqfSb6Zt6UVCy8fJpDxb2XxqzHUytNqeOuJfaiLu8=
github.com/sagernet/sing-mux v0.2.0 h1:4C+vd8HztJCWNYfufvgL49xaOoOHXty2+EAjnzN3IYo=
github.com/sagernet/sing-mux v0.2.0/go.mod h1:khzr9AOPocLa+g53dBplwNDz4gdsyx/YM3swtAhlkHQ=
github.com/sagernet/sing-quic v0.1.12 h1:4KjG7LASZck0svGDfzf3aVNidRRQRC/w2HUMk/PHiNE=
github.com/sagernet/sing-quic v0.1.12/go.mod h1:L+VtzvuPbf8VW8F4R7KiygqpXY4lO7t2wwcQuHjh8Ew=
github.com/sagernet/sing-quic v0.1.8 h1:G4iBXAKIII+uTzd55oZ/9cAQswGjlvHh/0yKMQioDS0=
github.com/sagernet/sing-quic v0.1.8/go.mod h1:2w7DZXtf4MPjIGpovA3+vpI6bvOf1n1f9cQ1E2qQJSg=
github.com/sagernet/sing-shadowsocks v0.2.6 h1:xr7ylAS/q1cQYS8oxKKajhuQcchd5VJJ4K4UZrrpp0s=
github.com/sagernet/sing-shadowsocks v0.2.6/go.mod h1:j2YZBIpWIuElPFL/5sJAj470bcn/3QQ5lxZUNKLDNAM=
github.com/sagernet/sing-shadowsocks2 v0.2.0 h1:wpZNs6wKnR7mh1wV9OHwOyUr21VkS3wKFHi+8XwgADg=
github.com/sagernet/sing-shadowsocks2 v0.2.0/go.mod h1:RnXS0lExcDAovvDeniJ4IKa2IuChrdipolPYWBv9hWQ=
github.com/sagernet/sing-shadowtls v0.1.4 h1:aTgBSJEgnumzFenPvc+kbD9/W0PywzWevnVpEx6Tw3k=
github.com/sagernet/sing-shadowtls v0.1.4/go.mod h1:F8NBgsY5YN2beQavdgdm1DPlhaKQlaL6lpDdcBglGK4=
github.com/sagernet/sing-tun v0.2.6 h1:FKXzh34uuO5RStBgf3Zi+Txan5eS9YTVOQrJRAbJBHk=
github.com/sagernet/sing-tun v0.2.6/go.mod h1:MKAAHUzVfj7d9zos4lsz6wjXu86/mJyd/gejiAnWj/w=
github.com/sagernet/sing-tun v0.2.1 h1:xZ/MkQbAX4yuOXq/s1pfhWa0lK1Ld7t4gOpSUbRl1Rs=
github.com/sagernet/sing-tun v0.2.1/go.mod h1:w1HTPPEL575m+Ob3GOIWaTs3ZrTdgLIwoldce/p3WPU=
github.com/sagernet/sing-vmess v0.1.8 h1:XVWad1RpTy9b5tPxdm5MCU8cGfrTGdR8qCq6HV2aCNc=
github.com/sagernet/sing-vmess v0.1.8/go.mod h1:vhx32UNzTDUkNwOyIjcZQohre1CaytquC5mPplId8uA=
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ=
@@ -134,6 +137,8 @@ github.com/sagernet/wireguard-go v0.0.0-20231215174105-89dec3b2f3e8 h1:R0OMYASco
github.com/sagernet/wireguard-go v0.0.0-20231215174105-89dec3b2f3e8/go.mod h1:K4J7/npM+VAMUeUmTa2JaA02JmyheP0GpRBOUvn3ecc=
github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854 h1:6uUiZcDRnZSAegryaUGwPC/Fj13JSHwiTftrXhMmYOc=
github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854/go.mod h1:LtfoSK3+NG57tvnVEHgcuBW9ujgE8enPSgzgwStwCAA=
github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9 h1:rc/CcqLH3lh8n+csdOuDfP+NuykE0U6AeYSJJHKDgSg=
github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9/go.mod h1:a/83NAfUXvEuLpmxDssAXxgUgrEy12MId3Wd7OTs76s=
github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
@@ -142,8 +147,8 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 h1:tHNk7XK9GkmKUR6Gh8gVBKXc2MVSZ4G/NnWLtzw4gNA=
github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923/go.mod h1:eLL9Nub3yfAho7qB0MzZizFhTU2QkLeoVsWdHtDW264=
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695APm9hlsSMoOoE65U4/TcqNj90mc69Rlg=
@@ -154,27 +159,26 @@ github.com/zeebo/blake3 v0.2.3 h1:TFoLXsjeXqRNFxSbk35Dk4YtszE/MQQGK10BH4ptoTg=
github.com/zeebo/blake3 v0.2.3/go.mod h1:mjJjZpnsyIVtVgTOSpJ9vmRE4wgDeyt2HU3qXvvKCaQ=
github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo=
github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M=
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f h1:99ci1mjWVBWwJiEKYY6jWa4d2nTQVIEhZIptnrVb1XY=
golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI=
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRjZPVIx+MXInMzdvQqcA=
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08=
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -184,10 +188,10 @@ golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q=
golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
@@ -195,16 +199,19 @@ golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.20.0 h1:hz/CVckiOxybQvFw6h7b/q80NTr9IUQb4s1IIzW7KNY=
golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg=
golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc=
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6 h1:CawjfCvYQH2OU3/TnxLx97WDSUDRABfT18pCOYwc2GE=
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6/go.mod h1:3rxYc4HtVcSG9gVaTs2GEBdehh+sYPOwKtyUWEOTb80=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de h1:cZGRis4/ot9uVm639a+rHCUaG0JJHEsdyzSQTMX+suY=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY=
google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM=
google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA=
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
google.golang.org/genproto/googleapis/rpc v0.0.0-20231106174013-bbf56f31fb17 h1:Jyp0Hsi0bmHXG6k9eATXoYtjd6e2UzZ1SCn/wIupY14=
google.golang.org/genproto/googleapis/rpc v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:oQ5rr10WTTMvP4A36n8JpR1OrO1BEiV4f78CneXZxkA=
google.golang.org/grpc v1.61.0 h1:TOvOcuXn30kRao+gfcvsebNEa5iZIiLkisYEkf7R7o0=
google.golang.org/grpc v1.61.0/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

View File

@@ -116,7 +116,6 @@ func NewHysteria(ctx context.Context, router adapter.Router, logger log.ContextL
func (h *Hysteria) newConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
ctx = log.ContextWithNewID(ctx)
metadata = h.createMetadata(conn, metadata)
h.logger.InfoContext(ctx, "inbound connection from ", metadata.Source)
userID, _ := auth.UserFromContext[int](ctx)
if userName := h.userNameList[userID]; userName != "" {
metadata.User = userName
@@ -130,7 +129,6 @@ func (h *Hysteria) newConnection(ctx context.Context, conn net.Conn, metadata ad
func (h *Hysteria) newPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
ctx = log.ContextWithNewID(ctx)
metadata = h.createPacketMetadata(conn, metadata)
h.logger.InfoContext(ctx, "inbound packet connection from ", metadata.Source)
userID, _ := auth.UserFromContext[int](ctx)
if userName := h.userNameList[userID]; userName != "" {
metadata.User = userName

View File

@@ -127,7 +127,6 @@ func NewHysteria2(ctx context.Context, router adapter.Router, logger log.Context
func (h *Hysteria2) newConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
ctx = log.ContextWithNewID(ctx)
metadata = h.createMetadata(conn, metadata)
h.logger.InfoContext(ctx, "inbound connection from ", metadata.Source)
userID, _ := auth.UserFromContext[int](ctx)
if userName := h.userNameList[userID]; userName != "" {
metadata.User = userName
@@ -141,7 +140,6 @@ func (h *Hysteria2) newConnection(ctx context.Context, conn net.Conn, metadata a
func (h *Hysteria2) newPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
ctx = log.ContextWithNewID(ctx)
metadata = h.createPacketMetadata(conn, metadata)
h.logger.InfoContext(ctx, "inbound packet connection from ", metadata.Source)
userID, _ := auth.UserFromContext[int](ctx)
if userName := h.userNameList[userID]; userName != "" {
metadata.User = userName

View File

@@ -15,7 +15,6 @@ import (
"github.com/sagernet/sing-box/common/tls"
"github.com/sagernet/sing-box/common/uot"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/include"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/option"
"github.com/sagernet/sing/common"
@@ -109,8 +108,8 @@ func (n *Naive) Start() error {
if common.Contains(n.network, N.NetworkUDP) {
err := n.configureHTTP3Listener()
if !include.WithQUIC && len(n.network) > 1 {
log.Warn(E.Cause(err, "naive http3 disabled"))
if !C.WithQUIC && len(n.network) > 1 {
n.logger.Warn(E.Cause(err, "naive http3 disabled"))
} else if err != nil {
return err
}

View File

@@ -98,7 +98,6 @@ func NewTUIC(ctx context.Context, router adapter.Router, logger log.ContextLogge
func (h *TUIC) newConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
ctx = log.ContextWithNewID(ctx)
metadata = h.createMetadata(conn, metadata)
h.logger.InfoContext(ctx, "inbound connection from ", metadata.Source)
userID, _ := auth.UserFromContext[int](ctx)
if userName := h.userNameList[userID]; userName != "" {
metadata.User = userName
@@ -112,7 +111,6 @@ func (h *TUIC) newConnection(ctx context.Context, conn net.Conn, metadata adapte
func (h *TUIC) newPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
ctx = log.ContextWithNewID(ctx)
metadata = h.createPacketMetadata(conn, metadata)
h.logger.InfoContext(ctx, "inbound packet connection from ", metadata.Source)
userID, _ := auth.UserFromContext[int](ctx)
if userName := h.userNameList[userID]; userName != "" {
metadata.User = userName

View File

@@ -153,7 +153,7 @@ func (t *Tun) Start() error {
tunInterface tun.Tun
err error
)
monitor := taskmonitor.New(t.logger, C.StartTimeout)
monitor := taskmonitor.New(t.logger, C.DefaultStartTimeout)
monitor.Start("open tun interface")
if t.platformInterface != nil {
tunInterface, err = t.platformInterface.OpenTun(&t.tunOptions, t.platformOptions)

View File

@@ -3,16 +3,12 @@
package include
import (
"context"
"github.com/sagernet/sing-dns"
E "github.com/sagernet/sing/common/exceptions"
"github.com/sagernet/sing/common/logger"
N "github.com/sagernet/sing/common/network"
)
func init() {
dns.RegisterTransport([]string{"dhcp"}, func(name string, ctx context.Context, logger logger.ContextLogger, dialer N.Dialer, link string) (dns.Transport, error) {
dns.RegisterTransport([]string{"dhcp"}, func(options dns.TransportOptions) (dns.Transport, error) {
return nil, E.New(`DHCP is not included in this build, rebuild with -tags with_dhcp`)
})
}

View File

@@ -1,10 +0,0 @@
//go:build with_quic
package include
import (
_ "github.com/sagernet/sing-box/transport/v2rayquic"
_ "github.com/sagernet/sing-dns/quic"
)
const WithQUIC = true

View File

@@ -16,8 +16,6 @@ import (
N "github.com/sagernet/sing/common/network"
)
const WithQUIC = false
func init() {
dns.RegisterTransport([]string{"quic", "h3"}, func(name string, ctx context.Context, logger logger.ContextLogger, dialer N.Dialer, link string) (dns.Transport, error) {
return nil, C.ErrQUICNotIncluded

21
include/tz_android.go Normal file
View File

@@ -0,0 +1,21 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// kanged from https://github.com/golang/mobile/blob/c713f31d574bb632a93f169b2cc99c9e753fef0e/app/android.go#L89
package include
// #include <time.h>
import "C"
import "time"
func init() {
var currentT C.time_t
var currentTM C.struct_tm
C.time(&currentT)
C.localtime_r(&currentT, &currentTM)
tzOffset := int(currentTM.tm_gmtoff)
tz := C.GoString(currentTM.tm_zone)
time.Local = time.FixedZone(tz, tzOffset)
}

30
include/tz_ios.go Normal file
View File

@@ -0,0 +1,30 @@
package include
/*
#cgo CFLAGS: -x objective-c
#cgo LDFLAGS: -framework Foundation
#import <Foundation/Foundation.h>
const char* getSystemTimeZone() {
NSTimeZone *timeZone = [NSTimeZone systemTimeZone];
NSString *timeZoneName = [timeZone description];
return [timeZoneName UTF8String];
}
*/
import "C"
import (
"strings"
"time"
)
func init() {
tzDescription := C.GoString(C.getSystemTimeZone())
if len(tzDescription) == 0 {
return
}
location, err := time.LoadLocation(strings.Split(tzDescription, " ")[0])
if err != nil {
return
}
time.Local = location
}

View File

@@ -133,6 +133,7 @@ nav:
- WireGuard: configuration/outbound/wireguard.md
- Hysteria: configuration/outbound/hysteria.md
- ShadowTLS: configuration/outbound/shadowtls.md
- ShadowsocksR: configuration/outbound/shadowsocksr.md
- VLESS: configuration/outbound/vless.md
- TUIC: configuration/outbound/tuic.md
- Hysteria2: configuration/outbound/hysteria2.md
@@ -235,4 +236,4 @@ plugins:
Manual: 手册
reconfigure_material: true
reconfigure_search: true
reconfigure_search: true

View File

@@ -19,6 +19,7 @@ type DNSServerOptions struct {
AddressFallbackDelay Duration `json:"address_fallback_delay,omitempty"`
Strategy DomainStrategy `json:"strategy,omitempty"`
Detour string `json:"detour,omitempty"`
ClientSubnet *ListenAddress `json:"client_subnet,omitempty"`
}
type DNSClientOptions struct {
@@ -26,6 +27,7 @@ type DNSClientOptions struct {
DisableCache bool `json:"disable_cache,omitempty"`
DisableExpire bool `json:"disable_expire,omitempty"`
IndependentCache bool `json:"independent_cache,omitempty"`
ClientSubnet *ListenAddress `json:"client_subnet,omitempty"`
}
type DNSFakeIPOptions struct {

View File

@@ -77,6 +77,9 @@ type DefaultDNSRule struct {
DomainRegex Listable[string] `json:"domain_regex,omitempty"`
Geosite Listable[string] `json:"geosite,omitempty"`
SourceGeoIP Listable[string] `json:"source_geoip,omitempty"`
GeoIP Listable[string] `json:"geoip,omitempty"`
IPCIDR Listable[string] `json:"ip_cidr,omitempty"`
IPIsPrivate bool `json:"ip_is_private,omitempty"`
SourceIPCIDR Listable[string] `json:"source_ip_cidr,omitempty"`
SourceIPIsPrivate bool `json:"source_ip_is_private,omitempty"`
SourcePort Listable[uint16] `json:"source_port,omitempty"`
@@ -97,6 +100,7 @@ type DefaultDNSRule struct {
Server string `json:"server,omitempty"`
DisableCache bool `json:"disable_cache,omitempty"`
RewriteTTL *uint32 `json:"rewrite_ttl,omitempty"`
ClientSubnet *ListenAddress `json:"client_subnet,omitempty"`
}
func (r DefaultDNSRule) IsValid() bool {
@@ -105,16 +109,18 @@ func (r DefaultDNSRule) IsValid() bool {
defaultValue.Server = r.Server
defaultValue.DisableCache = r.DisableCache
defaultValue.RewriteTTL = r.RewriteTTL
defaultValue.ClientSubnet = r.ClientSubnet
return !reflect.DeepEqual(r, defaultValue)
}
type LogicalDNSRule struct {
Mode string `json:"mode"`
Rules []DNSRule `json:"rules,omitempty"`
Invert bool `json:"invert,omitempty"`
Server string `json:"server,omitempty"`
DisableCache bool `json:"disable_cache,omitempty"`
RewriteTTL *uint32 `json:"rewrite_ttl,omitempty"`
Mode string `json:"mode"`
Rules []DNSRule `json:"rules,omitempty"`
Invert bool `json:"invert,omitempty"`
Server string `json:"server,omitempty"`
DisableCache bool `json:"disable_cache,omitempty"`
RewriteTTL *uint32 `json:"rewrite_ttl,omitempty"`
ClientSubnet *ListenAddress `json:"client_subnet,omitempty"`
}
func (r LogicalDNSRule) IsValid() bool {

View File

@@ -148,7 +148,7 @@ func (h *Direct) ListenPacket(ctx context.Context, destination M.Socksaddr) (net
if err != nil {
return nil, err
}
conn = h.loopBack.NewPacketConn(bufio.NewPacketConn(conn), destination)
conn = h.loopBack.NewPacketConn(bufio.NewPacketConn(conn))
if originDestination != destination {
conn = bufio.NewNATPacketConn(bufio.NewPacketConn(conn), destination, originDestination)
}
@@ -156,14 +156,14 @@ func (h *Direct) ListenPacket(ctx context.Context, destination M.Socksaddr) (net
}
func (h *Direct) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
if h.loopBack.CheckConn(metadata.Source.AddrPort(), M.AddrPortFromNet(conn.LocalAddr())) {
if h.loopBack.CheckConn(metadata.Source.AddrPort()) {
return E.New("reject loopback connection to ", metadata.Destination)
}
return NewConnection(ctx, h, conn, metadata)
}
func (h *Direct) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
if h.loopBack.CheckPacketConn(metadata.Source.AddrPort(), M.AddrPortFromNet(conn.LocalAddr())) {
if h.loopBack.CheckPacketConn(metadata.Source.AddrPort()) {
return E.New("reject loopback packet connection to ", metadata.Destination)
}
return NewPacketConnection(ctx, h, conn, metadata)

View File

@@ -10,83 +10,58 @@ import (
)
type loopBackDetector struct {
// router adapter.Router
connAccess sync.RWMutex
packetConnAccess sync.RWMutex
connMap map[netip.AddrPort]netip.AddrPort
packetConnMap map[uint16]uint16
connMap map[netip.AddrPort]bool
packetConnMap map[netip.AddrPort]bool
}
func newLoopBackDetector( /*router adapter.Router*/ ) *loopBackDetector {
func newLoopBackDetector() *loopBackDetector {
return &loopBackDetector{
// router: router,
connMap: make(map[netip.AddrPort]netip.AddrPort),
packetConnMap: make(map[uint16]uint16),
connMap: make(map[netip.AddrPort]bool),
packetConnMap: make(map[netip.AddrPort]bool),
}
}
func (l *loopBackDetector) NewConn(conn net.Conn) net.Conn {
source := M.AddrPortFromNet(conn.LocalAddr())
if !source.IsValid() {
connAddr := M.AddrPortFromNet(conn.LocalAddr())
if !connAddr.IsValid() {
return conn
}
if udpConn, isUDPConn := conn.(abstractUDPConn); isUDPConn {
/*if !source.Addr().IsLoopback() {
_, err := l.router.InterfaceFinder().InterfaceByAddr(source.Addr())
if err != nil {
return conn
}
}*/
if !N.IsPublicAddr(source.Addr()) {
return conn
}
l.packetConnAccess.Lock()
l.packetConnMap[source.Port()] = M.AddrPortFromNet(conn.RemoteAddr()).Port()
l.packetConnMap[connAddr] = true
l.packetConnAccess.Unlock()
return &loopBackDetectUDPWrapper{abstractUDPConn: udpConn, detector: l, connPort: source.Port()}
return &loopBackDetectUDPWrapper{abstractUDPConn: udpConn, detector: l, connAddr: connAddr}
} else {
l.connAccess.Lock()
l.connMap[source] = M.AddrPortFromNet(conn.RemoteAddr())
l.connMap[connAddr] = true
l.connAccess.Unlock()
return &loopBackDetectWrapper{Conn: conn, detector: l, connAddr: source}
return &loopBackDetectWrapper{Conn: conn, detector: l, connAddr: connAddr}
}
}
func (l *loopBackDetector) NewPacketConn(conn N.NetPacketConn, destination M.Socksaddr) N.NetPacketConn {
source := M.AddrPortFromNet(conn.LocalAddr())
if !source.IsValid() {
func (l *loopBackDetector) NewPacketConn(conn N.NetPacketConn) N.NetPacketConn {
connAddr := M.AddrPortFromNet(conn.LocalAddr())
if !connAddr.IsValid() {
return conn
}
l.packetConnAccess.Lock()
l.packetConnMap[source.Port()] = destination.AddrPort().Port()
l.packetConnMap[connAddr] = true
l.packetConnAccess.Unlock()
return &loopBackDetectPacketWrapper{NetPacketConn: conn, detector: l, connPort: source.Port()}
return &loopBackDetectPacketWrapper{NetPacketConn: conn, detector: l, connAddr: connAddr}
}
func (l *loopBackDetector) CheckConn(source netip.AddrPort, local netip.AddrPort) bool {
func (l *loopBackDetector) CheckConn(connAddr netip.AddrPort) bool {
l.connAccess.RLock()
defer l.connAccess.RUnlock()
destination, loaded := l.connMap[source]
return loaded && destination != local
return l.connMap[connAddr]
}
func (l *loopBackDetector) CheckPacketConn(source netip.AddrPort, local netip.AddrPort) bool {
if !source.IsValid() {
return false
}
/*if !source.Addr().IsLoopback() {
_, err := l.router.InterfaceFinder().InterfaceByAddr(source.Addr())
if err != nil {
return false
}
}*/
if N.IsPublicAddr(source.Addr()) {
return false
}
func (l *loopBackDetector) CheckPacketConn(connAddr netip.AddrPort) bool {
l.packetConnAccess.RLock()
defer l.packetConnAccess.RUnlock()
destinationPort, loaded := l.packetConnMap[source.Port()]
return loaded && destinationPort != local.Port()
return l.packetConnMap[connAddr]
}
type loopBackDetectWrapper struct {
@@ -120,14 +95,14 @@ func (w *loopBackDetectWrapper) Upstream() any {
type loopBackDetectPacketWrapper struct {
N.NetPacketConn
detector *loopBackDetector
connPort uint16
connAddr netip.AddrPort
closeOnce sync.Once
}
func (w *loopBackDetectPacketWrapper) Close() error {
w.closeOnce.Do(func() {
w.detector.packetConnAccess.Lock()
delete(w.detector.packetConnMap, w.connPort)
delete(w.detector.packetConnMap, w.connAddr)
w.detector.packetConnAccess.Unlock()
})
return w.NetPacketConn.Close()
@@ -153,14 +128,14 @@ type abstractUDPConn interface {
type loopBackDetectUDPWrapper struct {
abstractUDPConn
detector *loopBackDetector
connPort uint16
connAddr netip.AddrPort
closeOnce sync.Once
}
func (w *loopBackDetectUDPWrapper) Close() error {
w.closeOnce.Do(func() {
w.detector.packetConnAccess.Lock()
delete(w.detector.packetConnMap, w.connPort)
delete(w.detector.packetConnMap, w.connAddr)
w.detector.packetConnAccess.Unlock()
})
return w.abstractUDPConn.Close()

Some files were not shown because too many files have changed in this diff Show More