mirror of
https://github.com/SagerNet/sing-box.git
synced 2025-06-13 21:54:13 +08:00
Compare commits
68 Commits
230ac25f2c
...
bc01878605
Author | SHA1 | Date | |
---|---|---|---|
![]() |
bc01878605 | ||
![]() |
7489d3fff7 | ||
![]() |
794c5f81d1 | ||
![]() |
26bf8e3a0e | ||
![]() |
dcb7fb9880 | ||
![]() |
3e991b8068 | ||
![]() |
943d977bbb | ||
![]() |
af9ac17d0d | ||
![]() |
4760fd80ef | ||
![]() |
873b6194b7 | ||
![]() |
b801eb5eed | ||
![]() |
0044fca876 | ||
![]() |
40a8bf2a35 | ||
![]() |
fd460fbf52 | ||
![]() |
a69fd02e6a | ||
![]() |
ed57655e7e | ||
![]() |
e49704c819 | ||
![]() |
fc2724bac2 | ||
![]() |
9536f9f8b3 | ||
![]() |
cb7894b509 | ||
![]() |
0762a81cb3 | ||
![]() |
ab0c4f5c82 | ||
![]() |
b998ce8142 | ||
![]() |
855efbc0f6 | ||
![]() |
5a2a876c1b | ||
![]() |
9ec8100a91 | ||
![]() |
3f1b7919a9 | ||
![]() |
1ad4335d53 | ||
![]() |
f1023e4ea9 | ||
![]() |
989a0406d7 | ||
![]() |
ee6feb1d19 | ||
![]() |
1a5b1cd84c | ||
![]() |
ff6a00351f | ||
![]() |
4222b5d5f2 | ||
![]() |
f58172700a | ||
![]() |
91e3abceda | ||
![]() |
8c3eeb7208 | ||
![]() |
8df21000f8 | ||
![]() |
f3759a6065 | ||
![]() |
a5b95befb9 | ||
![]() |
90d5e7012a | ||
![]() |
a32065ee4f | ||
![]() |
7192e4b095 | ||
![]() |
69fbe7fa5d | ||
![]() |
d0e592a438 | ||
![]() |
2f315e233a | ||
![]() |
6de2817f54 | ||
![]() |
19dc4b8c54 | ||
![]() |
abf15ce617 | ||
![]() |
c77a1c4378 | ||
![]() |
011570491e | ||
![]() |
a8e3f53846 | ||
![]() |
17d7b212d4 | ||
![]() |
49c2b013d9 | ||
![]() |
d118cd28d2 | ||
![]() |
9b1a56f1f9 | ||
![]() |
11564386ef | ||
![]() |
9718996b62 | ||
![]() |
11ca25db71 | ||
![]() |
1e2293decf | ||
![]() |
bf16a98aab | ||
![]() |
882ccecae8 | ||
![]() |
c2cb4f4acd | ||
![]() |
d08375b1e3 | ||
![]() |
5a40ca4a8e | ||
![]() |
6ed29d81c1 | ||
![]() |
44329157c1 | ||
![]() |
5c495b3779 |
@ -1,12 +1,11 @@
|
|||||||
-s dir
|
-s dir
|
||||||
--name sing-box
|
--name sing-box
|
||||||
--category net
|
--category net
|
||||||
--license GPL-3.0-or-later
|
--license GPLv3-or-later
|
||||||
--description "The universal proxy platform."
|
--description "The universal proxy platform."
|
||||||
--url "https://sing-box.sagernet.org/"
|
--url "https://sing-box.sagernet.org/"
|
||||||
--maintainer "nekohasekai <contact-git@sekai.icu>"
|
--maintainer "nekohasekai <contact-git@sekai.icu>"
|
||||||
--deb-field "Bug: https://github.com/SagerNet/sing-box/issues"
|
--deb-field "Bug: https://github.com/SagerNet/sing-box/issues"
|
||||||
--no-deb-generate-changes
|
|
||||||
--config-files /etc/sing-box/config.json
|
--config-files /etc/sing-box/config.json
|
||||||
|
|
||||||
release/config/config.json=/etc/sing-box/config.json
|
release/config/config.json=/etc/sing-box/config.json
|
30
.fpm_openwrt
30
.fpm_openwrt
@ -1,30 +0,0 @@
|
|||||||
-s dir
|
|
||||||
--name sing-box
|
|
||||||
--category net
|
|
||||||
--license GPL-3.0-or-later
|
|
||||||
--description "The universal proxy platform."
|
|
||||||
--url "https://sing-box.sagernet.org/"
|
|
||||||
--maintainer "nekohasekai <contact-git@sekai.icu>"
|
|
||||||
--no-deb-generate-changes
|
|
||||||
|
|
||||||
--config-files /etc/config/sing-box
|
|
||||||
--config-files /etc/sing-box/config.json
|
|
||||||
|
|
||||||
--depends ca-bundle
|
|
||||||
--depends kmod-inet-diag
|
|
||||||
--depends kmod-tun
|
|
||||||
--depends firewall4
|
|
||||||
|
|
||||||
--before-remove release/config/openwrt.prerm
|
|
||||||
|
|
||||||
release/config/config.json=/etc/sing-box/config.json
|
|
||||||
|
|
||||||
release/config/openwrt.conf=/etc/config/sing-box
|
|
||||||
release/config/openwrt.init=/etc/init.d/sing-box
|
|
||||||
release/config/openwrt.keep=/lib/upgrade/keep.d/sing-box
|
|
||||||
|
|
||||||
release/completions/sing-box.bash=/usr/share/bash-completion/completions/sing-box.bash
|
|
||||||
release/completions/sing-box.fish=/usr/share/fish/vendor_completions.d/sing-box.fish
|
|
||||||
release/completions/sing-box.zsh=/usr/share/zsh/site-functions/_sing-box
|
|
||||||
|
|
||||||
LICENSE=/usr/share/licenses/sing-box/LICENSE
|
|
28
.github/deb2ipk.sh
vendored
28
.github/deb2ipk.sh
vendored
@ -1,28 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# mod from https://gist.github.com/pldubouilh/c5703052986bfdd404005951dee54683
|
|
||||||
|
|
||||||
set -e -o pipefail
|
|
||||||
|
|
||||||
PROJECT=$(dirname "$0")/../..
|
|
||||||
TMP_PATH=`mktemp -d`
|
|
||||||
cp $2 $TMP_PATH
|
|
||||||
pushd $TMP_PATH
|
|
||||||
|
|
||||||
DEB_NAME=`ls *.deb`
|
|
||||||
ar x $DEB_NAME
|
|
||||||
|
|
||||||
mkdir control
|
|
||||||
pushd control
|
|
||||||
tar xf ../control.tar.gz
|
|
||||||
rm md5sums
|
|
||||||
sed "s/Architecture:\\ \w*/Architecture:\\ $1/g" ./control -i
|
|
||||||
cat control
|
|
||||||
tar czf ../control.tar.gz ./*
|
|
||||||
popd
|
|
||||||
|
|
||||||
DEB_NAME=${DEB_NAME%.deb}
|
|
||||||
tar czf $DEB_NAME.ipk control.tar.gz data.tar.gz debian-binary
|
|
||||||
popd
|
|
||||||
|
|
||||||
cp $TMP_PATH/$DEB_NAME.ipk $3
|
|
||||||
rm -r $TMP_PATH
|
|
87
.github/workflows/build.yml
vendored
87
.github/workflows/build.yml
vendored
@ -68,38 +68,31 @@ jobs:
|
|||||||
- calculate_version
|
- calculate_version
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
|
os: [ linux, windows, darwin, android ]
|
||||||
|
arch: [ "386", amd64, arm64 ]
|
||||||
|
legacy_go: [ false ]
|
||||||
include:
|
include:
|
||||||
- { os: linux, arch: amd64, debian: amd64, rpm: x86_64, pacman: x86_64, openwrt: "x86_64" }
|
- { os: linux, arch: amd64, debian: amd64, rpm: x86_64, pacman: x86_64 }
|
||||||
- { os: linux, arch: "386", go386: sse2, debian: i386, rpm: i386, openwrt: "i386_pentium4" }
|
- { os: linux, arch: "386", debian: i386, rpm: i386 }
|
||||||
- { os: linux, arch: "386", go386: softfloat, openwrt: "i386_pentium-mmx" }
|
- { os: linux, arch: arm, goarm: "6", debian: armel, rpm: armv6hl }
|
||||||
- { os: linux, arch: arm64, debian: arm64, rpm: aarch64, pacman: aarch64, openwrt: "aarch64_cortex-a53 aarch64_cortex-a72 aarch64_cortex-a76 aarch64_generic" }
|
- { os: linux, arch: arm, goarm: "7", debian: armhf, rpm: armv7hl, pacman: armv7hl }
|
||||||
- { os: linux, arch: arm, goarm: "5", openwrt: "arm_arm926ej-s arm_cortex-a7 arm_cortex-a9 arm_fa526 arm_xscale" }
|
- { os: linux, arch: arm64, debian: arm64, rpm: aarch64, pacman: aarch64 }
|
||||||
- { os: linux, arch: arm, goarm: "6", debian: armel, rpm: armv6hl, openwrt: "arm_arm1176jzf-s_vfp" }
|
- { os: linux, arch: mips64le, debian: mips64el, rpm: mips64el }
|
||||||
- { os: linux, arch: arm, goarm: "7", debian: armhf, rpm: armv7hl, pacman: armv7hl, openwrt: "arm_cortex-a5_vfpv4 arm_cortex-a7_neon-vfpv4 arm_cortex-a7_vfpv4 arm_cortex-a8_vfpv3 arm_cortex-a9_neon arm_cortex-a9_vfpv3-d16 arm_cortex-a15_neon-vfpv4" }
|
- { os: linux, arch: mipsle, debian: mipsel, rpm: mipsel }
|
||||||
- { os: linux, arch: mips, gomips: softfloat, openwrt: "mips_24kc mips_4kec mips_mips32" }
|
|
||||||
- { os: linux, arch: mipsle, gomips: hardfloat, debian: mipsel, rpm: mipsel, openwrt: "mipsel_24kc_24kf" }
|
|
||||||
- { os: linux, arch: mipsle, gomips: softfloat, openwrt: "mipsel_24kc mipsel_74kc mipsel_mips32" }
|
|
||||||
- { os: linux, arch: mips64, gomips: softfloat, openwrt: "mips64_mips64r2 mips64_octeonplus" }
|
|
||||||
- { os: linux, arch: mips64le, gomips: hardfloat, debian: mips64el, rpm: mips64el }
|
|
||||||
- { os: linux, arch: mips64le, gomips: softfloat, openwrt: "mips64el_mips64r2" }
|
|
||||||
- { os: linux, arch: s390x, debian: s390x, rpm: s390x }
|
- { os: linux, arch: s390x, debian: s390x, rpm: s390x }
|
||||||
- { os: linux, arch: ppc64le, debian: ppc64el, rpm: ppc64le }
|
- { os: linux, arch: ppc64le, debian: ppc64el, rpm: ppc64le }
|
||||||
- { os: linux, arch: riscv64, debian: riscv64, rpm: riscv64, openwrt: "riscv64_generic" }
|
- { os: linux, arch: riscv64, debian: riscv64, rpm: riscv64 }
|
||||||
- { os: linux, arch: loong64, debian: loongarch64, rpm: loongarch64, openwrt: "loongarch64_generic" }
|
- { os: linux, arch: loong64, debian: loongarch64, rpm: loongarch64 }
|
||||||
|
|
||||||
- { os: windows, arch: amd64 }
|
|
||||||
- { os: windows, arch: amd64, legacy_go: true }
|
|
||||||
- { os: windows, arch: "386" }
|
|
||||||
- { os: windows, arch: "386", legacy_go: true }
|
- { os: windows, arch: "386", legacy_go: true }
|
||||||
- { os: windows, arch: arm64 }
|
- { os: windows, arch: amd64, legacy_go: true }
|
||||||
|
|
||||||
- { os: darwin, arch: amd64 }
|
|
||||||
- { os: darwin, arch: arm64 }
|
|
||||||
|
|
||||||
|
- { os: android, arch: "386", ndk: "i686-linux-android21" }
|
||||||
|
- { os: android, arch: amd64, ndk: "x86_64-linux-android21" }
|
||||||
- { os: android, arch: arm64, ndk: "aarch64-linux-android21" }
|
- { os: android, arch: arm64, ndk: "aarch64-linux-android21" }
|
||||||
- { os: android, arch: arm, ndk: "armv7a-linux-androideabi21" }
|
- { os: android, arch: arm, ndk: "armv7a-linux-androideabi21" }
|
||||||
- { os: android, arch: amd64, ndk: "x86_64-linux-android21" }
|
exclude:
|
||||||
- { os: android, arch: "386", ndk: "i686-linux-android21" }
|
- { os: darwin, arch: "386" }
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
|
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
|
||||||
@ -154,10 +147,7 @@ jobs:
|
|||||||
CGO_ENABLED: "0"
|
CGO_ENABLED: "0"
|
||||||
GOOS: ${{ matrix.os }}
|
GOOS: ${{ matrix.os }}
|
||||||
GOARCH: ${{ matrix.arch }}
|
GOARCH: ${{ matrix.arch }}
|
||||||
GO386: ${{ matrix.go386 }}
|
|
||||||
GOARM: ${{ matrix.goarm }}
|
GOARM: ${{ matrix.goarm }}
|
||||||
GOMIPS: ${{ matrix.gomips }}
|
|
||||||
GOMIPS64: ${{ matrix.gomips }}
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
- name: Build Android
|
- name: Build Android
|
||||||
if: matrix.os == 'android'
|
if: matrix.os == 'android'
|
||||||
@ -177,19 +167,14 @@ jobs:
|
|||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
- name: Set name
|
- name: Set name
|
||||||
run: |-
|
run: |-
|
||||||
DIR_NAME="sing-box-${{ needs.calculate_version.outputs.version }}-${{ matrix.os }}-${{ matrix.arch }}"
|
ARM_VERSION=$([ -n '${{ matrix.goarm}}' ] && echo 'v${{ matrix.goarm}}' || true)
|
||||||
if [[ -n "${{ matrix.goarm }}" ]]; then
|
LEGACY=$([ '${{ matrix.legacy_go }}' = 'true' ] && echo "-legacy" || true)
|
||||||
DIR_NAME="${DIR_NAME}v${{ matrix.goarm }}"
|
DIR_NAME="sing-box-${{ needs.calculate_version.outputs.version }}-${{ matrix.os }}-${{ matrix.arch }}${ARM_VERSION}${LEGACY}"
|
||||||
elif [[ -n "${{ matrix.go386 }}" && "${{ matrix.go386 }}" != 'sse2' ]]; then
|
PKG_NAME="sing-box_${{ needs.calculate_version.outputs.version }}_${{ matrix.os }}_${{ matrix.arch }}${ARM_VERSION}"
|
||||||
DIR_NAME="${DIR_NAME}-${{ matrix.go386 }}"
|
|
||||||
elif [[ -n "${{ matrix.gomips }}" && "${{ matrix.gomips }}" != 'hardfloat' ]]; then
|
|
||||||
DIR_NAME="${DIR_NAME}-${{ matrix.gomips }}"
|
|
||||||
elif [[ "${{ matrix.legacy_go }}" == 'true' ]]; then
|
|
||||||
DIR_NAME="${DIR_NAME}-legacy"
|
|
||||||
fi
|
|
||||||
echo "DIR_NAME=${DIR_NAME}" >> "${GITHUB_ENV}"
|
echo "DIR_NAME=${DIR_NAME}" >> "${GITHUB_ENV}"
|
||||||
|
echo "PKG_NAME=${PKG_NAME}" >> "${GITHUB_ENV}"
|
||||||
PKG_VERSION="${{ needs.calculate_version.outputs.version }}"
|
PKG_VERSION="${{ needs.calculate_version.outputs.version }}"
|
||||||
PKG_VERSION="${PKG_VERSION//-/\~}-1"
|
PKG_VERSION="${PKG_VERSION//-/\~}"
|
||||||
echo "PKG_VERSION=${PKG_VERSION}" >> "${GITHUB_ENV}"
|
echo "PKG_VERSION=${PKG_VERSION}" >> "${GITHUB_ENV}"
|
||||||
- name: Package DEB
|
- name: Package DEB
|
||||||
if: matrix.debian != ''
|
if: matrix.debian != ''
|
||||||
@ -197,10 +182,9 @@ jobs:
|
|||||||
set -xeuo pipefail
|
set -xeuo pipefail
|
||||||
sudo gem install fpm
|
sudo gem install fpm
|
||||||
sudo apt-get install -y debsigs
|
sudo apt-get install -y debsigs
|
||||||
cp .fpm_systemd .fpm
|
|
||||||
fpm -t deb \
|
fpm -t deb \
|
||||||
-v "$PKG_VERSION" \
|
-v "$PKG_VERSION" \
|
||||||
-p "dist/sing-box_${{ needs.calculate_version.outputs.version }}_${{ matrix.os }}_${{ matrix.debian }}.deb" \
|
-p "dist/${PKG_NAME}.deb" \
|
||||||
--architecture ${{ matrix.debian }} \
|
--architecture ${{ matrix.debian }} \
|
||||||
dist/sing-box=/usr/bin/sing-box
|
dist/sing-box=/usr/bin/sing-box
|
||||||
curl -Lo '/tmp/debsigs.diff' 'https://gitlab.com/debsigs/debsigs/-/commit/160138f5de1ec110376d3c807b60a37388bc7c90.diff'
|
curl -Lo '/tmp/debsigs.diff' 'https://gitlab.com/debsigs/debsigs/-/commit/160138f5de1ec110376d3c807b60a37388bc7c90.diff'
|
||||||
@ -215,10 +199,9 @@ jobs:
|
|||||||
run: |-
|
run: |-
|
||||||
set -xeuo pipefail
|
set -xeuo pipefail
|
||||||
sudo gem install fpm
|
sudo gem install fpm
|
||||||
cp .fpm_systemd .fpm
|
|
||||||
fpm -t rpm \
|
fpm -t rpm \
|
||||||
-v "$PKG_VERSION" \
|
-v "$PKG_VERSION" \
|
||||||
-p "dist/sing-box_${{ needs.calculate_version.outputs.version }}_${{ matrix.os }}_${{ matrix.rpm }}.rpm" \
|
-p "dist/${PKG_NAME}.rpm" \
|
||||||
--architecture ${{ matrix.rpm }} \
|
--architecture ${{ matrix.rpm }} \
|
||||||
dist/sing-box=/usr/bin/sing-box
|
dist/sing-box=/usr/bin/sing-box
|
||||||
cat > $HOME/.rpmmacros <<EOF
|
cat > $HOME/.rpmmacros <<EOF
|
||||||
@ -235,27 +218,11 @@ jobs:
|
|||||||
set -xeuo pipefail
|
set -xeuo pipefail
|
||||||
sudo gem install fpm
|
sudo gem install fpm
|
||||||
sudo apt-get install -y libarchive-tools
|
sudo apt-get install -y libarchive-tools
|
||||||
cp .fpm_systemd .fpm
|
|
||||||
fpm -t pacman \
|
fpm -t pacman \
|
||||||
-v "$PKG_VERSION" \
|
-v "$PKG_VERSION" \
|
||||||
-p "dist/sing-box_${{ needs.calculate_version.outputs.version }}_${{ matrix.os }}_${{ matrix.pacman }}.pkg.tar.zst" \
|
-p "dist/${PKG_NAME}.pkg.tar.zst" \
|
||||||
--architecture ${{ matrix.pacman }} \
|
--architecture ${{ matrix.pacman }} \
|
||||||
dist/sing-box=/usr/bin/sing-box
|
dist/sing-box=/usr/bin/sing-box
|
||||||
- name: Package OpenWrt
|
|
||||||
if: matrix.openwrt != ''
|
|
||||||
run: |-
|
|
||||||
set -xeuo pipefail
|
|
||||||
sudo gem install fpm
|
|
||||||
cp .fpm_openwrt .fpm
|
|
||||||
fpm -t deb \
|
|
||||||
-v "$PKG_VERSION" \
|
|
||||||
-p "dist/openwrt.deb" \
|
|
||||||
--architecture all \
|
|
||||||
dist/sing-box=/usr/bin/sing-box
|
|
||||||
for architecture in ${{ matrix.openwrt }}; do
|
|
||||||
.github/deb2ipk.sh "$architecture" "dist/openwrt.deb" "dist/sing-box_${{ needs.calculate_version.outputs.version }}_openwrt_${architecture}.ipk"
|
|
||||||
done
|
|
||||||
rm "dist/openwrt.deb"
|
|
||||||
- name: Archive
|
- name: Archive
|
||||||
run: |
|
run: |
|
||||||
set -xeuo pipefail
|
set -xeuo pipefail
|
||||||
@ -275,7 +242,7 @@ jobs:
|
|||||||
- name: Upload artifact
|
- name: Upload artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: binary-${{ matrix.os }}_${{ matrix.arch }}${{ matrix.goarm && format('v{0}', matrix.goarm) }}${{ matrix.go386 && format('_{0}', matrix.go386) }}${{ matrix.gomips && format('_{0}', matrix.gomips) }}${{ matrix.legacy_go && '-legacy' || '' }}
|
name: binary-${{ matrix.os }}_${{ matrix.arch }}${{ matrix.goarm && format('v{0}', matrix.goarm) }}${{ matrix.legacy_go && '-legacy' || '' }}
|
||||||
path: "dist"
|
path: "dist"
|
||||||
build_android:
|
build_android:
|
||||||
name: Build Android
|
name: Build Android
|
||||||
|
4
Makefile
4
Makefile
@ -8,7 +8,7 @@ GOHOSTARCH = $(shell go env GOHOSTARCH)
|
|||||||
VERSION=$(shell CGO_ENABLED=0 GOOS=$(GOHOSTOS) GOARCH=$(GOHOSTARCH) go run ./cmd/internal/read_tag)
|
VERSION=$(shell CGO_ENABLED=0 GOOS=$(GOHOSTOS) GOARCH=$(GOHOSTARCH) go run ./cmd/internal/read_tag)
|
||||||
|
|
||||||
PARAMS = -v -trimpath -ldflags "-X 'github.com/sagernet/sing-box/constant.Version=$(VERSION)' -s -w -buildid="
|
PARAMS = -v -trimpath -ldflags "-X 'github.com/sagernet/sing-box/constant.Version=$(VERSION)' -s -w -buildid="
|
||||||
MAIN_PARAMS = $(PARAMS) -tags "$(TAGS)"
|
MAIN_PARAMS = $(PARAMS) -tags $(TAGS)
|
||||||
MAIN = ./cmd/sing-box
|
MAIN = ./cmd/sing-box
|
||||||
PREFIX ?= $(shell go env GOPATH)
|
PREFIX ?= $(shell go env GOPATH)
|
||||||
|
|
||||||
@ -24,7 +24,7 @@ ci_build:
|
|||||||
go build $(MAIN_PARAMS) $(MAIN)
|
go build $(MAIN_PARAMS) $(MAIN)
|
||||||
|
|
||||||
generate_completions:
|
generate_completions:
|
||||||
go run -v --tags "$(TAGS),generate,generate_completions" $(MAIN)
|
go run -v --tags $(TAGS),generate,generate_completions $(MAIN)
|
||||||
|
|
||||||
install:
|
install:
|
||||||
go build -o $(PREFIX)/bin/$(NAME) $(MAIN_PARAMS) $(MAIN)
|
go build -o $(PREFIX)/bin/$(NAME) $(MAIN_PARAMS) $(MAIN)
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 55f31c29bb68895ce544e0dfbf852b4b3e32b530
|
Subproject commit 8354b78e5d002d636827cfeed6ed5df8ea057452
|
@ -83,7 +83,6 @@ func NewWithOptions(options Options) (N.Dialer, error) {
|
|||||||
dialOptions.DomainStrategy != option.DomainStrategy(C.DomainStrategyAsIS) {
|
dialOptions.DomainStrategy != option.DomainStrategy(C.DomainStrategyAsIS) {
|
||||||
//nolint:staticcheck
|
//nolint:staticcheck
|
||||||
strategy = C.DomainStrategy(dialOptions.DomainStrategy)
|
strategy = C.DomainStrategy(dialOptions.DomainStrategy)
|
||||||
deprecated.Report(options.Context, deprecated.OptionLegacyDomainStrategyOptions)
|
|
||||||
}
|
}
|
||||||
server = dialOptions.DomainResolver.Server
|
server = dialOptions.DomainResolver.Server
|
||||||
dnsQueryOptions = adapter.DNSQueryOptions{
|
dnsQueryOptions = adapter.DNSQueryOptions{
|
||||||
@ -96,8 +95,7 @@ func NewWithOptions(options Options) (N.Dialer, error) {
|
|||||||
resolveFallbackDelay = time.Duration(dialOptions.FallbackDelay)
|
resolveFallbackDelay = time.Duration(dialOptions.FallbackDelay)
|
||||||
} else if options.DirectResolver {
|
} else if options.DirectResolver {
|
||||||
return nil, E.New("missing domain resolver for domain server address")
|
return nil, E.New("missing domain resolver for domain server address")
|
||||||
} else {
|
} else if defaultOptions.DomainResolver != "" {
|
||||||
if defaultOptions.DomainResolver != "" {
|
|
||||||
dnsQueryOptions = defaultOptions.DomainResolveOptions
|
dnsQueryOptions = defaultOptions.DomainResolveOptions
|
||||||
transport, loaded := dnsTransport.Transport(defaultOptions.DomainResolver)
|
transport, loaded := dnsTransport.Transport(defaultOptions.DomainResolver)
|
||||||
if !loaded {
|
if !loaded {
|
||||||
@ -115,14 +113,6 @@ func NewWithOptions(options Options) (N.Dialer, error) {
|
|||||||
deprecated.Report(options.Context, deprecated.OptionMissingDomainResolver)
|
deprecated.Report(options.Context, deprecated.OptionMissingDomainResolver)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if
|
|
||||||
//nolint:staticcheck
|
|
||||||
dialOptions.DomainStrategy != option.DomainStrategy(C.DomainStrategyAsIS) {
|
|
||||||
//nolint:staticcheck
|
|
||||||
dnsQueryOptions.Strategy = C.DomainStrategy(dialOptions.DomainStrategy)
|
|
||||||
deprecated.Report(options.Context, deprecated.OptionLegacyDomainStrategyOptions)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dialer = NewResolveDialer(
|
dialer = NewResolveDialer(
|
||||||
options.Context,
|
options.Context,
|
||||||
dialer,
|
dialer,
|
||||||
|
@ -89,9 +89,6 @@ func NewRealityServer(ctx context.Context, logger log.Logger, options option.Inb
|
|||||||
tlsConfig.MaxTimeDiff = time.Duration(options.Reality.MaxTimeDifference)
|
tlsConfig.MaxTimeDiff = time.Duration(options.Reality.MaxTimeDifference)
|
||||||
|
|
||||||
tlsConfig.ShortIds = make(map[[8]byte]bool)
|
tlsConfig.ShortIds = make(map[[8]byte]bool)
|
||||||
if len(options.Reality.ShortID) == 0 {
|
|
||||||
tlsConfig.ShortIds[[8]byte{0}] = true
|
|
||||||
} else {
|
|
||||||
for i, shortIDString := range options.Reality.ShortID {
|
for i, shortIDString := range options.Reality.ShortID {
|
||||||
var shortID [8]byte
|
var shortID [8]byte
|
||||||
decodedLen, err := hex.Decode(shortID[:], []byte(shortIDString))
|
decodedLen, err := hex.Decode(shortID[:], []byte(shortIDString))
|
||||||
@ -103,7 +100,6 @@ func NewRealityServer(ctx context.Context, logger log.Logger, options option.Inb
|
|||||||
}
|
}
|
||||||
tlsConfig.ShortIds[shortID] = true
|
tlsConfig.ShortIds[shortID] = true
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
handshakeDialer, err := dialer.New(ctx, options.Reality.Handshake.DialerOptions, options.Reality.Handshake.ServerIsDomain())
|
handshakeDialer, err := dialer.New(ctx, options.Reality.Handshake.DialerOptions, options.Reality.Handshake.ServerIsDomain())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -6,7 +6,6 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/sagernet/fswatch"
|
"github.com/sagernet/fswatch"
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
@ -234,12 +233,8 @@ func NewSTDServer(ctx context.Context, logger log.Logger, options option.Inbound
|
|||||||
key = content
|
key = content
|
||||||
}
|
}
|
||||||
if certificate == nil && key == nil && options.Insecure {
|
if certificate == nil && key == nil && options.Insecure {
|
||||||
timeFunc := ntp.TimeFuncFromContext(ctx)
|
|
||||||
if timeFunc == nil {
|
|
||||||
timeFunc = time.Now
|
|
||||||
}
|
|
||||||
tlsConfig.GetCertificate = func(info *tls.ClientHelloInfo) (*tls.Certificate, error) {
|
tlsConfig.GetCertificate = func(info *tls.ClientHelloInfo) (*tls.Certificate, error) {
|
||||||
return GenerateKeyPair(nil, nil, timeFunc, info.ServerName)
|
return GenerateKeyPair(nil, nil, ntp.TimeFuncFromContext(ctx), info.ServerName)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if certificate == nil {
|
if certificate == nil {
|
||||||
|
@ -35,7 +35,6 @@ func NewTransport(ctx context.Context, logger log.ContextLogger, tag string, opt
|
|||||||
}
|
}
|
||||||
return &Transport{
|
return &Transport{
|
||||||
TransportAdapter: dns.NewTransportAdapterWithLocalOptions(C.DNSTypeLocal, tag, options),
|
TransportAdapter: dns.NewTransportAdapterWithLocalOptions(C.DNSTypeLocal, tag, options),
|
||||||
ctx: ctx,
|
|
||||||
hosts: hosts.NewFile(hosts.DefaultPath),
|
hosts: hosts.NewFile(hosts.DefaultPath),
|
||||||
dialer: transportDialer,
|
dialer: transportDialer,
|
||||||
}, nil
|
}, nil
|
||||||
@ -58,7 +57,7 @@ func (t *Transport) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg,
|
|||||||
return dns.FixedResponse(message.Id, question, addresses, C.DefaultDNSTTL), nil
|
return dns.FixedResponse(message.Id, question, addresses, C.DefaultDNSTTL), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
systemConfig := getSystemDNSConfig(t.ctx)
|
systemConfig := getSystemDNSConfig()
|
||||||
if systemConfig.singleRequest || !(message.Question[0].Qtype == mDNS.TypeA || message.Question[0].Qtype == mDNS.TypeAAAA) {
|
if systemConfig.singleRequest || !(message.Question[0].Qtype == mDNS.TypeA || message.Question[0].Qtype == mDNS.TypeAAAA) {
|
||||||
return t.exchangeSingleRequest(ctx, systemConfig, message, domain)
|
return t.exchangeSingleRequest(ctx, systemConfig, message, domain)
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package local
|
package local
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
@ -24,21 +23,19 @@ type resolverConfig struct {
|
|||||||
|
|
||||||
var resolvConf resolverConfig
|
var resolvConf resolverConfig
|
||||||
|
|
||||||
func getSystemDNSConfig(ctx context.Context) *dnsConfig {
|
func getSystemDNSConfig() *dnsConfig {
|
||||||
resolvConf.tryUpdate(ctx, "/etc/resolv.conf")
|
resolvConf.tryUpdate("/etc/resolv.conf")
|
||||||
return resolvConf.dnsConfig.Load()
|
return resolvConf.dnsConfig.Load()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (conf *resolverConfig) init(ctx context.Context) {
|
func (conf *resolverConfig) init() {
|
||||||
conf.dnsConfig.Store(dnsReadConfig(ctx, "/etc/resolv.conf"))
|
conf.dnsConfig.Store(dnsReadConfig("/etc/resolv.conf"))
|
||||||
conf.lastChecked = time.Now()
|
conf.lastChecked = time.Now()
|
||||||
conf.ch = make(chan struct{}, 1)
|
conf.ch = make(chan struct{}, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (conf *resolverConfig) tryUpdate(ctx context.Context, name string) {
|
func (conf *resolverConfig) tryUpdate(name string) {
|
||||||
conf.initOnce.Do(func() {
|
conf.initOnce.Do(conf.init)
|
||||||
conf.init(ctx)
|
|
||||||
})
|
|
||||||
|
|
||||||
if conf.dnsConfig.Load().noReload {
|
if conf.dnsConfig.Load().noReload {
|
||||||
return
|
return
|
||||||
@ -62,7 +59,7 @@ func (conf *resolverConfig) tryUpdate(ctx context.Context, name string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dnsConf := dnsReadConfig(ctx, name)
|
dnsConf := dnsReadConfig(name)
|
||||||
conf.dnsConfig.Store(dnsConf)
|
conf.dnsConfig.Store(dnsConf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,7 +11,6 @@ package local
|
|||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
@ -19,7 +18,7 @@ import (
|
|||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
)
|
)
|
||||||
|
|
||||||
func dnsReadConfig(_ context.Context, _ string) *dnsConfig {
|
func dnsReadConfig(_ string) *dnsConfig {
|
||||||
if C.res_init() != 0 {
|
if C.res_init() != 0 {
|
||||||
return &dnsConfig{
|
return &dnsConfig{
|
||||||
servers: defaultNS,
|
servers: defaultNS,
|
||||||
|
@ -4,7 +4,6 @@ package local
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"context"
|
|
||||||
"net"
|
"net"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"os"
|
"os"
|
||||||
@ -14,7 +13,7 @@ import (
|
|||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
)
|
)
|
||||||
|
|
||||||
func dnsReadConfig(_ context.Context, name string) *dnsConfig {
|
func dnsReadConfig(name string) *dnsConfig {
|
||||||
conf := &dnsConfig{
|
conf := &dnsConfig{
|
||||||
ndots: 1,
|
ndots: 1,
|
||||||
timeout: 5 * time.Second,
|
timeout: 5 * time.Second,
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package local
|
package local
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"net"
|
"net"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"os"
|
"os"
|
||||||
@ -9,13 +8,10 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
|
||||||
"github.com/sagernet/sing/service"
|
|
||||||
|
|
||||||
"golang.org/x/sys/windows"
|
"golang.org/x/sys/windows"
|
||||||
)
|
)
|
||||||
|
|
||||||
func dnsReadConfig(ctx context.Context, _ string) *dnsConfig {
|
func dnsReadConfig(_ string) *dnsConfig {
|
||||||
conf := &dnsConfig{
|
conf := &dnsConfig{
|
||||||
ndots: 1,
|
ndots: 1,
|
||||||
timeout: 5 * time.Second,
|
timeout: 5 * time.Second,
|
||||||
@ -26,35 +22,35 @@ func dnsReadConfig(ctx context.Context, _ string) *dnsConfig {
|
|||||||
conf.servers = defaultNS
|
conf.servers = defaultNS
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
addresses, err := adapterAddresses()
|
aas, err := adapterAddresses()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
var dnsAddresses []struct {
|
|
||||||
ifName string
|
for _, aa := range aas {
|
||||||
netip.Addr
|
// Only take interfaces whose OperStatus is IfOperStatusUp(0x01) into DNS configs.
|
||||||
}
|
if aa.OperStatus != windows.IfOperStatusUp {
|
||||||
for _, address := range addresses {
|
|
||||||
if address.OperStatus != windows.IfOperStatusUp {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if address.IfType == windows.IF_TYPE_TUNNEL {
|
|
||||||
|
// Only take interfaces which have at least one gateway
|
||||||
|
if aa.FirstGatewayAddress == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if address.FirstGatewayAddress == nil {
|
|
||||||
continue
|
for dns := aa.FirstDnsServerAddress; dns != nil; dns = dns.Next {
|
||||||
}
|
sa, err := dns.Address.Sockaddr.Sockaddr()
|
||||||
for dnsServerAddress := address.FirstDnsServerAddress; dnsServerAddress != nil; dnsServerAddress = dnsServerAddress.Next {
|
|
||||||
rawSockaddr, err := dnsServerAddress.Address.Sockaddr.Sockaddr()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
var dnsServerAddr netip.Addr
|
var ip netip.Addr
|
||||||
switch sockaddr := rawSockaddr.(type) {
|
switch sa := sa.(type) {
|
||||||
case *syscall.SockaddrInet4:
|
case *syscall.SockaddrInet4:
|
||||||
dnsServerAddr = netip.AddrFrom4(sockaddr.Addr)
|
ip = netip.AddrFrom4([4]byte{sa.Addr[0], sa.Addr[1], sa.Addr[2], sa.Addr[3]})
|
||||||
case *syscall.SockaddrInet6:
|
case *syscall.SockaddrInet6:
|
||||||
if sockaddr.Addr[0] == 0xfe && sockaddr.Addr[1] == 0xc0 {
|
var addr16 [16]byte
|
||||||
|
copy(addr16[:], sa.Addr[:])
|
||||||
|
if addr16[0] == 0xfe && addr16[1] == 0xc0 {
|
||||||
// fec0/10 IPv6 addresses are site local anycast DNS
|
// fec0/10 IPv6 addresses are site local anycast DNS
|
||||||
// addresses Microsoft sets by default if no other
|
// addresses Microsoft sets by default if no other
|
||||||
// IPv6 DNS address is set. Site local anycast is
|
// IPv6 DNS address is set. Site local anycast is
|
||||||
@ -62,27 +58,14 @@ func dnsReadConfig(ctx context.Context, _ string) *dnsConfig {
|
|||||||
// https://datatracker.ietf.org/doc/html/rfc3879
|
// https://datatracker.ietf.org/doc/html/rfc3879
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
dnsServerAddr = netip.AddrFrom16(sockaddr.Addr)
|
ip = netip.AddrFrom16(addr16)
|
||||||
default:
|
default:
|
||||||
// Unexpected type.
|
// Unexpected type.
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
dnsAddresses = append(dnsAddresses, struct {
|
conf.servers = append(conf.servers, net.JoinHostPort(ip.String(), "53"))
|
||||||
ifName string
|
|
||||||
netip.Addr
|
|
||||||
}{ifName: windows.UTF16PtrToString(address.FriendlyName), Addr: dnsServerAddr})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var myInterface string
|
|
||||||
if networkManager := service.FromContext[adapter.NetworkManager](ctx); networkManager != nil {
|
|
||||||
myInterface = networkManager.InterfaceMonitor().MyInterface()
|
|
||||||
}
|
|
||||||
for _, address := range dnsAddresses {
|
|
||||||
if address.ifName == myInterface {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
conf.servers = append(conf.servers, net.JoinHostPort(address.String(), "53"))
|
|
||||||
}
|
|
||||||
return conf
|
return conf
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,7 +117,7 @@ func (t *UDPTransport) exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.M
|
|||||||
conn.access.Unlock()
|
conn.access.Unlock()
|
||||||
defer func() {
|
defer func() {
|
||||||
conn.access.Lock()
|
conn.access.Lock()
|
||||||
delete(conn.callbacks, exMessage.Id)
|
delete(conn.callbacks, messageId)
|
||||||
conn.access.Unlock()
|
conn.access.Unlock()
|
||||||
}()
|
}()
|
||||||
rawMessage, err := exMessage.PackBuffer(buffer.FreeBytes())
|
rawMessage, err := exMessage.PackBuffer(buffer.FreeBytes())
|
||||||
|
@ -2,22 +2,6 @@
|
|||||||
icon: material/alert-decagram
|
icon: material/alert-decagram
|
||||||
---
|
---
|
||||||
|
|
||||||
#### 1.12.0-beta.4
|
|
||||||
|
|
||||||
* Fixes and improvements
|
|
||||||
|
|
||||||
### 1.11.8
|
|
||||||
|
|
||||||
* Improve `auto_redirect` **1**
|
|
||||||
* Fixes and improvements
|
|
||||||
|
|
||||||
**1**:
|
|
||||||
|
|
||||||
Now `auto_redirect` fixes compatibility issues between TUN and Docker bridge networks,
|
|
||||||
see [Tun](/configuration/inbound/tun/#auto_redirect).
|
|
||||||
|
|
||||||
_We are temporarily unable to update sing-box apps on the App Store because the reviewer mistakenly found that we violated the rules (TestFlight users are not affected)._
|
|
||||||
|
|
||||||
#### 1.12.0-beta.3
|
#### 1.12.0-beta.3
|
||||||
|
|
||||||
* Fixes and improvements
|
* Fixes and improvements
|
||||||
|
@ -9,10 +9,6 @@ and the data generated by the software is always on your device.
|
|||||||
|
|
||||||
## Android
|
## Android
|
||||||
|
|
||||||
The broad package (App) visibility (QUERY_ALL_PACKAGES) permission
|
|
||||||
is used to provide per-application proxy features for VPN,
|
|
||||||
sing-box will not collect your app list.
|
|
||||||
|
|
||||||
If your configuration contains `wifi_ssid` or `wifi_bssid` routing rules,
|
If your configuration contains `wifi_ssid` or `wifi_bssid` routing rules,
|
||||||
sing-box uses the location permission in the background
|
sing-box uses the location permission in the background
|
||||||
to get information about the connected Wi-Fi network to make them work.
|
to get information about the connected Wi-Fi network to make them work.
|
||||||
|
@ -28,16 +28,15 @@ icon: material/alert-decagram
|
|||||||
The type of the DNS server.
|
The type of the DNS server.
|
||||||
|
|
||||||
| Type | Format |
|
| Type | Format |
|
||||||
|-----------------|---------------------------|
|
|-----------------|-----------------------------|
|
||||||
| empty (default) | [Legacy](./legacy/) |
|
| empty (default) | [Legacy](./legacy/) |
|
||||||
| `local` | [Local](./local/) |
|
|
||||||
| `hosts` | [Hosts](./hosts/) |
|
|
||||||
| `tcp` | [TCP](./tcp/) |
|
| `tcp` | [TCP](./tcp/) |
|
||||||
| `udp` | [UDP](./udp/) |
|
| `udp` | [UDP](./udp/) |
|
||||||
| `tls` | [TLS](./tls/) |
|
| `tls` | [TLS](./tls/) |
|
||||||
| `quic` | [QUIC](./quic/) |
|
|
||||||
| `https` | [HTTPS](./https/) |
|
| `https` | [HTTPS](./https/) |
|
||||||
|
| `quic` | [QUIC](./quic/) |
|
||||||
| `h3` | [HTTP/3](./http3/) |
|
| `h3` | [HTTP/3](./http3/) |
|
||||||
|
| `predefined` | [Predefined](./predefined/) |
|
||||||
| `dhcp` | [DHCP](./dhcp/) |
|
| `dhcp` | [DHCP](./dhcp/) |
|
||||||
| `fakeip` | [Fake IP](./fakeip/) |
|
| `fakeip` | [Fake IP](./fakeip/) |
|
||||||
| `tailscale` | [Tailscale](./tailscale/) |
|
| `tailscale` | [Tailscale](./tailscale/) |
|
||||||
|
@ -28,16 +28,15 @@ icon: material/alert-decagram
|
|||||||
DNS 服务器的类型。
|
DNS 服务器的类型。
|
||||||
|
|
||||||
| 类型 | 格式 |
|
| 类型 | 格式 |
|
||||||
|-----------------|---------------------------|
|
|-----------------|-----------------------------|
|
||||||
| empty (default) | [Legacy](./legacy/) |
|
| empty (default) | [Legacy](./legacy/) |
|
||||||
| `local` | [Local](./local/) |
|
|
||||||
| `hosts` | [Hosts](./hosts/) |
|
|
||||||
| `tcp` | [TCP](./tcp/) |
|
| `tcp` | [TCP](./tcp/) |
|
||||||
| `udp` | [UDP](./udp/) |
|
| `udp` | [UDP](./udp/) |
|
||||||
| `tls` | [TLS](./tls/) |
|
| `tls` | [TLS](./tls/) |
|
||||||
| `quic` | [QUIC](./quic/) |
|
|
||||||
| `https` | [HTTPS](./https/) |
|
| `https` | [HTTPS](./https/) |
|
||||||
|
| `quic` | [QUIC](./quic/) |
|
||||||
| `h3` | [HTTP/3](./http3/) |
|
| `h3` | [HTTP/3](./http3/) |
|
||||||
|
| `predefined` | [Predefined](./predefined/) |
|
||||||
| `dhcp` | [DHCP](./dhcp/) |
|
| `dhcp` | [DHCP](./dhcp/) |
|
||||||
| `fakeip` | [Fake IP](./fakeip/) |
|
| `fakeip` | [Fake IP](./fakeip/) |
|
||||||
| `tailscale` | [Tailscale](./tailscale/) |
|
| `tailscale` | [Tailscale](./tailscale/) |
|
||||||
|
@ -213,7 +213,7 @@ Set the default route to the Tun.
|
|||||||
|
|
||||||
!!! note "Also enable `auto_redirect`"
|
!!! note "Also enable `auto_redirect`"
|
||||||
|
|
||||||
`auto_redirect` is always recommended on Linux, it provides better routing, higher performance (better than tproxy), and avoids conflicts between TUN and Docker bridge networks.
|
`auto_redirect` is always recommended on Linux, it provides better routing, higher performance (better than tproxy), and avoids conflicts with Docker bridge networks.
|
||||||
|
|
||||||
#### iproute2_table_index
|
#### iproute2_table_index
|
||||||
|
|
||||||
@ -239,21 +239,20 @@ Linux iproute2 rule start index generated by `auto_route`.
|
|||||||
|
|
||||||
Only supported on Linux with `auto_route` enabled.
|
Only supported on Linux with `auto_route` enabled.
|
||||||
|
|
||||||
Improve TUN routing and performance using nftables.
|
Automatically configure iptables/nftables to redirect connections.
|
||||||
|
|
||||||
`auto_redirect` is always recommended on Linux, it provides better routing,
|
Auto redirect is always recommended on Linux, it provides better routing,
|
||||||
higher performance (better than tproxy),
|
higher performance (better than tproxy),
|
||||||
and avoids conflicts between TUN and Docker bridge networks.
|
and avoids conflicts with Docker bridge networks.
|
||||||
|
|
||||||
Note that `auto_redirect` also works on Android,
|
*In Android*:
|
||||||
but due to the lack of `nftables` and `ip6tables`,
|
|
||||||
only simple IPv4 TCP forwarding is performed.
|
Only local IPv4 connections are forwarded. To share your VPN connection over hotspot or repeater,
|
||||||
To share your VPN connection over hotspot or repeater on Android,
|
|
||||||
use [VPNHotspot](https://github.com/Mygod/VPNHotspot).
|
use [VPNHotspot](https://github.com/Mygod/VPNHotspot).
|
||||||
|
|
||||||
`auto_redirect` also automatically inserts compatibility rules
|
*In Linux*:
|
||||||
into the OpenWrt fw4 table, i.e.
|
|
||||||
it will work on routers without any extra configuration.
|
`auto_route` with `auto_redirect` works as expected on routers **without intervention**.
|
||||||
|
|
||||||
Conflict with `route.default_mark` and `[dialOptions].routing_mark`.
|
Conflict with `route.default_mark` and `[dialOptions].routing_mark`.
|
||||||
|
|
||||||
@ -280,15 +279,17 @@ Enforce strict routing rules when `auto_route` is enabled:
|
|||||||
*In Linux*:
|
*In Linux*:
|
||||||
|
|
||||||
* Let unsupported network unreachable
|
* Let unsupported network unreachable
|
||||||
* For legacy reasons, when neither `strict_route` nor `auto_redirect` are enabled, all ICMP traffic will not go through TUN.
|
* Make ICMP traffic route to tun instead of upstream interfaces
|
||||||
|
* Route all connections to tun
|
||||||
|
|
||||||
|
It prevents IP address leaks and makes DNS hijacking work on Android.
|
||||||
|
|
||||||
*In Windows*:
|
*In Windows*:
|
||||||
|
|
||||||
* Let unsupported network unreachable
|
* Add firewall rules to prevent DNS leak caused by
|
||||||
* prevent DNS leak caused by
|
|
||||||
Windows' [ordinary multihomed DNS resolution behavior](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-R2-and-2008/dd197552%28v%3Dws.10%29)
|
Windows' [ordinary multihomed DNS resolution behavior](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-R2-and-2008/dd197552%28v%3Dws.10%29)
|
||||||
|
|
||||||
It may prevent some Windows applications (such as VirtualBox) from working properly in certain situations.
|
It may prevent some applications (such as VirtualBox) from working properly in certain situations.
|
||||||
|
|
||||||
#### route_address
|
#### route_address
|
||||||
|
|
||||||
|
@ -217,7 +217,7 @@ tun 接口的 IPv6 前缀。
|
|||||||
|
|
||||||
!!! note "也启用 `auto_redirect`"
|
!!! note "也启用 `auto_redirect`"
|
||||||
|
|
||||||
在 Linux 上始终推荐使用 `auto_redirect`,它提供更好的路由, 更高的性能(优于 tproxy), 并避免 TUN 与 Docker 桥接网络冲突。
|
在 Linux 上始终推荐使用 `auto_redirect`,它提供更好的路由, 更高的性能(优于 tproxy), 并避免与 Docker 桥接网络冲突。
|
||||||
|
|
||||||
#### iproute2_table_index
|
#### iproute2_table_index
|
||||||
|
|
||||||
@ -243,14 +243,17 @@ tun 接口的 IPv6 前缀。
|
|||||||
|
|
||||||
仅支持 Linux,且需要 `auto_route` 已启用。
|
仅支持 Linux,且需要 `auto_route` 已启用。
|
||||||
|
|
||||||
通过使用 nftables 改善 TUN 路由和性能。
|
自动配置 iptables/nftables 以重定向连接。
|
||||||
|
|
||||||
在 Linux 上始终推荐使用 `auto_redirect`,它提供更好的路由、更高的性能(优于 tproxy),并避免了 TUN 和 Docker 桥接网络之间的冲突。
|
在 Linux 上始终推荐使用 auto redirect,它提供更好的路由, 更高的性能(优于 tproxy), 并避免与 Docker 桥接网络冲突。
|
||||||
|
|
||||||
请注意,`auto_redirect` 也适用于 Android,但由于缺少 `nftables` 和 `ip6tables`,仅执行简单的 IPv4 TCP 转发。
|
*在 Android 中*:
|
||||||
若要在 Android 上通过热点或中继器共享 VPN 连接,请使用 [VPNHotspot](https://github.com/Mygod/VPNHotspot)。
|
|
||||||
|
|
||||||
`auto_redirect` 还会自动将兼容性规则插入 OpenWrt 的 fw4 表中,即无需额外配置即可在路由器上工作。
|
仅转发本地 IPv4 连接。 要通过热点或中继共享您的 VPN 连接,请使用 [VPNHotspot](https://github.com/Mygod/VPNHotspot)。
|
||||||
|
|
||||||
|
*在 Linux 中*:
|
||||||
|
|
||||||
|
带有 `auto_redirect` 的 `auto_route` 在路由器上**无需干预**即可按预期工作。
|
||||||
|
|
||||||
与 `route.default_mark` 和 `[dialOptions].routing_mark` 冲突。
|
与 `route.default_mark` 和 `[dialOptions].routing_mark` 冲突。
|
||||||
|
|
||||||
@ -258,7 +261,7 @@ tun 接口的 IPv6 前缀。
|
|||||||
|
|
||||||
!!! question "自 sing-box 1.10.0 起"
|
!!! question "自 sing-box 1.10.0 起"
|
||||||
|
|
||||||
`auto_redirect` 使用的连接输入标记。
|
`auto_redriect` 使用的连接输入标记。
|
||||||
|
|
||||||
默认使用 `0x2023`。
|
默认使用 `0x2023`。
|
||||||
|
|
||||||
@ -266,25 +269,29 @@ tun 接口的 IPv6 前缀。
|
|||||||
|
|
||||||
!!! question "自 sing-box 1.10.0 起"
|
!!! question "自 sing-box 1.10.0 起"
|
||||||
|
|
||||||
`auto_redirect` 使用的连接输出标记。
|
`auto_redriect` 使用的连接输出标记。
|
||||||
|
|
||||||
默认使用 `0x2024`。
|
默认使用 `0x2024`。
|
||||||
|
|
||||||
#### strict_route
|
#### strict_route
|
||||||
|
|
||||||
当启用 `auto_route` 时,强制执行严格的路由规则:
|
启用 `auto_route` 时执行严格的路由规则。
|
||||||
|
|
||||||
*在 Linux 中*:
|
*在 Linux 中*:
|
||||||
|
|
||||||
* 使不支持的网络不可达。
|
* 让不支持的网络无法到达
|
||||||
* 出于历史遗留原因,当未启用 `strict_route` 或 `auto_redirect` 时,所有 ICMP 流量将不会通过 TUN。
|
* 使 ICMP 流量路由到 tun 而不是上游接口
|
||||||
|
* 将所有连接路由到 tun
|
||||||
|
|
||||||
*在 Windows 中*:
|
它可以防止 IP 地址泄漏,并使 DNS 劫持在 Android 上工作。
|
||||||
|
|
||||||
* 使不支持的网络不可达。
|
*在 Windows 中*:
|
||||||
* 阻止 Windows 的 [普通多宿主 DNS 解析行为](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-R2-and-2008/dd197552%28v%3Dws.10%29) 造成的 DNS 泄露
|
|
||||||
|
|
||||||
它可能会使某些 Windows 应用程序(如 VirtualBox)在某些情况下无法正常工作。
|
* 添加防火墙规则以阻止 Windows
|
||||||
|
的 [普通多宿主 DNS 解析行为](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-R2-and-2008/dd197552%28v%3Dws.10%29)
|
||||||
|
造成的 DNS 泄露
|
||||||
|
|
||||||
|
它可能会使某些应用程序(如 VirtualBox)在某些情况下无法正常工作。
|
||||||
|
|
||||||
#### route_address
|
#### route_address
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
|
|
||||||
| QUIC 客户端 | 类型 |
|
| QUIC 客户端 | 类型 |
|
||||||
|:------------------------:|:----------:|
|
|:------------------------:|:----------:|
|
||||||
| Chromium/Cronet | `chromium` |
|
| Chromium/Cronet | `chrimium` |
|
||||||
| Safari/Apple Network API | `safari` |
|
| Safari/Apple Network API | `safari` |
|
||||||
| Firefox / uquic firefox | `firefox` |
|
| Firefox / uquic firefox | `firefox` |
|
||||||
| quic-go / uquic chrome | `quic-go` |
|
| quic-go / uquic chrome | `quic-go` |
|
@ -206,7 +206,7 @@ Only take effect when `domain_strategy` or `network_strategy` is set.
|
|||||||
|
|
||||||
!!! failure "Deprecated in sing-box 1.12.0"
|
!!! failure "Deprecated in sing-box 1.12.0"
|
||||||
|
|
||||||
`domain_strategy` is deprecated and will be removed in sing-box 1.14.0, check [Migration](/migration/#migrate-outbound-domain-strategy-option-to-domain-resolver).
|
`domain_strategy` is merged to [domain_resolver](#domain_resolver) in sing-box 1.12.0.
|
||||||
|
|
||||||
Available values: `prefer_ipv4`, `prefer_ipv6`, `ipv4_only`, `ipv6_only`.
|
Available values: `prefer_ipv4`, `prefer_ipv6`, `ipv4_only`, `ipv6_only`.
|
||||||
|
|
||||||
|
@ -194,10 +194,6 @@ icon: material/new-box
|
|||||||
|
|
||||||
#### domain_strategy
|
#### domain_strategy
|
||||||
|
|
||||||
!!! failure "已在 sing-box 1.12.0 废弃"
|
|
||||||
|
|
||||||
`domain_strategy` 已废弃且将在 sing-box 1.14.0 中被移除,参阅 [迁移指南](/migration/#migrate-outbound-domain-strategy-option-to-domain-resolver)。
|
|
||||||
|
|
||||||
可选值:`prefer_ipv4` `prefer_ipv6` `ipv4_only` `ipv6_only`。
|
可选值:`prefer_ipv4` `prefer_ipv6` `ipv4_only` `ipv6_only`。
|
||||||
|
|
||||||
如果设置,域名将在请求发出之前解析为 IP。
|
如果设置,域名将在请求发出之前解析为 IP。
|
||||||
|
@ -9,54 +9,42 @@ icon: material/package
|
|||||||
=== ":material-debian: Debian / APT"
|
=== ":material-debian: Debian / APT"
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo mkdir -p /etc/apt/keyrings &&
|
sudo curl -fsSL https://sing-box.app/gpg.key -o /etc/apt/keyrings/sagernet.asc
|
||||||
sudo curl -fsSL https://sing-box.app/gpg.key -o /etc/apt/keyrings/sagernet.asc &&
|
sudo chmod a+r /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/ * *" | \
|
||||||
echo '
|
sudo tee /etc/apt/sources.list.d/sagernet.list > /dev/null
|
||||||
Types: deb
|
sudo apt-get update
|
||||||
URIs: https://deb.sagernet.org/
|
|
||||||
Suites: *
|
|
||||||
Components: *
|
|
||||||
Enabled: yes
|
|
||||||
Signed-By: /etc/apt/keyrings/sagernet.asc
|
|
||||||
' | sudo tee /etc/apt/sources.list.d/sagernet.sources &&
|
|
||||||
sudo apt-get update &&
|
|
||||||
sudo apt-get install sing-box # or sing-box-beta
|
sudo apt-get install sing-box # or sing-box-beta
|
||||||
```
|
```
|
||||||
|
|
||||||
=== ":material-redhat: Redhat / DNF 5"
|
=== ":material-redhat: Redhat / DNF"
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo dnf config-manager addrepo --from-repofile=https://sing-box.app/sing-box.repo &&
|
sudo dnf -y install dnf-plugins-core
|
||||||
sudo dnf install sing-box # or sing-box-beta
|
sudo dnf config-manager --add-repo https://sing-box.app/sing-box.repo
|
||||||
```
|
|
||||||
|
|
||||||
=== ":material-redhat: Redhat / DNF 4"
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo dnf config-manager --add-repo https://sing-box.app/sing-box.repo &&
|
|
||||||
sudo dnf -y install dnf-plugins-core &&
|
|
||||||
sudo dnf install sing-box # or sing-box-beta
|
sudo dnf install sing-box # or sing-box-beta
|
||||||
```
|
```
|
||||||
|
(This applies to any distribution that uses `dnf` as the package manager: Fedora, CentOS, even OpenSUSE with DNF installed.)
|
||||||
|
|
||||||
## :material-download-box: Manual Installation
|
## :material-download-box: Manual Installation
|
||||||
|
|
||||||
The script download and install the latest package from GitHub releases for deb or rpm based Linux distributions, ArchLinux and OpenWrt.
|
=== ":material-debian: Debian / DEB"
|
||||||
|
|
||||||
```shell
|
```bash
|
||||||
curl -fsSL https://sing-box.app/install.sh | sh
|
bash <(curl -fsSL https://sing-box.app/deb-install.sh)
|
||||||
```
|
```
|
||||||
|
|
||||||
or latest beta:
|
=== ":material-redhat: Redhat / RPM"
|
||||||
|
|
||||||
```shell
|
```bash
|
||||||
curl -fsSL https://sing-box.app/install.sh | sh -s -- --beta
|
bash <(curl -fsSL https://sing-box.app/rpm-install.sh)
|
||||||
```
|
```
|
||||||
|
(This applies to any distribution that uses `rpm` and `systemd`. Because of how `rpm` defines dependencies, if it installs, it probably works.)
|
||||||
|
|
||||||
or specific version:
|
=== ":simple-archlinux: Archlinux / PKG"
|
||||||
|
|
||||||
```shell
|
```bash
|
||||||
curl -fsSL https://sing-box.app/install.sh | sh -s -- --version <version>
|
bash <(curl -fsSL https://sing-box.app/arch-install.sh)
|
||||||
```
|
```
|
||||||
|
|
||||||
## :material-book-lock-open: Managed Installation
|
## :material-book-lock-open: Managed Installation
|
||||||
|
@ -9,35 +9,22 @@ icon: material/package
|
|||||||
=== ":material-debian: Debian / APT"
|
=== ":material-debian: Debian / APT"
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo mkdir -p /etc/apt/keyrings &&
|
sudo curl -fsSL https://sing-box.app/gpg.key -o /etc/apt/keyrings/sagernet.asc
|
||||||
sudo curl -fsSL https://sing-box.app/gpg.key -o /etc/apt/keyrings/sagernet.asc &&
|
sudo chmod a+r /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/ * *" | \
|
||||||
echo '
|
sudo tee /etc/apt/sources.list.d/sagernet.list > /dev/null
|
||||||
Types: deb
|
sudo apt-get update
|
||||||
URIs: https://deb.sagernet.org/
|
|
||||||
Suites: *
|
|
||||||
Components: *
|
|
||||||
Enabled: yes
|
|
||||||
Signed-By: /etc/apt/keyrings/sagernet.asc
|
|
||||||
' | sudo tee /etc/apt/sources.list.d/sagernet.sources &&
|
|
||||||
sudo apt-get update &&
|
|
||||||
sudo apt-get install sing-box # or sing-box-beta
|
sudo apt-get install sing-box # or sing-box-beta
|
||||||
```
|
```
|
||||||
|
|
||||||
=== ":material-redhat: Redhat / DNF 5"
|
=== ":material-redhat: Redhat / DNF"
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo dnf config-manager addrepo --from-repofile=https://sing-box.app/sing-box.repo &&
|
sudo dnf -y install dnf-plugins-core
|
||||||
sudo dnf install sing-box # or sing-box-beta
|
sudo dnf config-manager --add-repo https://sing-box.app/sing-box.repo
|
||||||
```
|
|
||||||
|
|
||||||
=== ":material-redhat: Redhat / DNF 4"
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo dnf config-manager --add-repo https://sing-box.app/sing-box.repo &&
|
|
||||||
sudo dnf -y install dnf-plugins-core &&
|
|
||||||
sudo dnf install sing-box # or sing-box-beta
|
sudo dnf install sing-box # or sing-box-beta
|
||||||
```
|
```
|
||||||
|
(这适用于任何使用 `dnf` 作为包管理器的发行版:Fedora、CentOS,甚至安装了 DNF 的 OpenSUSE。)
|
||||||
|
|
||||||
## :material-download-box: 手动安装
|
## :material-download-box: 手动安装
|
||||||
|
|
||||||
|
@ -1,97 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
download_beta=false
|
|
||||||
download_version=""
|
|
||||||
|
|
||||||
for arg in "$@"; do
|
|
||||||
if [[ "$arg" == "--beta" ]]; then
|
|
||||||
download_beta=true
|
|
||||||
elif [[ "$arg" == "--version" ]]; then
|
|
||||||
download_version=true
|
|
||||||
elif [[ "$download_version" == 'true' ]]; then
|
|
||||||
download_version="$arg"
|
|
||||||
else
|
|
||||||
echo "Unknown argument: $arg"
|
|
||||||
echo "Usage: $0 [--beta] [--version <version>]"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
if [[ $(command -v dpkg) ]]; then
|
|
||||||
os="linux"
|
|
||||||
arch=$(dpkg --print-architecture)
|
|
||||||
package_suffix=".deb"
|
|
||||||
package_install="dpkg -i"
|
|
||||||
elif [[ $(command -v dnf) ]]; then
|
|
||||||
os="linux"
|
|
||||||
arch=$(uname -m)
|
|
||||||
package_suffix=".rpm"
|
|
||||||
package_install="dnf install -y"
|
|
||||||
elif [[ $(command -v rpm) ]]; then
|
|
||||||
os="linux"
|
|
||||||
arch=$(uname -m)
|
|
||||||
package_suffix=".rpm"
|
|
||||||
package_install="rpm -i"
|
|
||||||
elif [[ $(command -v pacman) ]]; then
|
|
||||||
os="linux"
|
|
||||||
arch=$(uname -m)
|
|
||||||
package_suffix=".pkg.tar.zst"
|
|
||||||
package_install="pacman -U --noconfirm"
|
|
||||||
elif [[ $(command -v opkg) ]]; then
|
|
||||||
os="openwrt"
|
|
||||||
source /etc/os-release
|
|
||||||
arch="$OPENWRT_ARCH"
|
|
||||||
package_suffix=".ipk"
|
|
||||||
package_install="opkg update && opkg install -y"
|
|
||||||
else
|
|
||||||
echo "Missing supported package manager."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -z "$download_version" ]]; then
|
|
||||||
if [[ "$download_beta" != 'true' ]]; then
|
|
||||||
if [[ -n "$GITHUB_TOKEN" ]]; then
|
|
||||||
latest_release=$(curl -s --fail-with-body -H "Authorization: token ${GITHUB_TOKEN}" https://api.github.com/repos/SagerNet/sing-box/releases/latest)
|
|
||||||
else
|
|
||||||
latest_release=$(curl -s --fail-with-body https://api.github.com/repos/SagerNet/sing-box/releases/latest)
|
|
||||||
fi
|
|
||||||
curl_exit_status=$?
|
|
||||||
if [[ $curl_exit_status -ne 0 ]]; then
|
|
||||||
echo "$latest_release"
|
|
||||||
exit $?
|
|
||||||
fi
|
|
||||||
download_version=$(echo "$latest_release" | grep tag_name | cut -d ":" -f2 | sed 's/\"//g;s/\,//g;s/\ //g;s/v//')
|
|
||||||
else
|
|
||||||
if [[ -n "$GITHUB_TOKEN" ]]; then
|
|
||||||
latest_release=$(curl -s --fail-with-body -H "Authorization: token ${GITHUB_TOKEN}" https://api.github.com/repos/SagerNet/sing-box/releases)
|
|
||||||
else
|
|
||||||
latest_release=$(curl -s --fail-with-body https://api.github.com/repos/SagerNet/sing-box/releases)
|
|
||||||
fi
|
|
||||||
curl_exit_status=$?
|
|
||||||
if [[ $? -ne 0 ]]; then
|
|
||||||
echo "$latest_release"
|
|
||||||
exit $?
|
|
||||||
fi
|
|
||||||
download_version=$(echo "$latest_release" | grep tag_name | head -n 1 | cut -d ":" -f2 | sed 's/\"//g;s/\,//g;s/\ //g;s/v//')
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
package_name="sing-box_${download_version}_${os}_${arch}${package_suffix}"
|
|
||||||
package_url="https://github.com/SagerNet/sing-box/releases/download/v${download_version}/${package_name}"
|
|
||||||
|
|
||||||
echo "Downloading $package_url"
|
|
||||||
if [[ -n "$GITHUB_TOKEN" ]]; then
|
|
||||||
curl --fail-with-body -Lo "$package_name" -H "Authorization: token ${GITHUB_TOKEN}" "$package_url"
|
|
||||||
else
|
|
||||||
curl --fail-with-body -Lo "$package_name" "$package_url"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ $? -ne 0 ]]; then
|
|
||||||
exit $?
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ $(command -v sudo) ]]; then
|
|
||||||
package_install="sudo $package_install"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "$package_install $package_name" && $package_install "$package_name" && rm "$package_name"
|
|
@ -292,7 +292,7 @@ DNS servers are refactored for better performance and scalability.
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"fakeip": {
|
"fakeip": {
|
||||||
"enabled": true,
|
"enable": true,
|
||||||
"inet4_range": "198.18.0.0/15",
|
"inet4_range": "198.18.0.0/15",
|
||||||
"inet6_range": "fc00::/18"
|
"inet6_range": "fc00::/18"
|
||||||
}
|
}
|
||||||
@ -556,8 +556,7 @@ The legacy outbound DNS rules are deprecated and can be replaced by new domain r
|
|||||||
"dns": {
|
"dns": {
|
||||||
"servers": [
|
"servers": [
|
||||||
{
|
{
|
||||||
"type": "local",
|
"type": "local"
|
||||||
"tag": "local"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -587,58 +586,6 @@ The legacy outbound DNS rules are deprecated and can be replaced by new domain r
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Migrate outbound domain strategy option to domain resolver
|
|
||||||
|
|
||||||
!!! info "References"
|
|
||||||
|
|
||||||
[Dial Fields](/configuration/shared/dial/#domain_strategy)
|
|
||||||
|
|
||||||
The `domain_strategy` option in Dial Fields has been deprecated and can be replaced with the new domain resolver option.
|
|
||||||
|
|
||||||
Note that due to the use of Dial Fields by some of the new DNS servers introduced in sing-box 1.12,
|
|
||||||
some people mistakenly believe that `domain_strategy` is the same feature as in the legacy DNS servers.
|
|
||||||
|
|
||||||
=== ":material-card-remove: Deprecated"
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"outbounds": [
|
|
||||||
{
|
|
||||||
"type": "socks",
|
|
||||||
"server": "example.org",
|
|
||||||
"server_port": 2080,
|
|
||||||
"domain_strategy": "prefer_ipv4",
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
=== ":material-card-multiple: New"
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"dns": {
|
|
||||||
"servers": [
|
|
||||||
{
|
|
||||||
"type": "local",
|
|
||||||
"tag": "local"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"outbounds": [
|
|
||||||
{
|
|
||||||
"type": "socks",
|
|
||||||
"server": "example.org",
|
|
||||||
"server_port": 2080,
|
|
||||||
"domain_resolver": {
|
|
||||||
"server": "local",
|
|
||||||
"strategy": "prefer_ipv4"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 1.11.0
|
## 1.11.0
|
||||||
|
|
||||||
### Migrate legacy special outbounds to rule actions
|
### Migrate legacy special outbounds to rule actions
|
||||||
|
@ -292,7 +292,7 @@ DNS 服务器已经重构。
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"fakeip": {
|
"fakeip": {
|
||||||
"enabled": true,
|
"enable": true,
|
||||||
"inet4_range": "198.18.0.0/15",
|
"inet4_range": "198.18.0.0/15",
|
||||||
"inet6_range": "fc00::/18"
|
"inet6_range": "fc00::/18"
|
||||||
}
|
}
|
||||||
@ -556,8 +556,7 @@ DNS 服务器已经重构。
|
|||||||
"dns": {
|
"dns": {
|
||||||
"servers": [
|
"servers": [
|
||||||
{
|
{
|
||||||
"type": "local",
|
"type": "local"
|
||||||
"tag": "local"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -587,57 +586,6 @@ DNS 服务器已经重构。
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 迁移出站域名策略选项到域名解析器
|
|
||||||
|
|
||||||
拨号字段中的 `domain_strategy` 选项已被弃用,可以用新的域名解析器选项替代。
|
|
||||||
|
|
||||||
请注意,由于 sing-box 1.12 中引入的一些新 DNS 服务器使用了拨号字段,一些人错误地认为 `domain_strategy` 与旧 DNS 服务器中的功能相同。
|
|
||||||
|
|
||||||
!!! info "参考"
|
|
||||||
|
|
||||||
[拨号字段](/configuration/shared/dial/#domain_strategy)
|
|
||||||
|
|
||||||
=== ":material-card-remove: 弃用的"
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"outbounds": [
|
|
||||||
{
|
|
||||||
"type": "socks",
|
|
||||||
"server": "example.org",
|
|
||||||
"server_port": 2080,
|
|
||||||
"domain_strategy": "prefer_ipv4",
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
=== ":material-card-multiple: 新的"
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"dns": {
|
|
||||||
"servers": [
|
|
||||||
{
|
|
||||||
"type": "local",
|
|
||||||
"tag": "local"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"outbounds": [
|
|
||||||
{
|
|
||||||
"type": "socks",
|
|
||||||
"server": "example.org",
|
|
||||||
"server_port": 2080,
|
|
||||||
"domain_resolver": {
|
|
||||||
"server": "local",
|
|
||||||
"strategy": "prefer_ipv4"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 1.11.0
|
## 1.11.0
|
||||||
|
|
||||||
### 迁移旧的特殊出站到规则动作
|
### 迁移旧的特殊出站到规则动作
|
||||||
|
@ -161,7 +161,6 @@ var OptionLegacyDNSFakeIPOptions = Note{
|
|||||||
Description: "legacy DNS fakeip options",
|
Description: "legacy DNS fakeip options",
|
||||||
DeprecatedVersion: "1.12.0",
|
DeprecatedVersion: "1.12.0",
|
||||||
ScheduledVersion: "1.14.0",
|
ScheduledVersion: "1.14.0",
|
||||||
EnvName: "LEGACY_DNS_FAKEIP_OPTIONS",
|
|
||||||
MigrationLink: "https://sing-box.sagernet.org/migration/#migrate-to-new-dns-server-formats",
|
MigrationLink: "https://sing-box.sagernet.org/migration/#migrate-to-new-dns-server-formats",
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,7 +169,6 @@ var OptionOutboundDNSRuleItem = Note{
|
|||||||
Description: "outbound DNS rule item",
|
Description: "outbound DNS rule item",
|
||||||
DeprecatedVersion: "1.12.0",
|
DeprecatedVersion: "1.12.0",
|
||||||
ScheduledVersion: "1.14.0",
|
ScheduledVersion: "1.14.0",
|
||||||
EnvName: "OUTBOUND_DNS_RULE_ITEM",
|
|
||||||
MigrationLink: "https://sing-box.sagernet.org/migration/#migrate-outbound-dns-rule-items-to-domain-resolver",
|
MigrationLink: "https://sing-box.sagernet.org/migration/#migrate-outbound-dns-rule-items-to-domain-resolver",
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,7 +177,6 @@ var OptionMissingDomainResolver = Note{
|
|||||||
Description: "missing `route.default_domain_resolver` or `domain_resolver` in dial fields",
|
Description: "missing `route.default_domain_resolver` or `domain_resolver` in dial fields",
|
||||||
DeprecatedVersion: "1.12.0",
|
DeprecatedVersion: "1.12.0",
|
||||||
ScheduledVersion: "1.14.0",
|
ScheduledVersion: "1.14.0",
|
||||||
EnvName: "MISSING_DOMAIN_RESOLVER",
|
|
||||||
MigrationLink: "https://sing-box.sagernet.org/migration/#migrate-outbound-dns-rule-items-to-domain-resolver",
|
MigrationLink: "https://sing-box.sagernet.org/migration/#migrate-outbound-dns-rule-items-to-domain-resolver",
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,19 +185,9 @@ var OptionLegacyECHOptions = Note{
|
|||||||
Description: "legacy ECH options",
|
Description: "legacy ECH options",
|
||||||
DeprecatedVersion: "1.12.0",
|
DeprecatedVersion: "1.12.0",
|
||||||
ScheduledVersion: "1.13.0",
|
ScheduledVersion: "1.13.0",
|
||||||
EnvName: "LEGACY_ECH_OPTIONS",
|
|
||||||
MigrationLink: "https://sing-box.sagernet.org/deprecated/#legacy-ech-fields",
|
MigrationLink: "https://sing-box.sagernet.org/deprecated/#legacy-ech-fields",
|
||||||
}
|
}
|
||||||
|
|
||||||
var OptionLegacyDomainStrategyOptions = Note{
|
|
||||||
Name: "legacy-domain-strategy-options",
|
|
||||||
Description: "legacy domain strategy options",
|
|
||||||
DeprecatedVersion: "1.12.0",
|
|
||||||
ScheduledVersion: "1.14.0",
|
|
||||||
EnvName: "LEGACY_DOMAIN_STRATEGY_OPTIONS",
|
|
||||||
MigrationLink: "https://sing-box.sagernet.org/migration/#migrate-domain-strategy-options",
|
|
||||||
}
|
|
||||||
|
|
||||||
var Options = []Note{
|
var Options = []Note{
|
||||||
OptionBadMatchSource,
|
OptionBadMatchSource,
|
||||||
OptionGEOIP,
|
OptionGEOIP,
|
||||||
@ -217,5 +204,4 @@ var Options = []Note{
|
|||||||
OptionOutboundDNSRuleItem,
|
OptionOutboundDNSRuleItem,
|
||||||
OptionMissingDomainResolver,
|
OptionMissingDomainResolver,
|
||||||
OptionLegacyECHOptions,
|
OptionLegacyECHOptions,
|
||||||
OptionLegacyDomainStrategyOptions,
|
|
||||||
}
|
}
|
||||||
|
@ -116,10 +116,6 @@ func (s *platformInterfaceStub) FindProcessInfo(ctx context.Context, network str
|
|||||||
return nil, os.ErrInvalid
|
return nil, os.ErrInvalid
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *platformInterfaceStub) SendNotification(notification *platform.Notification) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type interfaceMonitorStub struct{}
|
type interfaceMonitorStub struct{}
|
||||||
|
|
||||||
func (s *interfaceMonitorStub) Start() error {
|
func (s *interfaceMonitorStub) Start() error {
|
||||||
@ -149,11 +145,8 @@ func (s *interfaceMonitorStub) RegisterCallback(callback tun.DefaultInterfaceUpd
|
|||||||
func (s *interfaceMonitorStub) UnregisterCallback(element *list.Element[tun.DefaultInterfaceUpdateCallback]) {
|
func (s *interfaceMonitorStub) UnregisterCallback(element *list.Element[tun.DefaultInterfaceUpdateCallback]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *interfaceMonitorStub) RegisterMyInterface(interfaceName string) {
|
func (s *platformInterfaceStub) SendNotification(notification *platform.Notification) error {
|
||||||
}
|
return nil
|
||||||
|
|
||||||
func (s *interfaceMonitorStub) MyInterface() string {
|
|
||||||
return ""
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func FormatConfig(configContent string) (*StringBox, error) {
|
func FormatConfig(configContent string) (*StringBox, error) {
|
||||||
|
@ -15,10 +15,9 @@ var (
|
|||||||
|
|
||||||
type platformDefaultInterfaceMonitor struct {
|
type platformDefaultInterfaceMonitor struct {
|
||||||
*platformInterfaceWrapper
|
*platformInterfaceWrapper
|
||||||
logger logger.Logger
|
|
||||||
element *list.Element[tun.NetworkUpdateCallback]
|
element *list.Element[tun.NetworkUpdateCallback]
|
||||||
callbacks list.List[tun.DefaultInterfaceUpdateCallback]
|
callbacks list.List[tun.DefaultInterfaceUpdateCallback]
|
||||||
myInterface string
|
logger logger.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *platformDefaultInterfaceMonitor) Start() error {
|
func (m *platformDefaultInterfaceMonitor) Start() error {
|
||||||
@ -103,15 +102,3 @@ func (m *platformDefaultInterfaceMonitor) updateDefaultInterface(interfaceName s
|
|||||||
callback(newInterface, 0)
|
callback(newInterface, 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *platformDefaultInterfaceMonitor) RegisterMyInterface(interfaceName string) {
|
|
||||||
m.defaultInterfaceAccess.Lock()
|
|
||||||
defer m.defaultInterfaceAccess.Unlock()
|
|
||||||
m.myInterface = interfaceName
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *platformDefaultInterfaceMonitor) MyInterface() string {
|
|
||||||
m.defaultInterfaceAccess.Lock()
|
|
||||||
defer m.defaultInterfaceAccess.Unlock()
|
|
||||||
return m.myInterface
|
|
||||||
}
|
|
||||||
|
@ -164,7 +164,6 @@ func (w *platformInterfaceWrapper) OpenTun(options *tun.Options, platformOptions
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, E.Cause(err, "query tun name")
|
return nil, E.Cause(err, "query tun name")
|
||||||
}
|
}
|
||||||
options.InterfaceMonitor.RegisterMyInterface(options.Name)
|
|
||||||
dupFd, err := dup(int(tunFd))
|
dupFd, err := dup(int(tunFd))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, E.Cause(err, "dup tun file descriptor")
|
return nil, E.Cause(err, "dup tun file descriptor")
|
||||||
|
2
go.mod
2
go.mod
@ -32,7 +32,7 @@ require (
|
|||||||
github.com/sagernet/sing-shadowsocks v0.2.7
|
github.com/sagernet/sing-shadowsocks v0.2.7
|
||||||
github.com/sagernet/sing-shadowsocks2 v0.2.0
|
github.com/sagernet/sing-shadowsocks2 v0.2.0
|
||||||
github.com/sagernet/sing-shadowtls v0.2.1-0.20250316154757-6f9e732e5056
|
github.com/sagernet/sing-shadowtls v0.2.1-0.20250316154757-6f9e732e5056
|
||||||
github.com/sagernet/sing-tun v0.6.5-0.20250412112220-15069fc1c20a
|
github.com/sagernet/sing-tun v0.6.3-0.20250409030157-219c612399be
|
||||||
github.com/sagernet/sing-vmess v0.2.0
|
github.com/sagernet/sing-vmess v0.2.0
|
||||||
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7
|
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7
|
||||||
github.com/sagernet/tailscale v1.80.3-mod.2
|
github.com/sagernet/tailscale v1.80.3-mod.2
|
||||||
|
4
go.sum
4
go.sum
@ -190,8 +190,8 @@ github.com/sagernet/sing-shadowsocks2 v0.2.0 h1:wpZNs6wKnR7mh1wV9OHwOyUr21VkS3wK
|
|||||||
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.2.1-0.20250316154757-6f9e732e5056 h1:GFNJQAHhSXqAfxAw1wDG/QWbdpGH5Na3k8qUynqWnEA=
|
github.com/sagernet/sing-shadowtls v0.2.1-0.20250316154757-6f9e732e5056 h1:GFNJQAHhSXqAfxAw1wDG/QWbdpGH5Na3k8qUynqWnEA=
|
||||||
github.com/sagernet/sing-shadowtls v0.2.1-0.20250316154757-6f9e732e5056/go.mod h1:HyacBPIFiKihJQR8LQp56FM4hBtd/7MZXnRxxQIOPsc=
|
github.com/sagernet/sing-shadowtls v0.2.1-0.20250316154757-6f9e732e5056/go.mod h1:HyacBPIFiKihJQR8LQp56FM4hBtd/7MZXnRxxQIOPsc=
|
||||||
github.com/sagernet/sing-tun v0.6.5-0.20250412112220-15069fc1c20a h1:2aLxZFD2HPCLrnFGpH+KBuPqMOk0cuaDE2dgEvANuMk=
|
github.com/sagernet/sing-tun v0.6.3-0.20250409030157-219c612399be h1:E/JnQ1DEz5XIH6VVk3dIMD7aIX5o79jPkbyw57tWlJs=
|
||||||
github.com/sagernet/sing-tun v0.6.5-0.20250412112220-15069fc1c20a/go.mod h1:fisFCbC4Vfb6HqQNcwPJi2CDK2bf0Xapyz3j3t4cnHE=
|
github.com/sagernet/sing-tun v0.6.3-0.20250409030157-219c612399be/go.mod h1:fisFCbC4Vfb6HqQNcwPJi2CDK2bf0Xapyz3j3t4cnHE=
|
||||||
github.com/sagernet/sing-vmess v0.2.0 h1:pCMGUXN2k7RpikQV65/rtXtDHzb190foTfF9IGTMZrI=
|
github.com/sagernet/sing-vmess v0.2.0 h1:pCMGUXN2k7RpikQV65/rtXtDHzb190foTfF9IGTMZrI=
|
||||||
github.com/sagernet/sing-vmess v0.2.0/go.mod h1:jDAZ0A0St1zVRkyvhAPRySOFfhC+4SQtO5VYyeFotgA=
|
github.com/sagernet/sing-vmess v0.2.0/go.mod h1:jDAZ0A0St1zVRkyvhAPRySOFfhC+4SQtO5VYyeFotgA=
|
||||||
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ=
|
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ=
|
||||||
|
@ -94,7 +94,7 @@ func (i *Inbound) NewConnectionEx(ctx context.Context, conn net.Conn, metadata a
|
|||||||
case 2:
|
case 2:
|
||||||
destination.Addr = i.overrideDestination.Addr
|
destination.Addr = i.overrideDestination.Addr
|
||||||
case 3:
|
case 3:
|
||||||
destination.Port = i.overrideDestination.Port
|
destination.Port = metadata.Destination.Port
|
||||||
}
|
}
|
||||||
metadata.Destination = destination
|
metadata.Destination = destination
|
||||||
if i.overrideOption != 0 {
|
if i.overrideOption != 0 {
|
||||||
|
@ -396,16 +396,12 @@ func (g *URLTestGroup) urlTest(ctx context.Context, force bool) (map[string]uint
|
|||||||
func (g *URLTestGroup) performUpdateCheck() {
|
func (g *URLTestGroup) performUpdateCheck() {
|
||||||
var updated bool
|
var updated bool
|
||||||
if outbound, exists := g.Select(N.NetworkTCP); outbound != nil && (g.selectedOutboundTCP == nil || (exists && outbound != g.selectedOutboundTCP)) {
|
if outbound, exists := g.Select(N.NetworkTCP); outbound != nil && (g.selectedOutboundTCP == nil || (exists && outbound != g.selectedOutboundTCP)) {
|
||||||
if g.selectedOutboundTCP != nil {
|
|
||||||
updated = true
|
|
||||||
}
|
|
||||||
g.selectedOutboundTCP = outbound
|
g.selectedOutboundTCP = outbound
|
||||||
|
updated = true
|
||||||
}
|
}
|
||||||
if outbound, exists := g.Select(N.NetworkUDP); outbound != nil && (g.selectedOutboundUDP == nil || (exists && outbound != g.selectedOutboundUDP)) {
|
if outbound, exists := g.Select(N.NetworkUDP); outbound != nil && (g.selectedOutboundUDP == nil || (exists && outbound != g.selectedOutboundUDP)) {
|
||||||
if g.selectedOutboundUDP != nil {
|
|
||||||
updated = true
|
|
||||||
}
|
|
||||||
g.selectedOutboundUDP = outbound
|
g.selectedOutboundUDP = outbound
|
||||||
|
updated = true
|
||||||
}
|
}
|
||||||
if updated {
|
if updated {
|
||||||
g.interruptGroup.Interrupt(g.interruptExternalConnections)
|
g.interruptGroup.Interrupt(g.interruptExternalConnections)
|
||||||
|
@ -26,6 +26,11 @@ func RegisterEndpoint(registry *endpoint.Registry) {
|
|||||||
endpoint.Register[option.WireGuardEndpointOptions](registry, C.TypeWireGuard, NewEndpoint)
|
endpoint.Register[option.WireGuardEndpointOptions](registry, C.TypeWireGuard, NewEndpoint)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ adapter.Endpoint = (*Endpoint)(nil)
|
||||||
|
_ adapter.InterfaceUpdateListener = (*Endpoint)(nil)
|
||||||
|
)
|
||||||
|
|
||||||
type Endpoint struct {
|
type Endpoint struct {
|
||||||
endpoint.Adapter
|
endpoint.Adapter
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
@ -122,6 +127,10 @@ func (w *Endpoint) Close() error {
|
|||||||
return w.endpoint.Close()
|
return w.endpoint.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *Endpoint) InterfaceUpdated() {
|
||||||
|
w.endpoint.BindUpdate()
|
||||||
|
}
|
||||||
|
|
||||||
func (w *Endpoint) PrepareConnection(network string, source M.Socksaddr, destination M.Socksaddr) error {
|
func (w *Endpoint) PrepareConnection(network string, source M.Socksaddr, destination M.Socksaddr) error {
|
||||||
return w.router.PreMatch(adapter.InboundContext{
|
return w.router.PreMatch(adapter.InboundContext{
|
||||||
Inbound: w.Tag(),
|
Inbound: w.Tag(),
|
||||||
|
@ -25,6 +25,11 @@ func RegisterOutbound(registry *outbound.Registry) {
|
|||||||
outbound.Register[option.LegacyWireGuardOutboundOptions](registry, C.TypeWireGuard, NewOutbound)
|
outbound.Register[option.LegacyWireGuardOutboundOptions](registry, C.TypeWireGuard, NewOutbound)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ adapter.Endpoint = (*Endpoint)(nil)
|
||||||
|
_ adapter.InterfaceUpdateListener = (*Endpoint)(nil)
|
||||||
|
)
|
||||||
|
|
||||||
type Outbound struct {
|
type Outbound struct {
|
||||||
outbound.Adapter
|
outbound.Adapter
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
@ -126,6 +131,10 @@ func (o *Outbound) Close() error {
|
|||||||
return o.endpoint.Close()
|
return o.endpoint.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (o *Outbound) InterfaceUpdated() {
|
||||||
|
o.endpoint.BindUpdate()
|
||||||
|
}
|
||||||
|
|
||||||
func (o *Outbound) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
func (o *Outbound) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
||||||
switch network {
|
switch network {
|
||||||
case N.NetworkTCP:
|
case N.NetworkTCP:
|
||||||
|
11
release/config/openwrt.init
Executable file → Normal file
11
release/config/openwrt.init
Executable file → Normal file
@ -1,27 +1,26 @@
|
|||||||
#!/bin/sh /etc/rc.common
|
#!/bin/sh /etc/rc.common
|
||||||
|
|
||||||
USE_PROCD=1
|
|
||||||
START=99
|
|
||||||
PROG="/usr/bin/sing-box"
|
PROG="/usr/bin/sing-box"
|
||||||
|
|
||||||
start_service() {
|
start_service() {
|
||||||
config_load "sing-box"
|
config_load "sing-box"
|
||||||
|
|
||||||
local enabled config_file working_directory
|
local enabled config_file working_directory
|
||||||
local log_stderr
|
local log_stdout log_stderr
|
||||||
config_get_bool enabled "main" "enabled" "0"
|
config_get_bool enabled "main" "enabled" "0"
|
||||||
[ "$enabled" -eq "1" ] || return 0
|
[ "$enabled" -eq "1" ] || return 0
|
||||||
|
|
||||||
config_get config_file "main" "conffile" "/etc/sing-box/config.json"
|
config_get config_file "main" "conffile" "/etc/sing-box/config.json"
|
||||||
config_get working_directory "main" "workdir" "/usr/share/sing-box"
|
config_get working_directory "main" "workdir" "/usr/share/sing-box"
|
||||||
|
config_get_bool log_stdout "main" "log_stdout" "1"
|
||||||
config_get_bool log_stderr "main" "log_stderr" "1"
|
config_get_bool log_stderr "main" "log_stderr" "1"
|
||||||
|
|
||||||
procd_open_instance
|
procd_open_instance
|
||||||
procd_set_param command "$PROG" run -c "$config_file" -D "$working_directory"
|
procd_swet_param command "$PROG" run -c "$conffile" -D "$workdir"
|
||||||
procd_set_param file "$config_file"
|
procd_set_param file "$conffile"
|
||||||
procd_set_param stderr "$log_stderr"
|
procd_set_param stderr "$log_stderr"
|
||||||
procd_set_param limits core="unlimited"
|
procd_set_param limits core="unlimited"
|
||||||
procd_set_param limits nofile="1000000 1000000"
|
sprocd_set_param limits nofile="1000000 1000000"
|
||||||
procd_set_param respawn
|
procd_set_param respawn
|
||||||
|
|
||||||
procd_close_instance
|
procd_close_instance
|
||||||
|
@ -1 +0,0 @@
|
|||||||
/etc/sing-box/
|
|
@ -1,4 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
[ -s ${IPKG_INSTROOT}/lib/functions.sh ] || exit 0
|
|
||||||
. ${IPKG_INSTROOT}/lib/functions.sh
|
|
||||||
default_prerm $0 $@
|
|
@ -150,7 +150,7 @@ func (e *Endpoint) Start(resolve bool) error {
|
|||||||
connectAddr netip.AddrPort
|
connectAddr netip.AddrPort
|
||||||
reserved [3]uint8
|
reserved [3]uint8
|
||||||
)
|
)
|
||||||
if len(e.peers) == 1 && e.peers[0].endpoint.IsValid() {
|
if len(e.peers) == 1 {
|
||||||
isConnect = true
|
isConnect = true
|
||||||
connectAddr = e.peers[0].endpoint
|
connectAddr = e.peers[0].endpoint
|
||||||
reserved = e.peers[0].reserved
|
reserved = e.peers[0].reserved
|
||||||
@ -208,6 +208,10 @@ func (e *Endpoint) ListenPacket(ctx context.Context, destination M.Socksaddr) (n
|
|||||||
return e.tunDevice.ListenPacket(ctx, destination)
|
return e.tunDevice.ListenPacket(ctx, destination)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *Endpoint) BindUpdate() error {
|
||||||
|
return e.device.BindUpdate()
|
||||||
|
}
|
||||||
|
|
||||||
func (e *Endpoint) Close() error {
|
func (e *Endpoint) Close() error {
|
||||||
if e.device != nil {
|
if e.device != nil {
|
||||||
e.device.Close()
|
e.device.Close()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user