Compare commits
81 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0ae1afef44 | ||
|
|
a5e2a4073b | ||
|
|
b6cb3948a3 | ||
|
|
7b0f5061dc | ||
|
|
76f20482f7 | ||
|
|
e735a5bdc8 | ||
|
|
70381e93c8 | ||
|
|
07a40716e8 | ||
|
|
5fea5956db | ||
|
|
d20a389043 | ||
|
|
4a4180bde5 | ||
|
|
7ecb6daabb | ||
|
|
712bdd9ae5 | ||
|
|
a3b74591a7 | ||
|
|
2f4abc6523 | ||
|
|
965ab075d9 | ||
|
|
ed2f8b9637 | ||
|
|
0f71ce5120 | ||
|
|
f8085ab111 | ||
|
|
f61b272cbf | ||
|
|
59d437b9d2 | ||
|
|
a7338fdc2b | ||
|
|
d88860928e | ||
|
|
20a2e38f47 | ||
|
|
acd438be23 | ||
|
|
e27fb51b54 | ||
|
|
adc38b26eb | ||
|
|
7e943e743a | ||
|
|
ceffcc0ad2 | ||
|
|
fdc451f7c6 | ||
|
|
b48c471e6a | ||
|
|
4b1fabd007 | ||
|
|
2b5eb1c59e | ||
|
|
e2d3862e64 | ||
|
|
4f5e7b974d | ||
|
|
21dedddd93 | ||
|
|
e02502bec0 | ||
|
|
ba67633ee8 | ||
|
|
7fd9abe802 | ||
|
|
78a5f59202 | ||
|
|
8d0da685d2 | ||
|
|
e6644f784e | ||
|
|
2b93b74d38 | ||
|
|
dd52c26ae1 | ||
|
|
f288e3898b | ||
|
|
1bc893a73a | ||
|
|
7359fdf195 | ||
|
|
02b7041de6 | ||
|
|
96ac931b11 | ||
|
|
3077a82650 | ||
|
|
de998c5119 | ||
|
|
d32c30c4b7 | ||
|
|
4823023806 | ||
|
|
bb355d17b2 | ||
|
|
aaf30bf92b | ||
|
|
f8c400cffc | ||
|
|
3c24411e14 | ||
|
|
4a44aa3c21 | ||
|
|
8db2ae0c83 | ||
|
|
80d1aebcb7 | ||
|
|
5583e01c99 | ||
|
|
bca0b86549 | ||
|
|
8332878cdc | ||
|
|
d0ba69ad22 | ||
|
|
31b8834427 | ||
|
|
d0f7a59e9b | ||
|
|
71e7d517a8 | ||
|
|
e6885e9967 | ||
|
|
e2090923db | ||
|
|
46be319976 | ||
|
|
b27bc45cf2 | ||
|
|
3d735281f4 | ||
|
|
8760a0d94d | ||
|
|
2239b59933 | ||
|
|
425a63f59d | ||
|
|
b85725c009 | ||
|
|
17aebc56c1 | ||
|
|
f76b21b02c | ||
|
|
704545a2ec | ||
|
|
dc7b7afc06 | ||
|
|
e478d3c2dc |
6
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
6
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -65,6 +65,12 @@ body:
|
|||||||
For Apple platform clients, please check `Settings - View Service Log` for crash logs.
|
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.
|
For the Android client, please check the `/sdcard/Android/data/io.nekohasekai.sfa/files/stderr.log` file for crash logs.
|
||||||
render: shell
|
render: shell
|
||||||
|
- type: checkboxes
|
||||||
|
id: supporter
|
||||||
|
attributes:
|
||||||
|
label: Supporter
|
||||||
|
options:
|
||||||
|
- label: I am a [sponsor](https://github.com/sponsors/nekohasekai/)
|
||||||
- type: checkboxes
|
- type: checkboxes
|
||||||
attributes:
|
attributes:
|
||||||
label: Integrity requirements
|
label: Integrity requirements
|
||||||
|
|||||||
6
.github/ISSUE_TEMPLATE/bug_report_zh.yml
vendored
6
.github/ISSUE_TEMPLATE/bug_report_zh.yml
vendored
@@ -65,6 +65,12 @@ body:
|
|||||||
对于 Apple 平台图形客户端程序,请检查 `Settings - View Service Log` 以导出崩溃日志。
|
对于 Apple 平台图形客户端程序,请检查 `Settings - View Service Log` 以导出崩溃日志。
|
||||||
对于 Android 图形客户端程序,请检查 `/sdcard/Android/data/io.nekohasekai.sfa/files/stderr.log` 文件以导出崩溃日志。
|
对于 Android 图形客户端程序,请检查 `/sdcard/Android/data/io.nekohasekai.sfa/files/stderr.log` 文件以导出崩溃日志。
|
||||||
render: shell
|
render: shell
|
||||||
|
- type: checkboxes
|
||||||
|
id: supporter
|
||||||
|
attributes:
|
||||||
|
label: 支持我们
|
||||||
|
options:
|
||||||
|
- label: 我已经 [赞助](https://github.com/sponsors/nekohasekai/)
|
||||||
- type: checkboxes
|
- type: checkboxes
|
||||||
attributes:
|
attributes:
|
||||||
label: 完整性要求
|
label: 完整性要求
|
||||||
|
|||||||
14
.github/update_clients.sh
vendored
Executable file
14
.github/update_clients.sh
vendored
Executable file
@@ -0,0 +1,14 @@
|
|||||||
|
#!/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"
|
||||||
60
.github/workflows/debug.yml
vendored
60
.github/workflows/debug.yml
vendored
@@ -25,22 +25,10 @@ jobs:
|
|||||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
|
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- name: Get latest go version
|
|
||||||
id: version
|
|
||||||
run: |
|
|
||||||
echo go_version=$(curl -s https://raw.githubusercontent.com/actions/go-versions/main/versions-manifest.json | grep -oE '"version": "[0-9]{1}.[0-9]{1,}(.[0-9]{1,})?"' | head -1 | cut -d':' -f2 | sed 's/ //g; s/"//g') >> $GITHUB_OUTPUT
|
|
||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: ${{ steps.version.outputs.go_version }}
|
go-version: ^1.22
|
||||||
- name: Add cache to Go proxy
|
|
||||||
run: |
|
|
||||||
version=`git rev-parse HEAD`
|
|
||||||
mkdir build
|
|
||||||
pushd build
|
|
||||||
go mod init build
|
|
||||||
go get -v github.com/sagernet/sing-box@$version
|
|
||||||
popd
|
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
- name: Run Test
|
- name: Run Test
|
||||||
run: |
|
run: |
|
||||||
@@ -56,9 +44,9 @@ jobs:
|
|||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: 1.18.10
|
go-version: ~1.18
|
||||||
- name: Cache go module
|
- name: Cache go module
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/go/pkg/mod
|
~/go/pkg/mod
|
||||||
@@ -76,13 +64,33 @@ jobs:
|
|||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: 1.20.7
|
go-version: ~1.20
|
||||||
- name: Cache go module
|
- name: Cache go module
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/go/pkg/mod
|
~/go/pkg/mod
|
||||||
key: go118-${{ hashFiles('**/go.sum') }}
|
key: go120-${{ hashFiles('**/go.sum') }}
|
||||||
|
- name: Run Test
|
||||||
|
run: make ci_build_go120
|
||||||
|
build_go121:
|
||||||
|
name: Debug build (Go 1.21)
|
||||||
|
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.21
|
||||||
|
- name: Cache go module
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/go/pkg/mod
|
||||||
|
key: go121-${{ hashFiles('**/go.sum') }}
|
||||||
- name: Run Test
|
- name: Run Test
|
||||||
run: make ci_build
|
run: make ci_build
|
||||||
cross:
|
cross:
|
||||||
@@ -188,8 +196,7 @@ jobs:
|
|||||||
- name: freebsd-arm64
|
- name: freebsd-arm64
|
||||||
goos: freebsd
|
goos: freebsd
|
||||||
goarch: arm64
|
goarch: arm64
|
||||||
|
fail-fast: true
|
||||||
fail-fast: false
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
env:
|
env:
|
||||||
GOOS: ${{ matrix.goos }}
|
GOOS: ${{ matrix.goos }}
|
||||||
@@ -204,19 +211,10 @@ jobs:
|
|||||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
|
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- name: Get latest go version
|
|
||||||
id: version
|
|
||||||
run: |
|
|
||||||
echo go_version=$(curl -s https://raw.githubusercontent.com/actions/go-versions/main/versions-manifest.json | grep -oE '"version": "[0-9]{1}.[0-9]{1,}(.[0-9]{1,})?"' | head -1 | cut -d':' -f2 | sed 's/ //g; s/"//g') >> $GITHUB_OUTPUT
|
|
||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: ${{ steps.version.outputs.go_version }}
|
go-version: ^1.21
|
||||||
- name: Build
|
- name: Build
|
||||||
id: build
|
id: build
|
||||||
run: make
|
run: make
|
||||||
- name: Upload artifact
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: sing-box-${{ matrix.name }}
|
|
||||||
path: sing-box*
|
|
||||||
22
.github/workflows/docker.yml
vendored
22
.github/workflows/docker.yml
vendored
@@ -1,9 +1,10 @@
|
|||||||
name: Build Docker Images
|
name: Build Docker Images
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
release:
|
||||||
inputs:
|
types:
|
||||||
tag:
|
- released
|
||||||
description: "The tag version you want to build"
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -25,15 +26,6 @@ jobs:
|
|||||||
uses: docker/metadata-action@v5
|
uses: docker/metadata-action@v5
|
||||||
with:
|
with:
|
||||||
images: ghcr.io/sagernet/sing-box
|
images: ghcr.io/sagernet/sing-box
|
||||||
- name: Get tag to build
|
|
||||||
id: tag
|
|
||||||
run: |
|
|
||||||
echo "latest=ghcr.io/sagernet/sing-box:latest" >> $GITHUB_OUTPUT
|
|
||||||
if [[ -z "${{ github.event.inputs.tag }}" ]]; then
|
|
||||||
echo "versioned=ghcr.io/sagernet/sing-box:${{ github.ref_name }}" >> $GITHUB_OUTPUT
|
|
||||||
else
|
|
||||||
echo "versioned=ghcr.io/sagernet/sing-box:${{ github.event.inputs.tag }}" >> $GITHUB_OUTPUT
|
|
||||||
fi
|
|
||||||
- name: Build and release Docker images
|
- name: Build and release Docker images
|
||||||
uses: docker/build-push-action@v5
|
uses: docker/build-push-action@v5
|
||||||
with:
|
with:
|
||||||
@@ -42,6 +34,6 @@ jobs:
|
|||||||
build-args: |
|
build-args: |
|
||||||
BUILDKIT_CONTEXT_KEEP_GIT_DIR=1
|
BUILDKIT_CONTEXT_KEEP_GIT_DIR=1
|
||||||
tags: |
|
tags: |
|
||||||
${{ steps.tag.outputs.latest }}
|
ghcr.io/sagernet/sing-box:latest
|
||||||
${{ steps.tag.outputs.versioned }}
|
ghcr.io/sagernet/sing-box:${{ github.ref_name }}
|
||||||
push: true
|
push: true
|
||||||
|
|||||||
8
.github/workflows/lint.yml
vendored
8
.github/workflows/lint.yml
vendored
@@ -25,16 +25,12 @@ jobs:
|
|||||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
|
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- name: Get latest go version
|
|
||||||
id: version
|
|
||||||
run: |
|
|
||||||
echo go_version=$(curl -s https://raw.githubusercontent.com/actions/go-versions/main/versions-manifest.json | grep -oE '"version": "[0-9]{1}.[0-9]{1,}(.[0-9]{1,})?"' | head -1 | cut -d':' -f2 | sed 's/ //g; s/"//g') >> $GITHUB_OUTPUT
|
|
||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: ${{ steps.version.outputs.go_version }}
|
go-version: ^1.22
|
||||||
- name: golangci-lint
|
- name: golangci-lint
|
||||||
uses: golangci/golangci-lint-action@v3
|
uses: golangci/golangci-lint-action@v4
|
||||||
with:
|
with:
|
||||||
version: latest
|
version: latest
|
||||||
args: --timeout=30m
|
args: --timeout=30m
|
||||||
|
|||||||
37
.github/workflows/linux.yml
vendored
Normal file
37
.github/workflows/linux.yml
vendored
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
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
Normal file
6
.gitmodules
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
[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
|
||||||
87
.goreleaser.fury.yaml
Normal file
87
.goreleaser.fury.yaml
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
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 }}"
|
||||||
@@ -1,14 +1,11 @@
|
|||||||
project_name: sing-box
|
project_name: sing-box
|
||||||
builds:
|
builds:
|
||||||
- id: main
|
- &template
|
||||||
|
id: main
|
||||||
main: ./cmd/sing-box
|
main: ./cmd/sing-box
|
||||||
flags:
|
flags:
|
||||||
- -v
|
- -v
|
||||||
- -trimpath
|
- -trimpath
|
||||||
asmflags:
|
|
||||||
- all=-trimpath={{.Env.GOPATH}}
|
|
||||||
gcflags:
|
|
||||||
- all=-trimpath={{.Env.GOPATH}}
|
|
||||||
ldflags:
|
ldflags:
|
||||||
- -X github.com/sagernet/sing-box/constant.Version={{ .Version }} -s -w -buildid=
|
- -X github.com/sagernet/sing-box/constant.Version={{ .Version }} -s -w -buildid=
|
||||||
tags:
|
tags:
|
||||||
@@ -30,65 +27,35 @@ builds:
|
|||||||
- linux_arm64
|
- linux_arm64
|
||||||
- linux_arm_7
|
- linux_arm_7
|
||||||
- linux_s390x
|
- linux_s390x
|
||||||
|
- linux_riscv64
|
||||||
- windows_amd64_v1
|
- windows_amd64_v1
|
||||||
- windows_amd64_v3
|
- windows_amd64_v3
|
||||||
- windows_386
|
- windows_386
|
||||||
- windows_arm64
|
- windows_arm64
|
||||||
- darwin_amd64_v1
|
- darwin_amd64_v1
|
||||||
- darwin_amd64_v3
|
|
||||||
- darwin_arm64
|
- darwin_arm64
|
||||||
mod_timestamp: '{{ .CommitTimestamp }}'
|
mod_timestamp: '{{ .CommitTimestamp }}'
|
||||||
- id: legacy
|
- id: legacy
|
||||||
main: ./cmd/sing-box
|
<<: *template
|
||||||
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:
|
tags:
|
||||||
- with_gvisor
|
- with_gvisor
|
||||||
- with_quic
|
- with_quic
|
||||||
- with_dhcp
|
- with_dhcp
|
||||||
- with_wireguard
|
- with_wireguard
|
||||||
- with_ech
|
|
||||||
- with_utls
|
- with_utls
|
||||||
- with_reality_server
|
- with_reality_server
|
||||||
- with_acme
|
- with_acme
|
||||||
- with_clash_api
|
- with_clash_api
|
||||||
env:
|
env:
|
||||||
- CGO_ENABLED=0
|
- CGO_ENABLED=0
|
||||||
- GOROOT=/nix/store/kg6i737jjqs923jcijnm003h68c1dghj-go-1.20.11/share/go
|
- GOROOT={{ .Env.GOPATH }}/go1.20.14
|
||||||
gobinary: /nix/store/kg6i737jjqs923jcijnm003h68c1dghj-go-1.20.11/bin/go
|
gobinary: "{{ .Env.GOPATH }}/go1.20.14/bin/go"
|
||||||
targets:
|
targets:
|
||||||
- windows_amd64_v1
|
- windows_amd64_v1
|
||||||
- windows_386
|
- windows_386
|
||||||
- darwin_amd64_v1
|
- darwin_amd64_v1
|
||||||
mod_timestamp: '{{ .CommitTimestamp }}'
|
|
||||||
- id: android
|
- id: android
|
||||||
main: ./cmd/sing-box
|
<<: *template
|
||||||
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:
|
env:
|
||||||
- CGO_ENABLED=1
|
- CGO_ENABLED=1
|
||||||
overrides:
|
overrides:
|
||||||
@@ -96,8 +63,8 @@ builds:
|
|||||||
goarch: arm
|
goarch: arm
|
||||||
goarm: 7
|
goarm: 7
|
||||||
env:
|
env:
|
||||||
- CC=armv7a-linux-androideabi19-clang
|
- CC=armv7a-linux-androideabi21-clang
|
||||||
- CXX=armv7a-linux-androideabi19-clang++
|
- CXX=armv7a-linux-androideabi21-clang++
|
||||||
- goos: android
|
- goos: android
|
||||||
goarch: arm64
|
goarch: arm64
|
||||||
env:
|
env:
|
||||||
@@ -106,8 +73,8 @@ builds:
|
|||||||
- goos: android
|
- goos: android
|
||||||
goarch: 386
|
goarch: 386
|
||||||
env:
|
env:
|
||||||
- CC=i686-linux-android19-clang
|
- CC=i686-linux-android21-clang
|
||||||
- CXX=i686-linux-android19-clang++
|
- CXX=i686-linux-android21-clang++
|
||||||
- goos: android
|
- goos: android
|
||||||
goarch: amd64
|
goarch: amd64
|
||||||
goamd64: v1
|
goamd64: v1
|
||||||
@@ -119,11 +86,11 @@ builds:
|
|||||||
- android_arm64
|
- android_arm64
|
||||||
- android_386
|
- android_386
|
||||||
- android_amd64
|
- android_amd64
|
||||||
mod_timestamp: '{{ .CommitTimestamp }}'
|
|
||||||
snapshot:
|
snapshot:
|
||||||
name_template: "{{ .Version }}.{{ .ShortCommit }}"
|
name_template: "{{ .Version }}.{{ .ShortCommit }}"
|
||||||
archives:
|
archives:
|
||||||
- id: archive
|
- &template
|
||||||
|
id: archive
|
||||||
builds:
|
builds:
|
||||||
- main
|
- main
|
||||||
- android
|
- android
|
||||||
@@ -136,20 +103,16 @@ archives:
|
|||||||
- LICENSE
|
- LICENSE
|
||||||
name_template: '{{ .ProjectName }}-{{ .Version }}-{{ .Os }}-{{ .Arch }}{{ with .Arm }}v{{ . }}{{ end }}{{ with .Mips }}_{{ . }}{{ end }}{{ if not (eq .Amd64 "v1") }}{{ .Amd64 }}{{ end }}'
|
name_template: '{{ .ProjectName }}-{{ .Version }}-{{ .Os }}-{{ .Arch }}{{ with .Arm }}v{{ . }}{{ end }}{{ with .Mips }}_{{ . }}{{ end }}{{ if not (eq .Amd64 "v1") }}{{ .Amd64 }}{{ end }}'
|
||||||
- id: archive-legacy
|
- id: archive-legacy
|
||||||
|
<<: *template
|
||||||
builds:
|
builds:
|
||||||
- legacy
|
- legacy
|
||||||
format: tar.gz
|
|
||||||
format_overrides:
|
|
||||||
- goos: windows
|
|
||||||
format: zip
|
|
||||||
wrap_in_directory: true
|
|
||||||
files:
|
|
||||||
- LICENSE
|
|
||||||
name_template: '{{ .ProjectName }}-{{ .Version }}-{{ .Os }}-{{ .Arch }}-legacy'
|
name_template: '{{ .ProjectName }}-{{ .Version }}-{{ .Os }}-{{ .Arch }}-legacy'
|
||||||
nfpms:
|
nfpms:
|
||||||
- id: package
|
- id: package
|
||||||
package_name: sing-box
|
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 }}'
|
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
|
vendor: sagernet
|
||||||
homepage: https://sing-box.sagernet.org/
|
homepage: https://sing-box.sagernet.org/
|
||||||
maintainer: nekohasekai <contact-git@sekai.icu>
|
maintainer: nekohasekai <contact-git@sekai.icu>
|
||||||
@@ -165,11 +128,27 @@ nfpms:
|
|||||||
dst: /etc/sing-box/config.json
|
dst: /etc/sing-box/config.json
|
||||||
type: config
|
type: config
|
||||||
- src: release/config/sing-box.service
|
- src: release/config/sing-box.service
|
||||||
dst: /etc/systemd/system/sing-box.service
|
dst: /usr/lib/systemd/system/sing-box.service
|
||||||
- src: release/config/sing-box@.service
|
- src: release/config/sing-box@.service
|
||||||
dst: /etc/systemd/system/sing-box@.service
|
dst: /usr/lib/systemd/system/sing-box@.service
|
||||||
- src: LICENSE
|
- src: LICENSE
|
||||||
dst: /usr/share/licenses/sing-box/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:
|
source:
|
||||||
enabled: false
|
enabled: false
|
||||||
name_template: '{{ .ProjectName }}-{{ .Version }}.source'
|
name_template: '{{ .ProjectName }}-{{ .Version }}.source'
|
||||||
@@ -183,6 +162,10 @@ release:
|
|||||||
github:
|
github:
|
||||||
owner: SagerNet
|
owner: SagerNet
|
||||||
name: sing-box
|
name: sing-box
|
||||||
name_template: '{{ if .IsSnapshot }}{{ nightly }}{{ else }}{{ .Version }}{{ end }}'
|
|
||||||
draft: true
|
draft: true
|
||||||
mode: replace
|
prerelease: auto
|
||||||
|
mode: replace
|
||||||
|
ids:
|
||||||
|
- archive
|
||||||
|
- package
|
||||||
|
skip_upload: true
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM --platform=$BUILDPLATFORM golang:1.21-alpine AS builder
|
FROM --platform=$BUILDPLATFORM golang:1.22-alpine AS builder
|
||||||
LABEL maintainer="nekohasekai <contact-git@sekai.icu>"
|
LABEL maintainer="nekohasekai <contact-git@sekai.icu>"
|
||||||
COPY . /go/src/github.com/sagernet/sing-box
|
COPY . /go/src/github.com/sagernet/sing-box
|
||||||
WORKDIR /go/src/github.com/sagernet/sing-box
|
WORKDIR /go/src/github.com/sagernet/sing-box
|
||||||
|
|||||||
33
Makefile
33
Makefile
@@ -1,8 +1,9 @@
|
|||||||
NAME = sing-box
|
NAME = sing-box
|
||||||
COMMIT = $(shell git rev-parse --short HEAD)
|
COMMIT = $(shell git rev-parse --short HEAD)
|
||||||
TAGS_GO118 = with_gvisor,with_dhcp,with_wireguard,with_reality_server,with_clash_api
|
TAGS_GO118 = with_gvisor,with_dhcp,with_wireguard,with_reality_server,with_clash_api
|
||||||
TAGS_GO120 = with_quic,with_ech,with_utls
|
TAGS_GO120 = with_quic,with_utls
|
||||||
TAGS ?= $(TAGS_GO118),$(TAGS_GO120)
|
TAGS_GO121 = with_ech
|
||||||
|
TAGS ?= $(TAGS_GO118),$(TAGS_GO120),$(TAGS_GO121)
|
||||||
TAGS_TEST ?= with_gvisor,with_quic,with_wireguard,with_grpc,with_ech,with_utls,with_reality_server
|
TAGS_TEST ?= with_gvisor,with_quic,with_wireguard,with_grpc,with_ech,with_utls,with_reality_server
|
||||||
|
|
||||||
GOHOSTOS = $(shell go env GOHOSTOS)
|
GOHOSTOS = $(shell go env GOHOSTOS)
|
||||||
@@ -14,7 +15,7 @@ MAIN_PARAMS = $(PARAMS) -tags $(TAGS)
|
|||||||
MAIN = ./cmd/sing-box
|
MAIN = ./cmd/sing-box
|
||||||
PREFIX ?= $(shell go env GOPATH)
|
PREFIX ?= $(shell go env GOPATH)
|
||||||
|
|
||||||
.PHONY: test release docs
|
.PHONY: test release docs build
|
||||||
|
|
||||||
build:
|
build:
|
||||||
go build $(MAIN_PARAMS) $(MAIN)
|
go build $(MAIN_PARAMS) $(MAIN)
|
||||||
@@ -23,6 +24,10 @@ ci_build_go118:
|
|||||||
go build $(PARAMS) $(MAIN)
|
go build $(PARAMS) $(MAIN)
|
||||||
go build $(PARAMS) -tags "$(TAGS_GO118)" $(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:
|
ci_build:
|
||||||
go build $(PARAMS) $(MAIN)
|
go build $(PARAMS) $(MAIN)
|
||||||
go build $(MAIN_PARAMS) $(MAIN)
|
go build $(MAIN_PARAMS) $(MAIN)
|
||||||
@@ -59,25 +64,35 @@ proto_install:
|
|||||||
go install -v google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
|
go install -v google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
|
||||||
|
|
||||||
release:
|
release:
|
||||||
go run ./cmd/internal/build goreleaser release --clean --skip-publish || exit 1
|
go run ./cmd/internal/build goreleaser release --clean --skip publish
|
||||||
mkdir dist/release
|
mkdir dist/release
|
||||||
mv dist/*.tar.gz dist/*.zip dist/*.deb dist/*.rpm dist/*.pkg.tar.zst 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
|
||||||
ghr --replace --draft --prerelease -p 3 "v${VERSION}" dist/release
|
ghr --replace --draft --prerelease -p 3 "v${VERSION}" dist/release
|
||||||
rm -r dist/release
|
rm -r dist/release
|
||||||
|
|
||||||
|
release_repo:
|
||||||
|
go run ./cmd/internal/build goreleaser release -f .goreleaser.fury.yaml --clean
|
||||||
|
|
||||||
release_install:
|
release_install:
|
||||||
go install -v github.com/goreleaser/goreleaser@latest
|
|
||||||
go install -v github.com/tcnksm/ghr@latest
|
go install -v github.com/tcnksm/ghr@latest
|
||||||
|
|
||||||
update_android_version:
|
update_android_version:
|
||||||
go run ./cmd/internal/update_android_version
|
go run ./cmd/internal/update_android_version
|
||||||
|
|
||||||
build_android:
|
build_android:
|
||||||
cd ../sing-box-for-android && ./gradlew :app:assemblePlayRelease && ./gradlew --stop
|
cd ../sing-box-for-android && ./gradlew :app:clean :app:assemblePlayRelease :app:assembleOtherRelease && ./gradlew --stop
|
||||||
|
|
||||||
upload_android:
|
upload_android:
|
||||||
mkdir -p dist/release_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/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
|
ghr --replace --draft --prerelease -p 3 "v${VERSION}" dist/release_android
|
||||||
rm -rf dist/release_android
|
rm -rf dist/release_android
|
||||||
|
|
||||||
@@ -178,8 +193,8 @@ lib:
|
|||||||
go run ./cmd/internal/build_libbox -target ios
|
go run ./cmd/internal/build_libbox -target ios
|
||||||
|
|
||||||
lib_install:
|
lib_install:
|
||||||
go install -v github.com/sagernet/gomobile/cmd/gomobile@v0.1.1
|
go install -v github.com/sagernet/gomobile/cmd/gomobile@v0.1.3
|
||||||
go install -v github.com/sagernet/gomobile/cmd/gobind@v0.1.1
|
go install -v github.com/sagernet/gomobile/cmd/gobind@v0.1.3
|
||||||
|
|
||||||
docs:
|
docs:
|
||||||
mkdocs serve
|
mkdocs serve
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ type Router interface {
|
|||||||
|
|
||||||
RuleSet(tag string) (RuleSet, bool)
|
RuleSet(tag string) (RuleSet, bool)
|
||||||
|
|
||||||
|
NeedWIFIState() bool
|
||||||
|
|
||||||
Exchange(ctx context.Context, message *mdns.Msg) (*mdns.Msg, error)
|
Exchange(ctx context.Context, message *mdns.Msg) (*mdns.Msg, error)
|
||||||
Lookup(ctx context.Context, domain string, strategy dns.DomainStrategy) ([]netip.Addr, error)
|
Lookup(ctx context.Context, domain string, strategy dns.DomainStrategy) ([]netip.Addr, error)
|
||||||
LookupDefault(ctx context.Context, domain string) ([]netip.Addr, error)
|
LookupDefault(ctx context.Context, domain string) ([]netip.Addr, error)
|
||||||
|
|||||||
4
box.go
4
box.go
@@ -235,7 +235,7 @@ func (s *Box) Start() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Box) preStart() error {
|
func (s *Box) preStart() error {
|
||||||
monitor := taskmonitor.New(s.logger, C.DefaultStartTimeout)
|
monitor := taskmonitor.New(s.logger, C.StartTimeout)
|
||||||
monitor.Start("start logger")
|
monitor.Start("start logger")
|
||||||
err := s.logFactory.Start()
|
err := s.logFactory.Start()
|
||||||
monitor.Finish()
|
monitor.Finish()
|
||||||
@@ -331,7 +331,7 @@ func (s *Box) Close() error {
|
|||||||
default:
|
default:
|
||||||
close(s.done)
|
close(s.done)
|
||||||
}
|
}
|
||||||
monitor := taskmonitor.New(s.logger, C.DefaultStopTimeout)
|
monitor := taskmonitor.New(s.logger, C.StopTimeout)
|
||||||
var errors error
|
var errors error
|
||||||
for serviceName, service := range s.postServices {
|
for serviceName, service := range s.postServices {
|
||||||
monitor.Start("close ", serviceName)
|
monitor.Start("close ", serviceName)
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (s *Box) startOutbounds() error {
|
func (s *Box) startOutbounds() error {
|
||||||
monitor := taskmonitor.New(s.logger, C.DefaultStartTimeout)
|
monitor := taskmonitor.New(s.logger, C.StartTimeout)
|
||||||
outboundTags := make(map[adapter.Outbound]string)
|
outboundTags := make(map[adapter.Outbound]string)
|
||||||
outbounds := make(map[string]adapter.Outbound)
|
outbounds := make(map[string]adapter.Outbound)
|
||||||
for i, outboundToStart := range s.outbounds {
|
for i, outboundToStart := range s.outbounds {
|
||||||
|
|||||||
1
clients/android
Submodule
1
clients/android
Submodule
Submodule clients/android added at 288a6f34db
1
clients/apple
Submodule
1
clients/apple
Submodule
Submodule clients/apple added at 1c5bc23a25
@@ -46,13 +46,13 @@ var (
|
|||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
sharedFlags = append(sharedFlags, "-trimpath")
|
sharedFlags = append(sharedFlags, "-trimpath")
|
||||||
sharedFlags = append(sharedFlags, "-ldflags")
|
sharedFlags = append(sharedFlags, "-buildvcs=false")
|
||||||
currentTag, err := build_shared.ReadTag()
|
currentTag, err := build_shared.ReadTag()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
currentTag = "unknown"
|
currentTag = "unknown"
|
||||||
}
|
}
|
||||||
sharedFlags = append(sharedFlags, "-X github.com/sagernet/sing-box/constant.Version="+currentTag+" -s -w -buildid=")
|
sharedFlags = append(sharedFlags, "-ldflags", "-X github.com/sagernet/sing-box/constant.Version="+currentTag+" -s -w -buildid=")
|
||||||
debugFlags = append(debugFlags, "-X github.com/sagernet/sing-box/constant.Version="+currentTag)
|
debugFlags = append(debugFlags, "-ldflags", "-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")
|
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")
|
iosTags = append(iosTags, "with_dhcp", "with_low_memory", "with_conntrack")
|
||||||
|
|||||||
@@ -11,7 +11,9 @@ import (
|
|||||||
|
|
||||||
"github.com/sagernet/sing-box/log"
|
"github.com/sagernet/sing-box/log"
|
||||||
"github.com/sagernet/sing/common"
|
"github.com/sagernet/sing/common"
|
||||||
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
"github.com/sagernet/sing/common/rw"
|
"github.com/sagernet/sing/common/rw"
|
||||||
|
"github.com/sagernet/sing/common/shell"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -28,7 +30,7 @@ func FindSDK() {
|
|||||||
}
|
}
|
||||||
for _, path := range searchPath {
|
for _, path := range searchPath {
|
||||||
path = os.ExpandEnv(path)
|
path = os.ExpandEnv(path)
|
||||||
if rw.FileExists(path + "/licenses/android-sdk-license") {
|
if rw.FileExists(filepath.Join(path, "licenses", "android-sdk-license")) {
|
||||||
androidSDKPath = path
|
androidSDKPath = path
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -40,6 +42,14 @@ func FindSDK() {
|
|||||||
log.Fatal("android NDK not found")
|
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_HOME", androidSDKPath)
|
||||||
os.Setenv("ANDROID_SDK_HOME", androidSDKPath)
|
os.Setenv("ANDROID_SDK_HOME", androidSDKPath)
|
||||||
os.Setenv("ANDROID_NDK_HOME", androidNDKPath)
|
os.Setenv("ANDROID_NDK_HOME", androidNDKPath)
|
||||||
@@ -48,11 +58,13 @@ func FindSDK() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func findNDK() bool {
|
func findNDK() bool {
|
||||||
if rw.FileExists(androidSDKPath + "/ndk/25.1.8937393") {
|
const fixedVersion = "26.2.11394342"
|
||||||
androidNDKPath = androidSDKPath + "/ndk/25.1.8937393"
|
const versionFile = "source.properties"
|
||||||
|
if fixedPath := filepath.Join(androidSDKPath, "ndk", fixedVersion); rw.FileExists(filepath.Join(fixedPath, versionFile)) {
|
||||||
|
androidNDKPath = fixedPath
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
ndkVersions, err := os.ReadDir(androidSDKPath + "/ndk")
|
ndkVersions, err := os.ReadDir(filepath.Join(androidSDKPath, "ndk"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -73,8 +85,10 @@ func findNDK() bool {
|
|||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
for _, versionName := range versionNames {
|
for _, versionName := range versionNames {
|
||||||
if rw.FileExists(androidSDKPath + "/ndk/" + versionName) {
|
currentNDKPath := filepath.Join(androidSDKPath, "ndk", versionName)
|
||||||
androidNDKPath = androidSDKPath + "/ndk/" + versionName
|
if rw.FileExists(filepath.Join(androidSDKPath, versionFile)) {
|
||||||
|
androidNDKPath = currentNDKPath
|
||||||
|
log.Warn("reproducibility warning: using NDK version " + versionName + " instead of " + fixedVersion)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -85,8 +99,14 @@ var GoBinPath string
|
|||||||
|
|
||||||
func FindMobile() {
|
func FindMobile() {
|
||||||
goBin := filepath.Join(build.Default.GOPATH, "bin")
|
goBin := filepath.Join(build.Default.GOPATH, "bin")
|
||||||
if !rw.FileExists(goBin + "/" + "gobind") {
|
if runtime.GOOS == "windows" {
|
||||||
log.Fatal("missing gomobile installation")
|
if !rw.FileExists(filepath.Join(goBin, "gobind.exe")) {
|
||||||
|
log.Fatal("missing gomobile installation")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if !rw.FileExists(filepath.Join(goBin, "gobind")) {
|
||||||
|
log.Fatal("missing gomobile installation")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
GoBinPath = goBin
|
GoBinPath = goBin
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -18,34 +19,46 @@ func main() {
|
|||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
common.Must(os.Chdir(androidPath))
|
common.Must(os.Chdir(androidPath))
|
||||||
localProps := common.Must1(os.ReadFile("local.properties"))
|
localProps := common.Must1(os.ReadFile("version.properties"))
|
||||||
var propsList [][]string
|
var propsList [][]string
|
||||||
for _, propLine := range strings.Split(string(localProps), "\n") {
|
for _, propLine := range strings.Split(string(localProps), "\n") {
|
||||||
propsList = append(propsList, strings.Split(propLine, "="))
|
propsList = append(propsList, strings.Split(propLine, "="))
|
||||||
}
|
}
|
||||||
|
var (
|
||||||
|
versionUpdated bool
|
||||||
|
goVersionUpdated bool
|
||||||
|
)
|
||||||
for _, propPair := range propsList {
|
for _, propPair := range propsList {
|
||||||
if propPair[0] == "VERSION_NAME" {
|
switch propPair[0] {
|
||||||
if propPair[1] == newVersion.String() {
|
case "VERSION_NAME":
|
||||||
log.Info("version not changed")
|
if propPair[1] != newVersion.String() {
|
||||||
return
|
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())
|
||||||
}
|
}
|
||||||
propPair[1] = newVersion.String()
|
|
||||||
log.Info("updated version to ", newVersion.String())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if !(versionUpdated || goVersionUpdated) {
|
||||||
|
log.Info("version not changed")
|
||||||
|
return
|
||||||
|
}
|
||||||
for _, propPair := range propsList {
|
for _, propPair := range propsList {
|
||||||
switch propPair[0] {
|
switch propPair[0] {
|
||||||
case "VERSION_CODE":
|
case "VERSION_CODE":
|
||||||
versionCode := common.Must1(strconv.ParseInt(propPair[1], 10, 64))
|
versionCode := common.Must1(strconv.ParseInt(propPair[1], 10, 64))
|
||||||
propPair[1] = strconv.Itoa(int(versionCode + 1))
|
propPair[1] = strconv.Itoa(int(versionCode + 1))
|
||||||
log.Info("updated version code to ", propPair[1])
|
log.Info("updated version code to ", propPair[1])
|
||||||
case "RELEASE_NOTES":
|
|
||||||
propPair[1] = "sing-box " + newVersion.String()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var newProps []string
|
var newProps []string
|
||||||
for _, propPair := range propsList {
|
for _, propPair := range propsList {
|
||||||
newProps = append(newProps, strings.Join(propPair, "="))
|
newProps = append(newProps, strings.Join(propPair, "="))
|
||||||
}
|
}
|
||||||
common.Must(os.WriteFile("local.properties", []byte(strings.Join(newProps, "\n")), 0o644))
|
common.Must(os.WriteFile("version.properties", []byte(strings.Join(newProps, "\n")), 0o644))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -199,7 +199,7 @@ func run() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func closeMonitor(ctx context.Context) {
|
func closeMonitor(ctx context.Context) {
|
||||||
time.Sleep(C.DefaultStopFatalTimeout)
|
time.Sleep(C.FatalStopTimeout)
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -3,15 +3,16 @@ package constant
|
|||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
const (
|
const (
|
||||||
TCPTimeout = 5 * time.Second
|
TCPTimeout = 5 * time.Second
|
||||||
ReadPayloadTimeout = 300 * time.Millisecond
|
ReadPayloadTimeout = 300 * time.Millisecond
|
||||||
DNSTimeout = 10 * time.Second
|
DNSTimeout = 10 * time.Second
|
||||||
QUICTimeout = 30 * time.Second
|
QUICTimeout = 30 * time.Second
|
||||||
STUNTimeout = 15 * time.Second
|
STUNTimeout = 15 * time.Second
|
||||||
UDPTimeout = 5 * time.Minute
|
UDPTimeout = 5 * time.Minute
|
||||||
DefaultURLTestInterval = 3 * time.Minute
|
DefaultURLTestInterval = 3 * time.Minute
|
||||||
DefaultURLTestIdleTimeout = 30 * time.Minute
|
DefaultURLTestIdleTimeout = 30 * time.Minute
|
||||||
DefaultStartTimeout = 10 * time.Second
|
StartTimeout = 10 * time.Second
|
||||||
DefaultStopTimeout = 5 * time.Second
|
StopTimeout = 5 * time.Second
|
||||||
DefaultStopFatalTimeout = 10 * time.Second
|
FatalStopTimeout = 10 * time.Second
|
||||||
|
FakeIPMetadataSaveInterval = 10 * time.Second
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -2,6 +2,44 @@
|
|||||||
icon: material/alert-decagram
|
icon: material/alert-decagram
|
||||||
---
|
---
|
||||||
|
|
||||||
|
#### 1.8.12
|
||||||
|
|
||||||
|
* Now we have official APT and DNF repositories **1**
|
||||||
|
* Fix packet MTU for QUIC protocols
|
||||||
|
* Fixes and improvements
|
||||||
|
|
||||||
|
**1**:
|
||||||
|
|
||||||
|
Including stable and beta versions, see https://sing-box.sagernet.org/installation/package-manager/
|
||||||
|
|
||||||
|
#### 1.8.11
|
||||||
|
|
||||||
|
* Fixes and improvements
|
||||||
|
|
||||||
|
#### 1.8.10
|
||||||
|
|
||||||
|
* Fixes and improvements
|
||||||
|
|
||||||
|
#### 1.8.9
|
||||||
|
|
||||||
|
* Fixes and improvements
|
||||||
|
|
||||||
|
#### 1.8.8
|
||||||
|
|
||||||
|
* Fixes and improvements
|
||||||
|
|
||||||
|
#### 1.8.7
|
||||||
|
|
||||||
|
* Fixes and improvements
|
||||||
|
|
||||||
|
#### 1.8.6
|
||||||
|
|
||||||
|
* Fixes and improvements
|
||||||
|
|
||||||
|
#### 1.8.5
|
||||||
|
|
||||||
|
* Fixes and improvements
|
||||||
|
|
||||||
#### 1.8.4
|
#### 1.8.4
|
||||||
|
|
||||||
* Fixes and improvements
|
* Fixes and improvements
|
||||||
@@ -96,8 +134,8 @@ Also, starting with this release, uTLS requires at least Go 1.20.
|
|||||||
|
|
||||||
**11**:
|
**11**:
|
||||||
|
|
||||||
Updated `cloudflare-tls`, `gomobile`, `smux`, `tfo-go` and `wireguard-go` to latest, `quic-go` to `0.40.1` and `gvisor` to `20231204.0`
|
Updated `cloudflare-tls`, `gomobile`, `smux`, `tfo-go` and `wireguard-go` to latest, `quic-go` to `0.40.1` and `gvisor`
|
||||||
|
to `20231204.0`
|
||||||
|
|
||||||
#### 1.8.0-rc.11
|
#### 1.8.0-rc.11
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ 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](https://play.google.com/store/apps/details?id=io.nekohasekai.sfa)
|
||||||
* [Play Store (Beta)](https://play.google.com/apps/testing/io.nekohasekai.sfa)
|
* [Play Store (Beta)](https://play.google.com/apps/testing/io.nekohasekai.sfa)
|
||||||
* [GitHub Releases](https://github.com/SagerNet/sing-box/releases)
|
* [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
|
## :material-source-repository: Source code
|
||||||
|
|
||||||
|
|||||||
@@ -6,3 +6,9 @@ icon: material/security
|
|||||||
|
|
||||||
sing-box and official graphics clients do not collect or share personal data,
|
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.
|
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.
|
||||||
|
|||||||
@@ -32,8 +32,6 @@ 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,
|
sing-box 1.8.0 introduces [Rule Set](/configuration/rule-set/), which can completely replace Geosite,
|
||||||
check [Migration](/migration/#migrate-geosite-to-rule-sets).
|
check [Migration](/migration/#migrate-geosite-to-rule-sets).
|
||||||
|
|
||||||
Geosite,即由 V2Ray 维护的 domain-list-community 项目,作为早期流量绕过解决方案,存在着大量问题,包括缺少维护、规则不准确、管理困难。
|
|
||||||
|
|
||||||
## 1.6.0
|
## 1.6.0
|
||||||
|
|
||||||
The following features will be marked deprecated in 1.5.0 and removed entirely in 1.6.0.
|
The following features will be marked deprecated in 1.5.0 and removed entirely in 1.6.0.
|
||||||
|
|||||||
@@ -23,7 +23,8 @@ Since sing-box 1.5.0:
|
|||||||
Since sing-box 1.8.0:
|
Since sing-box 1.8.0:
|
||||||
|
|
||||||
* Go 1.18.5 - ~
|
* Go 1.18.5 - ~
|
||||||
* Go 1.20.0 - ~ with tag `with_quic`, `with_ech`, or `with_utls` enabled
|
* Go 1.20.0 - ~ with tag `with_quic`, or `with_utls` enabled
|
||||||
|
* Go 1.21.0 - ~ with tag `with_ech` enabled
|
||||||
|
|
||||||
You can download and install Go from: https://go.dev/doc/install, latest version is recommended.
|
You can download and install Go from: https://go.dev/doc/install, latest version is recommended.
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,8 @@ sing-box 1.4.0 前:
|
|||||||
从 sing-box 1.8.0:
|
从 sing-box 1.8.0:
|
||||||
|
|
||||||
* Go 1.18.5 - ~
|
* Go 1.18.5 - ~
|
||||||
* Go 1.20.0 - ~ 如果启用构建标记 `with_quic`、`with_ech` 或 `with_utls`
|
* Go 1.20.0 - ~ 如果启用构建标记 `with_quic` 或 `with_utls`
|
||||||
|
* Go 1.20.1 - ~ 如果启用构建标记 `with_ech`
|
||||||
|
|
||||||
您可以从 https://go.dev/doc/install 下载并安装 Go,推荐使用最新版本。
|
您可以从 https://go.dev/doc/install 下载并安装 Go,推荐使用最新版本。
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,35 @@ icon: material/package
|
|||||||
|
|
||||||
# Package Manager
|
# 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-download-box: Manual Installation
|
||||||
|
|
||||||
=== ":material-debian: Debian / DEB"
|
=== ":material-debian: Debian / DEB"
|
||||||
|
|||||||
@@ -4,6 +4,35 @@ 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-download-box: 手动安装
|
||||||
|
|
||||||
=== ":material-debian: Debian / DEB"
|
=== ":material-debian: Debian / DEB"
|
||||||
|
|||||||
8
docs/installation/tools/sing-box.repo
Normal file
8
docs/installation/tools/sing-box.repo
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
[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
|
||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
|
|
||||||
"github.com/sagernet/bbolt"
|
"github.com/sagernet/bbolt"
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
|
C "github.com/sagernet/sing-box/constant"
|
||||||
"github.com/sagernet/sing/common/logger"
|
"github.com/sagernet/sing/common/logger"
|
||||||
M "github.com/sagernet/sing/common/metadata"
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
)
|
)
|
||||||
@@ -58,12 +59,13 @@ func (c *CacheFile) FakeIPSaveMetadata(metadata *adapter.FakeIPMetadata) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *CacheFile) FakeIPSaveMetadataAsync(metadata *adapter.FakeIPMetadata) {
|
func (c *CacheFile) FakeIPSaveMetadataAsync(metadata *adapter.FakeIPMetadata) {
|
||||||
if timer := c.saveMetadataTimer; timer != nil {
|
if c.saveMetadataTimer == nil {
|
||||||
timer.Stop()
|
c.saveMetadataTimer = time.AfterFunc(C.FakeIPMetadataSaveInterval, func() {
|
||||||
|
_ = c.FakeIPSaveMetadata(metadata)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
c.saveMetadataTimer.Reset(C.FakeIPMetadataSaveInterval)
|
||||||
}
|
}
|
||||||
c.saveMetadataTimer = time.AfterFunc(10*time.Second, func() {
|
|
||||||
_ = c.FakeIPSaveMetadata(metadata)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *CacheFile) FakeIPStore(address netip.Addr, domain string) error {
|
func (c *CacheFile) FakeIPStore(address netip.Addr, domain string) error {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ const (
|
|||||||
CommandLog int32 = iota
|
CommandLog int32 = iota
|
||||||
CommandStatus
|
CommandStatus
|
||||||
CommandServiceReload
|
CommandServiceReload
|
||||||
|
CommandServiceClose
|
||||||
CommandCloseConnections
|
CommandCloseConnections
|
||||||
CommandGroup
|
CommandGroup
|
||||||
CommandSelectOutbound
|
CommandSelectOutbound
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ func (c *CommandClient) SetClashMode(newMode string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *CommandServer) handleSetClashMode(conn net.Conn) error {
|
func (s *CommandServer) handleSetClashMode(conn net.Conn) error {
|
||||||
defer conn.Close()
|
|
||||||
newMode, err := rw.ReadVString(conn)
|
newMode, err := rw.ReadVString(conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -61,7 +60,6 @@ func (c *CommandClient) handleModeConn(conn net.Conn) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *CommandServer) handleModeConn(conn net.Conn) error {
|
func (s *CommandServer) handleModeConn(conn net.Conn) error {
|
||||||
defer conn.Close()
|
|
||||||
ctx := connKeepAlive(conn)
|
ctx := connKeepAlive(conn)
|
||||||
for s.service == nil {
|
for s.service == nil {
|
||||||
select {
|
select {
|
||||||
@@ -73,7 +71,6 @@ func (s *CommandServer) handleModeConn(conn net.Conn) error {
|
|||||||
}
|
}
|
||||||
clashServer := s.service.instance.Router().ClashServer()
|
clashServer := s.service.instance.Router().ClashServer()
|
||||||
if clashServer == nil {
|
if clashServer == nil {
|
||||||
defer conn.Close()
|
|
||||||
return binary.Write(conn, binary.BigEndian, uint16(0))
|
return binary.Write(conn, binary.BigEndian, uint16(0))
|
||||||
}
|
}
|
||||||
err := writeClashModeList(conn, clashServer)
|
err := writeClashModeList(conn, clashServer)
|
||||||
|
|||||||
@@ -58,7 +58,13 @@ func (c *CommandClient) handleGroupConn(conn net.Conn) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *CommandServer) handleGroupConn(conn net.Conn) error {
|
func (s *CommandServer) handleGroupConn(conn net.Conn) error {
|
||||||
defer conn.Close()
|
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()
|
||||||
ctx := connKeepAlive(conn)
|
ctx := connKeepAlive(conn)
|
||||||
for {
|
for {
|
||||||
service := s.service
|
service := s.service
|
||||||
@@ -76,7 +82,7 @@ func (s *CommandServer) handleGroupConn(conn net.Conn) error {
|
|||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return ctx.Err()
|
return ctx.Err()
|
||||||
case <-time.After(2 * time.Second):
|
case <-ticker.C:
|
||||||
}
|
}
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
@@ -274,7 +280,6 @@ func (c *CommandClient) SetGroupExpand(groupTag string, isExpand bool) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *CommandServer) handleSetGroupExpand(conn net.Conn) error {
|
func (s *CommandServer) handleSetGroupExpand(conn net.Conn) error {
|
||||||
defer conn.Close()
|
|
||||||
groupTag, err := rw.ReadVString(conn)
|
groupTag, err := rw.ReadVString(conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -44,3 +44,41 @@ func (s *CommandServer) handleServiceReload(conn net.Conn) error {
|
|||||||
}
|
}
|
||||||
return nil
|
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
|
||||||
|
}
|
||||||
@@ -31,7 +31,6 @@ func (c *CommandClient) SelectOutbound(groupTag string, outboundTag string) erro
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *CommandServer) handleSelectOutbound(conn net.Conn) error {
|
func (s *CommandServer) handleSelectOutbound(conn net.Conn) error {
|
||||||
defer conn.Close()
|
|
||||||
groupTag, err := rw.ReadVString(conn)
|
groupTag, err := rw.ReadVString(conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ type CommandServer struct {
|
|||||||
|
|
||||||
type CommandServerHandler interface {
|
type CommandServerHandler interface {
|
||||||
ServiceReload() error
|
ServiceReload() error
|
||||||
|
PostServiceClose()
|
||||||
GetSystemProxyStatus() *SystemProxyStatus
|
GetSystemProxyStatus() *SystemProxyStatus
|
||||||
SetSystemProxyEnabled(isEnabled bool) error
|
SetSystemProxyEnabled(isEnabled bool) error
|
||||||
}
|
}
|
||||||
@@ -58,16 +59,19 @@ func (s *CommandServer) SetService(newService *BoxService) {
|
|||||||
if newService != nil {
|
if newService != nil {
|
||||||
service.PtrFromContext[urltest.HistoryStorage](newService.ctx).SetHook(s.urlTestUpdate)
|
service.PtrFromContext[urltest.HistoryStorage](newService.ctx).SetHook(s.urlTestUpdate)
|
||||||
newService.instance.Router().ClashServer().(*clashapi.Server).SetModeUpdateHook(s.modeUpdate)
|
newService.instance.Router().ClashServer().(*clashapi.Server).SetModeUpdateHook(s.modeUpdate)
|
||||||
s.savedLines.Init()
|
|
||||||
select {
|
|
||||||
case s.logReset <- struct{}{}:
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
s.service = newService
|
s.service = newService
|
||||||
s.notifyURLTestUpdate()
|
s.notifyURLTestUpdate()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *CommandServer) ResetLog() {
|
||||||
|
s.savedLines.Init()
|
||||||
|
select {
|
||||||
|
case s.logReset <- struct{}{}:
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (s *CommandServer) notifyURLTestUpdate() {
|
func (s *CommandServer) notifyURLTestUpdate() {
|
||||||
select {
|
select {
|
||||||
case s.urlTestUpdate <- struct{}{}:
|
case s.urlTestUpdate <- struct{}{}:
|
||||||
@@ -152,6 +156,8 @@ func (s *CommandServer) handleConnection(conn net.Conn) error {
|
|||||||
return s.handleStatusConn(conn)
|
return s.handleStatusConn(conn)
|
||||||
case CommandServiceReload:
|
case CommandServiceReload:
|
||||||
return s.handleServiceReload(conn)
|
return s.handleServiceReload(conn)
|
||||||
|
case CommandServiceClose:
|
||||||
|
return s.handleServiceClose(conn)
|
||||||
case CommandCloseConnections:
|
case CommandCloseConnections:
|
||||||
return s.handleCloseConnections(conn)
|
return s.handleCloseConnections(conn)
|
||||||
case CommandGroup:
|
case CommandGroup:
|
||||||
|
|||||||
@@ -35,7 +35,6 @@ func (c *CommandClient) GetSystemProxyStatus() (*SystemProxyStatus, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *CommandServer) handleGetSystemProxyStatus(conn net.Conn) error {
|
func (s *CommandServer) handleGetSystemProxyStatus(conn net.Conn) error {
|
||||||
defer conn.Close()
|
|
||||||
status := s.handler.GetSystemProxyStatus()
|
status := s.handler.GetSystemProxyStatus()
|
||||||
err := binary.Write(conn, binary.BigEndian, status.Available)
|
err := binary.Write(conn, binary.BigEndian, status.Available)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -68,7 +67,6 @@ func (c *CommandClient) SetSystemProxyEnabled(isEnabled bool) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *CommandServer) handleSetSystemProxyEnabled(conn net.Conn) error {
|
func (s *CommandServer) handleSetSystemProxyEnabled(conn net.Conn) error {
|
||||||
defer conn.Close()
|
|
||||||
var isEnabled bool
|
var isEnabled bool
|
||||||
err := binary.Read(conn, binary.BigEndian, &isEnabled)
|
err := binary.Read(conn, binary.BigEndian, &isEnabled)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ func (c *CommandClient) URLTest(groupTag string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *CommandServer) handleURLTest(conn net.Conn) error {
|
func (s *CommandServer) handleURLTest(conn net.Conn) error {
|
||||||
defer conn.Close()
|
|
||||||
groupTag, err := rw.ReadVString(conn)
|
groupTag, err := rw.ReadVString(conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -97,6 +97,17 @@ func (m *platformDefaultInterfaceMonitor) UnregisterCallback(element *list.Eleme
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *platformDefaultInterfaceMonitor) UpdateDefaultInterface(interfaceName string, interfaceIndex32 int32) {
|
func (m *platformDefaultInterfaceMonitor) UpdateDefaultInterface(interfaceName string, interfaceIndex32 int32) {
|
||||||
|
if interfaceName == "" || interfaceIndex32 == -1 {
|
||||||
|
m.defaultInterfaceName = ""
|
||||||
|
m.defaultInterfaceIndex = -1
|
||||||
|
m.access.Lock()
|
||||||
|
callbacks := m.callbacks.Array()
|
||||||
|
m.access.Unlock()
|
||||||
|
for _, callback := range callbacks {
|
||||||
|
callback(tun.EventNoRoute)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
var err error
|
var err error
|
||||||
if m.iif.UsePlatformInterfaceGetter() {
|
if m.iif.UsePlatformInterfaceGetter() {
|
||||||
err = m.updateInterfacesPlatform()
|
err = m.updateInterfacesPlatform()
|
||||||
@@ -110,28 +121,6 @@ func (m *platformDefaultInterfaceMonitor) UpdateDefaultInterface(interfaceName s
|
|||||||
m.logger.Error(E.Cause(err, "update interfaces"))
|
m.logger.Error(E.Cause(err, "update interfaces"))
|
||||||
}
|
}
|
||||||
interfaceIndex := int(interfaceIndex32)
|
interfaceIndex := int(interfaceIndex32)
|
||||||
if interfaceName == "" {
|
|
||||||
for _, netIf := range m.networkAddresses {
|
|
||||||
if netIf.interfaceIndex == interfaceIndex {
|
|
||||||
interfaceName = netIf.interfaceName
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if interfaceIndex == -1 {
|
|
||||||
for _, netIf := range m.networkAddresses {
|
|
||||||
if netIf.interfaceName == interfaceName {
|
|
||||||
interfaceIndex = netIf.interfaceIndex
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if interfaceName == "" {
|
|
||||||
m.logger.Error(E.New("invalid interface name for ", interfaceIndex))
|
|
||||||
return
|
|
||||||
} else if interfaceIndex == -1 {
|
|
||||||
m.logger.Error(E.New("invalid interface index for ", interfaceName))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if m.defaultInterfaceName == interfaceName && m.defaultInterfaceIndex == interfaceIndex {
|
if m.defaultInterfaceName == interfaceName && m.defaultInterfaceIndex == interfaceIndex {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,14 +3,17 @@ package libbox
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
runtimeDebug "runtime/debug"
|
runtimeDebug "runtime/debug"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box"
|
"github.com/sagernet/sing-box"
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
"github.com/sagernet/sing-box/common/process"
|
"github.com/sagernet/sing-box/common/process"
|
||||||
"github.com/sagernet/sing-box/common/urltest"
|
"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/internal/procfs"
|
||||||
"github.com/sagernet/sing-box/experimental/libbox/platform"
|
"github.com/sagernet/sing-box/experimental/libbox/platform"
|
||||||
"github.com/sagernet/sing-box/log"
|
"github.com/sagernet/sing-box/log"
|
||||||
@@ -32,6 +35,8 @@ type BoxService struct {
|
|||||||
instance *box.Box
|
instance *box.Box
|
||||||
pauseManager pause.Manager
|
pauseManager pause.Manager
|
||||||
urlTestHistoryStorage *urltest.HistoryStorage
|
urlTestHistoryStorage *urltest.HistoryStorage
|
||||||
|
|
||||||
|
servicePauseFields
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewService(configContent string, platformInterface PlatformInterface) (*BoxService, error) {
|
func NewService(configContent string, platformInterface PlatformInterface) (*BoxService, error) {
|
||||||
@@ -70,19 +75,23 @@ func (s *BoxService) Start() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *BoxService) Close() 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.cancel()
|
||||||
s.urlTestHistoryStorage.Close()
|
s.urlTestHistoryStorage.Close()
|
||||||
return s.instance.Close()
|
return s.instance.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *BoxService) Sleep() {
|
func (s *BoxService) NeedWIFIState() bool {
|
||||||
s.pauseManager.DevicePause()
|
return s.instance.Router().NeedWIFIState()
|
||||||
_ = s.instance.Router().ResetNetwork()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *BoxService) Wake() {
|
|
||||||
s.pauseManager.DeviceWake()
|
|
||||||
_ = s.instance.Router().ResetNetwork()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|||||||
40
experimental/libbox/service_pause.go
Normal file
40
experimental/libbox/service_pause.go
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
package libbox
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type servicePauseFields struct {
|
||||||
|
pauseAccess sync.Mutex
|
||||||
|
pauseTimer *time.Timer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *BoxService) Pause() {
|
||||||
|
s.pauseAccess.Lock()
|
||||||
|
defer s.pauseAccess.Unlock()
|
||||||
|
if s.pauseTimer != nil {
|
||||||
|
s.pauseTimer.Stop()
|
||||||
|
}
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s.pauseManager.DeviceWake()
|
||||||
|
}
|
||||||
45
go.mod
45
go.mod
@@ -8,32 +8,32 @@ require (
|
|||||||
github.com/cloudflare/circl v1.3.7
|
github.com/cloudflare/circl v1.3.7
|
||||||
github.com/cretz/bine v0.2.0
|
github.com/cretz/bine v0.2.0
|
||||||
github.com/fsnotify/fsnotify v1.7.0
|
github.com/fsnotify/fsnotify v1.7.0
|
||||||
github.com/go-chi/chi/v5 v5.0.11
|
github.com/go-chi/chi/v5 v5.0.12
|
||||||
github.com/go-chi/cors v1.2.1
|
github.com/go-chi/cors v1.2.1
|
||||||
github.com/go-chi/render v1.0.3
|
github.com/go-chi/render v1.0.3
|
||||||
github.com/gofrs/uuid/v5 v5.0.0
|
github.com/gofrs/uuid/v5 v5.1.0
|
||||||
github.com/insomniacslk/dhcp v0.0.0-20231206064809-8c70d406f6d2
|
github.com/insomniacslk/dhcp v0.0.0-20231206064809-8c70d406f6d2
|
||||||
github.com/libdns/alidns v1.0.3
|
github.com/libdns/alidns v1.0.3
|
||||||
github.com/libdns/cloudflare v0.1.0
|
github.com/libdns/cloudflare v0.1.1
|
||||||
github.com/logrusorgru/aurora v2.0.3+incompatible
|
github.com/logrusorgru/aurora v2.0.3+incompatible
|
||||||
github.com/mholt/acmez v1.2.0
|
github.com/mholt/acmez v1.2.0
|
||||||
github.com/miekg/dns v1.1.58
|
github.com/miekg/dns v1.1.59
|
||||||
github.com/ooni/go-libtor v1.1.8
|
github.com/ooni/go-libtor v1.1.8
|
||||||
github.com/oschwald/maxminddb-golang v1.12.0
|
github.com/oschwald/maxminddb-golang v1.12.0
|
||||||
github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a
|
github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a
|
||||||
github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1
|
github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1
|
||||||
github.com/sagernet/gomobile v0.1.1
|
github.com/sagernet/gomobile v0.1.3
|
||||||
github.com/sagernet/gvisor v0.0.0-20231209105102-8d27a30e436e
|
github.com/sagernet/gvisor v0.0.0-20231209105102-8d27a30e436e
|
||||||
github.com/sagernet/quic-go v0.40.1
|
github.com/sagernet/quic-go v0.40.1
|
||||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691
|
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691
|
||||||
github.com/sagernet/sing v0.3.0
|
github.com/sagernet/sing v0.3.8
|
||||||
github.com/sagernet/sing-dns v0.1.12
|
github.com/sagernet/sing-dns v0.1.14
|
||||||
github.com/sagernet/sing-mux v0.2.0
|
github.com/sagernet/sing-mux v0.2.0
|
||||||
github.com/sagernet/sing-quic v0.1.7
|
github.com/sagernet/sing-quic v0.1.12
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.6
|
github.com/sagernet/sing-shadowsocks v0.2.6
|
||||||
github.com/sagernet/sing-shadowsocks2 v0.2.0
|
github.com/sagernet/sing-shadowsocks2 v0.2.0
|
||||||
github.com/sagernet/sing-shadowtls v0.1.4
|
github.com/sagernet/sing-shadowtls v0.1.4
|
||||||
github.com/sagernet/sing-tun v0.2.0
|
github.com/sagernet/sing-tun v0.2.6
|
||||||
github.com/sagernet/sing-vmess v0.1.8
|
github.com/sagernet/sing-vmess v0.1.8
|
||||||
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7
|
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7
|
||||||
github.com/sagernet/tfo-go v0.0.0-20231209031829-7b5343ac1dc6
|
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/wireguard-go v0.0.0-20231215174105-89dec3b2f3e8
|
||||||
github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854
|
github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854
|
||||||
github.com/spf13/cobra v1.8.0
|
github.com/spf13/cobra v1.8.0
|
||||||
github.com/stretchr/testify v1.8.4
|
github.com/stretchr/testify v1.9.0
|
||||||
go.uber.org/zap v1.26.0
|
go.uber.org/zap v1.27.0
|
||||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
|
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
|
||||||
golang.org/x/crypto v0.18.0
|
golang.org/x/crypto v0.22.0
|
||||||
golang.org/x/net v0.20.0
|
golang.org/x/net v0.24.0
|
||||||
golang.org/x/sys v0.16.0
|
golang.org/x/sys v0.19.0
|
||||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6
|
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6
|
||||||
google.golang.org/grpc v1.60.1
|
google.golang.org/grpc v1.63.2
|
||||||
google.golang.org/protobuf v1.32.0
|
google.golang.org/protobuf v1.33.0
|
||||||
howett.net/plist v1.0.1
|
howett.net/plist v1.0.1
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -64,7 +64,6 @@ require (
|
|||||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
|
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
|
||||||
github.com/gobwas/httphead v0.1.0 // indirect
|
github.com/gobwas/httphead v0.1.0 // indirect
|
||||||
github.com/gobwas/pool v0.2.1 // 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/btree v1.1.2 // indirect
|
||||||
github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a // indirect
|
github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a // indirect
|
||||||
github.com/hashicorp/yamux v0.1.1 // indirect
|
github.com/hashicorp/yamux v0.1.1 // indirect
|
||||||
@@ -72,7 +71,7 @@ require (
|
|||||||
github.com/josharian/native v1.1.0 // indirect
|
github.com/josharian/native v1.1.0 // indirect
|
||||||
github.com/klauspost/compress v1.17.4 // indirect
|
github.com/klauspost/compress v1.17.4 // indirect
|
||||||
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
|
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
|
||||||
github.com/libdns/libdns v0.2.1 // indirect
|
github.com/libdns/libdns v0.2.2 // indirect
|
||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
|
||||||
github.com/onsi/ginkgo/v2 v2.9.7 // indirect
|
github.com/onsi/ginkgo/v2 v2.9.7 // indirect
|
||||||
github.com/pierrec/lz4/v4 v4.1.14 // indirect
|
github.com/pierrec/lz4/v4 v4.1.14 // indirect
|
||||||
@@ -80,18 +79,18 @@ require (
|
|||||||
github.com/quic-go/qpack v0.4.0 // indirect
|
github.com/quic-go/qpack v0.4.0 // indirect
|
||||||
github.com/quic-go/qtls-go1-20 v0.4.1 // indirect
|
github.com/quic-go/qtls-go1-20 v0.4.1 // indirect
|
||||||
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 // 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/spf13/pflag v1.0.5 // indirect
|
||||||
github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 // indirect
|
github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 // indirect
|
||||||
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect
|
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect
|
||||||
github.com/zeebo/blake3 v0.2.3 // indirect
|
github.com/zeebo/blake3 v0.2.3 // indirect
|
||||||
go.uber.org/multierr v1.11.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc // indirect
|
golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f // indirect
|
||||||
golang.org/x/mod v0.14.0 // indirect
|
golang.org/x/mod v0.17.0 // indirect
|
||||||
|
golang.org/x/sync v0.7.0 // indirect
|
||||||
golang.org/x/text v0.14.0 // indirect
|
golang.org/x/text v0.14.0 // indirect
|
||||||
golang.org/x/time v0.5.0 // indirect
|
golang.org/x/time v0.5.0 // indirect
|
||||||
golang.org/x/tools v0.17.0 // indirect
|
golang.org/x/tools v0.20.0 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97 // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect
|
||||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
|
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
lukechampine.com/blake3 v1.2.1 // indirect
|
lukechampine.com/blake3 v1.2.1 // indirect
|
||||||
|
|||||||
103
go.sum
103
go.sum
@@ -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/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 h1:NlRaXb3J6hAnTmWdsEKb9bcSBD6BvcIjdGdeb0zfXbk=
|
||||||
github.com/gaukas/godicttls v0.0.4/go.mod h1:l6EenT4TLWgTdwslVb4sEMOCf7Bv0JAK67deKr9/NCI=
|
github.com/gaukas/godicttls v0.0.4/go.mod h1:l6EenT4TLWgTdwslVb4sEMOCf7Bv0JAK67deKr9/NCI=
|
||||||
github.com/go-chi/chi/v5 v5.0.11 h1:BnpYbFZ3T3S1WMpD79r7R5ThWX40TaFB7L31Y8xqSwA=
|
github.com/go-chi/chi/v5 v5.0.12 h1:9euLV5sTrTNTRUU9POmDUvfxyj6LAABLUcEWO+JJb4s=
|
||||||
github.com/go-chi/chi/v5 v5.0.11/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
github.com/go-chi/chi/v5 v5.0.12/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||||
github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4=
|
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/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
|
||||||
github.com/go-chi/render v1.0.3 h1:AsXqd2a1/INaIfUSKq3G5uA8weYx20FOsM7uSoCyyt4=
|
github.com/go-chi/render v1.0.3 h1:AsXqd2a1/INaIfUSKq3G5uA8weYx20FOsM7uSoCyyt4=
|
||||||
@@ -34,15 +34,12 @@ 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/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 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=
|
||||||
github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
|
github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
|
||||||
github.com/gofrs/uuid/v5 v5.0.0 h1:p544++a97kEL+svbcFbCQVM9KFu0Yo25UoISXGNNH9M=
|
github.com/gofrs/uuid/v5 v5.1.0 h1:S5rqVKIigghZTCBKPCw0Y+bXkn26K3TB5mvQq2Ix8dk=
|
||||||
github.com/gofrs/uuid/v5 v5.0.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8=
|
github.com/gofrs/uuid/v5 v5.1.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.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||||
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 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=
|
||||||
github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
|
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/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
|
||||||
github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a h1:fEBsGL/sjAuJrgah5XqmmYsTLzJp/TO9Lhy39gkverk=
|
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=
|
github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
|
||||||
github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE=
|
github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE=
|
||||||
@@ -65,17 +62,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/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 h1:LFHuGnbseq5+HCeGa1aW8awyX/4M2psB9962fdD2+yQ=
|
||||||
github.com/libdns/alidns v1.0.3/go.mod h1:e18uAG6GanfRhcJj6/tps2rCMzQJaYVcGKT+ELjdjGE=
|
github.com/libdns/alidns v1.0.3/go.mod h1:e18uAG6GanfRhcJj6/tps2rCMzQJaYVcGKT+ELjdjGE=
|
||||||
github.com/libdns/cloudflare v0.1.0 h1:93WkJaGaiXCe353LHEP36kAWCUw0YjFqwhkBkU2/iic=
|
github.com/libdns/cloudflare v0.1.1 h1:FVPfWwP8zZCqj268LZjmkDleXlHPlFU9KC4OJ3yn054=
|
||||||
github.com/libdns/cloudflare v0.1.0/go.mod h1:a44IP6J1YH6nvcNl1PverfJviADgXUnsozR3a7vBKN8=
|
github.com/libdns/cloudflare v0.1.1/go.mod h1:9VK91idpOjg6v7/WbjkEW49bSCxj00ALesIFDhJ8PBU=
|
||||||
github.com/libdns/libdns v0.2.0/go.mod h1:yQCXzk1lEZmmCPa857bnk4TsOiqYasqpyOEeSObbb40=
|
github.com/libdns/libdns v0.2.0/go.mod h1:yQCXzk1lEZmmCPa857bnk4TsOiqYasqpyOEeSObbb40=
|
||||||
github.com/libdns/libdns v0.2.1 h1:Wu59T7wSHRgtA0cfxC+n1c/e+O3upJGWytknkmFEDis=
|
github.com/libdns/libdns v0.2.2 h1:O6ws7bAfRPaBsgAYt8MDe2HcNBGC29hkZ9MX2eUSX3s=
|
||||||
github.com/libdns/libdns v0.2.1/go.mod h1:yQCXzk1lEZmmCPa857bnk4TsOiqYasqpyOEeSObbb40=
|
github.com/libdns/libdns v0.2.2/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ=
|
||||||
github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8=
|
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/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 h1:1hhLxSgY5FvH5HCnGUuwbKY2VQVo8IU7rxXKSnZ7F30=
|
||||||
github.com/mholt/acmez v1.2.0/go.mod h1:VT9YwH1xgNX1kmYY89gY8xPJC84BFAisjo8Egigt4kE=
|
github.com/mholt/acmez v1.2.0/go.mod h1:VT9YwH1xgNX1kmYY89gY8xPJC84BFAisjo8Egigt4kE=
|
||||||
github.com/miekg/dns v1.1.58 h1:ca2Hdkz+cDg/7eNF6V56jjzuZ4aCAE+DbVkILdQWG/4=
|
github.com/miekg/dns v1.1.59 h1:C9EXc/UToRwKLhK5wKU/I4QVsBUc8kE6MkHBkeypWZs=
|
||||||
github.com/miekg/dns v1.1.58/go.mod h1:Ypv+3b/KadlvW9vJfXOTf300O4UqaHFzFCuHz+rPkBY=
|
github.com/miekg/dns v1.1.59/go.mod h1:nZpewl5p6IvctfgrckopVx2OlSEHPRO/U4SYkRklrEk=
|
||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
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/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||||
github.com/onsi/ginkgo/v2 v2.9.7 h1:06xGQy5www2oN160RtEZoTvnP2sPhEfePYmCDc2szss=
|
github.com/onsi/ginkgo/v2 v2.9.7 h1:06xGQy5www2oN160RtEZoTvnP2sPhEfePYmCDc2szss=
|
||||||
@@ -98,8 +95,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/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 h1:YbmpqPQEMdlk9oFSKYWRqVuu9qzNiOayIonKmv1gCXY=
|
||||||
github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1/go.mod h1:J2yAxTFPDjrDPhuAi9aWFz2L3ox9it4qAluBBbN0H5k=
|
github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1/go.mod h1:J2yAxTFPDjrDPhuAi9aWFz2L3ox9it4qAluBBbN0H5k=
|
||||||
github.com/sagernet/gomobile v0.1.1 h1:3vihRGyUfFTToHMeeak0UK6/ldt2MV2bcWKFi2VyECU=
|
github.com/sagernet/gomobile v0.1.3 h1:ohjIb1Ou2+1558PnZour3od69suSuvkdSVOlO1tC4B8=
|
||||||
github.com/sagernet/gomobile v0.1.1/go.mod h1:Pqq2+ZVvs10U7xK+UwJgwYWUykewi8H6vlslAO73n9E=
|
github.com/sagernet/gomobile v0.1.3/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 h1:DOkjByVeAR56dkszjnMZke4wr7yM/1xHaJF3G9olkEE=
|
||||||
github.com/sagernet/gvisor v0.0.0-20231209105102-8d27a30e436e/go.mod h1:fLxq/gtp0qzkaEwywlRRiGmjOK5ES/xUzyIKIFP2Asw=
|
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=
|
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 h1:iL5gZI3uFp0X6EslacyapiRz7LLSJyr4RajF/BhMVyE=
|
||||||
@@ -109,22 +106,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 h1:5Th31OC6yj8byLGkEnIYp6grlXfo1QYUfiYFGjewIdc=
|
||||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691/go.mod h1:B8lp4WkQ1PwNnrVMM6KyuFR20pU8jYBD+A4EhJovEXU=
|
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.2.18/go.mod h1:OL6k2F0vHmEzXz2KW19qQzu172FDgSbUSODylighuVo=
|
||||||
github.com/sagernet/sing v0.3.0 h1:PIDVFZHnQAAYRL1UYqNM+0k5s8f/tb1lUW6UDcQiOc8=
|
github.com/sagernet/sing v0.3.8 h1:gm4JKalPhydMYX2zFOTnnd4TXtM/16WFRqSjMepYQQk=
|
||||||
github.com/sagernet/sing v0.3.0/go.mod h1:9pfuAH6mZfgnz/YjP6xu5sxx882rfyjpcrTdUpd6w3g=
|
github.com/sagernet/sing v0.3.8/go.mod h1:+60H3Cm91RnL9dpVGWDPHt0zTQImO9Vfqt9a4rSambI=
|
||||||
github.com/sagernet/sing-dns v0.1.12 h1:1HqZ+ln+Rezx/aJMStaS0d7oPeX2EobSV1NT537kyj4=
|
github.com/sagernet/sing-dns v0.1.14 h1:kxE/Ik3jMXmD3sXsdt9MgrNzLFWt64mghV+MQqzyf40=
|
||||||
github.com/sagernet/sing-dns v0.1.12/go.mod h1:rx/DTOisneQpCgNQ4jbFU/JNEtnz0lYcHXenlVzpjEU=
|
github.com/sagernet/sing-dns v0.1.14/go.mod h1:AA+vZMNovuPN5i/sPnfF6756Nq94nzb5nXodMWbta5w=
|
||||||
github.com/sagernet/sing-mux v0.2.0 h1:4C+vd8HztJCWNYfufvgL49xaOoOHXty2+EAjnzN3IYo=
|
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-mux v0.2.0/go.mod h1:khzr9AOPocLa+g53dBplwNDz4gdsyx/YM3swtAhlkHQ=
|
||||||
github.com/sagernet/sing-quic v0.1.7 h1:SC45rAnvQ9BuyO0V186OdDScMBitmZo0XcM9LBYRUW8=
|
github.com/sagernet/sing-quic v0.1.12 h1:4KjG7LASZck0svGDfzf3aVNidRRQRC/w2HUMk/PHiNE=
|
||||||
github.com/sagernet/sing-quic v0.1.7/go.mod h1:wUg1Z6AGKeJguruZo0lhrie3dqPiRCKaidLAbK2ttEs=
|
github.com/sagernet/sing-quic v0.1.12/go.mod h1:L+VtzvuPbf8VW8F4R7KiygqpXY4lO7t2wwcQuHjh8Ew=
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.6 h1:xr7ylAS/q1cQYS8oxKKajhuQcchd5VJJ4K4UZrrpp0s=
|
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-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 h1:wpZNs6wKnR7mh1wV9OHwOyUr21VkS3wKFHi+8XwgADg=
|
||||||
github.com/sagernet/sing-shadowsocks2 v0.2.0/go.mod h1:RnXS0lExcDAovvDeniJ4IKa2IuChrdipolPYWBv9hWQ=
|
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 h1:aTgBSJEgnumzFenPvc+kbD9/W0PywzWevnVpEx6Tw3k=
|
||||||
github.com/sagernet/sing-shadowtls v0.1.4/go.mod h1:F8NBgsY5YN2beQavdgdm1DPlhaKQlaL6lpDdcBglGK4=
|
github.com/sagernet/sing-shadowtls v0.1.4/go.mod h1:F8NBgsY5YN2beQavdgdm1DPlhaKQlaL6lpDdcBglGK4=
|
||||||
github.com/sagernet/sing-tun v0.2.0 h1:/WloeRTWvwKIuiIvY+HVJaaZsTGb3XqJXZUbn6wVhz4=
|
github.com/sagernet/sing-tun v0.2.6 h1:FKXzh34uuO5RStBgf3Zi+Txan5eS9YTVOQrJRAbJBHk=
|
||||||
github.com/sagernet/sing-tun v0.2.0/go.mod h1:vJHzPAbwFUHxdFHUFQlH+Fb4rT3K4/SHODdMLU1rrQI=
|
github.com/sagernet/sing-tun v0.2.6/go.mod h1:MKAAHUzVfj7d9zos4lsz6wjXu86/mJyd/gejiAnWj/w=
|
||||||
github.com/sagernet/sing-vmess v0.1.8 h1:XVWad1RpTy9b5tPxdm5MCU8cGfrTGdR8qCq6HV2aCNc=
|
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/sing-vmess v0.1.8/go.mod h1:vhx32UNzTDUkNwOyIjcZQohre1CaytquC5mPplId8uA=
|
||||||
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ=
|
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ=
|
||||||
@@ -137,8 +134,6 @@ 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/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 h1:6uUiZcDRnZSAegryaUGwPC/Fj13JSHwiTftrXhMmYOc=
|
||||||
github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854/go.mod h1:LtfoSK3+NG57tvnVEHgcuBW9ujgE8enPSgzgwStwCAA=
|
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 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
|
||||||
github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
|
github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
|
||||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||||
@@ -147,8 +142,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.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.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.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 h1:tHNk7XK9GkmKUR6Gh8gVBKXc2MVSZ4G/NnWLtzw4gNA=
|
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/u-root/uio v0.0.0-20230220225925-ffce2a382923/go.mod h1:eLL9Nub3yfAho7qB0MzZizFhTU2QkLeoVsWdHtDW264=
|
||||||
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695APm9hlsSMoOoE65U4/TcqNj90mc69Rlg=
|
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695APm9hlsSMoOoE65U4/TcqNj90mc69Rlg=
|
||||||
@@ -159,26 +154,27 @@ github.com/zeebo/blake3 v0.2.3 h1:TFoLXsjeXqRNFxSbk35Dk4YtszE/MQQGK10BH4ptoTg=
|
|||||||
github.com/zeebo/blake3 v0.2.3/go.mod h1:mjJjZpnsyIVtVgTOSpJ9vmRE4wgDeyt2HU3qXvvKCaQ=
|
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 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo=
|
||||||
github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4=
|
github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4=
|
||||||
go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
|
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
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/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||||
go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
|
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
||||||
go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
|
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M=
|
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=
|
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-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.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
||||||
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
|
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
|
||||||
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
|
||||||
golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc h1:ao2WRsKSzW6KuUY9IWPwWahcHCgR0s52IfwutMfEbdM=
|
golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f h1:99ci1mjWVBWwJiEKYY6jWa4d2nTQVIEhZIptnrVb1XY=
|
||||||
golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI=
|
golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI=
|
||||||
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
|
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
|
||||||
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
golang.org/x/mod v0.17.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-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
|
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
|
||||||
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
|
||||||
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
|
||||||
|
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
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-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@@ -188,10 +184,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.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.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.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
|
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
|
||||||
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.19.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.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE=
|
golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
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.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||||
@@ -199,19 +195,16 @@ 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 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||||
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
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.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc=
|
golang.org/x/tools v0.20.0 h1:hz/CVckiOxybQvFw6h7b/q80NTr9IUQb4s1IIzW7KNY=
|
||||||
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
|
golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg=
|
||||||
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 h1:CawjfCvYQH2OU3/TnxLx97WDSUDRABfT18pCOYwc2GE=
|
||||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6/go.mod h1:3rxYc4HtVcSG9gVaTs2GEBdehh+sYPOwKtyUWEOTb80=
|
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6/go.mod h1:3rxYc4HtVcSG9gVaTs2GEBdehh+sYPOwKtyUWEOTb80=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97 h1:6GQBEOdGkX6MMTLT9V+TjtIRZCw9VPD5Z+yHY9wMgS0=
|
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-20231002182017-d307bd883b97/go.mod h1:v7nGkzlmW8P3n/bKmWBn2WpBjpOEx8Q6gMueudAmKfY=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY=
|
||||||
google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU=
|
google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM=
|
||||||
google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM=
|
google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA=
|
||||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
||||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||||
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 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 h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
|
||||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
|||||||
@@ -116,6 +116,7 @@ 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 {
|
func (h *Hysteria) newConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
|
||||||
ctx = log.ContextWithNewID(ctx)
|
ctx = log.ContextWithNewID(ctx)
|
||||||
metadata = h.createMetadata(conn, metadata)
|
metadata = h.createMetadata(conn, metadata)
|
||||||
|
h.logger.InfoContext(ctx, "inbound connection from ", metadata.Source)
|
||||||
userID, _ := auth.UserFromContext[int](ctx)
|
userID, _ := auth.UserFromContext[int](ctx)
|
||||||
if userName := h.userNameList[userID]; userName != "" {
|
if userName := h.userNameList[userID]; userName != "" {
|
||||||
metadata.User = userName
|
metadata.User = userName
|
||||||
@@ -129,6 +130,7 @@ 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 {
|
func (h *Hysteria) newPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
|
||||||
ctx = log.ContextWithNewID(ctx)
|
ctx = log.ContextWithNewID(ctx)
|
||||||
metadata = h.createPacketMetadata(conn, metadata)
|
metadata = h.createPacketMetadata(conn, metadata)
|
||||||
|
h.logger.InfoContext(ctx, "inbound packet connection from ", metadata.Source)
|
||||||
userID, _ := auth.UserFromContext[int](ctx)
|
userID, _ := auth.UserFromContext[int](ctx)
|
||||||
if userName := h.userNameList[userID]; userName != "" {
|
if userName := h.userNameList[userID]; userName != "" {
|
||||||
metadata.User = userName
|
metadata.User = userName
|
||||||
|
|||||||
@@ -127,6 +127,7 @@ 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 {
|
func (h *Hysteria2) newConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
|
||||||
ctx = log.ContextWithNewID(ctx)
|
ctx = log.ContextWithNewID(ctx)
|
||||||
metadata = h.createMetadata(conn, metadata)
|
metadata = h.createMetadata(conn, metadata)
|
||||||
|
h.logger.InfoContext(ctx, "inbound connection from ", metadata.Source)
|
||||||
userID, _ := auth.UserFromContext[int](ctx)
|
userID, _ := auth.UserFromContext[int](ctx)
|
||||||
if userName := h.userNameList[userID]; userName != "" {
|
if userName := h.userNameList[userID]; userName != "" {
|
||||||
metadata.User = userName
|
metadata.User = userName
|
||||||
@@ -140,6 +141,7 @@ 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 {
|
func (h *Hysteria2) newPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
|
||||||
ctx = log.ContextWithNewID(ctx)
|
ctx = log.ContextWithNewID(ctx)
|
||||||
metadata = h.createPacketMetadata(conn, metadata)
|
metadata = h.createPacketMetadata(conn, metadata)
|
||||||
|
h.logger.InfoContext(ctx, "inbound packet connection from ", metadata.Source)
|
||||||
userID, _ := auth.UserFromContext[int](ctx)
|
userID, _ := auth.UserFromContext[int](ctx)
|
||||||
if userName := h.userNameList[userID]; userName != "" {
|
if userName := h.userNameList[userID]; userName != "" {
|
||||||
metadata.User = userName
|
metadata.User = userName
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ 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 {
|
func (h *TUIC) newConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
|
||||||
ctx = log.ContextWithNewID(ctx)
|
ctx = log.ContextWithNewID(ctx)
|
||||||
metadata = h.createMetadata(conn, metadata)
|
metadata = h.createMetadata(conn, metadata)
|
||||||
|
h.logger.InfoContext(ctx, "inbound connection from ", metadata.Source)
|
||||||
userID, _ := auth.UserFromContext[int](ctx)
|
userID, _ := auth.UserFromContext[int](ctx)
|
||||||
if userName := h.userNameList[userID]; userName != "" {
|
if userName := h.userNameList[userID]; userName != "" {
|
||||||
metadata.User = userName
|
metadata.User = userName
|
||||||
@@ -111,6 +112,7 @@ 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 {
|
func (h *TUIC) newPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
|
||||||
ctx = log.ContextWithNewID(ctx)
|
ctx = log.ContextWithNewID(ctx)
|
||||||
metadata = h.createPacketMetadata(conn, metadata)
|
metadata = h.createPacketMetadata(conn, metadata)
|
||||||
|
h.logger.InfoContext(ctx, "inbound packet connection from ", metadata.Source)
|
||||||
userID, _ := auth.UserFromContext[int](ctx)
|
userID, _ := auth.UserFromContext[int](ctx)
|
||||||
if userName := h.userNameList[userID]; userName != "" {
|
if userName := h.userNameList[userID]; userName != "" {
|
||||||
metadata.User = userName
|
metadata.User = userName
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ func (t *Tun) Start() error {
|
|||||||
tunInterface tun.Tun
|
tunInterface tun.Tun
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
monitor := taskmonitor.New(t.logger, C.DefaultStartTimeout)
|
monitor := taskmonitor.New(t.logger, C.StartTimeout)
|
||||||
monitor.Start("open tun interface")
|
monitor.Start("open tun interface")
|
||||||
if t.platformInterface != nil {
|
if t.platformInterface != nil {
|
||||||
tunInterface, err = t.platformInterface.OpenTun(&t.tunOptions, t.platformOptions)
|
tunInterface, err = t.platformInterface.OpenTun(&t.tunOptions, t.platformOptions)
|
||||||
|
|||||||
@@ -133,7 +133,6 @@ nav:
|
|||||||
- WireGuard: configuration/outbound/wireguard.md
|
- WireGuard: configuration/outbound/wireguard.md
|
||||||
- Hysteria: configuration/outbound/hysteria.md
|
- Hysteria: configuration/outbound/hysteria.md
|
||||||
- ShadowTLS: configuration/outbound/shadowtls.md
|
- ShadowTLS: configuration/outbound/shadowtls.md
|
||||||
- ShadowsocksR: configuration/outbound/shadowsocksr.md
|
|
||||||
- VLESS: configuration/outbound/vless.md
|
- VLESS: configuration/outbound/vless.md
|
||||||
- TUIC: configuration/outbound/tuic.md
|
- TUIC: configuration/outbound/tuic.md
|
||||||
- Hysteria2: configuration/outbound/hysteria2.md
|
- Hysteria2: configuration/outbound/hysteria2.md
|
||||||
@@ -236,4 +235,4 @@ plugins:
|
|||||||
|
|
||||||
Manual: 手册
|
Manual: 手册
|
||||||
reconfigure_material: true
|
reconfigure_material: true
|
||||||
reconfigure_search: true
|
reconfigure_search: true
|
||||||
|
|||||||
@@ -148,7 +148,7 @@ func (h *Direct) ListenPacket(ctx context.Context, destination M.Socksaddr) (net
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
conn = h.loopBack.NewPacketConn(conn)
|
conn = h.loopBack.NewPacketConn(bufio.NewPacketConn(conn), destination)
|
||||||
if originDestination != destination {
|
if originDestination != destination {
|
||||||
conn = bufio.NewNATPacketConn(bufio.NewPacketConn(conn), destination, originDestination)
|
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 {
|
func (h *Direct) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
|
||||||
if h.loopBack.CheckConn(metadata.Source.AddrPort()) {
|
if h.loopBack.CheckConn(metadata.Source.AddrPort(), M.AddrPortFromNet(conn.LocalAddr())) {
|
||||||
return E.New("reject loopback connection to ", metadata.Destination)
|
return E.New("reject loopback connection to ", metadata.Destination)
|
||||||
}
|
}
|
||||||
return NewConnection(ctx, h, conn, metadata)
|
return NewConnection(ctx, h, conn, metadata)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Direct) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
|
func (h *Direct) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
|
||||||
if h.loopBack.CheckPacketConn(metadata.Source.AddrPort()) {
|
if h.loopBack.CheckPacketConn(metadata.Source.AddrPort(), M.AddrPortFromNet(conn.LocalAddr())) {
|
||||||
return E.New("reject loopback packet connection to ", metadata.Destination)
|
return E.New("reject loopback packet connection to ", metadata.Destination)
|
||||||
}
|
}
|
||||||
return NewPacketConnection(ctx, h, conn, metadata)
|
return NewPacketConnection(ctx, h, conn, metadata)
|
||||||
|
|||||||
@@ -6,61 +6,87 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
M "github.com/sagernet/sing/common/metadata"
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
|
N "github.com/sagernet/sing/common/network"
|
||||||
)
|
)
|
||||||
|
|
||||||
type loopBackDetector struct {
|
type loopBackDetector struct {
|
||||||
|
// router adapter.Router
|
||||||
connAccess sync.RWMutex
|
connAccess sync.RWMutex
|
||||||
packetConnAccess sync.RWMutex
|
packetConnAccess sync.RWMutex
|
||||||
connMap map[netip.AddrPort]bool
|
connMap map[netip.AddrPort]netip.AddrPort
|
||||||
packetConnMap map[netip.AddrPort]bool
|
packetConnMap map[uint16]uint16
|
||||||
}
|
}
|
||||||
|
|
||||||
func newLoopBackDetector() *loopBackDetector {
|
func newLoopBackDetector( /*router adapter.Router*/ ) *loopBackDetector {
|
||||||
return &loopBackDetector{
|
return &loopBackDetector{
|
||||||
connMap: make(map[netip.AddrPort]bool),
|
// router: router,
|
||||||
packetConnMap: make(map[netip.AddrPort]bool),
|
connMap: make(map[netip.AddrPort]netip.AddrPort),
|
||||||
|
packetConnMap: make(map[uint16]uint16),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *loopBackDetector) NewConn(conn net.Conn) net.Conn {
|
func (l *loopBackDetector) NewConn(conn net.Conn) net.Conn {
|
||||||
connAddr := M.AddrPortFromNet(conn.LocalAddr())
|
source := M.AddrPortFromNet(conn.LocalAddr())
|
||||||
if !connAddr.IsValid() {
|
if !source.IsValid() {
|
||||||
return conn
|
return conn
|
||||||
}
|
}
|
||||||
if udpConn, isUDPConn := conn.(abstractUDPConn); isUDPConn {
|
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.packetConnAccess.Lock()
|
||||||
l.packetConnMap[connAddr] = true
|
l.packetConnMap[source.Port()] = M.AddrPortFromNet(conn.RemoteAddr()).Port()
|
||||||
l.packetConnAccess.Unlock()
|
l.packetConnAccess.Unlock()
|
||||||
return &loopBackDetectUDPWrapper{abstractUDPConn: udpConn, detector: l, connAddr: connAddr}
|
return &loopBackDetectUDPWrapper{abstractUDPConn: udpConn, detector: l, connPort: source.Port()}
|
||||||
} else {
|
} else {
|
||||||
l.connAccess.Lock()
|
l.connAccess.Lock()
|
||||||
l.connMap[connAddr] = true
|
l.connMap[source] = M.AddrPortFromNet(conn.RemoteAddr())
|
||||||
l.connAccess.Unlock()
|
l.connAccess.Unlock()
|
||||||
return &loopBackDetectWrapper{Conn: conn, detector: l, connAddr: connAddr}
|
return &loopBackDetectWrapper{Conn: conn, detector: l, connAddr: source}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *loopBackDetector) NewPacketConn(conn net.PacketConn) net.PacketConn {
|
func (l *loopBackDetector) NewPacketConn(conn N.NetPacketConn, destination M.Socksaddr) N.NetPacketConn {
|
||||||
connAddr := M.AddrPortFromNet(conn.LocalAddr())
|
source := M.AddrPortFromNet(conn.LocalAddr())
|
||||||
if !connAddr.IsValid() {
|
if !source.IsValid() {
|
||||||
return conn
|
return conn
|
||||||
}
|
}
|
||||||
l.packetConnAccess.Lock()
|
l.packetConnAccess.Lock()
|
||||||
l.packetConnMap[connAddr] = true
|
l.packetConnMap[source.Port()] = destination.AddrPort().Port()
|
||||||
l.packetConnAccess.Unlock()
|
l.packetConnAccess.Unlock()
|
||||||
return &loopBackDetectPacketWrapper{PacketConn: conn, detector: l, connAddr: connAddr}
|
return &loopBackDetectPacketWrapper{NetPacketConn: conn, detector: l, connPort: source.Port()}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *loopBackDetector) CheckConn(connAddr netip.AddrPort) bool {
|
func (l *loopBackDetector) CheckConn(source netip.AddrPort, local netip.AddrPort) bool {
|
||||||
l.connAccess.RLock()
|
l.connAccess.RLock()
|
||||||
defer l.connAccess.RUnlock()
|
defer l.connAccess.RUnlock()
|
||||||
return l.connMap[connAddr]
|
destination, loaded := l.connMap[source]
|
||||||
|
return loaded && destination != local
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *loopBackDetector) CheckPacketConn(connAddr netip.AddrPort) bool {
|
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
|
||||||
|
}
|
||||||
l.packetConnAccess.RLock()
|
l.packetConnAccess.RLock()
|
||||||
defer l.packetConnAccess.RUnlock()
|
defer l.packetConnAccess.RUnlock()
|
||||||
return l.packetConnMap[connAddr]
|
destinationPort, loaded := l.packetConnMap[source.Port()]
|
||||||
|
return loaded && destinationPort != local.Port()
|
||||||
}
|
}
|
||||||
|
|
||||||
type loopBackDetectWrapper struct {
|
type loopBackDetectWrapper struct {
|
||||||
@@ -92,19 +118,19 @@ func (w *loopBackDetectWrapper) Upstream() any {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type loopBackDetectPacketWrapper struct {
|
type loopBackDetectPacketWrapper struct {
|
||||||
net.PacketConn
|
N.NetPacketConn
|
||||||
detector *loopBackDetector
|
detector *loopBackDetector
|
||||||
connAddr netip.AddrPort
|
connPort uint16
|
||||||
closeOnce sync.Once
|
closeOnce sync.Once
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *loopBackDetectPacketWrapper) Close() error {
|
func (w *loopBackDetectPacketWrapper) Close() error {
|
||||||
w.closeOnce.Do(func() {
|
w.closeOnce.Do(func() {
|
||||||
w.detector.packetConnAccess.Lock()
|
w.detector.packetConnAccess.Lock()
|
||||||
delete(w.detector.packetConnMap, w.connAddr)
|
delete(w.detector.packetConnMap, w.connPort)
|
||||||
w.detector.packetConnAccess.Unlock()
|
w.detector.packetConnAccess.Unlock()
|
||||||
})
|
})
|
||||||
return w.PacketConn.Close()
|
return w.NetPacketConn.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *loopBackDetectPacketWrapper) ReaderReplaceable() bool {
|
func (w *loopBackDetectPacketWrapper) ReaderReplaceable() bool {
|
||||||
@@ -116,7 +142,7 @@ func (w *loopBackDetectPacketWrapper) WriterReplaceable() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (w *loopBackDetectPacketWrapper) Upstream() any {
|
func (w *loopBackDetectPacketWrapper) Upstream() any {
|
||||||
return w.PacketConn
|
return w.NetPacketConn
|
||||||
}
|
}
|
||||||
|
|
||||||
type abstractUDPConn interface {
|
type abstractUDPConn interface {
|
||||||
@@ -127,14 +153,14 @@ type abstractUDPConn interface {
|
|||||||
type loopBackDetectUDPWrapper struct {
|
type loopBackDetectUDPWrapper struct {
|
||||||
abstractUDPConn
|
abstractUDPConn
|
||||||
detector *loopBackDetector
|
detector *loopBackDetector
|
||||||
connAddr netip.AddrPort
|
connPort uint16
|
||||||
closeOnce sync.Once
|
closeOnce sync.Once
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *loopBackDetectUDPWrapper) Close() error {
|
func (w *loopBackDetectUDPWrapper) Close() error {
|
||||||
w.closeOnce.Do(func() {
|
w.closeOnce.Do(func() {
|
||||||
w.detector.packetConnAccess.Lock()
|
w.detector.packetConnAccess.Lock()
|
||||||
delete(w.detector.packetConnMap, w.connAddr)
|
delete(w.detector.packetConnMap, w.connPort)
|
||||||
w.detector.packetConnAccess.Unlock()
|
w.detector.packetConnAccess.Unlock()
|
||||||
})
|
})
|
||||||
return w.abstractUDPConn.Close()
|
return w.abstractUDPConn.Close()
|
||||||
|
|||||||
@@ -241,7 +241,8 @@ func (d *DNS) newPacketConnection(ctx context.Context, conn N.PacketConn, readWa
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
timeout.Update()
|
timeout.Update()
|
||||||
responseBuffer := buf.NewPacket()
|
response = truncateDNSMessage(response, 512) // TODO: add an option to custom UDP buffer size
|
||||||
|
responseBuffer := buf.NewSize(dns.FixedPacketSize)
|
||||||
responseBuffer.Resize(1024, 0)
|
responseBuffer.Resize(1024, 0)
|
||||||
n, err := response.PackBuffer(responseBuffer.FreeBytes())
|
n, err := response.PackBuffer(responseBuffer.FreeBytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -263,3 +264,22 @@ func (d *DNS) newPacketConnection(ctx context.Context, conn N.PacketConn, readWa
|
|||||||
})
|
})
|
||||||
return group.Run(fastClose)
|
return group.Run(fastClose)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func truncateDNSMessage(response *mDNS.Msg, maxLen int) *mDNS.Msg {
|
||||||
|
responseLen := response.Len()
|
||||||
|
if responseLen <= maxLen {
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
newResponse := *response
|
||||||
|
response = &newResponse
|
||||||
|
for len(response.Answer) > 0 && responseLen > maxLen {
|
||||||
|
response.Answer = response.Answer[:len(response.Answer)-1]
|
||||||
|
response.Truncated = true
|
||||||
|
responseLen = response.Len()
|
||||||
|
}
|
||||||
|
if responseLen > maxLen {
|
||||||
|
response.Ns = nil
|
||||||
|
response.Extra = nil
|
||||||
|
}
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|||||||
@@ -125,7 +125,18 @@ func (s *URLTest) CheckOutbounds() {
|
|||||||
|
|
||||||
func (s *URLTest) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
func (s *URLTest) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
||||||
s.group.Touch()
|
s.group.Touch()
|
||||||
outbound := s.group.Select(network)
|
var outbound adapter.Outbound
|
||||||
|
switch N.NetworkName(network) {
|
||||||
|
case N.NetworkTCP:
|
||||||
|
outbound = s.group.selectedOutboundTCP
|
||||||
|
case N.NetworkUDP:
|
||||||
|
outbound = s.group.selectedOutboundUDP
|
||||||
|
default:
|
||||||
|
return nil, E.Extend(N.ErrUnknownNetwork, network)
|
||||||
|
}
|
||||||
|
if outbound == nil {
|
||||||
|
outbound, _ = s.group.Select(network)
|
||||||
|
}
|
||||||
if outbound == nil {
|
if outbound == nil {
|
||||||
return nil, E.New("missing supported outbound")
|
return nil, E.New("missing supported outbound")
|
||||||
}
|
}
|
||||||
@@ -140,7 +151,10 @@ func (s *URLTest) DialContext(ctx context.Context, network string, destination M
|
|||||||
|
|
||||||
func (s *URLTest) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
|
func (s *URLTest) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
|
||||||
s.group.Touch()
|
s.group.Touch()
|
||||||
outbound := s.group.Select(N.NetworkUDP)
|
outbound := s.group.selectedOutboundUDP
|
||||||
|
if outbound == nil {
|
||||||
|
outbound, _ = s.group.Select(N.NetworkUDP)
|
||||||
|
}
|
||||||
if outbound == nil {
|
if outbound == nil {
|
||||||
return nil, E.New("missing supported outbound")
|
return nil, E.New("missing supported outbound")
|
||||||
}
|
}
|
||||||
@@ -271,7 +285,7 @@ func (g *URLTestGroup) Close() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *URLTestGroup) Select(network string) adapter.Outbound {
|
func (g *URLTestGroup) Select(network string) (adapter.Outbound, bool) {
|
||||||
var minDelay uint16
|
var minDelay uint16
|
||||||
var minTime time.Time
|
var minTime time.Time
|
||||||
var minOutbound adapter.Outbound
|
var minOutbound adapter.Outbound
|
||||||
@@ -294,11 +308,11 @@ func (g *URLTestGroup) Select(network string) adapter.Outbound {
|
|||||||
if !common.Contains(detour.Network(), network) {
|
if !common.Contains(detour.Network(), network) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
minOutbound = detour
|
return detour, false
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
return nil, false
|
||||||
}
|
}
|
||||||
return minOutbound
|
return minOutbound, true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *URLTestGroup) loopCheck() {
|
func (g *URLTestGroup) loopCheck() {
|
||||||
@@ -382,14 +396,12 @@ func (g *URLTestGroup) urlTest(ctx context.Context, force bool) (map[string]uint
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (g *URLTestGroup) performUpdateCheck() {
|
func (g *URLTestGroup) performUpdateCheck() {
|
||||||
outbound := g.Select(N.NetworkTCP)
|
|
||||||
var updated bool
|
var updated bool
|
||||||
if outbound != nil && outbound != g.selectedOutboundTCP {
|
if outbound, exists := g.Select(N.NetworkTCP); outbound != nil && (g.selectedOutboundTCP == nil || (exists && outbound != g.selectedOutboundTCP)) {
|
||||||
g.selectedOutboundTCP = outbound
|
g.selectedOutboundTCP = outbound
|
||||||
updated = true
|
updated = true
|
||||||
}
|
}
|
||||||
outbound = g.Select(N.NetworkUDP)
|
if outbound, exists := g.Select(N.NetworkUDP); outbound != nil && (g.selectedOutboundUDP == nil || (exists && outbound != g.selectedOutboundUDP)) {
|
||||||
if outbound != nil && outbound != g.selectedOutboundUDP {
|
|
||||||
g.selectedOutboundUDP = outbound
|
g.selectedOutboundUDP = outbound
|
||||||
updated = true
|
updated = true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -415,11 +415,14 @@ func (r *Router) Initialize(inbounds []adapter.Inbound, outbounds []adapter.Outb
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *Router) Outbounds() []adapter.Outbound {
|
func (r *Router) Outbounds() []adapter.Outbound {
|
||||||
|
if !r.started {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
return r.outbounds
|
return r.outbounds
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Router) PreStart() error {
|
func (r *Router) PreStart() error {
|
||||||
monitor := taskmonitor.New(r.logger, C.DefaultStartTimeout)
|
monitor := taskmonitor.New(r.logger, C.StartTimeout)
|
||||||
if r.interfaceMonitor != nil {
|
if r.interfaceMonitor != nil {
|
||||||
monitor.Start("initialize interface monitor")
|
monitor.Start("initialize interface monitor")
|
||||||
err := r.interfaceMonitor.Start()
|
err := r.interfaceMonitor.Start()
|
||||||
@@ -448,7 +451,7 @@ func (r *Router) PreStart() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *Router) Start() error {
|
func (r *Router) Start() error {
|
||||||
monitor := taskmonitor.New(r.logger, C.DefaultStartTimeout)
|
monitor := taskmonitor.New(r.logger, C.StartTimeout)
|
||||||
if r.needGeoIPDatabase {
|
if r.needGeoIPDatabase {
|
||||||
monitor.Start("initialize geoip database")
|
monitor.Start("initialize geoip database")
|
||||||
err := r.prepareGeoIPDatabase()
|
err := r.prepareGeoIPDatabase()
|
||||||
@@ -557,13 +560,12 @@ func (r *Router) Start() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if needWIFIStateFromRuleSet || r.needWIFIState {
|
if (needWIFIStateFromRuleSet || r.needWIFIState) && r.platformInterface != nil {
|
||||||
monitor.Start("initialize WIFI state")
|
monitor.Start("initialize WIFI state")
|
||||||
if r.platformInterface != nil && r.interfaceMonitor != nil {
|
r.needWIFIState = true
|
||||||
r.interfaceMonitor.RegisterCallback(func(_ int) {
|
r.interfaceMonitor.RegisterCallback(func(_ int) {
|
||||||
r.updateWIFIState()
|
r.updateWIFIState()
|
||||||
})
|
})
|
||||||
}
|
|
||||||
r.updateWIFIState()
|
r.updateWIFIState()
|
||||||
monitor.Finish()
|
monitor.Finish()
|
||||||
}
|
}
|
||||||
@@ -604,7 +606,7 @@ func (r *Router) Start() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *Router) Close() error {
|
func (r *Router) Close() error {
|
||||||
monitor := taskmonitor.New(r.logger, C.DefaultStopTimeout)
|
monitor := taskmonitor.New(r.logger, C.StopTimeout)
|
||||||
var err error
|
var err error
|
||||||
for i, rule := range r.rules {
|
for i, rule := range r.rules {
|
||||||
monitor.Start("close rule[", i, "]")
|
monitor.Start("close rule[", i, "]")
|
||||||
@@ -713,6 +715,10 @@ func (r *Router) RuleSet(tag string) (adapter.RuleSet, bool) {
|
|||||||
return ruleSet, loaded
|
return ruleSet, loaded
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *Router) NeedWIFIState() bool {
|
||||||
|
return r.needWIFIState
|
||||||
|
}
|
||||||
|
|
||||||
func (r *Router) RouteConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
|
func (r *Router) RouteConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
|
||||||
if r.pauseManager.IsDevicePaused() {
|
if r.pauseManager.IsDevicePaused() {
|
||||||
return E.New("reject connection to ", metadata.Destination, " while device paused")
|
return E.New("reject connection to ", metadata.Destination, " while device paused")
|
||||||
@@ -1176,6 +1182,10 @@ func (r *Router) updateWIFIState() {
|
|||||||
state := r.platformInterface.ReadWIFIState()
|
state := r.platformInterface.ReadWIFIState()
|
||||||
if state != r.wifiState {
|
if state != r.wifiState {
|
||||||
r.wifiState = state
|
r.wifiState = state
|
||||||
r.logger.Info("updated WIFI state: SSID=", state.SSID, ", BSSID=", state.BSSID)
|
if state.SSID == "" && state.BSSID == "" {
|
||||||
|
r.logger.Info("updated WIFI state: disconnected")
|
||||||
|
} else {
|
||||||
|
r.logger.Info("updated WIFI state: SSID=", state.SSID, ", BSSID=", state.BSSID)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ func NewRawIPCIDRItem(isSource bool, ipSet *netipx.IPSet) *IPCIDRItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *IPCIDRItem) Match(metadata *adapter.InboundContext) bool {
|
func (r *IPCIDRItem) Match(metadata *adapter.InboundContext) bool {
|
||||||
if r.isSource || metadata.QueryType != 0 || metadata.IPCIDRMatchSource {
|
if r.isSource || metadata.IPCIDRMatchSource {
|
||||||
return r.ipSet.Contains(metadata.Source.Addr)
|
return r.ipSet.Contains(metadata.Source.Addr)
|
||||||
} else {
|
} else {
|
||||||
if metadata.Destination.IsIP() {
|
if metadata.Destination.IsIP() {
|
||||||
|
|||||||
@@ -30,11 +30,11 @@ func NewDomainItem(domains []string, domainSuffixes []string) *DomainItem {
|
|||||||
description += " "
|
description += " "
|
||||||
}
|
}
|
||||||
if dsLen == 1 {
|
if dsLen == 1 {
|
||||||
description += "domainSuffix=" + domainSuffixes[0]
|
description += "domain_suffix=" + domainSuffixes[0]
|
||||||
} else if dsLen > 3 {
|
} else if dsLen > 3 {
|
||||||
description += "domainSuffix=[" + strings.Join(domainSuffixes[:3], " ") + "...]"
|
description += "domain_suffix=[" + strings.Join(domainSuffixes[:3], " ") + "...]"
|
||||||
} else {
|
} else {
|
||||||
description += "domainSuffix=[" + strings.Join(domainSuffixes, " ") + "]"
|
description += "domain_suffix=[" + strings.Join(domainSuffixes, " ") + "]"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &DomainItem{
|
return &DomainItem{
|
||||||
|
|||||||
@@ -24,12 +24,14 @@ func (r *IPIsPrivateItem) Match(metadata *adapter.InboundContext) bool {
|
|||||||
} else {
|
} else {
|
||||||
destination = metadata.Destination.Addr
|
destination = metadata.Destination.Addr
|
||||||
}
|
}
|
||||||
if destination.IsValid() && !N.IsPublicAddr(destination) {
|
if destination.IsValid() {
|
||||||
return true
|
return !N.IsPublicAddr(destination)
|
||||||
}
|
}
|
||||||
for _, destinationAddress := range metadata.DestinationAddresses {
|
if !r.isSource {
|
||||||
if !N.IsPublicAddr(destinationAddress) {
|
for _, destinationAddress := range metadata.DestinationAddresses {
|
||||||
return true
|
if !N.IsPublicAddr(destinationAddress) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
|||||||
@@ -89,6 +89,8 @@ func (c *Client) connect() (*grpc.ClientConn, error) {
|
|||||||
if conn != nil && conn.GetState() != connectivity.Shutdown {
|
if conn != nil && conn.GetState() != connectivity.Shutdown {
|
||||||
return conn, nil
|
return conn, nil
|
||||||
}
|
}
|
||||||
|
//nolint:staticcheck
|
||||||
|
//goland:noinspection GoDeprecation
|
||||||
conn, err := grpc.DialContext(c.ctx, c.serverAddr, c.dialOptions...)
|
conn, err := grpc.DialContext(c.ctx, c.serverAddr, c.dialOptions...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ func NewClientBind(ctx context.Context, errorHandler E.Handler, dialer N.Dialer,
|
|||||||
errorHandler: errorHandler,
|
errorHandler: errorHandler,
|
||||||
dialer: dialer,
|
dialer: dialer,
|
||||||
reservedForEndpoint: make(map[netip.AddrPort][3]uint8),
|
reservedForEndpoint: make(map[netip.AddrPort][3]uint8),
|
||||||
|
done: make(chan struct{}),
|
||||||
isConnect: isConnect,
|
isConnect: isConnect,
|
||||||
connectAddr: connectAddr,
|
connectAddr: connectAddr,
|
||||||
reserved: reserved,
|
reserved: reserved,
|
||||||
@@ -88,8 +89,7 @@ func (c *ClientBind) connect() (*wireConn, error) {
|
|||||||
func (c *ClientBind) Open(port uint16) (fns []conn.ReceiveFunc, actualPort uint16, err error) {
|
func (c *ClientBind) Open(port uint16) (fns []conn.ReceiveFunc, actualPort uint16, err error) {
|
||||||
select {
|
select {
|
||||||
case <-c.done:
|
case <-c.done:
|
||||||
err = net.ErrClosed
|
c.done = make(chan struct{})
|
||||||
return
|
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
return []conn.ReceiveFunc{c.receive}, 0, nil
|
return []conn.ReceiveFunc{c.receive}, 0, nil
|
||||||
@@ -129,19 +129,10 @@ func (c *ClientBind) receive(packets [][]byte, sizes []int, eps []conn.Endpoint)
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ClientBind) Reset() {
|
|
||||||
common.Close(common.PtrOrNil(c.conn))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ClientBind) Close() error {
|
func (c *ClientBind) Close() error {
|
||||||
common.Close(common.PtrOrNil(c.conn))
|
common.Close(common.PtrOrNil(c.conn))
|
||||||
if c.done == nil {
|
|
||||||
c.done = make(chan struct{})
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
select {
|
select {
|
||||||
case <-c.done:
|
case <-c.done:
|
||||||
return net.ErrClosed
|
|
||||||
default:
|
default:
|
||||||
close(c.done)
|
close(c.done)
|
||||||
}
|
}
|
||||||
@@ -166,7 +157,7 @@ func (c *ClientBind) Send(bufs [][]byte, ep conn.Endpoint) error {
|
|||||||
}
|
}
|
||||||
copy(b[1:4], reserved[:])
|
copy(b[1:4], reserved[:])
|
||||||
}
|
}
|
||||||
_, err = udpConn.WriteTo(b, M.SocksaddrFromNetIP(destination))
|
_, err = udpConn.WriteToUDPAddrPort(b, destination)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
udpConn.Close()
|
udpConn.Close()
|
||||||
return err
|
return err
|
||||||
@@ -193,10 +184,18 @@ func (c *ClientBind) SetReservedForEndpoint(destination netip.AddrPort, reserved
|
|||||||
|
|
||||||
type wireConn struct {
|
type wireConn struct {
|
||||||
net.PacketConn
|
net.PacketConn
|
||||||
|
conn net.Conn
|
||||||
access sync.Mutex
|
access sync.Mutex
|
||||||
done chan struct{}
|
done chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *wireConn) WriteToUDPAddrPort(b []byte, addr netip.AddrPort) (int, error) {
|
||||||
|
if w.conn != nil {
|
||||||
|
return w.conn.Write(b)
|
||||||
|
}
|
||||||
|
return w.PacketConn.WriteTo(b, M.SocksaddrFromNetIP(addr).UDPAddr())
|
||||||
|
}
|
||||||
|
|
||||||
func (w *wireConn) Close() error {
|
func (w *wireConn) Close() error {
|
||||||
w.access.Lock()
|
w.access.Lock()
|
||||||
defer w.access.Unlock()
|
defer w.access.Unlock()
|
||||||
|
|||||||
Reference in New Issue
Block a user