mirror of
https://github.com/SagerNet/sing-box.git
synced 2025-06-08 11:44:13 +08:00
Compare commits
125 Commits
v1.12.0-be
...
dev-next
Author | SHA1 | Date | |
---|---|---|---|
![]() |
c3cc010880 | ||
![]() |
1920c191be | ||
![]() |
e0ac459204 | ||
![]() |
09fb897805 | ||
![]() |
a1b3d891a3 | ||
![]() |
d866a40469 | ||
![]() |
45cd04b07e | ||
![]() |
2cf0528c4d | ||
![]() |
905a2ded93 | ||
![]() |
cb3c0829c5 | ||
![]() |
1a8f6e053d | ||
![]() |
99a09a6ce5 | ||
![]() |
01b4c7fcdd | ||
![]() |
fe89f946c1 | ||
![]() |
6c17c7a8f5 | ||
![]() |
ea067e5478 | ||
![]() |
75af9a824e | ||
![]() |
a5d4a42119 | ||
![]() |
9821fbc3e3 | ||
![]() |
c0408ad1de | ||
![]() |
6b0e861afa | ||
![]() |
e32d686d6c | ||
![]() |
844308e128 | ||
![]() |
93c14db281 | ||
![]() |
b893a27dfc | ||
![]() |
d39960fa23 | ||
![]() |
ba0badd4bf | ||
![]() |
cfbb5d63d5 | ||
![]() |
8447a3edfe | ||
![]() |
1a9747a531 | ||
![]() |
583ecbea3b | ||
![]() |
bb6c8535a5 | ||
![]() |
10d90e4acc | ||
![]() |
e625012219 | ||
![]() |
670863fd5b | ||
![]() |
f7cf87142f | ||
![]() |
2597a68a01 | ||
![]() |
7354332daa | ||
![]() |
a0d382fc4e | ||
![]() |
a6da8b6654 | ||
![]() |
7385616cca | ||
![]() |
4b6784b446 | ||
![]() |
68579bb93b | ||
![]() |
6aace7b1b7 | ||
![]() |
148234b742 | ||
![]() |
97b7a451be | ||
![]() |
73b67e0b48 | ||
![]() |
88b4d04d59 | ||
![]() |
d1ec6c6dd2 | ||
![]() |
523825336a | ||
![]() |
032565a026 | ||
![]() |
aeea24ae30 | ||
![]() |
af22549f1a | ||
![]() |
57b17ceb4b | ||
![]() |
3dd308e7c3 | ||
![]() |
7f75195d86 | ||
![]() |
2fe4cad905 | ||
![]() |
f55eb75a53 | ||
![]() |
5ffb5b6ad2 | ||
![]() |
a1d5931759 | ||
![]() |
9e68e909cb | ||
![]() |
117e8b76cc | ||
![]() |
d2f83bfd50 | ||
![]() |
eaef13febe | ||
![]() |
0110c69dc9 | ||
![]() |
fb2f5af1fb | ||
![]() |
1553923118 | ||
![]() |
0ada49489d | ||
![]() |
95d5ca9393 | ||
![]() |
6cebbb4590 | ||
![]() |
0ef81bb5ef | ||
![]() |
0d30a1df9d | ||
![]() |
563499d2f9 | ||
![]() |
f10c0c1c8d | ||
![]() |
428074d88b | ||
![]() |
fa18832ad2 | ||
![]() |
87bce2de29 | ||
![]() |
f5020554e4 | ||
![]() |
31f3623b8a | ||
![]() |
bb42657177 | ||
![]() |
f19ff7eca7 | ||
![]() |
8e45133f2e | ||
![]() |
63df88675f | ||
![]() |
0423244298 | ||
![]() |
a5f1af9587 | ||
![]() |
112817c1a4 | ||
![]() |
6e91de51f1 | ||
![]() |
efc5c542fb | ||
![]() |
f1b569c7d1 | ||
![]() |
a752197d5e | ||
![]() |
65517d4513 | ||
![]() |
ccf4fa4d3a | ||
![]() |
18dbb823a1 | ||
![]() |
4ec058e91a | ||
![]() |
6eed06b2c2 | ||
![]() |
dd209cc9d5 | ||
![]() |
b0c0a6b07d | ||
![]() |
951a8fabbf | ||
![]() |
928298b528 | ||
![]() |
5b84fa0137 | ||
![]() |
2bb85ac8a1 | ||
![]() |
43a9016c83 | ||
![]() |
255068fd40 | ||
![]() |
098a00b025 | ||
![]() |
dba0b5276b | ||
![]() |
78ae935468 | ||
![]() |
3ea5f76470 | ||
![]() |
b4d294c05e | ||
![]() |
83cf5f5c6a | ||
![]() |
e7b3a8eebe | ||
![]() |
ee3a42a67e | ||
![]() |
50227c0f5f | ||
![]() |
bc5eb1e1a5 | ||
![]() |
995267a042 | ||
![]() |
41226a6075 | ||
![]() |
81d32181ce | ||
![]() |
c5ecca3938 | ||
![]() |
900888731c | ||
![]() |
13e648e4b1 | ||
![]() |
aff12ff671 | ||
![]() |
101fb88255 | ||
![]() |
8b489354e4 | ||
![]() |
7dea6eb7a6 | ||
![]() |
af1bfe4e3e | ||
![]() |
d574e9eb52 |
@ -8,11 +8,15 @@
|
|||||||
--deb-field "Bug: https://github.com/SagerNet/sing-box/issues"
|
--deb-field "Bug: https://github.com/SagerNet/sing-box/issues"
|
||||||
--no-deb-generate-changes
|
--no-deb-generate-changes
|
||||||
--config-files /etc/sing-box/config.json
|
--config-files /etc/sing-box/config.json
|
||||||
|
--after-install release/config/sing-box.postinst
|
||||||
|
|
||||||
release/config/config.json=/etc/sing-box/config.json
|
release/config/config.json=/etc/sing-box/config.json
|
||||||
|
|
||||||
release/config/sing-box.service=/usr/lib/systemd/system/sing-box.service
|
release/config/sing-box.service=/usr/lib/systemd/system/sing-box.service
|
||||||
release/config/sing-box@.service=/usr/lib/systemd/system/sing-box@.service
|
release/config/sing-box@.service=/usr/lib/systemd/system/sing-box@.service
|
||||||
|
release/config/sing-box.sysusers=/usr/lib/sysusers.d/sing-box.conf
|
||||||
|
release/config/sing-box.rules=usr/share/polkit-1/rules.d/sing-box.rules
|
||||||
|
release/config/sing-box-split-dns.xml=/usr/share/dbus-1/system.d/sing-box-split-dns.conf
|
||||||
|
|
||||||
release/completions/sing-box.bash=/usr/share/bash-completion/completions/sing-box.bash
|
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.fish=/usr/share/fish/vendor_completions.d/sing-box.fish
|
||||||
|
12
.github/workflows/build.yml
vendored
12
.github/workflows/build.yml
vendored
@ -46,7 +46,7 @@ jobs:
|
|||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: ^1.24.2
|
go-version: ^1.24.3
|
||||||
- name: Check input version
|
- name: Check input version
|
||||||
if: github.event_name == 'workflow_dispatch'
|
if: github.event_name == 'workflow_dispatch'
|
||||||
run: |-
|
run: |-
|
||||||
@ -109,7 +109,7 @@ jobs:
|
|||||||
if: ${{ ! matrix.legacy_go }}
|
if: ${{ ! matrix.legacy_go }}
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: ^1.24.2
|
go-version: ^1.24.3
|
||||||
- name: Cache Legacy Go
|
- name: Cache Legacy Go
|
||||||
if: matrix.require_legacy_go
|
if: matrix.require_legacy_go
|
||||||
id: cache-legacy-go
|
id: cache-legacy-go
|
||||||
@ -140,7 +140,7 @@ jobs:
|
|||||||
- name: Set build tags
|
- name: Set build tags
|
||||||
run: |
|
run: |
|
||||||
set -xeuo pipefail
|
set -xeuo pipefail
|
||||||
TAGS='with_gvisor,with_quic,with_dhcp,with_wireguard,with_utls,with_reality_server,with_acme,with_clash_api,with_tailscale'
|
TAGS='with_gvisor,with_quic,with_dhcp,with_wireguard,with_utls,with_acme,with_clash_api,with_tailscale'
|
||||||
echo "BUILD_TAGS=${TAGS}" >> "${GITHUB_ENV}"
|
echo "BUILD_TAGS=${TAGS}" >> "${GITHUB_ENV}"
|
||||||
- name: Build
|
- name: Build
|
||||||
if: matrix.os != 'android'
|
if: matrix.os != 'android'
|
||||||
@ -294,7 +294,7 @@ jobs:
|
|||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: ^1.24.2
|
go-version: ^1.24.3
|
||||||
- name: Setup Android NDK
|
- name: Setup Android NDK
|
||||||
id: setup-ndk
|
id: setup-ndk
|
||||||
uses: nttld/setup-ndk@v1
|
uses: nttld/setup-ndk@v1
|
||||||
@ -374,7 +374,7 @@ jobs:
|
|||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: ^1.24.2
|
go-version: ^1.24.3
|
||||||
- name: Setup Android NDK
|
- name: Setup Android NDK
|
||||||
id: setup-ndk
|
id: setup-ndk
|
||||||
uses: nttld/setup-ndk@v1
|
uses: nttld/setup-ndk@v1
|
||||||
@ -472,7 +472,7 @@ jobs:
|
|||||||
if: matrix.if
|
if: matrix.if
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: ^1.24.2
|
go-version: ^1.24.3
|
||||||
- name: Setup Xcode stable
|
- name: Setup Xcode stable
|
||||||
if: matrix.if && github.ref == 'refs/heads/main-next'
|
if: matrix.if && github.ref == 'refs/heads/main-next'
|
||||||
run: |-
|
run: |-
|
||||||
|
2
.github/workflows/lint.yml
vendored
2
.github/workflows/lint.yml
vendored
@ -28,7 +28,7 @@ jobs:
|
|||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: ^1.24.2
|
go-version: ^1.24.3
|
||||||
- name: golangci-lint
|
- name: golangci-lint
|
||||||
uses: golangci/golangci-lint-action@v6
|
uses: golangci/golangci-lint-action@v6
|
||||||
with:
|
with:
|
||||||
|
9
.github/workflows/linux.yml
vendored
9
.github/workflows/linux.yml
vendored
@ -25,7 +25,7 @@ jobs:
|
|||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: ^1.24.2
|
go-version: ^1.24.3
|
||||||
- name: Check input version
|
- name: Check input version
|
||||||
if: github.event_name == 'workflow_dispatch'
|
if: github.event_name == 'workflow_dispatch'
|
||||||
run: |-
|
run: |-
|
||||||
@ -66,7 +66,7 @@ jobs:
|
|||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: ^1.24.2
|
go-version: ^1.24.3
|
||||||
- name: Setup Android NDK
|
- name: Setup Android NDK
|
||||||
if: matrix.os == 'android'
|
if: matrix.os == 'android'
|
||||||
uses: nttld/setup-ndk@v1
|
uses: nttld/setup-ndk@v1
|
||||||
@ -80,10 +80,7 @@ jobs:
|
|||||||
- name: Set build tags
|
- name: Set build tags
|
||||||
run: |
|
run: |
|
||||||
set -xeuo pipefail
|
set -xeuo pipefail
|
||||||
TAGS='with_gvisor,with_quic,with_dhcp,with_wireguard,with_utls,with_reality_server,with_acme,with_clash_api'
|
TAGS='with_gvisor,with_quic,with_dhcp,with_wireguard,with_utls,with_acme,with_clash_api,with_tailscale'
|
||||||
if [ ! '${{ matrix.legacy_go }}' = 'true' ]; then
|
|
||||||
TAGS="${TAGS},with_ech"
|
|
||||||
fi
|
|
||||||
echo "BUILD_TAGS=${TAGS}" >> "${GITHUB_ENV}"
|
echo "BUILD_TAGS=${TAGS}" >> "${GITHUB_ENV}"
|
||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
|
@ -21,14 +21,13 @@ linters-settings:
|
|||||||
- -SA1003
|
- -SA1003
|
||||||
|
|
||||||
run:
|
run:
|
||||||
go: "1.24"
|
go: "1.23"
|
||||||
build-tags:
|
build-tags:
|
||||||
- with_gvisor
|
- with_gvisor
|
||||||
- with_quic
|
- with_quic
|
||||||
- with_dhcp
|
- with_dhcp
|
||||||
- with_wireguard
|
- with_wireguard
|
||||||
- with_utls
|
- with_utls
|
||||||
- with_reality_server
|
|
||||||
- with_acme
|
- with_acme
|
||||||
- with_clash_api
|
- with_clash_api
|
||||||
|
|
||||||
|
@ -15,7 +15,6 @@ builds:
|
|||||||
- with_dhcp
|
- with_dhcp
|
||||||
- with_wireguard
|
- with_wireguard
|
||||||
- with_utls
|
- with_utls
|
||||||
- with_reality_server
|
|
||||||
- with_acme
|
- with_acme
|
||||||
- with_clash_api
|
- with_clash_api
|
||||||
- with_tailscale
|
- with_tailscale
|
||||||
@ -56,6 +55,12 @@ nfpms:
|
|||||||
dst: /usr/lib/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: /usr/lib/systemd/system/sing-box@.service
|
dst: /usr/lib/systemd/system/sing-box@.service
|
||||||
|
- src: release/config/sing-box.sysusers
|
||||||
|
dst: /usr/lib/sysusers.d/sing-box.conf
|
||||||
|
- src: release/config/sing-box.rules
|
||||||
|
dst: /usr/share/polkit-1/rules.d/sing-box.rules
|
||||||
|
- src: release/config/sing-box-split-dns.xml
|
||||||
|
dst: /usr/share/dbus-1/system.d/sing-box-split-dns.conf
|
||||||
|
|
||||||
- src: release/completions/sing-box.bash
|
- src: release/completions/sing-box.bash
|
||||||
dst: /usr/share/bash-completion/completions/sing-box.bash
|
dst: /usr/share/bash-completion/completions/sing-box.bash
|
||||||
|
@ -17,7 +17,6 @@ builds:
|
|||||||
- with_dhcp
|
- with_dhcp
|
||||||
- with_wireguard
|
- with_wireguard
|
||||||
- with_utls
|
- with_utls
|
||||||
- with_reality_server
|
|
||||||
- with_acme
|
- with_acme
|
||||||
- with_clash_api
|
- with_clash_api
|
||||||
- with_tailscale
|
- with_tailscale
|
||||||
@ -47,7 +46,6 @@ builds:
|
|||||||
- with_dhcp
|
- with_dhcp
|
||||||
- with_wireguard
|
- with_wireguard
|
||||||
- with_utls
|
- with_utls
|
||||||
- with_reality_server
|
|
||||||
- with_acme
|
- with_acme
|
||||||
- with_clash_api
|
- with_clash_api
|
||||||
- with_tailscale
|
- with_tailscale
|
||||||
@ -138,6 +136,12 @@ nfpms:
|
|||||||
dst: /usr/lib/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: /usr/lib/systemd/system/sing-box@.service
|
dst: /usr/lib/systemd/system/sing-box@.service
|
||||||
|
- src: release/config/sing-box.sysusers
|
||||||
|
dst: /usr/lib/sysusers.d/sing-box.conf
|
||||||
|
- src: release/config/sing-box.rules
|
||||||
|
dst: /usr/share/polkit-1/rules.d/sing-box.rules
|
||||||
|
- src: release/config/sing-box-split-dns.xml
|
||||||
|
dst: /usr/share/dbus-1/system.d/sing-box-split-dns.conf
|
||||||
|
|
||||||
- src: release/completions/sing-box.bash
|
- src: release/completions/sing-box.bash
|
||||||
dst: /usr/share/bash-completion/completions/sing-box.bash
|
dst: /usr/share/bash-completion/completions/sing-box.bash
|
||||||
|
@ -13,7 +13,7 @@ RUN set -ex \
|
|||||||
&& export COMMIT=$(git rev-parse --short HEAD) \
|
&& export COMMIT=$(git rev-parse --short HEAD) \
|
||||||
&& export VERSION=$(go run ./cmd/internal/read_tag) \
|
&& export VERSION=$(go run ./cmd/internal/read_tag) \
|
||||||
&& go build -v -trimpath -tags \
|
&& go build -v -trimpath -tags \
|
||||||
"with_gvisor,with_quic,with_dhcp,with_wireguard,with_utls,with_reality_server,with_acme,with_clash_api,with_tailscale" \
|
"with_gvisor,with_quic,with_dhcp,with_wireguard,with_utls,with_acme,with_clash_api,with_tailscale" \
|
||||||
-o /go/bin/sing-box \
|
-o /go/bin/sing-box \
|
||||||
-ldflags "-X \"github.com/sagernet/sing-box/constant.Version=$VERSION\" -s -w -buildid=" \
|
-ldflags "-X \"github.com/sagernet/sing-box/constant.Version=$VERSION\" -s -w -buildid=" \
|
||||||
./cmd/sing-box
|
./cmd/sing-box
|
||||||
|
5
Makefile
5
Makefile
@ -1,11 +1,10 @@
|
|||||||
NAME = sing-box
|
NAME = sing-box
|
||||||
COMMIT = $(shell git rev-parse --short HEAD)
|
COMMIT = $(shell git rev-parse --short HEAD)
|
||||||
TAGS ?= with_gvisor,with_dhcp,with_wireguard,with_reality_server,with_clash_api,with_quic,with_utls,with_tailscale
|
TAGS ?= with_gvisor,with_quic,with_dhcp,with_wireguard,with_utls,with_acme,with_clash_api,with_tailscale
|
||||||
TAGS_TEST ?= with_gvisor,with_quic,with_wireguard,with_grpc,with_utls,with_reality_server
|
|
||||||
|
|
||||||
GOHOSTOS = $(shell go env GOHOSTOS)
|
GOHOSTOS = $(shell go env GOHOSTOS)
|
||||||
GOHOSTARCH = $(shell go env GOHOSTARCH)
|
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 github.com/sagernet/sing-box/cmd/internal/read_tag@latest)
|
||||||
|
|
||||||
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)"
|
||||||
|
@ -7,7 +7,9 @@ import (
|
|||||||
C "github.com/sagernet/sing-box/constant"
|
C "github.com/sagernet/sing-box/constant"
|
||||||
"github.com/sagernet/sing-box/log"
|
"github.com/sagernet/sing-box/log"
|
||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
"github.com/sagernet/sing/common/logger"
|
"github.com/sagernet/sing/common/logger"
|
||||||
|
"github.com/sagernet/sing/service"
|
||||||
|
|
||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
)
|
)
|
||||||
@ -31,11 +33,30 @@ type DNSClient interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type DNSQueryOptions struct {
|
type DNSQueryOptions struct {
|
||||||
Transport DNSTransport
|
Transport DNSTransport
|
||||||
Strategy C.DomainStrategy
|
Strategy C.DomainStrategy
|
||||||
DisableCache bool
|
LookupStrategy C.DomainStrategy
|
||||||
RewriteTTL *uint32
|
DisableCache bool
|
||||||
ClientSubnet netip.Prefix
|
RewriteTTL *uint32
|
||||||
|
ClientSubnet netip.Prefix
|
||||||
|
}
|
||||||
|
|
||||||
|
func DNSQueryOptionsFrom(ctx context.Context, options *option.DomainResolveOptions) (*DNSQueryOptions, error) {
|
||||||
|
if options == nil {
|
||||||
|
return &DNSQueryOptions{}, nil
|
||||||
|
}
|
||||||
|
transportManager := service.FromContext[DNSTransportManager](ctx)
|
||||||
|
transport, loaded := transportManager.Transport(options.Server)
|
||||||
|
if !loaded {
|
||||||
|
return nil, E.New("domain resolver not found: " + options.Server)
|
||||||
|
}
|
||||||
|
return &DNSQueryOptions{
|
||||||
|
Transport: transport,
|
||||||
|
Strategy: C.DomainStrategy(options.Strategy),
|
||||||
|
DisableCache: options.DisableCache,
|
||||||
|
RewriteTTL: options.RewriteTTL,
|
||||||
|
ClientSubnet: options.ClientSubnet.Build(netip.Prefix{}),
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type RDRCStore interface {
|
type RDRCStore interface {
|
||||||
|
@ -7,7 +7,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type FakeIPStore interface {
|
type FakeIPStore interface {
|
||||||
Service
|
SimpleLifecycle
|
||||||
Contains(address netip.Addr) bool
|
Contains(address netip.Addr) bool
|
||||||
Create(domain string, isIPv6 bool) (netip.Addr, error)
|
Create(domain string, isIPv6 bool) (netip.Addr, error)
|
||||||
Lookup(address netip.Addr) (string, bool)
|
Lookup(address netip.Addr) (string, bool)
|
||||||
|
@ -74,6 +74,7 @@ type InboundContext struct {
|
|||||||
UDPTimeout time.Duration
|
UDPTimeout time.Duration
|
||||||
TLSFragment bool
|
TLSFragment bool
|
||||||
TLSFragmentFallbackDelay time.Duration
|
TLSFragmentFallbackDelay time.Duration
|
||||||
|
TLSRecordFragment bool
|
||||||
|
|
||||||
NetworkStrategy *C.NetworkStrategy
|
NetworkStrategy *C.NetworkStrategy
|
||||||
NetworkType []C.InterfaceType
|
NetworkType []C.InterfaceType
|
||||||
|
@ -37,13 +37,14 @@ func NewManager(logger log.ContextLogger, registry adapter.InboundRegistry, endp
|
|||||||
|
|
||||||
func (m *Manager) Start(stage adapter.StartStage) error {
|
func (m *Manager) Start(stage adapter.StartStage) error {
|
||||||
m.access.Lock()
|
m.access.Lock()
|
||||||
defer m.access.Unlock()
|
|
||||||
if m.started && m.stage >= stage {
|
if m.started && m.stage >= stage {
|
||||||
panic("already started")
|
panic("already started")
|
||||||
}
|
}
|
||||||
m.started = true
|
m.started = true
|
||||||
m.stage = stage
|
m.stage = stage
|
||||||
for _, inbound := range m.inbounds {
|
inbounds := m.inbounds
|
||||||
|
m.access.Unlock()
|
||||||
|
for _, inbound := range inbounds {
|
||||||
err := adapter.LegacyStart(inbound, stage)
|
err := adapter.LegacyStart(inbound, stage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return E.Cause(err, stage, " inbound/", inbound.Type(), "[", inbound.Tag(), "]")
|
return E.Cause(err, stage, " inbound/", inbound.Type(), "[", inbound.Tag(), "]")
|
||||||
|
@ -2,6 +2,11 @@ package adapter
|
|||||||
|
|
||||||
import E "github.com/sagernet/sing/common/exceptions"
|
import E "github.com/sagernet/sing/common/exceptions"
|
||||||
|
|
||||||
|
type SimpleLifecycle interface {
|
||||||
|
Start() error
|
||||||
|
Close() error
|
||||||
|
}
|
||||||
|
|
||||||
type StartStage uint8
|
type StartStage uint8
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -28,14 +28,14 @@ func LegacyStart(starter any, stage StartStage) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type lifecycleServiceWrapper struct {
|
type lifecycleServiceWrapper struct {
|
||||||
Service
|
SimpleLifecycle
|
||||||
name string
|
name string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewLifecycleService(service Service, name string) LifecycleService {
|
func NewLifecycleService(service SimpleLifecycle, name string) LifecycleService {
|
||||||
return &lifecycleServiceWrapper{
|
return &lifecycleServiceWrapper{
|
||||||
Service: service,
|
SimpleLifecycle: service,
|
||||||
name: name,
|
name: name,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,9 +44,9 @@ func (l *lifecycleServiceWrapper) Name() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (l *lifecycleServiceWrapper) Start(stage StartStage) error {
|
func (l *lifecycleServiceWrapper) Start(stage StartStage) error {
|
||||||
return LegacyStart(l.Service, stage)
|
return LegacyStart(l.SimpleLifecycle, stage)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *lifecycleServiceWrapper) Close() error {
|
func (l *lifecycleServiceWrapper) Close() error {
|
||||||
return l.Service.Close()
|
return l.SimpleLifecycle.Close()
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ type HeadlessRule interface {
|
|||||||
|
|
||||||
type Rule interface {
|
type Rule interface {
|
||||||
HeadlessRule
|
HeadlessRule
|
||||||
Service
|
SimpleLifecycle
|
||||||
Type() string
|
Type() string
|
||||||
Action() RuleAction
|
Action() RuleAction
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,27 @@
|
|||||||
package adapter
|
package adapter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing-box/log"
|
||||||
|
"github.com/sagernet/sing-box/option"
|
||||||
|
)
|
||||||
|
|
||||||
type Service interface {
|
type Service interface {
|
||||||
Start() error
|
Lifecycle
|
||||||
Close() error
|
Type() string
|
||||||
|
Tag() string
|
||||||
|
}
|
||||||
|
|
||||||
|
type ServiceRegistry interface {
|
||||||
|
option.ServiceOptionsRegistry
|
||||||
|
Create(ctx context.Context, logger log.ContextLogger, tag string, serviceType string, options any) (Service, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type ServiceManager interface {
|
||||||
|
Lifecycle
|
||||||
|
Services() []Service
|
||||||
|
Get(tag string) (Service, bool)
|
||||||
|
Remove(tag string) error
|
||||||
|
Create(ctx context.Context, logger log.ContextLogger, tag string, serviceType string, options any) error
|
||||||
}
|
}
|
||||||
|
21
adapter/service/adapter.go
Normal file
21
adapter/service/adapter.go
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
type Adapter struct {
|
||||||
|
serviceType string
|
||||||
|
serviceTag string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAdapter(serviceType string, serviceTag string) Adapter {
|
||||||
|
return Adapter{
|
||||||
|
serviceType: serviceType,
|
||||||
|
serviceTag: serviceTag,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Adapter) Type() string {
|
||||||
|
return a.serviceType
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Adapter) Tag() string {
|
||||||
|
return a.serviceTag
|
||||||
|
}
|
144
adapter/service/manager.go
Normal file
144
adapter/service/manager.go
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"os"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing-box/adapter"
|
||||||
|
"github.com/sagernet/sing-box/common/taskmonitor"
|
||||||
|
C "github.com/sagernet/sing-box/constant"
|
||||||
|
"github.com/sagernet/sing-box/log"
|
||||||
|
"github.com/sagernet/sing/common"
|
||||||
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ adapter.ServiceManager = (*Manager)(nil)
|
||||||
|
|
||||||
|
type Manager struct {
|
||||||
|
logger log.ContextLogger
|
||||||
|
registry adapter.ServiceRegistry
|
||||||
|
access sync.Mutex
|
||||||
|
started bool
|
||||||
|
stage adapter.StartStage
|
||||||
|
services []adapter.Service
|
||||||
|
serviceByTag map[string]adapter.Service
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewManager(logger log.ContextLogger, registry adapter.ServiceRegistry) *Manager {
|
||||||
|
return &Manager{
|
||||||
|
logger: logger,
|
||||||
|
registry: registry,
|
||||||
|
serviceByTag: make(map[string]adapter.Service),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager) Start(stage adapter.StartStage) error {
|
||||||
|
m.access.Lock()
|
||||||
|
if m.started && m.stage >= stage {
|
||||||
|
panic("already started")
|
||||||
|
}
|
||||||
|
m.started = true
|
||||||
|
m.stage = stage
|
||||||
|
services := m.services
|
||||||
|
m.access.Unlock()
|
||||||
|
for _, service := range services {
|
||||||
|
err := adapter.LegacyStart(service, stage)
|
||||||
|
if err != nil {
|
||||||
|
return E.Cause(err, stage, " service/", service.Type(), "[", service.Tag(), "]")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager) Close() error {
|
||||||
|
m.access.Lock()
|
||||||
|
defer m.access.Unlock()
|
||||||
|
if !m.started {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
m.started = false
|
||||||
|
services := m.services
|
||||||
|
m.services = nil
|
||||||
|
monitor := taskmonitor.New(m.logger, C.StopTimeout)
|
||||||
|
var err error
|
||||||
|
for _, service := range services {
|
||||||
|
monitor.Start("close service/", service.Type(), "[", service.Tag(), "]")
|
||||||
|
err = E.Append(err, service.Close(), func(err error) error {
|
||||||
|
return E.Cause(err, "close service/", service.Type(), "[", service.Tag(), "]")
|
||||||
|
})
|
||||||
|
monitor.Finish()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager) Services() []adapter.Service {
|
||||||
|
m.access.Lock()
|
||||||
|
defer m.access.Unlock()
|
||||||
|
return m.services
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager) Get(tag string) (adapter.Service, bool) {
|
||||||
|
m.access.Lock()
|
||||||
|
service, found := m.serviceByTag[tag]
|
||||||
|
m.access.Unlock()
|
||||||
|
return service, found
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager) Remove(tag string) error {
|
||||||
|
m.access.Lock()
|
||||||
|
service, found := m.serviceByTag[tag]
|
||||||
|
if !found {
|
||||||
|
m.access.Unlock()
|
||||||
|
return os.ErrInvalid
|
||||||
|
}
|
||||||
|
delete(m.serviceByTag, tag)
|
||||||
|
index := common.Index(m.services, func(it adapter.Service) bool {
|
||||||
|
return it == service
|
||||||
|
})
|
||||||
|
if index == -1 {
|
||||||
|
panic("invalid service index")
|
||||||
|
}
|
||||||
|
m.services = append(m.services[:index], m.services[index+1:]...)
|
||||||
|
started := m.started
|
||||||
|
m.access.Unlock()
|
||||||
|
if started {
|
||||||
|
return service.Close()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager) Create(ctx context.Context, logger log.ContextLogger, tag string, serviceType string, options any) error {
|
||||||
|
service, err := m.registry.Create(ctx, logger, tag, serviceType, options)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
m.access.Lock()
|
||||||
|
defer m.access.Unlock()
|
||||||
|
if m.started {
|
||||||
|
for _, stage := range adapter.ListStartStages {
|
||||||
|
err = adapter.LegacyStart(service, stage)
|
||||||
|
if err != nil {
|
||||||
|
return E.Cause(err, stage, " service/", service.Type(), "[", service.Tag(), "]")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if existsService, loaded := m.serviceByTag[tag]; loaded {
|
||||||
|
if m.started {
|
||||||
|
err = existsService.Close()
|
||||||
|
if err != nil {
|
||||||
|
return E.Cause(err, "close service/", existsService.Type(), "[", existsService.Tag(), "]")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
existsIndex := common.Index(m.services, func(it adapter.Service) bool {
|
||||||
|
return it == existsService
|
||||||
|
})
|
||||||
|
if existsIndex == -1 {
|
||||||
|
panic("invalid service index")
|
||||||
|
}
|
||||||
|
m.services = append(m.services[:existsIndex], m.services[existsIndex+1:]...)
|
||||||
|
}
|
||||||
|
m.services = append(m.services, service)
|
||||||
|
m.serviceByTag[tag] = service
|
||||||
|
return nil
|
||||||
|
}
|
72
adapter/service/registry.go
Normal file
72
adapter/service/registry.go
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing-box/adapter"
|
||||||
|
"github.com/sagernet/sing-box/log"
|
||||||
|
"github.com/sagernet/sing/common"
|
||||||
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ConstructorFunc[T any] func(ctx context.Context, logger log.ContextLogger, tag string, options T) (adapter.Service, error)
|
||||||
|
|
||||||
|
func Register[Options any](registry *Registry, outboundType string, constructor ConstructorFunc[Options]) {
|
||||||
|
registry.register(outboundType, func() any {
|
||||||
|
return new(Options)
|
||||||
|
}, func(ctx context.Context, logger log.ContextLogger, tag string, rawOptions any) (adapter.Service, error) {
|
||||||
|
var options *Options
|
||||||
|
if rawOptions != nil {
|
||||||
|
options = rawOptions.(*Options)
|
||||||
|
}
|
||||||
|
return constructor(ctx, logger, tag, common.PtrValueOrDefault(options))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ adapter.ServiceRegistry = (*Registry)(nil)
|
||||||
|
|
||||||
|
type (
|
||||||
|
optionsConstructorFunc func() any
|
||||||
|
constructorFunc func(ctx context.Context, logger log.ContextLogger, tag string, options any) (adapter.Service, error)
|
||||||
|
)
|
||||||
|
|
||||||
|
type Registry struct {
|
||||||
|
access sync.Mutex
|
||||||
|
optionsType map[string]optionsConstructorFunc
|
||||||
|
constructor map[string]constructorFunc
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewRegistry() *Registry {
|
||||||
|
return &Registry{
|
||||||
|
optionsType: make(map[string]optionsConstructorFunc),
|
||||||
|
constructor: make(map[string]constructorFunc),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Registry) CreateOptions(outboundType string) (any, bool) {
|
||||||
|
m.access.Lock()
|
||||||
|
defer m.access.Unlock()
|
||||||
|
optionsConstructor, loaded := m.optionsType[outboundType]
|
||||||
|
if !loaded {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
return optionsConstructor(), true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Registry) Create(ctx context.Context, logger log.ContextLogger, tag string, outboundType string, options any) (adapter.Service, error) {
|
||||||
|
m.access.Lock()
|
||||||
|
defer m.access.Unlock()
|
||||||
|
constructor, loaded := m.constructor[outboundType]
|
||||||
|
if !loaded {
|
||||||
|
return nil, E.New("outbound type not found: " + outboundType)
|
||||||
|
}
|
||||||
|
return constructor(ctx, logger, tag, options)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Registry) register(outboundType string, optionsConstructor optionsConstructorFunc, constructor constructorFunc) {
|
||||||
|
m.access.Lock()
|
||||||
|
defer m.access.Unlock()
|
||||||
|
m.optionsType[outboundType] = optionsConstructor
|
||||||
|
m.constructor[outboundType] = constructor
|
||||||
|
}
|
18
adapter/ssm.go
Normal file
18
adapter/ssm.go
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
package adapter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
|
||||||
|
N "github.com/sagernet/sing/common/network"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ManagedSSMServer interface {
|
||||||
|
Inbound
|
||||||
|
SetTracker(tracker SSMTracker)
|
||||||
|
UpdateUsers(users []string, uPSKs []string) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type SSMTracker interface {
|
||||||
|
TrackConnection(conn net.Conn, metadata InboundContext) net.Conn
|
||||||
|
TrackPacketConnection(conn N.PacketConn, metadata InboundContext) N.PacketConn
|
||||||
|
}
|
@ -3,6 +3,6 @@ package adapter
|
|||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
type TimeService interface {
|
type TimeService interface {
|
||||||
Service
|
SimpleLifecycle
|
||||||
TimeFunc() func() time.Time
|
TimeFunc() func() time.Time
|
||||||
}
|
}
|
||||||
|
123
box.go
123
box.go
@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/sagernet/sing-box/adapter/endpoint"
|
"github.com/sagernet/sing-box/adapter/endpoint"
|
||||||
"github.com/sagernet/sing-box/adapter/inbound"
|
"github.com/sagernet/sing-box/adapter/inbound"
|
||||||
"github.com/sagernet/sing-box/adapter/outbound"
|
"github.com/sagernet/sing-box/adapter/outbound"
|
||||||
|
boxService "github.com/sagernet/sing-box/adapter/service"
|
||||||
"github.com/sagernet/sing-box/common/certificate"
|
"github.com/sagernet/sing-box/common/certificate"
|
||||||
"github.com/sagernet/sing-box/common/dialer"
|
"github.com/sagernet/sing-box/common/dialer"
|
||||||
"github.com/sagernet/sing-box/common/taskmonitor"
|
"github.com/sagernet/sing-box/common/taskmonitor"
|
||||||
@ -34,22 +35,23 @@ import (
|
|||||||
"github.com/sagernet/sing/service/pause"
|
"github.com/sagernet/sing/service/pause"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ adapter.Service = (*Box)(nil)
|
var _ adapter.SimpleLifecycle = (*Box)(nil)
|
||||||
|
|
||||||
type Box struct {
|
type Box struct {
|
||||||
createdAt time.Time
|
createdAt time.Time
|
||||||
logFactory log.Factory
|
logFactory log.Factory
|
||||||
logger log.ContextLogger
|
logger log.ContextLogger
|
||||||
network *route.NetworkManager
|
network *route.NetworkManager
|
||||||
endpoint *endpoint.Manager
|
endpoint *endpoint.Manager
|
||||||
inbound *inbound.Manager
|
inbound *inbound.Manager
|
||||||
outbound *outbound.Manager
|
outbound *outbound.Manager
|
||||||
dnsTransport *dns.TransportManager
|
service *boxService.Manager
|
||||||
dnsRouter *dns.Router
|
dnsTransport *dns.TransportManager
|
||||||
connection *route.ConnectionManager
|
dnsRouter *dns.Router
|
||||||
router *route.Router
|
connection *route.ConnectionManager
|
||||||
services []adapter.LifecycleService
|
router *route.Router
|
||||||
done chan struct{}
|
internalService []adapter.LifecycleService
|
||||||
|
done chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Options struct {
|
type Options struct {
|
||||||
@ -64,6 +66,7 @@ func Context(
|
|||||||
outboundRegistry adapter.OutboundRegistry,
|
outboundRegistry adapter.OutboundRegistry,
|
||||||
endpointRegistry adapter.EndpointRegistry,
|
endpointRegistry adapter.EndpointRegistry,
|
||||||
dnsTransportRegistry adapter.DNSTransportRegistry,
|
dnsTransportRegistry adapter.DNSTransportRegistry,
|
||||||
|
serviceRegistry adapter.ServiceRegistry,
|
||||||
) context.Context {
|
) context.Context {
|
||||||
if service.FromContext[option.InboundOptionsRegistry](ctx) == nil ||
|
if service.FromContext[option.InboundOptionsRegistry](ctx) == nil ||
|
||||||
service.FromContext[adapter.InboundRegistry](ctx) == nil {
|
service.FromContext[adapter.InboundRegistry](ctx) == nil {
|
||||||
@ -84,6 +87,10 @@ func Context(
|
|||||||
ctx = service.ContextWith[option.DNSTransportOptionsRegistry](ctx, dnsTransportRegistry)
|
ctx = service.ContextWith[option.DNSTransportOptionsRegistry](ctx, dnsTransportRegistry)
|
||||||
ctx = service.ContextWith[adapter.DNSTransportRegistry](ctx, dnsTransportRegistry)
|
ctx = service.ContextWith[adapter.DNSTransportRegistry](ctx, dnsTransportRegistry)
|
||||||
}
|
}
|
||||||
|
if service.FromContext[adapter.ServiceRegistry](ctx) == nil {
|
||||||
|
ctx = service.ContextWith[option.ServiceOptionsRegistry](ctx, serviceRegistry)
|
||||||
|
ctx = service.ContextWith[adapter.ServiceRegistry](ctx, serviceRegistry)
|
||||||
|
}
|
||||||
return ctx
|
return ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,6 +106,7 @@ func New(options Options) (*Box, error) {
|
|||||||
inboundRegistry := service.FromContext[adapter.InboundRegistry](ctx)
|
inboundRegistry := service.FromContext[adapter.InboundRegistry](ctx)
|
||||||
outboundRegistry := service.FromContext[adapter.OutboundRegistry](ctx)
|
outboundRegistry := service.FromContext[adapter.OutboundRegistry](ctx)
|
||||||
dnsTransportRegistry := service.FromContext[adapter.DNSTransportRegistry](ctx)
|
dnsTransportRegistry := service.FromContext[adapter.DNSTransportRegistry](ctx)
|
||||||
|
serviceRegistry := service.FromContext[adapter.ServiceRegistry](ctx)
|
||||||
|
|
||||||
if endpointRegistry == nil {
|
if endpointRegistry == nil {
|
||||||
return nil, E.New("missing endpoint registry in context")
|
return nil, E.New("missing endpoint registry in context")
|
||||||
@ -109,6 +117,12 @@ func New(options Options) (*Box, error) {
|
|||||||
if outboundRegistry == nil {
|
if outboundRegistry == nil {
|
||||||
return nil, E.New("missing outbound registry in context")
|
return nil, E.New("missing outbound registry in context")
|
||||||
}
|
}
|
||||||
|
if dnsTransportRegistry == nil {
|
||||||
|
return nil, E.New("missing DNS transport registry in context")
|
||||||
|
}
|
||||||
|
if serviceRegistry == nil {
|
||||||
|
return nil, E.New("missing service registry in context")
|
||||||
|
}
|
||||||
|
|
||||||
ctx = pause.WithDefaultManager(ctx)
|
ctx = pause.WithDefaultManager(ctx)
|
||||||
experimentalOptions := common.PtrValueOrDefault(options.Experimental)
|
experimentalOptions := common.PtrValueOrDefault(options.Experimental)
|
||||||
@ -142,7 +156,7 @@ func New(options Options) (*Box, error) {
|
|||||||
return nil, E.Cause(err, "create log factory")
|
return nil, E.Cause(err, "create log factory")
|
||||||
}
|
}
|
||||||
|
|
||||||
var services []adapter.LifecycleService
|
var internalServices []adapter.LifecycleService
|
||||||
certificateOptions := common.PtrValueOrDefault(options.Certificate)
|
certificateOptions := common.PtrValueOrDefault(options.Certificate)
|
||||||
if C.IsAndroid || certificateOptions.Store != "" && certificateOptions.Store != C.CertificateStoreSystem ||
|
if C.IsAndroid || certificateOptions.Store != "" && certificateOptions.Store != C.CertificateStoreSystem ||
|
||||||
len(certificateOptions.Certificate) > 0 ||
|
len(certificateOptions.Certificate) > 0 ||
|
||||||
@ -153,7 +167,7 @@ func New(options Options) (*Box, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
service.MustRegister[adapter.CertificateStore](ctx, certificateStore)
|
service.MustRegister[adapter.CertificateStore](ctx, certificateStore)
|
||||||
services = append(services, certificateStore)
|
internalServices = append(internalServices, certificateStore)
|
||||||
}
|
}
|
||||||
|
|
||||||
routeOptions := common.PtrValueOrDefault(options.Route)
|
routeOptions := common.PtrValueOrDefault(options.Route)
|
||||||
@ -162,10 +176,12 @@ func New(options Options) (*Box, error) {
|
|||||||
inboundManager := inbound.NewManager(logFactory.NewLogger("inbound"), inboundRegistry, endpointManager)
|
inboundManager := inbound.NewManager(logFactory.NewLogger("inbound"), inboundRegistry, endpointManager)
|
||||||
outboundManager := outbound.NewManager(logFactory.NewLogger("outbound"), outboundRegistry, endpointManager, routeOptions.Final)
|
outboundManager := outbound.NewManager(logFactory.NewLogger("outbound"), outboundRegistry, endpointManager, routeOptions.Final)
|
||||||
dnsTransportManager := dns.NewTransportManager(logFactory.NewLogger("dns/transport"), dnsTransportRegistry, outboundManager, dnsOptions.Final)
|
dnsTransportManager := dns.NewTransportManager(logFactory.NewLogger("dns/transport"), dnsTransportRegistry, outboundManager, dnsOptions.Final)
|
||||||
|
serviceManager := boxService.NewManager(logFactory.NewLogger("service"), serviceRegistry)
|
||||||
service.MustRegister[adapter.EndpointManager](ctx, endpointManager)
|
service.MustRegister[adapter.EndpointManager](ctx, endpointManager)
|
||||||
service.MustRegister[adapter.InboundManager](ctx, inboundManager)
|
service.MustRegister[adapter.InboundManager](ctx, inboundManager)
|
||||||
service.MustRegister[adapter.OutboundManager](ctx, outboundManager)
|
service.MustRegister[adapter.OutboundManager](ctx, outboundManager)
|
||||||
service.MustRegister[adapter.DNSTransportManager](ctx, dnsTransportManager)
|
service.MustRegister[adapter.DNSTransportManager](ctx, dnsTransportManager)
|
||||||
|
service.MustRegister[adapter.ServiceManager](ctx, serviceManager)
|
||||||
dnsRouter := dns.NewRouter(ctx, logFactory, dnsOptions)
|
dnsRouter := dns.NewRouter(ctx, logFactory, dnsOptions)
|
||||||
service.MustRegister[adapter.DNSRouter](ctx, dnsRouter)
|
service.MustRegister[adapter.DNSRouter](ctx, dnsRouter)
|
||||||
networkManager, err := route.NewNetworkManager(ctx, logFactory.NewLogger("network"), routeOptions)
|
networkManager, err := route.NewNetworkManager(ctx, logFactory.NewLogger("network"), routeOptions)
|
||||||
@ -280,6 +296,24 @@ func New(options Options) (*Box, error) {
|
|||||||
return nil, E.Cause(err, "initialize outbound[", i, "]")
|
return nil, E.Cause(err, "initialize outbound[", i, "]")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for i, serviceOptions := range options.Services {
|
||||||
|
var tag string
|
||||||
|
if serviceOptions.Tag != "" {
|
||||||
|
tag = serviceOptions.Tag
|
||||||
|
} else {
|
||||||
|
tag = F.ToString(i)
|
||||||
|
}
|
||||||
|
err = serviceManager.Create(
|
||||||
|
ctx,
|
||||||
|
logFactory.NewLogger(F.ToString("service/", serviceOptions.Type, "[", tag, "]")),
|
||||||
|
tag,
|
||||||
|
serviceOptions.Type,
|
||||||
|
serviceOptions.Options,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, E.Cause(err, "initialize service[", i, "]")
|
||||||
|
}
|
||||||
|
}
|
||||||
outboundManager.Initialize(common.Must1(
|
outboundManager.Initialize(common.Must1(
|
||||||
direct.NewOutbound(
|
direct.NewOutbound(
|
||||||
ctx,
|
ctx,
|
||||||
@ -305,7 +339,7 @@ func New(options Options) (*Box, error) {
|
|||||||
if needCacheFile {
|
if needCacheFile {
|
||||||
cacheFile := cachefile.New(ctx, common.PtrValueOrDefault(experimentalOptions.CacheFile))
|
cacheFile := cachefile.New(ctx, common.PtrValueOrDefault(experimentalOptions.CacheFile))
|
||||||
service.MustRegister[adapter.CacheFile](ctx, cacheFile)
|
service.MustRegister[adapter.CacheFile](ctx, cacheFile)
|
||||||
services = append(services, cacheFile)
|
internalServices = append(internalServices, cacheFile)
|
||||||
}
|
}
|
||||||
if needClashAPI {
|
if needClashAPI {
|
||||||
clashAPIOptions := common.PtrValueOrDefault(experimentalOptions.ClashAPI)
|
clashAPIOptions := common.PtrValueOrDefault(experimentalOptions.ClashAPI)
|
||||||
@ -316,7 +350,7 @@ func New(options Options) (*Box, error) {
|
|||||||
}
|
}
|
||||||
router.AppendTracker(clashServer)
|
router.AppendTracker(clashServer)
|
||||||
service.MustRegister[adapter.ClashServer](ctx, clashServer)
|
service.MustRegister[adapter.ClashServer](ctx, clashServer)
|
||||||
services = append(services, clashServer)
|
internalServices = append(internalServices, clashServer)
|
||||||
}
|
}
|
||||||
if needV2RayAPI {
|
if needV2RayAPI {
|
||||||
v2rayServer, err := experimental.NewV2RayServer(logFactory.NewLogger("v2ray-api"), common.PtrValueOrDefault(experimentalOptions.V2RayAPI))
|
v2rayServer, err := experimental.NewV2RayServer(logFactory.NewLogger("v2ray-api"), common.PtrValueOrDefault(experimentalOptions.V2RayAPI))
|
||||||
@ -325,7 +359,7 @@ func New(options Options) (*Box, error) {
|
|||||||
}
|
}
|
||||||
if v2rayServer.StatsService() != nil {
|
if v2rayServer.StatsService() != nil {
|
||||||
router.AppendTracker(v2rayServer.StatsService())
|
router.AppendTracker(v2rayServer.StatsService())
|
||||||
services = append(services, v2rayServer)
|
internalServices = append(internalServices, v2rayServer)
|
||||||
service.MustRegister[adapter.V2RayServer](ctx, v2rayServer)
|
service.MustRegister[adapter.V2RayServer](ctx, v2rayServer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -343,22 +377,23 @@ func New(options Options) (*Box, error) {
|
|||||||
WriteToSystem: ntpOptions.WriteToSystem,
|
WriteToSystem: ntpOptions.WriteToSystem,
|
||||||
})
|
})
|
||||||
timeService.TimeService = ntpService
|
timeService.TimeService = ntpService
|
||||||
services = append(services, adapter.NewLifecycleService(ntpService, "ntp service"))
|
internalServices = append(internalServices, adapter.NewLifecycleService(ntpService, "ntp service"))
|
||||||
}
|
}
|
||||||
return &Box{
|
return &Box{
|
||||||
network: networkManager,
|
network: networkManager,
|
||||||
endpoint: endpointManager,
|
endpoint: endpointManager,
|
||||||
inbound: inboundManager,
|
inbound: inboundManager,
|
||||||
outbound: outboundManager,
|
outbound: outboundManager,
|
||||||
dnsTransport: dnsTransportManager,
|
dnsTransport: dnsTransportManager,
|
||||||
dnsRouter: dnsRouter,
|
service: serviceManager,
|
||||||
connection: connectionManager,
|
dnsRouter: dnsRouter,
|
||||||
router: router,
|
connection: connectionManager,
|
||||||
createdAt: createdAt,
|
router: router,
|
||||||
logFactory: logFactory,
|
createdAt: createdAt,
|
||||||
logger: logFactory.Logger(),
|
logFactory: logFactory,
|
||||||
services: services,
|
logger: logFactory.Logger(),
|
||||||
done: make(chan struct{}),
|
internalService: internalServices,
|
||||||
|
done: make(chan struct{}),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -408,11 +443,11 @@ func (s *Box) preStart() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return E.Cause(err, "start logger")
|
return E.Cause(err, "start logger")
|
||||||
}
|
}
|
||||||
err = adapter.StartNamed(adapter.StartStateInitialize, s.services) // cache-file clash-api v2ray-api
|
err = adapter.StartNamed(adapter.StartStateInitialize, s.internalService) // cache-file clash-api v2ray-api
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = adapter.Start(adapter.StartStateInitialize, s.network, s.dnsTransport, s.dnsRouter, s.connection, s.router, s.outbound, s.inbound, s.endpoint)
|
err = adapter.Start(adapter.StartStateInitialize, s.network, s.dnsTransport, s.dnsRouter, s.connection, s.router, s.outbound, s.inbound, s.endpoint, s.service)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -428,31 +463,27 @@ func (s *Box) start() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = adapter.StartNamed(adapter.StartStateStart, s.services)
|
err = adapter.StartNamed(adapter.StartStateStart, s.internalService)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = s.inbound.Start(adapter.StartStateStart)
|
err = adapter.Start(adapter.StartStateStart, s.inbound, s.endpoint, s.service)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = adapter.Start(adapter.StartStateStart, s.endpoint)
|
err = adapter.Start(adapter.StartStatePostStart, s.outbound, s.network, s.dnsTransport, s.dnsRouter, s.connection, s.router, s.inbound, s.endpoint, s.service)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = adapter.Start(adapter.StartStatePostStart, s.outbound, s.network, s.dnsTransport, s.dnsRouter, s.connection, s.router, s.inbound, s.endpoint)
|
err = adapter.StartNamed(adapter.StartStatePostStart, s.internalService)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = adapter.StartNamed(adapter.StartStatePostStart, s.services)
|
err = adapter.Start(adapter.StartStateStarted, s.network, s.dnsTransport, s.dnsRouter, s.connection, s.router, s.outbound, s.inbound, s.endpoint, s.service)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = adapter.Start(adapter.StartStateStarted, s.network, s.dnsTransport, s.dnsRouter, s.connection, s.router, s.outbound, s.inbound, s.endpoint)
|
err = adapter.StartNamed(adapter.StartStateStarted, s.internalService)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = adapter.StartNamed(adapter.StartStateStarted, s.services)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -469,7 +500,7 @@ func (s *Box) Close() error {
|
|||||||
err := common.Close(
|
err := common.Close(
|
||||||
s.inbound, s.outbound, s.endpoint, s.router, s.connection, s.dnsRouter, s.dnsTransport, s.network,
|
s.inbound, s.outbound, s.endpoint, s.router, s.connection, s.dnsRouter, s.dnsTransport, s.network,
|
||||||
)
|
)
|
||||||
for _, lifecycleService := range s.services {
|
for _, lifecycleService := range s.internalService {
|
||||||
err = E.Append(err, lifecycleService.Close(), func(err error) error {
|
err = E.Append(err, lifecycleService.Close(), func(err error) error {
|
||||||
return E.Cause(err, "close ", lifecycleService.Name())
|
return E.Cause(err, "close ", lifecycleService.Name())
|
||||||
})
|
})
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 6a15780ce1659a234816f7248cbc09e8ea54a1be
|
Subproject commit 320170a1077ea5c93872b3e055b96b8836615ef0
|
@ -105,7 +105,7 @@ func publishTestflight(ctx context.Context) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
tag := tagVersion.VersionString()
|
tag := tagVersion.VersionString()
|
||||||
client := createClient(10 * time.Minute)
|
client := createClient(20 * time.Minute)
|
||||||
|
|
||||||
log.Info(tag, " list build IDs")
|
log.Info(tag, " list build IDs")
|
||||||
buildIDsResponse, _, err := client.TestFlight.ListBuildIDsForBetaGroup(ctx, groupID, nil)
|
buildIDsResponse, _, err := client.TestFlight.ListBuildIDsForBetaGroup(ctx, groupID, nil)
|
||||||
@ -145,7 +145,7 @@ func publishTestflight(ctx context.Context) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
build := builds.Data[0]
|
build := builds.Data[0]
|
||||||
if common.Contains(buildIDs, build.ID) || time.Since(build.Attributes.UploadedDate.Time) > 5*time.Minute {
|
if common.Contains(buildIDs, build.ID) || time.Since(build.Attributes.UploadedDate.Time) > 30*time.Minute {
|
||||||
log.Info(string(platform), " ", tag, " waiting for process")
|
log.Info(string(platform), " ", tag, " waiting for process")
|
||||||
time.Sleep(15 * time.Second)
|
time.Sleep(15 * time.Second)
|
||||||
continue
|
continue
|
||||||
|
@ -59,8 +59,8 @@ func init() {
|
|||||||
sharedFlags = append(sharedFlags, "-ldflags", "-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, "-ldflags", "-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_utls", "with_clash_api")
|
sharedTags = append(sharedTags, "with_gvisor", "with_quic", "with_wireguard", "with_utls", "with_clash_api", "with_conntrack")
|
||||||
iosTags = append(iosTags, "with_dhcp", "with_low_memory", "with_conntrack")
|
iosTags = append(iosTags, "with_dhcp", "with_low_memory")
|
||||||
memcTags = append(memcTags, "with_tailscale")
|
memcTags = append(memcTags, "with_tailscale")
|
||||||
debugTags = append(debugTags, "debug")
|
debugTags = append(debugTags, "debug")
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,6 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box"
|
|
||||||
"github.com/sagernet/sing-box/experimental/deprecated"
|
"github.com/sagernet/sing-box/experimental/deprecated"
|
||||||
"github.com/sagernet/sing-box/include"
|
"github.com/sagernet/sing-box/include"
|
||||||
"github.com/sagernet/sing-box/log"
|
"github.com/sagernet/sing-box/log"
|
||||||
@ -68,6 +67,5 @@ func preRun(cmd *cobra.Command, args []string) {
|
|||||||
if len(configPaths) == 0 && len(configDirectories) == 0 {
|
if len(configPaths) == 0 && len(configDirectories) == 0 {
|
||||||
configPaths = append(configPaths, "config.json")
|
configPaths = append(configPaths, "config.json")
|
||||||
}
|
}
|
||||||
globalCtx = service.ContextWith(globalCtx, deprecated.NewStderrManager(log.StdLogger()))
|
globalCtx = include.Context(service.ContextWith(globalCtx, deprecated.NewStderrManager(log.StdLogger())))
|
||||||
globalCtx = box.Context(globalCtx, include.InboundRegistry(), include.OutboundRegistry(), include.EndpointRegistry(), include.DNSTransportRegistry())
|
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
"github.com/sagernet/sing-box/common/srs"
|
"github.com/sagernet/sing-box/common/srs"
|
||||||
@ -56,6 +57,14 @@ func ruleSetMatch(sourcePath string, domain string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return E.Cause(err, "read rule-set")
|
return E.Cause(err, "read rule-set")
|
||||||
}
|
}
|
||||||
|
if flagRuleSetMatchFormat == "" {
|
||||||
|
switch filepath.Ext(sourcePath) {
|
||||||
|
case ".json":
|
||||||
|
flagRuleSetMatchFormat = C.RuleSetFormatSource
|
||||||
|
case ".srs":
|
||||||
|
flagRuleSetMatchFormat = C.RuleSetFormatBinary
|
||||||
|
}
|
||||||
|
}
|
||||||
var ruleSet option.PlainRuleSetCompat
|
var ruleSet option.PlainRuleSetCompat
|
||||||
switch flagRuleSetMatchFormat {
|
switch flagRuleSetMatchFormat {
|
||||||
case C.RuleSetFormatSource:
|
case C.RuleSetFormatSource:
|
||||||
|
@ -7,7 +7,8 @@ import (
|
|||||||
_ "unsafe"
|
_ "unsafe"
|
||||||
|
|
||||||
"github.com/sagernet/sing/common"
|
"github.com/sagernet/sing/common"
|
||||||
"github.com/sagernet/utls"
|
|
||||||
|
"github.com/metacubex/utls"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -24,8 +25,8 @@ func init() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:linkname utlsReadRecord github.com/sagernet/utls.(*Conn).readRecord
|
//go:linkname utlsReadRecord github.com/metacubex/utls.(*Conn).readRecord
|
||||||
func utlsReadRecord(c *tls.Conn) error
|
func utlsReadRecord(c *tls.Conn) error
|
||||||
|
|
||||||
//go:linkname utlsHandlePostHandshakeMessage github.com/sagernet/utls.(*Conn).handlePostHandshakeMessage
|
//go:linkname utlsHandlePostHandshakeMessage github.com/metacubex/utls.(*Conn).handlePostHandshakeMessage
|
||||||
func utlsHandlePostHandshakeMessage(c *tls.Conn) error
|
func utlsHandlePostHandshakeMessage(c *tls.Conn) error
|
||||||
|
@ -66,11 +66,17 @@ func NewDefault(ctx context.Context, options option.DialerOptions) (*DefaultDial
|
|||||||
interfaceFinder = control.NewDefaultInterfaceFinder()
|
interfaceFinder = control.NewDefaultInterfaceFinder()
|
||||||
}
|
}
|
||||||
if options.BindInterface != "" {
|
if options.BindInterface != "" {
|
||||||
|
if !(C.IsLinux || C.IsDarwin || C.IsWindows) {
|
||||||
|
return nil, E.New("`bind_interface` is only supported on Linux, macOS and Windows")
|
||||||
|
}
|
||||||
bindFunc := control.BindToInterface(interfaceFinder, options.BindInterface, -1)
|
bindFunc := control.BindToInterface(interfaceFinder, options.BindInterface, -1)
|
||||||
dialer.Control = control.Append(dialer.Control, bindFunc)
|
dialer.Control = control.Append(dialer.Control, bindFunc)
|
||||||
listener.Control = control.Append(listener.Control, bindFunc)
|
listener.Control = control.Append(listener.Control, bindFunc)
|
||||||
}
|
}
|
||||||
if options.RoutingMark > 0 {
|
if options.RoutingMark > 0 {
|
||||||
|
if !C.IsLinux {
|
||||||
|
return nil, E.New("`routing_mark` is only supported on Linux")
|
||||||
|
}
|
||||||
dialer.Control = control.Append(dialer.Control, setMarkWrapper(networkManager, uint32(options.RoutingMark), false))
|
dialer.Control = control.Append(dialer.Control, setMarkWrapper(networkManager, uint32(options.RoutingMark), false))
|
||||||
listener.Control = control.Append(listener.Control, setMarkWrapper(networkManager, uint32(options.RoutingMark), false))
|
listener.Control = control.Append(listener.Control, setMarkWrapper(networkManager, uint32(options.RoutingMark), false))
|
||||||
}
|
}
|
||||||
@ -91,10 +97,6 @@ func NewDefault(ctx context.Context, options option.DialerOptions) (*DefaultDial
|
|||||||
} else if networkManager.AutoDetectInterface() {
|
} else if networkManager.AutoDetectInterface() {
|
||||||
if platformInterface != nil {
|
if platformInterface != nil {
|
||||||
networkStrategy = (*C.NetworkStrategy)(options.NetworkStrategy)
|
networkStrategy = (*C.NetworkStrategy)(options.NetworkStrategy)
|
||||||
if networkStrategy == nil {
|
|
||||||
networkStrategy = common.Ptr(C.NetworkStrategyDefault)
|
|
||||||
defaultNetworkStrategy = true
|
|
||||||
}
|
|
||||||
networkType = common.Map(options.NetworkType, option.InterfaceType.Build)
|
networkType = common.Map(options.NetworkType, option.InterfaceType.Build)
|
||||||
fallbackNetworkType = common.Map(options.FallbackNetworkType, option.InterfaceType.Build)
|
fallbackNetworkType = common.Map(options.FallbackNetworkType, option.InterfaceType.Build)
|
||||||
if networkStrategy == nil && len(networkType) == 0 && len(fallbackNetworkType) == 0 {
|
if networkStrategy == nil && len(networkType) == 0 && len(fallbackNetworkType) == 0 {
|
||||||
@ -106,6 +108,10 @@ func NewDefault(ctx context.Context, options option.DialerOptions) (*DefaultDial
|
|||||||
if networkFallbackDelay == 0 && defaultOptions.FallbackDelay != 0 {
|
if networkFallbackDelay == 0 && defaultOptions.FallbackDelay != 0 {
|
||||||
networkFallbackDelay = defaultOptions.FallbackDelay
|
networkFallbackDelay = defaultOptions.FallbackDelay
|
||||||
}
|
}
|
||||||
|
if networkStrategy == nil {
|
||||||
|
networkStrategy = common.Ptr(C.NetworkStrategyDefault)
|
||||||
|
defaultNetworkStrategy = true
|
||||||
|
}
|
||||||
bindFunc := networkManager.ProtectFunc()
|
bindFunc := networkManager.ProtectFunc()
|
||||||
dialer.Control = control.Append(dialer.Control, bindFunc)
|
dialer.Control = control.Append(dialer.Control, bindFunc)
|
||||||
listener.Control = control.Append(listener.Control, bindFunc)
|
listener.Control = control.Append(listener.Control, bindFunc)
|
||||||
|
@ -12,7 +12,6 @@ import (
|
|||||||
|
|
||||||
"github.com/sagernet/sing/common"
|
"github.com/sagernet/sing/common"
|
||||||
"github.com/sagernet/sing/common/bufio"
|
"github.com/sagernet/sing/common/bufio"
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
|
||||||
M "github.com/sagernet/sing/common/metadata"
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
N "github.com/sagernet/sing/common/network"
|
N "github.com/sagernet/sing/common/network"
|
||||||
|
|
||||||
@ -76,10 +75,11 @@ func (c *slowOpenConn) Write(b []byte) (n int, err error) {
|
|||||||
return c.conn.Write(b)
|
return c.conn.Write(b)
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
c.conn, err = c.dialer.DialContext(c.ctx, c.network, c.destination.String(), b)
|
conn, err := c.dialer.DialContext(c.ctx, c.network, c.destination.String(), b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.conn = nil
|
c.err = err
|
||||||
c.err = E.Cause(err, "dial tcp fast open")
|
} else {
|
||||||
|
c.conn = conn
|
||||||
}
|
}
|
||||||
n = len(b)
|
n = len(b)
|
||||||
close(c.create)
|
close(c.create)
|
||||||
|
@ -32,6 +32,7 @@ type Listener struct {
|
|||||||
disablePacketOutput bool
|
disablePacketOutput bool
|
||||||
setSystemProxy bool
|
setSystemProxy bool
|
||||||
systemProxySOCKS bool
|
systemProxySOCKS bool
|
||||||
|
tproxy bool
|
||||||
|
|
||||||
tcpListener net.Listener
|
tcpListener net.Listener
|
||||||
systemProxy settings.SystemProxy
|
systemProxy settings.SystemProxy
|
||||||
@ -54,6 +55,7 @@ type Options struct {
|
|||||||
DisablePacketOutput bool
|
DisablePacketOutput bool
|
||||||
SetSystemProxy bool
|
SetSystemProxy bool
|
||||||
SystemProxySOCKS bool
|
SystemProxySOCKS bool
|
||||||
|
TProxy bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(
|
func New(
|
||||||
@ -71,6 +73,7 @@ func New(
|
|||||||
disablePacketOutput: options.DisablePacketOutput,
|
disablePacketOutput: options.DisablePacketOutput,
|
||||||
setSystemProxy: options.SetSystemProxy,
|
setSystemProxy: options.SetSystemProxy,
|
||||||
systemProxySOCKS: options.SystemProxySOCKS,
|
systemProxySOCKS: options.SystemProxySOCKS,
|
||||||
|
tproxy: options.TProxy,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,14 +3,18 @@ package listener
|
|||||||
import (
|
import (
|
||||||
"net"
|
"net"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
|
"github.com/sagernet/sing-box/common/redir"
|
||||||
C "github.com/sagernet/sing-box/constant"
|
C "github.com/sagernet/sing-box/constant"
|
||||||
"github.com/sagernet/sing-box/log"
|
"github.com/sagernet/sing-box/log"
|
||||||
|
"github.com/sagernet/sing/common/control"
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
M "github.com/sagernet/sing/common/metadata"
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
N "github.com/sagernet/sing/common/network"
|
N "github.com/sagernet/sing/common/network"
|
||||||
|
"github.com/sagernet/sing/service"
|
||||||
|
|
||||||
"github.com/metacubex/tfo-go"
|
"github.com/metacubex/tfo-go"
|
||||||
)
|
)
|
||||||
@ -23,6 +27,15 @@ func (l *Listener) ListenTCP() (net.Listener, error) {
|
|||||||
var err error
|
var err error
|
||||||
bindAddr := M.SocksaddrFrom(l.listenOptions.Listen.Build(netip.AddrFrom4([4]byte{127, 0, 0, 1})), l.listenOptions.ListenPort)
|
bindAddr := M.SocksaddrFrom(l.listenOptions.Listen.Build(netip.AddrFrom4([4]byte{127, 0, 0, 1})), l.listenOptions.ListenPort)
|
||||||
var listenConfig net.ListenConfig
|
var listenConfig net.ListenConfig
|
||||||
|
if l.listenOptions.BindInterface != "" {
|
||||||
|
listenConfig.Control = control.Append(listenConfig.Control, control.BindToInterface(service.FromContext[adapter.NetworkManager](l.ctx).InterfaceFinder(), l.listenOptions.BindInterface, -1))
|
||||||
|
}
|
||||||
|
if l.listenOptions.RoutingMark != 0 {
|
||||||
|
listenConfig.Control = control.Append(listenConfig.Control, control.RoutingMark(uint32(l.listenOptions.RoutingMark)))
|
||||||
|
}
|
||||||
|
if l.listenOptions.ReuseAddr {
|
||||||
|
listenConfig.Control = control.Append(listenConfig.Control, control.ReuseAddr())
|
||||||
|
}
|
||||||
if l.listenOptions.TCPKeepAlive >= 0 {
|
if l.listenOptions.TCPKeepAlive >= 0 {
|
||||||
keepIdle := time.Duration(l.listenOptions.TCPKeepAlive)
|
keepIdle := time.Duration(l.listenOptions.TCPKeepAlive)
|
||||||
if keepIdle == 0 {
|
if keepIdle == 0 {
|
||||||
@ -40,6 +53,13 @@ func (l *Listener) ListenTCP() (net.Listener, error) {
|
|||||||
}
|
}
|
||||||
setMultiPathTCP(&listenConfig)
|
setMultiPathTCP(&listenConfig)
|
||||||
}
|
}
|
||||||
|
if l.tproxy {
|
||||||
|
listenConfig.Control = control.Append(listenConfig.Control, func(network, address string, conn syscall.RawConn) error {
|
||||||
|
return control.Raw(conn, func(fd uintptr) error {
|
||||||
|
return redir.TProxy(fd, M.ParseSocksaddr(address).IsIPv6(), false)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
tcpListener, err := ListenNetworkNamespace[net.Listener](l.listenOptions.NetNs, func() (net.Listener, error) {
|
tcpListener, err := ListenNetworkNamespace[net.Listener](l.listenOptions.NetNs, func() (net.Listener, error) {
|
||||||
if l.listenOptions.TCPFastOpen {
|
if l.listenOptions.TCPFastOpen {
|
||||||
var tfoConfig tfo.ListenConfig
|
var tfoConfig tfo.ListenConfig
|
||||||
|
@ -5,17 +5,30 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"os"
|
"os"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing-box/adapter"
|
||||||
|
"github.com/sagernet/sing-box/common/redir"
|
||||||
"github.com/sagernet/sing/common/buf"
|
"github.com/sagernet/sing/common/buf"
|
||||||
"github.com/sagernet/sing/common/control"
|
"github.com/sagernet/sing/common/control"
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
M "github.com/sagernet/sing/common/metadata"
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
N "github.com/sagernet/sing/common/network"
|
N "github.com/sagernet/sing/common/network"
|
||||||
|
"github.com/sagernet/sing/service"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (l *Listener) ListenUDP() (net.PacketConn, error) {
|
func (l *Listener) ListenUDP() (net.PacketConn, error) {
|
||||||
bindAddr := M.SocksaddrFrom(l.listenOptions.Listen.Build(netip.AddrFrom4([4]byte{127, 0, 0, 1})), l.listenOptions.ListenPort)
|
bindAddr := M.SocksaddrFrom(l.listenOptions.Listen.Build(netip.AddrFrom4([4]byte{127, 0, 0, 1})), l.listenOptions.ListenPort)
|
||||||
var lc net.ListenConfig
|
var listenConfig net.ListenConfig
|
||||||
|
if l.listenOptions.BindInterface != "" {
|
||||||
|
listenConfig.Control = control.Append(listenConfig.Control, control.BindToInterface(service.FromContext[adapter.NetworkManager](l.ctx).InterfaceFinder(), l.listenOptions.BindInterface, -1))
|
||||||
|
}
|
||||||
|
if l.listenOptions.RoutingMark != 0 {
|
||||||
|
listenConfig.Control = control.Append(listenConfig.Control, control.RoutingMark(uint32(l.listenOptions.RoutingMark)))
|
||||||
|
}
|
||||||
|
if l.listenOptions.ReuseAddr {
|
||||||
|
listenConfig.Control = control.Append(listenConfig.Control, control.ReuseAddr())
|
||||||
|
}
|
||||||
var udpFragment bool
|
var udpFragment bool
|
||||||
if l.listenOptions.UDPFragment != nil {
|
if l.listenOptions.UDPFragment != nil {
|
||||||
udpFragment = *l.listenOptions.UDPFragment
|
udpFragment = *l.listenOptions.UDPFragment
|
||||||
@ -23,10 +36,17 @@ func (l *Listener) ListenUDP() (net.PacketConn, error) {
|
|||||||
udpFragment = l.listenOptions.UDPFragmentDefault
|
udpFragment = l.listenOptions.UDPFragmentDefault
|
||||||
}
|
}
|
||||||
if !udpFragment {
|
if !udpFragment {
|
||||||
lc.Control = control.Append(lc.Control, control.DisableUDPFragment())
|
listenConfig.Control = control.Append(listenConfig.Control, control.DisableUDPFragment())
|
||||||
|
}
|
||||||
|
if l.tproxy {
|
||||||
|
listenConfig.Control = control.Append(listenConfig.Control, func(network, address string, conn syscall.RawConn) error {
|
||||||
|
return control.Raw(conn, func(fd uintptr) error {
|
||||||
|
return redir.TProxy(fd, M.ParseSocksaddr(address).IsIPv6(), true)
|
||||||
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
udpConn, err := ListenNetworkNamespace[net.PacketConn](l.listenOptions.NetNs, func() (net.PacketConn, error) {
|
udpConn, err := ListenNetworkNamespace[net.PacketConn](l.listenOptions.NetNs, func() (net.PacketConn, error) {
|
||||||
return lc.ListenPacket(l.ctx, M.NetworkFromNetAddr(N.NetworkUDP, bindAddr.Addr), bindAddr.String())
|
return listenConfig.ListenPacket(l.ctx, M.NetworkFromNetAddr(N.NetworkUDP, bindAddr.Addr), bindAddr.String())
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -37,8 +57,32 @@ func (l *Listener) ListenUDP() (net.PacketConn, error) {
|
|||||||
return udpConn, err
|
return udpConn, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (l *Listener) DialContext(dialer net.Dialer, ctx context.Context, network string, address string) (net.Conn, error) {
|
||||||
|
return ListenNetworkNamespace[net.Conn](l.listenOptions.NetNs, func() (net.Conn, error) {
|
||||||
|
if l.listenOptions.BindInterface != "" {
|
||||||
|
dialer.Control = control.Append(dialer.Control, control.BindToInterface(service.FromContext[adapter.NetworkManager](l.ctx).InterfaceFinder(), l.listenOptions.BindInterface, -1))
|
||||||
|
}
|
||||||
|
if l.listenOptions.RoutingMark != 0 {
|
||||||
|
dialer.Control = control.Append(dialer.Control, control.RoutingMark(uint32(l.listenOptions.RoutingMark)))
|
||||||
|
}
|
||||||
|
if l.listenOptions.ReuseAddr {
|
||||||
|
dialer.Control = control.Append(dialer.Control, control.ReuseAddr())
|
||||||
|
}
|
||||||
|
return dialer.DialContext(ctx, network, address)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func (l *Listener) ListenPacket(listenConfig net.ListenConfig, ctx context.Context, network string, address string) (net.PacketConn, error) {
|
func (l *Listener) ListenPacket(listenConfig net.ListenConfig, ctx context.Context, network string, address string) (net.PacketConn, error) {
|
||||||
return ListenNetworkNamespace[net.PacketConn](l.listenOptions.NetNs, func() (net.PacketConn, error) {
|
return ListenNetworkNamespace[net.PacketConn](l.listenOptions.NetNs, func() (net.PacketConn, error) {
|
||||||
|
if l.listenOptions.BindInterface != "" {
|
||||||
|
listenConfig.Control = control.Append(listenConfig.Control, control.BindToInterface(service.FromContext[adapter.NetworkManager](l.ctx).InterfaceFinder(), l.listenOptions.BindInterface, -1))
|
||||||
|
}
|
||||||
|
if l.listenOptions.RoutingMark != 0 {
|
||||||
|
listenConfig.Control = control.Append(listenConfig.Control, control.RoutingMark(uint32(l.listenOptions.RoutingMark)))
|
||||||
|
}
|
||||||
|
if l.listenOptions.ReuseAddr {
|
||||||
|
listenConfig.Control = control.Append(listenConfig.Control, control.ReuseAddr())
|
||||||
|
}
|
||||||
return listenConfig.ListenPacket(ctx, network, address)
|
return listenConfig.ListenPacket(ctx, network, address)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ import (
|
|||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TProxy(fd uintptr, isIPv6 bool) error {
|
func TProxy(fd uintptr, isIPv6 bool, isUDP bool) error {
|
||||||
err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
|
err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
err = syscall.SetsockoptInt(int(fd), syscall.SOL_IP, syscall.IP_TRANSPARENT, 1)
|
err = syscall.SetsockoptInt(int(fd), syscall.SOL_IP, syscall.IP_TRANSPARENT, 1)
|
||||||
@ -20,11 +20,13 @@ func TProxy(fd uintptr, isIPv6 bool) error {
|
|||||||
if err == nil && isIPv6 {
|
if err == nil && isIPv6 {
|
||||||
err = syscall.SetsockoptInt(int(fd), syscall.SOL_IPV6, unix.IPV6_TRANSPARENT, 1)
|
err = syscall.SetsockoptInt(int(fd), syscall.SOL_IPV6, unix.IPV6_TRANSPARENT, 1)
|
||||||
}
|
}
|
||||||
if err == nil {
|
if isUDP {
|
||||||
err = syscall.SetsockoptInt(int(fd), syscall.SOL_IP, syscall.IP_RECVORIGDSTADDR, 1)
|
if err == nil {
|
||||||
}
|
err = syscall.SetsockoptInt(int(fd), syscall.SOL_IP, syscall.IP_RECVORIGDSTADDR, 1)
|
||||||
if err == nil && isIPv6 {
|
}
|
||||||
err = syscall.SetsockoptInt(int(fd), syscall.SOL_IPV6, unix.IPV6_RECVORIGDSTADDR, 1)
|
if err == nil && isIPv6 {
|
||||||
|
err = syscall.SetsockoptInt(int(fd), syscall.SOL_IPV6, unix.IPV6_RECVORIGDSTADDR, 1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ import (
|
|||||||
"github.com/sagernet/sing/common/control"
|
"github.com/sagernet/sing/common/control"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TProxy(fd uintptr, isIPv6 bool) error {
|
func TProxy(fd uintptr, isIPv6 bool, isUDP bool) error {
|
||||||
return os.ErrInvalid
|
return os.ErrInvalid
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ func (w *acmeWrapper) Close() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func startACME(ctx context.Context, options option.InboundACMEOptions) (*tls.Config, adapter.Service, error) {
|
func startACME(ctx context.Context, options option.InboundACMEOptions) (*tls.Config, adapter.SimpleLifecycle, error) {
|
||||||
var acmeServer string
|
var acmeServer string
|
||||||
switch options.Provider {
|
switch options.Provider {
|
||||||
case "", "letsencrypt":
|
case "", "letsencrypt":
|
||||||
|
@ -11,6 +11,6 @@ import (
|
|||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
)
|
)
|
||||||
|
|
||||||
func startACME(ctx context.Context, options option.InboundACMEOptions) (*tls.Config, adapter.Service, error) {
|
func startACME(ctx context.Context, options option.InboundACMEOptions) (*tls.Config, adapter.SimpleLifecycle, error) {
|
||||||
return nil, nil, E.New(`ACME is not included in this build, rebuild with -tags with_acme`)
|
return nil, nil, E.New(`ACME is not included in this build, rebuild with -tags with_acme`)
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ type (
|
|||||||
STDConfig = tls.Config
|
STDConfig = tls.Config
|
||||||
STDConn = tls.Conn
|
STDConn = tls.Conn
|
||||||
ConnectionState = tls.ConnectionState
|
ConnectionState = tls.ConnectionState
|
||||||
|
CurveID = tls.CurveID
|
||||||
)
|
)
|
||||||
|
|
||||||
func ParseTLSVersion(version string) (uint16, error) {
|
func ParseTLSVersion(version string) (uint16, error) {
|
||||||
|
5
common/tls/ech_tag_stub.go
Normal file
5
common/tls/ech_tag_stub.go
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
//go:build with_ech
|
||||||
|
|
||||||
|
package tls
|
||||||
|
|
||||||
|
var _ int = "Due to the migration to stdlib, the separate `with_ech` build tag has been deprecated and is no longer needed, please update your build configuration."
|
@ -29,12 +29,13 @@ import (
|
|||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
|
"github.com/sagernet/sing/common"
|
||||||
"github.com/sagernet/sing/common/debug"
|
"github.com/sagernet/sing/common/debug"
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
"github.com/sagernet/sing/common/ntp"
|
"github.com/sagernet/sing/common/ntp"
|
||||||
aTLS "github.com/sagernet/sing/common/tls"
|
aTLS "github.com/sagernet/sing/common/tls"
|
||||||
utls "github.com/sagernet/utls"
|
|
||||||
|
|
||||||
|
utls "github.com/metacubex/utls"
|
||||||
"golang.org/x/crypto/hkdf"
|
"golang.org/x/crypto/hkdf"
|
||||||
"golang.org/x/net/http2"
|
"golang.org/x/net/http2"
|
||||||
)
|
)
|
||||||
@ -114,6 +115,22 @@ func (e *RealityClientConfig) ClientHandshake(ctx context.Context, conn net.Conn
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
for _, extension := range uConn.Extensions {
|
||||||
|
if ce, ok := extension.(*utls.SupportedCurvesExtension); ok {
|
||||||
|
ce.Curves = common.Filter(ce.Curves, func(curveID utls.CurveID) bool {
|
||||||
|
return curveID != utls.X25519MLKEM768
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if ks, ok := extension.(*utls.KeyShareExtension); ok {
|
||||||
|
ks.KeyShares = common.Filter(ks.KeyShares, func(share utls.KeyShare) bool {
|
||||||
|
return share.Group != utls.X25519MLKEM768
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
err = uConn.BuildHandshakeState()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
if len(uConfig.NextProtos) > 0 {
|
if len(uConfig.NextProtos) > 0 {
|
||||||
for _, extension := range uConn.Extensions {
|
for _, extension := range uConn.Extensions {
|
||||||
@ -148,9 +165,13 @@ func (e *RealityClientConfig) ClientHandshake(ctx context.Context, conn net.Conn
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
ecdheKey := uConn.HandshakeState.State13.EcdheKey
|
keyShareKeys := uConn.HandshakeState.State13.KeyShareKeys
|
||||||
|
if keyShareKeys == nil {
|
||||||
|
return nil, E.New("nil KeyShareKeys")
|
||||||
|
}
|
||||||
|
ecdheKey := keyShareKeys.Ecdhe
|
||||||
if ecdheKey == nil {
|
if ecdheKey == nil {
|
||||||
return nil, E.New("nil ecdhe_key")
|
return nil, E.New("nil ecdheKey")
|
||||||
}
|
}
|
||||||
authKey, err := ecdheKey.ECDH(publicKey)
|
authKey, err := ecdheKey.ECDH(publicKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -214,10 +235,6 @@ func realityClientFallback(ctx context.Context, uConn net.Conn, serverName strin
|
|||||||
response.Body.Close()
|
response.Body.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *RealityClientConfig) SetSessionIDGenerator(generator func(clientHello []byte, sessionID []byte) error) {
|
|
||||||
e.uClient.config.SessionIDGenerator = generator
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *RealityClientConfig) Clone() Config {
|
func (e *RealityClientConfig) Clone() Config {
|
||||||
return &RealityClientConfig{
|
return &RealityClientConfig{
|
||||||
e.ctx,
|
e.ctx,
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
//go:build with_reality_server
|
//go:build with_utls
|
||||||
|
|
||||||
package tls
|
package tls
|
||||||
|
|
||||||
@ -7,28 +7,29 @@ import (
|
|||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/sagernet/reality"
|
|
||||||
"github.com/sagernet/sing-box/common/dialer"
|
"github.com/sagernet/sing-box/common/dialer"
|
||||||
"github.com/sagernet/sing-box/log"
|
"github.com/sagernet/sing-box/log"
|
||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
"github.com/sagernet/sing/common/debug"
|
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
M "github.com/sagernet/sing/common/metadata"
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
N "github.com/sagernet/sing/common/network"
|
N "github.com/sagernet/sing/common/network"
|
||||||
"github.com/sagernet/sing/common/ntp"
|
"github.com/sagernet/sing/common/ntp"
|
||||||
|
|
||||||
|
utls "github.com/metacubex/utls"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ ServerConfigCompat = (*RealityServerConfig)(nil)
|
var _ ServerConfigCompat = (*RealityServerConfig)(nil)
|
||||||
|
|
||||||
type RealityServerConfig struct {
|
type RealityServerConfig struct {
|
||||||
config *reality.Config
|
config *utls.RealityConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRealityServer(ctx context.Context, logger log.Logger, options option.InboundTLSOptions) (*RealityServerConfig, error) {
|
func NewRealityServer(ctx context.Context, logger log.Logger, options option.InboundTLSOptions) (*RealityServerConfig, error) {
|
||||||
var tlsConfig reality.Config
|
var tlsConfig utls.RealityConfig
|
||||||
|
|
||||||
if options.ACME != nil && len(options.ACME.Domain) > 0 {
|
if options.ACME != nil && len(options.ACME.Domain) > 0 {
|
||||||
return nil, E.New("acme is unavailable in reality")
|
return nil, E.New("acme is unavailable in reality")
|
||||||
@ -74,6 +75,11 @@ func NewRealityServer(ctx context.Context, logger log.Logger, options option.Inb
|
|||||||
}
|
}
|
||||||
|
|
||||||
tlsConfig.SessionTicketsDisabled = true
|
tlsConfig.SessionTicketsDisabled = true
|
||||||
|
tlsConfig.Log = func(format string, v ...any) {
|
||||||
|
if logger != nil {
|
||||||
|
logger.Trace(fmt.Sprintf(format, v...))
|
||||||
|
}
|
||||||
|
}
|
||||||
tlsConfig.Type = N.NetworkTCP
|
tlsConfig.Type = N.NetworkTCP
|
||||||
tlsConfig.Dest = options.Reality.Handshake.ServerOptions.Build().String()
|
tlsConfig.Dest = options.Reality.Handshake.ServerOptions.Build().String()
|
||||||
|
|
||||||
@ -113,10 +119,6 @@ func NewRealityServer(ctx context.Context, logger log.Logger, options option.Inb
|
|||||||
return handshakeDialer.DialContext(ctx, network, M.ParseSocksaddr(addr))
|
return handshakeDialer.DialContext(ctx, network, M.ParseSocksaddr(addr))
|
||||||
}
|
}
|
||||||
|
|
||||||
if debug.Enabled {
|
|
||||||
tlsConfig.Show = true
|
|
||||||
}
|
|
||||||
|
|
||||||
return &RealityServerConfig{&tlsConfig}, nil
|
return &RealityServerConfig{&tlsConfig}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,7 +159,7 @@ func (c *RealityServerConfig) Server(conn net.Conn) (Conn, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *RealityServerConfig) ServerHandshake(ctx context.Context, conn net.Conn) (Conn, error) {
|
func (c *RealityServerConfig) ServerHandshake(ctx context.Context, conn net.Conn) (Conn, error) {
|
||||||
tlsConn, err := reality.Server(ctx, conn, c.config)
|
tlsConn, err := utls.RealityServer(ctx, conn, c.config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -173,7 +175,7 @@ func (c *RealityServerConfig) Clone() Config {
|
|||||||
var _ Conn = (*realityConnWrapper)(nil)
|
var _ Conn = (*realityConnWrapper)(nil)
|
||||||
|
|
||||||
type realityConnWrapper struct {
|
type realityConnWrapper struct {
|
||||||
*reality.Conn
|
*utls.Conn
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *realityConnWrapper) ConnectionState() ConnectionState {
|
func (c *realityConnWrapper) ConnectionState() ConnectionState {
|
||||||
|
@ -1,15 +1,5 @@
|
|||||||
//go:build !with_reality_server
|
//go:build with_reality_server
|
||||||
|
|
||||||
package tls
|
package tls
|
||||||
|
|
||||||
import (
|
var _ int = "The separate `with_reality_server` build tag has been merged into `with_utls` and is no longer needed, please update your build configuration."
|
||||||
"context"
|
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/log"
|
|
||||||
"github.com/sagernet/sing-box/option"
|
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
|
||||||
)
|
|
||||||
|
|
||||||
func NewRealityServer(ctx context.Context, logger log.Logger, options option.InboundTLSOptions) (ServerConfig, error) {
|
|
||||||
return nil, E.New(`reality server is not included in this build, rebuild with -tags with_reality_server`)
|
|
||||||
}
|
|
||||||
|
@ -22,7 +22,7 @@ var errInsecureUnused = E.New("tls: insecure unused")
|
|||||||
type STDServerConfig struct {
|
type STDServerConfig struct {
|
||||||
config *tls.Config
|
config *tls.Config
|
||||||
logger log.Logger
|
logger log.Logger
|
||||||
acmeService adapter.Service
|
acmeService adapter.SimpleLifecycle
|
||||||
certificate []byte
|
certificate []byte
|
||||||
key []byte
|
key []byte
|
||||||
certificatePath string
|
certificatePath string
|
||||||
@ -165,7 +165,7 @@ func NewSTDServer(ctx context.Context, logger log.Logger, options option.Inbound
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
var tlsConfig *tls.Config
|
var tlsConfig *tls.Config
|
||||||
var acmeService adapter.Service
|
var acmeService adapter.SimpleLifecycle
|
||||||
var err error
|
var err error
|
||||||
if options.ACME != nil && len(options.ACME.Domain) > 0 {
|
if options.ACME != nil && len(options.ACME.Domain) > 0 {
|
||||||
//nolint:staticcheck
|
//nolint:staticcheck
|
||||||
|
@ -16,8 +16,8 @@ import (
|
|||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
"github.com/sagernet/sing/common/ntp"
|
"github.com/sagernet/sing/common/ntp"
|
||||||
utls "github.com/sagernet/utls"
|
|
||||||
|
|
||||||
|
utls "github.com/metacubex/utls"
|
||||||
"golang.org/x/net/http2"
|
"golang.org/x/net/http2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ package tls
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing-box/log"
|
||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
)
|
)
|
||||||
@ -14,5 +15,9 @@ func NewUTLSClient(ctx context.Context, serverAddress string, options option.Out
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewRealityClient(ctx context.Context, serverAddress string, options option.OutboundTLSOptions) (Config, error) {
|
func NewRealityClient(ctx context.Context, serverAddress string, options option.OutboundTLSOptions) (Config, error) {
|
||||||
return nil, E.New(`uTLS, which is required by reality client is not included in this build, rebuild with -tags with_utls`)
|
return nil, E.New(`uTLS, which is required by reality is not included in this build, rebuild with -tags with_utls`)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewRealityServer(ctx context.Context, logger log.Logger, options option.InboundTLSOptions) (ServerConfig, error) {
|
||||||
|
return nil, E.New(`uTLS, which is required by reality is not included in this build, rebuild with -tags with_utls`)
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
package tf
|
package tf
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/binary"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net"
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
@ -17,17 +19,19 @@ type Conn struct {
|
|||||||
tcpConn *net.TCPConn
|
tcpConn *net.TCPConn
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
firstPacketWritten bool
|
firstPacketWritten bool
|
||||||
|
splitRecord bool
|
||||||
fallbackDelay time.Duration
|
fallbackDelay time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConn(conn net.Conn, ctx context.Context, fallbackDelay time.Duration) (*Conn, error) {
|
func NewConn(conn net.Conn, ctx context.Context, splitRecord bool, fallbackDelay time.Duration) *Conn {
|
||||||
tcpConn, _ := N.UnwrapReader(conn).(*net.TCPConn)
|
tcpConn, _ := N.UnwrapReader(conn).(*net.TCPConn)
|
||||||
return &Conn{
|
return &Conn{
|
||||||
Conn: conn,
|
Conn: conn,
|
||||||
tcpConn: tcpConn,
|
tcpConn: tcpConn,
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
|
splitRecord: splitRecord,
|
||||||
fallbackDelay: fallbackDelay,
|
fallbackDelay: fallbackDelay,
|
||||||
}, nil
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Conn) Write(b []byte) (n int, err error) {
|
func (c *Conn) Write(b []byte) (n int, err error) {
|
||||||
@ -37,10 +41,12 @@ func (c *Conn) Write(b []byte) (n int, err error) {
|
|||||||
}()
|
}()
|
||||||
serverName := indexTLSServerName(b)
|
serverName := indexTLSServerName(b)
|
||||||
if serverName != nil {
|
if serverName != nil {
|
||||||
if c.tcpConn != nil {
|
if !c.splitRecord {
|
||||||
err = c.tcpConn.SetNoDelay(true)
|
if c.tcpConn != nil {
|
||||||
if err != nil {
|
err = c.tcpConn.SetNoDelay(true)
|
||||||
return
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
splits := strings.Split(serverName.ServerName, ".")
|
splits := strings.Split(serverName.ServerName, ".")
|
||||||
@ -61,16 +67,25 @@ func (c *Conn) Write(b []byte) (n int, err error) {
|
|||||||
currentIndex++
|
currentIndex++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
var buffer bytes.Buffer
|
||||||
for i := 0; i <= len(splitIndexes); i++ {
|
for i := 0; i <= len(splitIndexes); i++ {
|
||||||
var payload []byte
|
var payload []byte
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
payload = b[:splitIndexes[i]]
|
payload = b[:splitIndexes[i]]
|
||||||
|
if c.splitRecord {
|
||||||
|
payload = payload[recordLayerHeaderLen:]
|
||||||
|
}
|
||||||
} else if i == len(splitIndexes) {
|
} else if i == len(splitIndexes) {
|
||||||
payload = b[splitIndexes[i-1]:]
|
payload = b[splitIndexes[i-1]:]
|
||||||
} else {
|
} else {
|
||||||
payload = b[splitIndexes[i-1]:splitIndexes[i]]
|
payload = b[splitIndexes[i-1]:splitIndexes[i]]
|
||||||
}
|
}
|
||||||
if c.tcpConn != nil && i != len(splitIndexes) {
|
if c.splitRecord {
|
||||||
|
payloadLen := uint16(len(payload))
|
||||||
|
buffer.Write(b[:3])
|
||||||
|
binary.Write(&buffer, binary.BigEndian, payloadLen)
|
||||||
|
buffer.Write(payload)
|
||||||
|
} else if c.tcpConn != nil && i != len(splitIndexes) {
|
||||||
err = writeAndWaitAck(c.ctx, c.tcpConn, payload, c.fallbackDelay)
|
err = writeAndWaitAck(c.ctx, c.tcpConn, payload, c.fallbackDelay)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@ -82,11 +97,18 @@ func (c *Conn) Write(b []byte) (n int, err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if c.tcpConn != nil {
|
if c.splitRecord {
|
||||||
err = c.tcpConn.SetNoDelay(false)
|
_, err = c.Conn.Write(buffer.Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if c.tcpConn != nil {
|
||||||
|
err = c.tcpConn.SetNoDelay(false)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return len(b), nil
|
return len(b), nil
|
||||||
}
|
}
|
||||||
|
32
common/tlsfragment/conn_test.go
Normal file
32
common/tlsfragment/conn_test.go
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
package tf_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"crypto/tls"
|
||||||
|
"net"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
tf "github.com/sagernet/sing-box/common/tlsfragment"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestTLSFragment(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
tcpConn, err := net.Dial("tcp", "1.1.1.1:443")
|
||||||
|
require.NoError(t, err)
|
||||||
|
tlsConn := tls.Client(tf.NewConn(tcpConn, context.Background(), false, 0), &tls.Config{
|
||||||
|
ServerName: "www.cloudflare.com",
|
||||||
|
})
|
||||||
|
require.NoError(t, tlsConn.Handshake())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTLSRecordFragment(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
tcpConn, err := net.Dial("tcp", "1.1.1.1:443")
|
||||||
|
require.NoError(t, err)
|
||||||
|
tlsConn := tls.Client(tf.NewConn(tcpConn, context.Background(), true, 0), &tls.Config{
|
||||||
|
ServerName: "www.cloudflare.com",
|
||||||
|
})
|
||||||
|
require.NoError(t, tlsConn.Handshake())
|
||||||
|
}
|
@ -25,6 +25,9 @@ const (
|
|||||||
TypeTUIC = "tuic"
|
TypeTUIC = "tuic"
|
||||||
TypeHysteria2 = "hysteria2"
|
TypeHysteria2 = "hysteria2"
|
||||||
TypeTailscale = "tailscale"
|
TypeTailscale = "tailscale"
|
||||||
|
TypeDERP = "derp"
|
||||||
|
TypeResolved = "resolved"
|
||||||
|
TypeSSMAPI = "ssm-api"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -34,6 +34,7 @@ type Client struct {
|
|||||||
disableCache bool
|
disableCache bool
|
||||||
disableExpire bool
|
disableExpire bool
|
||||||
independentCache bool
|
independentCache bool
|
||||||
|
clientSubnet netip.Prefix
|
||||||
rdrc adapter.RDRCStore
|
rdrc adapter.RDRCStore
|
||||||
initRDRCFunc func() adapter.RDRCStore
|
initRDRCFunc func() adapter.RDRCStore
|
||||||
logger logger.ContextLogger
|
logger logger.ContextLogger
|
||||||
@ -47,6 +48,7 @@ type ClientOptions struct {
|
|||||||
DisableExpire bool
|
DisableExpire bool
|
||||||
IndependentCache bool
|
IndependentCache bool
|
||||||
CacheCapacity uint32
|
CacheCapacity uint32
|
||||||
|
ClientSubnet netip.Prefix
|
||||||
RDRC func() adapter.RDRCStore
|
RDRC func() adapter.RDRCStore
|
||||||
Logger logger.ContextLogger
|
Logger logger.ContextLogger
|
||||||
}
|
}
|
||||||
@ -57,6 +59,7 @@ func NewClient(options ClientOptions) *Client {
|
|||||||
disableCache: options.DisableCache,
|
disableCache: options.DisableCache,
|
||||||
disableExpire: options.DisableExpire,
|
disableExpire: options.DisableExpire,
|
||||||
independentCache: options.IndependentCache,
|
independentCache: options.IndependentCache,
|
||||||
|
clientSubnet: options.ClientSubnet,
|
||||||
initRDRCFunc: options.RDRC,
|
initRDRCFunc: options.RDRC,
|
||||||
logger: options.Logger,
|
logger: options.Logger,
|
||||||
}
|
}
|
||||||
@ -104,8 +107,12 @@ func (c *Client) Exchange(ctx context.Context, transport adapter.DNSTransport, m
|
|||||||
return &responseMessage, nil
|
return &responseMessage, nil
|
||||||
}
|
}
|
||||||
question := message.Question[0]
|
question := message.Question[0]
|
||||||
if options.ClientSubnet.IsValid() {
|
clientSubnet := options.ClientSubnet
|
||||||
message = SetClientSubnet(message, options.ClientSubnet, true)
|
if !clientSubnet.IsValid() {
|
||||||
|
clientSubnet = c.clientSubnet
|
||||||
|
}
|
||||||
|
if clientSubnet.IsValid() {
|
||||||
|
message = SetClientSubnet(message, clientSubnet)
|
||||||
}
|
}
|
||||||
isSimpleRequest := len(message.Question) == 1 &&
|
isSimpleRequest := len(message.Question) == 1 &&
|
||||||
len(message.Ns) == 0 &&
|
len(message.Ns) == 0 &&
|
||||||
@ -232,10 +239,20 @@ func (c *Client) Exchange(ctx context.Context, transport adapter.DNSTransport, m
|
|||||||
record.Header().Ttl = timeToLive
|
record.Header().Ttl = timeToLive
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
response.Id = messageId
|
|
||||||
if !disableCache {
|
if !disableCache {
|
||||||
c.storeCache(transport, question, response, timeToLive)
|
c.storeCache(transport, question, response, timeToLive)
|
||||||
}
|
}
|
||||||
|
response.Id = messageId
|
||||||
|
requestEDNSOpt := message.IsEdns0()
|
||||||
|
responseEDNSOpt := response.IsEdns0()
|
||||||
|
if responseEDNSOpt != nil && (requestEDNSOpt == nil || requestEDNSOpt.Version() < responseEDNSOpt.Version()) {
|
||||||
|
response.Extra = common.Filter(response.Extra, func(it dns.RR) bool {
|
||||||
|
return it.Header().Rrtype != dns.TypeOPT
|
||||||
|
})
|
||||||
|
if requestEDNSOpt != nil {
|
||||||
|
response.SetEdns0(responseEDNSOpt.UDPSize(), responseEDNSOpt.Do())
|
||||||
|
}
|
||||||
|
}
|
||||||
logExchangedResponse(c.logger, ctx, response, timeToLive)
|
logExchangedResponse(c.logger, ctx, response, timeToLive)
|
||||||
return response, err
|
return response, err
|
||||||
}
|
}
|
||||||
@ -243,9 +260,15 @@ func (c *Client) Exchange(ctx context.Context, transport adapter.DNSTransport, m
|
|||||||
func (c *Client) Lookup(ctx context.Context, transport adapter.DNSTransport, domain string, options adapter.DNSQueryOptions, responseChecker func(responseAddrs []netip.Addr) bool) ([]netip.Addr, error) {
|
func (c *Client) Lookup(ctx context.Context, transport adapter.DNSTransport, domain string, options adapter.DNSQueryOptions, responseChecker func(responseAddrs []netip.Addr) bool) ([]netip.Addr, error) {
|
||||||
domain = FqdnToDomain(domain)
|
domain = FqdnToDomain(domain)
|
||||||
dnsName := dns.Fqdn(domain)
|
dnsName := dns.Fqdn(domain)
|
||||||
if options.Strategy == C.DomainStrategyIPv4Only {
|
var strategy C.DomainStrategy
|
||||||
|
if options.LookupStrategy != C.DomainStrategyAsIS {
|
||||||
|
strategy = options.LookupStrategy
|
||||||
|
} else {
|
||||||
|
strategy = options.Strategy
|
||||||
|
}
|
||||||
|
if strategy == C.DomainStrategyIPv4Only {
|
||||||
return c.lookupToExchange(ctx, transport, dnsName, dns.TypeA, options, responseChecker)
|
return c.lookupToExchange(ctx, transport, dnsName, dns.TypeA, options, responseChecker)
|
||||||
} else if options.Strategy == C.DomainStrategyIPv6Only {
|
} else if strategy == C.DomainStrategyIPv6Only {
|
||||||
return c.lookupToExchange(ctx, transport, dnsName, dns.TypeAAAA, options, responseChecker)
|
return c.lookupToExchange(ctx, transport, dnsName, dns.TypeAAAA, options, responseChecker)
|
||||||
}
|
}
|
||||||
var response4 []netip.Addr
|
var response4 []netip.Addr
|
||||||
@ -271,7 +294,7 @@ func (c *Client) Lookup(ctx context.Context, transport adapter.DNSTransport, dom
|
|||||||
if len(response4) == 0 && len(response6) == 0 {
|
if len(response4) == 0 && len(response6) == 0 {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return sortAddresses(response4, response6, options.Strategy), nil
|
return sortAddresses(response4, response6, strategy), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) ClearCache() {
|
func (c *Client) ClearCache() {
|
||||||
@ -527,12 +550,26 @@ func transportTagFromContext(ctx context.Context) (string, bool) {
|
|||||||
return value, loaded
|
return value, loaded
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func FixedResponseStatus(message *dns.Msg, rcode int) *dns.Msg {
|
||||||
|
return &dns.Msg{
|
||||||
|
MsgHdr: dns.MsgHdr{
|
||||||
|
Id: message.Id,
|
||||||
|
Rcode: rcode,
|
||||||
|
Response: true,
|
||||||
|
},
|
||||||
|
Question: message.Question,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func FixedResponse(id uint16, question dns.Question, addresses []netip.Addr, timeToLive uint32) *dns.Msg {
|
func FixedResponse(id uint16, question dns.Question, addresses []netip.Addr, timeToLive uint32) *dns.Msg {
|
||||||
response := dns.Msg{
|
response := dns.Msg{
|
||||||
MsgHdr: dns.MsgHdr{
|
MsgHdr: dns.MsgHdr{
|
||||||
Id: id,
|
Id: id,
|
||||||
Rcode: dns.RcodeSuccess,
|
Response: true,
|
||||||
Response: true,
|
Authoritative: true,
|
||||||
|
RecursionDesired: true,
|
||||||
|
RecursionAvailable: true,
|
||||||
|
Rcode: dns.RcodeSuccess,
|
||||||
},
|
},
|
||||||
Question: []dns.Question{question},
|
Question: []dns.Question{question},
|
||||||
}
|
}
|
||||||
@ -565,9 +602,12 @@ func FixedResponse(id uint16, question dns.Question, addresses []netip.Addr, tim
|
|||||||
func FixedResponseCNAME(id uint16, question dns.Question, record string, timeToLive uint32) *dns.Msg {
|
func FixedResponseCNAME(id uint16, question dns.Question, record string, timeToLive uint32) *dns.Msg {
|
||||||
response := dns.Msg{
|
response := dns.Msg{
|
||||||
MsgHdr: dns.MsgHdr{
|
MsgHdr: dns.MsgHdr{
|
||||||
Id: id,
|
Id: id,
|
||||||
Rcode: dns.RcodeSuccess,
|
Response: true,
|
||||||
Response: true,
|
Authoritative: true,
|
||||||
|
RecursionDesired: true,
|
||||||
|
RecursionAvailable: true,
|
||||||
|
Rcode: dns.RcodeSuccess,
|
||||||
},
|
},
|
||||||
Question: []dns.Question{question},
|
Question: []dns.Question{question},
|
||||||
Answer: []dns.RR{
|
Answer: []dns.RR{
|
||||||
@ -588,9 +628,12 @@ func FixedResponseCNAME(id uint16, question dns.Question, record string, timeToL
|
|||||||
func FixedResponseTXT(id uint16, question dns.Question, records []string, timeToLive uint32) *dns.Msg {
|
func FixedResponseTXT(id uint16, question dns.Question, records []string, timeToLive uint32) *dns.Msg {
|
||||||
response := dns.Msg{
|
response := dns.Msg{
|
||||||
MsgHdr: dns.MsgHdr{
|
MsgHdr: dns.MsgHdr{
|
||||||
Id: id,
|
Id: id,
|
||||||
Rcode: dns.RcodeSuccess,
|
Response: true,
|
||||||
Response: true,
|
Authoritative: true,
|
||||||
|
RecursionDesired: true,
|
||||||
|
RecursionAvailable: true,
|
||||||
|
Rcode: dns.RcodeSuccess,
|
||||||
},
|
},
|
||||||
Question: []dns.Question{question},
|
Question: []dns.Question{question},
|
||||||
Answer: []dns.RR{
|
Answer: []dns.RR{
|
||||||
@ -611,9 +654,12 @@ func FixedResponseTXT(id uint16, question dns.Question, records []string, timeTo
|
|||||||
func FixedResponseMX(id uint16, question dns.Question, records []*net.MX, timeToLive uint32) *dns.Msg {
|
func FixedResponseMX(id uint16, question dns.Question, records []*net.MX, timeToLive uint32) *dns.Msg {
|
||||||
response := dns.Msg{
|
response := dns.Msg{
|
||||||
MsgHdr: dns.MsgHdr{
|
MsgHdr: dns.MsgHdr{
|
||||||
Id: id,
|
Id: id,
|
||||||
Rcode: dns.RcodeSuccess,
|
Response: true,
|
||||||
Response: true,
|
Authoritative: true,
|
||||||
|
RecursionDesired: true,
|
||||||
|
RecursionAvailable: true,
|
||||||
|
Rcode: dns.RcodeSuccess,
|
||||||
},
|
},
|
||||||
Question: []dns.Question{question},
|
Question: []dns.Question{question},
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,11 @@ import (
|
|||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
)
|
)
|
||||||
|
|
||||||
func SetClientSubnet(message *dns.Msg, clientSubnet netip.Prefix, override bool) *dns.Msg {
|
func SetClientSubnet(message *dns.Msg, clientSubnet netip.Prefix) *dns.Msg {
|
||||||
|
return setClientSubnet(message, clientSubnet, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func setClientSubnet(message *dns.Msg, clientSubnet netip.Prefix, clone bool) *dns.Msg {
|
||||||
var (
|
var (
|
||||||
optRecord *dns.OPT
|
optRecord *dns.OPT
|
||||||
subnetOption *dns.EDNS0_SUBNET
|
subnetOption *dns.EDNS0_SUBNET
|
||||||
@ -19,9 +23,6 @@ findExists:
|
|||||||
var isEDNS0Subnet bool
|
var isEDNS0Subnet bool
|
||||||
subnetOption, isEDNS0Subnet = option.(*dns.EDNS0_SUBNET)
|
subnetOption, isEDNS0Subnet = option.(*dns.EDNS0_SUBNET)
|
||||||
if isEDNS0Subnet {
|
if isEDNS0Subnet {
|
||||||
if !override {
|
|
||||||
return message
|
|
||||||
}
|
|
||||||
break findExists
|
break findExists
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -37,14 +38,14 @@ findExists:
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
message.Extra = append(message.Extra, optRecord)
|
message.Extra = append(message.Extra, optRecord)
|
||||||
} else {
|
} else if clone {
|
||||||
message = message.Copy()
|
return setClientSubnet(message.Copy(), clientSubnet, false)
|
||||||
}
|
}
|
||||||
if subnetOption == nil {
|
if subnetOption == nil {
|
||||||
subnetOption = new(dns.EDNS0_SUBNET)
|
subnetOption = new(dns.EDNS0_SUBNET)
|
||||||
|
subnetOption.Code = dns.EDNS0SUBNET
|
||||||
optRecord.Option = append(optRecord.Option, subnetOption)
|
optRecord.Option = append(optRecord.Option, subnetOption)
|
||||||
}
|
}
|
||||||
subnetOption.Code = dns.EDNS0SUBNET
|
|
||||||
if clientSubnet.Addr().Is4() {
|
if clientSubnet.Addr().Is4() {
|
||||||
subnetOption.Family = 1
|
subnetOption.Family = 1
|
||||||
} else {
|
} else {
|
||||||
|
@ -55,6 +55,7 @@ func NewRouter(ctx context.Context, logFactory log.Factory, options option.DNSOp
|
|||||||
DisableExpire: options.DNSClientOptions.DisableExpire,
|
DisableExpire: options.DNSClientOptions.DisableExpire,
|
||||||
IndependentCache: options.DNSClientOptions.IndependentCache,
|
IndependentCache: options.DNSClientOptions.IndependentCache,
|
||||||
CacheCapacity: options.DNSClientOptions.CacheCapacity,
|
CacheCapacity: options.DNSClientOptions.CacheCapacity,
|
||||||
|
ClientSubnet: options.DNSClientOptions.ClientSubnet.Build(netip.Prefix{}),
|
||||||
RDRC: func() adapter.RDRCStore {
|
RDRC: func() adapter.RDRCStore {
|
||||||
cacheFile := service.FromContext[adapter.CacheFile](ctx)
|
cacheFile := service.FromContext[adapter.CacheFile](ctx)
|
||||||
if cacheFile == nil {
|
if cacheFile == nil {
|
||||||
@ -258,7 +259,14 @@ func (r *Router) Exchange(ctx context.Context, message *mDNS.Msg, options adapte
|
|||||||
case *R.RuleActionReject:
|
case *R.RuleActionReject:
|
||||||
switch action.Method {
|
switch action.Method {
|
||||||
case C.RuleActionRejectMethodDefault:
|
case C.RuleActionRejectMethodDefault:
|
||||||
return FixedResponse(message.Id, message.Question[0], nil, 0), nil
|
return &mDNS.Msg{
|
||||||
|
MsgHdr: mDNS.MsgHdr{
|
||||||
|
Id: message.Id,
|
||||||
|
Rcode: mDNS.RcodeRefused,
|
||||||
|
Response: true,
|
||||||
|
},
|
||||||
|
Question: []mDNS.Question{message.Question[0]},
|
||||||
|
}, nil
|
||||||
case C.RuleActionRejectMethodDrop:
|
case C.RuleActionRejectMethodDrop:
|
||||||
return nil, tun.ErrDrop
|
return nil, tun.ErrDrop
|
||||||
}
|
}
|
||||||
@ -285,7 +293,12 @@ func (r *Router) Exchange(ctx context.Context, message *mDNS.Msg, options adapte
|
|||||||
} else if errors.Is(err, ErrResponseRejected) {
|
} else if errors.Is(err, ErrResponseRejected) {
|
||||||
rejected = true
|
rejected = true
|
||||||
r.logger.DebugContext(ctx, E.Cause(err, "response rejected for ", FormatQuestion(message.Question[0].String())))
|
r.logger.DebugContext(ctx, E.Cause(err, "response rejected for ", FormatQuestion(message.Question[0].String())))
|
||||||
|
/*} else if responseCheck!= nil && errors.Is(err, RcodeError(mDNS.RcodeNameError)) {
|
||||||
|
rejected = true
|
||||||
|
r.logger.DebugContext(ctx, E.Cause(err, "response rejected for ", FormatQuestion(message.Question[0].String())))
|
||||||
|
*/
|
||||||
} else if len(message.Question) > 0 {
|
} else if len(message.Question) > 0 {
|
||||||
|
rejected = true
|
||||||
r.logger.ErrorContext(ctx, E.Cause(err, "exchange failed for ", FormatQuestion(message.Question[0].String())))
|
r.logger.ErrorContext(ctx, E.Cause(err, "exchange failed for ", FormatQuestion(message.Question[0].String())))
|
||||||
} else {
|
} else {
|
||||||
r.logger.ErrorContext(ctx, E.Cause(err, "exchange failed for <empty query>"))
|
r.logger.ErrorContext(ctx, E.Cause(err, "exchange failed for <empty query>"))
|
||||||
|
@ -60,13 +60,17 @@ func NewTLS(ctx context.Context, logger log.ContextLogger, tag string, options o
|
|||||||
if !serverAddr.IsValid() {
|
if !serverAddr.IsValid() {
|
||||||
return nil, E.New("invalid server address: ", serverAddr)
|
return nil, E.New("invalid server address: ", serverAddr)
|
||||||
}
|
}
|
||||||
|
return NewTLSRaw(logger, dns.NewTransportAdapterWithRemoteOptions(C.DNSTypeTLS, tag, options.RemoteDNSServerOptions), transportDialer, serverAddr, tlsConfig), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewTLSRaw(logger logger.ContextLogger, adapter dns.TransportAdapter, dialer N.Dialer, serverAddr M.Socksaddr, tlsConfig tls.Config) *TLSTransport {
|
||||||
return &TLSTransport{
|
return &TLSTransport{
|
||||||
TransportAdapter: dns.NewTransportAdapterWithRemoteOptions(C.DNSTypeTLS, tag, options.RemoteDNSServerOptions),
|
TransportAdapter: adapter,
|
||||||
logger: logger,
|
logger: logger,
|
||||||
dialer: transportDialer,
|
dialer: dialer,
|
||||||
serverAddr: serverAddr,
|
serverAddr: serverAddr,
|
||||||
tlsConfig: tlsConfig,
|
tlsConfig: tlsConfig,
|
||||||
}, nil
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TLSTransport) Start(stage adapter.StartStage) error {
|
func (t *TLSTransport) Start(stage adapter.StartStage) error {
|
||||||
|
@ -2,15 +2,115 @@
|
|||||||
icon: material/alert-decagram
|
icon: material/alert-decagram
|
||||||
---
|
---
|
||||||
|
|
||||||
#### 1.12.0-beta.8
|
#### 1.12.0-beta.22
|
||||||
|
|
||||||
* Fixes and improvements
|
* Fixes and improvements
|
||||||
|
|
||||||
|
#### 1.12.0-beta.21
|
||||||
|
|
||||||
|
* Fix missing `home` option for DERP service **1**
|
||||||
|
* Fixes and improvements
|
||||||
|
|
||||||
|
**1**:
|
||||||
|
|
||||||
|
You can now choose what the DERP home page shows, just like with derper's `-home` flag.
|
||||||
|
|
||||||
|
See [DERP](/configuration/service/derp/#home).
|
||||||
|
|
||||||
|
### 1.11.13
|
||||||
|
|
||||||
|
* Fixes and improvements
|
||||||
|
|
||||||
|
_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.17
|
||||||
|
|
||||||
|
* Update quic-go to v0.52.0
|
||||||
|
* Fixes and improvements
|
||||||
|
|
||||||
|
#### 1.12.0-beta.15
|
||||||
|
|
||||||
|
* Add DERP service **1**
|
||||||
|
* Add Resolved service and DNS server **2**
|
||||||
|
* Add SSM API service **3**
|
||||||
|
* Fixes and improvements
|
||||||
|
|
||||||
|
**1**:
|
||||||
|
|
||||||
|
DERP service is a Tailscale DERP server, similar to [derper](https://pkg.go.dev/tailscale.com/cmd/derper).
|
||||||
|
|
||||||
|
See [DERP Service](/configuration/service/derp/).
|
||||||
|
|
||||||
|
**2**:
|
||||||
|
|
||||||
|
Resolved service is a fake systemd-resolved DBUS service to receive DNS settings from other programs
|
||||||
|
(e.g. NetworkManager) and provide DNS resolution.
|
||||||
|
|
||||||
|
See [Resolved Service](/configuration/service/resolved/) and [Resolved DNS Server](/configuration/dns/server/resolved/).
|
||||||
|
|
||||||
|
**3**:
|
||||||
|
|
||||||
|
SSM API service is a RESTful API server for managing Shadowsocks servers.
|
||||||
|
|
||||||
|
See [SSM API Service](/configuration/service/ssm-api/).
|
||||||
|
|
||||||
|
### 1.11.11
|
||||||
|
|
||||||
|
* Fixes and improvements
|
||||||
|
|
||||||
|
_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.13
|
||||||
|
|
||||||
|
* Add TLS record fragment route options **1**
|
||||||
|
* Add missing `accept_routes` option for Tailscale **2**
|
||||||
|
* Fixes and improvements
|
||||||
|
|
||||||
|
**1**:
|
||||||
|
|
||||||
|
See [Route Action](/configuration/route/rule_action/#tls_record_fragment).
|
||||||
|
|
||||||
|
**2**:
|
||||||
|
|
||||||
|
See [Tailscale](/configuration/endpoint/tailscale/#accept_routes).
|
||||||
|
|
||||||
|
#### 1.12.0-beta.10
|
||||||
|
|
||||||
|
* Add control options for listeners **1**
|
||||||
|
* Fixes and improvements
|
||||||
|
|
||||||
|
**1**:
|
||||||
|
|
||||||
|
You can now set `bind_interface`, `routing_mark` and `reuse_addr` in Listen Fields.
|
||||||
|
|
||||||
|
See [Listen Fields](/configuration/shared/listen/).
|
||||||
|
|
||||||
|
### 1.11.10
|
||||||
|
|
||||||
|
* Undeprecate the `block` outbound **1**
|
||||||
|
* Fixes and improvements
|
||||||
|
|
||||||
|
**1**:
|
||||||
|
|
||||||
|
Since we don’t have a replacement for using the `block` outbound in selectors yet,
|
||||||
|
we decided to temporarily undeprecate the `block` outbound until a replacement is available in the future.
|
||||||
|
|
||||||
|
_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.9
|
||||||
|
|
||||||
|
* Update quic-go to v0.51.0
|
||||||
|
* Fixes and improvements
|
||||||
|
|
||||||
### 1.11.9
|
### 1.11.9
|
||||||
|
|
||||||
* Fixes and improvements
|
* Fixes and improvements
|
||||||
|
|
||||||
_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)._
|
_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.5
|
#### 1.12.0-beta.5
|
||||||
|
|
||||||
@ -26,7 +126,8 @@ _We are temporarily unable to update sing-box apps on the App Store because the
|
|||||||
Now `auto_redirect` fixes compatibility issues between TUN and Docker bridge networks,
|
Now `auto_redirect` fixes compatibility issues between TUN and Docker bridge networks,
|
||||||
see [Tun](/configuration/inbound/tun/#auto_redirect).
|
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)._
|
_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
|
||||||
|
|
||||||
@ -36,7 +137,8 @@ _We are temporarily unable to update sing-box apps on the App Store because the
|
|||||||
|
|
||||||
* Fixes and improvements
|
* Fixes and improvements
|
||||||
|
|
||||||
_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)._
|
_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.1
|
#### 1.12.0-beta.1
|
||||||
|
|
||||||
@ -51,7 +153,8 @@ see [Tun](/configuration/inbound/tun/#auto_redirect).
|
|||||||
|
|
||||||
* Fixes and improvements
|
* Fixes and improvements
|
||||||
|
|
||||||
_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)._
|
_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-alpha.19
|
#### 1.12.0-alpha.19
|
||||||
|
|
||||||
@ -91,7 +194,8 @@ See [Dial Fields](/configuration/shared/dial/#domain_resolver).
|
|||||||
|
|
||||||
* Fixes and improvements
|
* Fixes and improvements
|
||||||
|
|
||||||
_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)._
|
_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-alpha.13
|
#### 1.12.0-alpha.13
|
||||||
|
|
||||||
@ -162,7 +266,8 @@ For Windows 7 users, legacy binaries now continue to compile with Go 1.23 and pa
|
|||||||
|
|
||||||
* Fixes and improvements
|
* Fixes and improvements
|
||||||
|
|
||||||
_This version overwrites 1.11.2, as incorrect binaries were released due to a bug in the continuous integration process._
|
_This version overwrites 1.11.2, as incorrect binaries were released due to a bug in the continuous integration
|
||||||
|
process._
|
||||||
|
|
||||||
#### 1.12.0-alpha.5
|
#### 1.12.0-alpha.5
|
||||||
|
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
---
|
---
|
||||||
icon: material/new-box
|
icon: material/alert-decagram
|
||||||
---
|
---
|
||||||
|
|
||||||
|
!!! quote "Changes in sing-box 1.12.0"
|
||||||
|
|
||||||
|
:material-decagram: [servers](#servers)
|
||||||
|
|
||||||
!!! quote "Changes in sing-box 1.11.0"
|
!!! quote "Changes in sing-box 1.11.0"
|
||||||
|
|
||||||
:material-plus: [cache_capacity](#cache_capacity)
|
:material-plus: [cache_capacity](#cache_capacity)
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
---
|
---
|
||||||
icon: material/new-box
|
icon: material/alert-decagram
|
||||||
---
|
---
|
||||||
|
|
||||||
|
!!! quote "sing-box 1.12.0 中的更改"
|
||||||
|
|
||||||
|
:material-decagram: [servers](#servers)
|
||||||
|
|
||||||
!!! quote "sing-box 1.11.0 中的更改"
|
!!! quote "sing-box 1.11.0 中的更改"
|
||||||
|
|
||||||
:material-plus: [cache_capacity](#cache_capacity)
|
:material-plus: [cache_capacity](#cache_capacity)
|
||||||
|
@ -81,7 +81,7 @@ Will overrides `dns.client_subnet`.
|
|||||||
|
|
||||||
#### method
|
#### method
|
||||||
|
|
||||||
- `default`: Reply with NXDOMAIN.
|
- `default`: Reply with REFUSED.
|
||||||
- `drop`: Drop the request.
|
- `drop`: Drop the request.
|
||||||
|
|
||||||
`default` will be used by default.
|
`default` will be used by default.
|
||||||
|
@ -81,7 +81,7 @@ icon: material/new-box
|
|||||||
|
|
||||||
#### method
|
#### method
|
||||||
|
|
||||||
- `default`: 返回 NXDOMAIN。
|
- `default`: 返回 REFUSED。
|
||||||
- `drop`: 丢弃请求。
|
- `drop`: 丢弃请求。
|
||||||
|
|
||||||
默认使用 `defualt`。
|
默认使用 `defualt`。
|
||||||
|
@ -41,6 +41,7 @@ The type of the DNS server.
|
|||||||
| `dhcp` | [DHCP](./dhcp/) |
|
| `dhcp` | [DHCP](./dhcp/) |
|
||||||
| `fakeip` | [Fake IP](./fakeip/) |
|
| `fakeip` | [Fake IP](./fakeip/) |
|
||||||
| `tailscale` | [Tailscale](./tailscale/) |
|
| `tailscale` | [Tailscale](./tailscale/) |
|
||||||
|
| `resolved` | [Resolved](./resolved/) |
|
||||||
|
|
||||||
#### tag
|
#### tag
|
||||||
|
|
||||||
|
@ -41,6 +41,7 @@ DNS 服务器的类型。
|
|||||||
| `dhcp` | [DHCP](./dhcp/) |
|
| `dhcp` | [DHCP](./dhcp/) |
|
||||||
| `fakeip` | [Fake IP](./fakeip/) |
|
| `fakeip` | [Fake IP](./fakeip/) |
|
||||||
| `tailscale` | [Tailscale](./tailscale/) |
|
| `tailscale` | [Tailscale](./tailscale/) |
|
||||||
|
| `resolved` | [Resolved](./resolved/) |
|
||||||
|
|
||||||
#### tag
|
#### tag
|
||||||
|
|
||||||
|
84
docs/configuration/dns/server/resolved.md
Normal file
84
docs/configuration/dns/server/resolved.md
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
---
|
||||||
|
icon: material/new-box
|
||||||
|
---
|
||||||
|
|
||||||
|
!!! question "Since sing-box 1.12.0"
|
||||||
|
|
||||||
|
# Resolved
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"dns": {
|
||||||
|
"servers": [
|
||||||
|
{
|
||||||
|
"type": "resolved",
|
||||||
|
"tag": "",
|
||||||
|
|
||||||
|
"service": "resolved",
|
||||||
|
"accept_default_resolvers": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### Fields
|
||||||
|
|
||||||
|
#### service
|
||||||
|
|
||||||
|
==Required==
|
||||||
|
|
||||||
|
The tag of the [Resolved Service](/configuration/service/resolved).
|
||||||
|
|
||||||
|
#### accept_default_resolvers
|
||||||
|
|
||||||
|
Indicates whether the default DNS resolvers should be accepted for fallback queries in addition to matching domains.
|
||||||
|
|
||||||
|
Specifically, default DNS resolvers are DNS servers that have `SetLinkDefaultRoute` or `SetLinkDomains ~.` set.
|
||||||
|
|
||||||
|
If not enabled, `NXDOMAIN` will be returned for requests that do not match search or match domains.
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
=== "Split DNS only"
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"dns": {
|
||||||
|
"servers": [
|
||||||
|
{
|
||||||
|
"type": "local",
|
||||||
|
"tag": "local"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "resolved",
|
||||||
|
"tag": "resolved",
|
||||||
|
"service": "resolved"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"rules": [
|
||||||
|
{
|
||||||
|
"ip_accept_any": true,
|
||||||
|
"server": "resolved"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
=== "Use as global DNS"
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"dns": {
|
||||||
|
"servers": [
|
||||||
|
{
|
||||||
|
"type": "resolved",
|
||||||
|
"service": "resolved",
|
||||||
|
"accept_default_resolvers": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
@ -30,13 +30,13 @@ icon: material/new-box
|
|||||||
|
|
||||||
==Required==
|
==Required==
|
||||||
|
|
||||||
The tag of the Tailscale endpoint.
|
The tag of the [Tailscale Endpoint](/configuration/endpoint/tailscale).
|
||||||
|
|
||||||
#### accept_default_resolvers
|
#### accept_default_resolvers
|
||||||
|
|
||||||
Indicates whether default DNS resolvers should be accepted for fallback queries in addition to MagicDNS。
|
Indicates whether default DNS resolvers should be accepted for fallback queries in addition to MagicDNS。
|
||||||
|
|
||||||
if not enabled, NXDOMAIN will be returned for non-Tailscale domain queries.
|
if not enabled, `NXDOMAIN` will be returned for non-Tailscale domain queries.
|
||||||
|
|
||||||
### Examples
|
### Examples
|
||||||
|
|
||||||
@ -80,4 +80,4 @@ if not enabled, NXDOMAIN will be returned for non-Tailscale domain queries.
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -6,7 +6,7 @@ icon: material/new-box
|
|||||||
|
|
||||||
# Endpoint
|
# Endpoint
|
||||||
|
|
||||||
Endpoint is protocols that has both inbound and outbound behavior.
|
An endpoint is a protocol with inbound and outbound behavior.
|
||||||
|
|
||||||
### Structure
|
### Structure
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ icon: material/new-box
|
|||||||
"control_url": "",
|
"control_url": "",
|
||||||
"ephemeral": false,
|
"ephemeral": false,
|
||||||
"hostname": "",
|
"hostname": "",
|
||||||
|
"accept_routes": false,
|
||||||
"exit_node": "",
|
"exit_node": "",
|
||||||
"exit_node_allow_lan_access": false,
|
"exit_node_allow_lan_access": false,
|
||||||
"advertise_routes": [],
|
"advertise_routes": [],
|
||||||
@ -62,6 +63,10 @@ System hostname is used by default.
|
|||||||
|
|
||||||
Example: `localhost`
|
Example: `localhost`
|
||||||
|
|
||||||
|
#### accept_routes
|
||||||
|
|
||||||
|
Indicates whether the node should accept routes advertised by other nodes.
|
||||||
|
|
||||||
#### exit_node
|
#### exit_node
|
||||||
|
|
||||||
The exit node name or IP address to use.
|
The exit node name or IP address to use.
|
||||||
|
@ -398,11 +398,11 @@ UDP NAT 过期时间。
|
|||||||
|
|
||||||
TCP/IP 栈。
|
TCP/IP 栈。
|
||||||
|
|
||||||
| 栈 | 描述 |
|
| 栈 | 描述 |
|
||||||
|--------|------------------------------------------------------------------|
|
|----------|-------------------------------------------------------------------------------------------------------|
|
||||||
| system | 基于系统网络栈执行 L3 到 L4 转换 |
|
| `system` | 基于系统网络栈执行 L3 到 L4 转换 |
|
||||||
| gVisor | 基于 [gVisor](https://github.com/google/gvisor) 虚拟网络栈执行 L3 到 L4 转换 |
|
| `gvisor` | 基于 [gVisor](https://github.com/google/gvisor) 虚拟网络栈执行 L3 到 L4 转换 |
|
||||||
| mixed | 混合 `system` TCP 栈与 `gvisor` UDP 栈 |
|
| `mixed` | 混合 `system` TCP 栈与 `gvisor` UDP 栈 |
|
||||||
|
|
||||||
默认使用 `mixed` 栈如果 gVisor 构建标记已启用,否则默认使用 `system` 栈。
|
默认使用 `mixed` 栈如果 gVisor 构建标记已启用,否则默认使用 `system` 栈。
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ sing-box uses JSON for configuration files.
|
|||||||
"inbounds": [],
|
"inbounds": [],
|
||||||
"outbounds": [],
|
"outbounds": [],
|
||||||
"route": {},
|
"route": {},
|
||||||
|
"services": [],
|
||||||
"experimental": {}
|
"experimental": {}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -30,6 +31,7 @@ sing-box uses JSON for configuration files.
|
|||||||
| `inbounds` | [Inbound](./inbound/) |
|
| `inbounds` | [Inbound](./inbound/) |
|
||||||
| `outbounds` | [Outbound](./outbound/) |
|
| `outbounds` | [Outbound](./outbound/) |
|
||||||
| `route` | [Route](./route/) |
|
| `route` | [Route](./route/) |
|
||||||
|
| `services` | [Service](./service/) |
|
||||||
| `experimental` | [Experimental](./experimental/) |
|
| `experimental` | [Experimental](./experimental/) |
|
||||||
|
|
||||||
### Check
|
### Check
|
||||||
|
@ -14,6 +14,7 @@ sing-box 使用 JSON 作为配置文件格式。
|
|||||||
"inbounds": [],
|
"inbounds": [],
|
||||||
"outbounds": [],
|
"outbounds": [],
|
||||||
"route": {},
|
"route": {},
|
||||||
|
"services": [],
|
||||||
"experimental": {}
|
"experimental": {}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -30,6 +31,7 @@ sing-box 使用 JSON 作为配置文件格式。
|
|||||||
| `inbounds` | [入站](./inbound/) |
|
| `inbounds` | [入站](./inbound/) |
|
||||||
| `outbounds` | [出站](./outbound/) |
|
| `outbounds` | [出站](./outbound/) |
|
||||||
| `route` | [路由](./route/) |
|
| `route` | [路由](./route/) |
|
||||||
|
| `services` | [服务](./service/) |
|
||||||
| `experimental` | [实验性](./experimental/) |
|
| `experimental` | [实验性](./experimental/) |
|
||||||
|
|
||||||
### 检查
|
### 检查
|
||||||
|
@ -2,10 +2,6 @@
|
|||||||
icon: material/delete-clock
|
icon: material/delete-clock
|
||||||
---
|
---
|
||||||
|
|
||||||
!!! failure "Deprecated in sing-box 1.11.0"
|
|
||||||
|
|
||||||
Legacy special outbounds are deprecated and will be removed in sing-box 1.13.0, check [Migration](/migration/#migrate-legacy-special-outbounds-to-rule-actions).
|
|
||||||
|
|
||||||
### Structure
|
### Structure
|
||||||
|
|
||||||
```json
|
```json
|
||||||
|
@ -2,10 +2,6 @@
|
|||||||
icon: material/delete-clock
|
icon: material/delete-clock
|
||||||
---
|
---
|
||||||
|
|
||||||
!!! failure "已在 sing-box 1.11.0 废弃"
|
|
||||||
|
|
||||||
旧的特殊出站已被弃用,且将在 sing-box 1.13.0 中被移除,参阅 [迁移指南](/migration/#migrate-legacy-special-outbounds-to-rule-actions).
|
|
||||||
|
|
||||||
`block` 出站关闭所有传入请求。
|
`block` 出站关闭所有传入请求。
|
||||||
|
|
||||||
### 结构
|
### 结构
|
||||||
|
@ -6,6 +6,7 @@ icon: material/new-box
|
|||||||
|
|
||||||
:material-plus: [tls_fragment](#tls_fragment)
|
:material-plus: [tls_fragment](#tls_fragment)
|
||||||
:material-plus: [tls_fragment_fallback_delay](#tls_fragment_fallback_delay)
|
:material-plus: [tls_fragment_fallback_delay](#tls_fragment_fallback_delay)
|
||||||
|
:material-plus: [tls_record_fragment](#tls_record_fragment)
|
||||||
:material-plus: [resolve.disable_cache](#disable_cache)
|
:material-plus: [resolve.disable_cache](#disable_cache)
|
||||||
:material-plus: [resolve.rewrite_ttl](#rewrite_ttl)
|
:material-plus: [resolve.rewrite_ttl](#rewrite_ttl)
|
||||||
:material-plus: [resolve.client_subnet](#client_subnet)
|
:material-plus: [resolve.client_subnet](#client_subnet)
|
||||||
@ -91,7 +92,8 @@ Not available when `method` is set to drop.
|
|||||||
"udp_connect": false,
|
"udp_connect": false,
|
||||||
"udp_timeout": "",
|
"udp_timeout": "",
|
||||||
"tls_fragment": false,
|
"tls_fragment": false,
|
||||||
"tls_fragment_fallback_delay": ""
|
"tls_fragment_fallback_delay": "",
|
||||||
|
"tls_record_fragment": ""
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -164,13 +166,19 @@ If no protocol is sniffed, the following ports will be recognized as protocols b
|
|||||||
|
|
||||||
Fragment TLS handshakes to bypass firewalls.
|
Fragment TLS handshakes to bypass firewalls.
|
||||||
|
|
||||||
This feature is intended to circumvent simple firewalls based on **plaintext packet matching**, and should not be used to circumvent real censorship.
|
This feature is intended to circumvent simple firewalls based on **plaintext packet matching**,
|
||||||
|
and should not be used to circumvent real censorship.
|
||||||
|
|
||||||
Since it is not designed for performance, it should not be applied to all connections, but only to server names that are known to be blocked.
|
Due to poor performance, try `tls_record_fragment` first, and only apply to server names known to be blocked.
|
||||||
|
|
||||||
On Linux, Apple platforms, (administrator privileges required) Windows, the wait time can be automatically detected, otherwise it will fall back to waiting for a fixed time specified by `tls_fragment_fallback_delay`.
|
On Linux, Apple platforms, (administrator privileges required) Windows,
|
||||||
|
the wait time can be automatically detected, otherwise it will fall back to
|
||||||
|
waiting for a fixed time specified by `tls_fragment_fallback_delay`.
|
||||||
|
|
||||||
In addition, if the actual wait time is less than 20ms, it will also fall back to waiting for a fixed time, because the target is considered to be local or behind a transparent proxy.
|
In addition, if the actual wait time is less than 20ms, it will also fall back to waiting for a fixed time,
|
||||||
|
because the target is considered to be local or behind a transparent proxy.
|
||||||
|
|
||||||
|
Conflict with `tls_record_fragment`.
|
||||||
|
|
||||||
#### tls_fragment_fallback_delay
|
#### tls_fragment_fallback_delay
|
||||||
|
|
||||||
@ -180,6 +188,17 @@ The fallback value used when TLS segmentation cannot automatically determine the
|
|||||||
|
|
||||||
`500ms` is used by default.
|
`500ms` is used by default.
|
||||||
|
|
||||||
|
#### tls_record_fragment
|
||||||
|
|
||||||
|
!!! question "Since sing-box 1.12.0"
|
||||||
|
|
||||||
|
Fragment TLS handshake into multiple TLS records to bypass firewalls.
|
||||||
|
|
||||||
|
This feature is intended to circumvent simple firewalls based on **plaintext packet matching**,
|
||||||
|
and should not be used to circumvent real censorship.
|
||||||
|
|
||||||
|
Conflict with `tls_fragment`.
|
||||||
|
|
||||||
### sniff
|
### sniff
|
||||||
|
|
||||||
```json
|
```json
|
||||||
|
@ -5,7 +5,11 @@ icon: material/new-box
|
|||||||
!!! quote "sing-box 1.12.0 中的更改"
|
!!! quote "sing-box 1.12.0 中的更改"
|
||||||
|
|
||||||
:material-plus: [tls_fragment](#tls_fragment)
|
:material-plus: [tls_fragment](#tls_fragment)
|
||||||
:material-plus: [tls_fragment_fallback_delay](#tls_fragment_fallback_delay)
|
:material-plus: [tls_fragment_fallback_delay](#tls_fragment_fallback_delay)
|
||||||
|
:material-plus: [tls_record_fragment](#tls_record_fragment)
|
||||||
|
:material-plus: [resolve.disable_cache](#disable_cache)
|
||||||
|
:material-plus: [resolve.rewrite_ttl](#rewrite_ttl)
|
||||||
|
:material-plus: [resolve.client_subnet](#client_subnet)
|
||||||
|
|
||||||
## 最终动作
|
## 最终动作
|
||||||
|
|
||||||
@ -159,12 +163,15 @@ UDP 连接超时时间。
|
|||||||
|
|
||||||
此功能旨在规避基于**明文数据包匹配**的简单防火墙,不应该用于规避真的审查。
|
此功能旨在规避基于**明文数据包匹配**的简单防火墙,不应该用于规避真的审查。
|
||||||
|
|
||||||
由于它不是为性能设计的,不应被应用于所有连接,而仅应用于已知被阻止的服务器名称。
|
由于性能不佳,请首先尝试 `tls_record_fragment`,且仅应用于已知被阻止的服务器名称。
|
||||||
|
|
||||||
在 Linux、Apple 平台和需要管理员权限的 Windows 系统上,可自动检测等待时间。若无法自动检测,将回退使用 `tls_fragment_fallback_delay` 指定的固定等待时间。
|
在 Linux、Apple 平台和需要管理员权限的 Windows 系统上,可自动检测等待时间。
|
||||||
|
若无法自动检测,将回退使用 `tls_fragment_fallback_delay` 指定的固定等待时间。
|
||||||
|
|
||||||
此外,若实际等待时间小于 20 毫秒,同样会回退至固定等待时间模式,因为此时判定目标处于本地或透明代理之后。
|
此外,若实际等待时间小于 20 毫秒,同样会回退至固定等待时间模式,因为此时判定目标处于本地或透明代理之后。
|
||||||
|
|
||||||
|
与 `tls_record_fragment` 冲突。
|
||||||
|
|
||||||
#### tls_fragment_fallback_delay
|
#### tls_fragment_fallback_delay
|
||||||
|
|
||||||
!!! question "自 sing-box 1.12.0 起"
|
!!! question "自 sing-box 1.12.0 起"
|
||||||
@ -173,6 +180,16 @@ UDP 连接超时时间。
|
|||||||
|
|
||||||
默认使用 `500ms`。
|
默认使用 `500ms`。
|
||||||
|
|
||||||
|
#### tls_record_fragment
|
||||||
|
|
||||||
|
!!! question "自 sing-box 1.12.0 起"
|
||||||
|
|
||||||
|
通过分段 TLS 握手数据包到多个 TLS 记录来绕过防火墙检测。
|
||||||
|
|
||||||
|
此功能旨在规避基于**明文数据包匹配**的简单防火墙,不应该用于规避真的审查。
|
||||||
|
|
||||||
|
与 `tls_fragment` 冲突。
|
||||||
|
|
||||||
### sniff
|
### sniff
|
||||||
|
|
||||||
```json
|
```json
|
||||||
|
@ -80,6 +80,8 @@ List of [Headless Rule](./headless-rule/).
|
|||||||
|
|
||||||
Format of rule-set file, `source` or `binary`.
|
Format of rule-set file, `source` or `binary`.
|
||||||
|
|
||||||
|
Optional when `path` or `url` uses `json` or `srs` as extension.
|
||||||
|
|
||||||
### Local Fields
|
### Local Fields
|
||||||
|
|
||||||
#### path
|
#### path
|
||||||
|
@ -80,6 +80,8 @@
|
|||||||
|
|
||||||
规则集格式, `source` 或 `binary`。
|
规则集格式, `source` 或 `binary`。
|
||||||
|
|
||||||
|
当 `path` 或 `url` 使用 `json` 或 `srs` 作为扩展名时可选。
|
||||||
|
|
||||||
### 本地字段
|
### 本地字段
|
||||||
|
|
||||||
#### path
|
#### path
|
||||||
|
135
docs/configuration/service/derp.md
Normal file
135
docs/configuration/service/derp.md
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
---
|
||||||
|
icon: material/new-box
|
||||||
|
---
|
||||||
|
|
||||||
|
!!! question "Since sing-box 1.12.0"
|
||||||
|
|
||||||
|
# DERP
|
||||||
|
|
||||||
|
DERP service is a Tailscale DERP server, similar to [derper](https://pkg.go.dev/tailscale.com/cmd/derper).
|
||||||
|
|
||||||
|
### Structure
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "derp",
|
||||||
|
|
||||||
|
... // Listen Fields
|
||||||
|
|
||||||
|
"tls": {},
|
||||||
|
"config_path": "",
|
||||||
|
"verify_client_endpoint": [],
|
||||||
|
"verify_client_url": [],
|
||||||
|
"home": "",
|
||||||
|
"mesh_with": [],
|
||||||
|
"mesh_psk": "",
|
||||||
|
"mesh_psk_file": "",
|
||||||
|
"stun": {}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Listen Fields
|
||||||
|
|
||||||
|
See [Listen Fields](/configuration/shared/listen/) for details.
|
||||||
|
|
||||||
|
### Fields
|
||||||
|
|
||||||
|
#### tls
|
||||||
|
|
||||||
|
TLS configuration, see [TLS](/configuration/shared/tls/#inbound).
|
||||||
|
|
||||||
|
#### config_path
|
||||||
|
|
||||||
|
==Required==
|
||||||
|
|
||||||
|
Derper configuration file path.
|
||||||
|
|
||||||
|
Example: `derper.key`
|
||||||
|
|
||||||
|
#### verify_client_endpoint
|
||||||
|
|
||||||
|
Tailscale endpoints tags to verify clients.
|
||||||
|
|
||||||
|
#### verify_client_url
|
||||||
|
|
||||||
|
URL to verify clients.
|
||||||
|
|
||||||
|
Object format:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"url": "https://my-headscale.com/verify",
|
||||||
|
|
||||||
|
... // Dial Fields
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Setting Array value to a string `__URL__` is equivalent to configuring:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "url": __URL__ }
|
||||||
|
```
|
||||||
|
|
||||||
|
#### home
|
||||||
|
|
||||||
|
What to serve at the root path. It may be left empty (the default, for a default homepage), `blank` for a blank page, or a URL to redirect to
|
||||||
|
|
||||||
|
#### mesh_with
|
||||||
|
|
||||||
|
Mesh with other DERP servers.
|
||||||
|
|
||||||
|
Object format:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"server": "",
|
||||||
|
"server_port": "",
|
||||||
|
"host": "",
|
||||||
|
"tls": {},
|
||||||
|
|
||||||
|
... // Dial Fields
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Object fields:
|
||||||
|
|
||||||
|
- `server`: **Required** DERP server address.
|
||||||
|
- `server_port`: **Required** DERP server port.
|
||||||
|
- `host`: Custom DERP hostname.
|
||||||
|
- `tls`: [TLS](/configuration/shared/tls/#outbound)
|
||||||
|
- `Dial Fields`: [Dial Fields](/configuration/shared/dial/)
|
||||||
|
|
||||||
|
#### mesh_psk
|
||||||
|
|
||||||
|
Pre-shared key for DERP mesh.
|
||||||
|
|
||||||
|
#### mesh_psk_file
|
||||||
|
|
||||||
|
Pre-shared key file for DERP mesh.
|
||||||
|
|
||||||
|
#### stun
|
||||||
|
|
||||||
|
STUN server listen options.
|
||||||
|
|
||||||
|
Object format:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"enabled": true,
|
||||||
|
|
||||||
|
... // Listen Fields
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Object fields:
|
||||||
|
|
||||||
|
- `enabled`: **Required** Enable STUN server.
|
||||||
|
- `listen`: **Required** STUN server listen address, default to `::`.
|
||||||
|
- `listen_port`: **Required** STUN server listen port, default to `3478`.
|
||||||
|
- `other Listen Fields`: [Listen Fields](/configuration/shared/listen/)
|
||||||
|
|
||||||
|
Setting `stun` value to a number `__PORT__` is equivalent to configuring:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "enabled": true, "listen_port": __PORT__ }
|
||||||
|
```
|
32
docs/configuration/service/index.md
Normal file
32
docs/configuration/service/index.md
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
---
|
||||||
|
icon: material/new-box
|
||||||
|
---
|
||||||
|
|
||||||
|
!!! question "Since sing-box 1.12.0"
|
||||||
|
|
||||||
|
# Service
|
||||||
|
|
||||||
|
### Structure
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"services": [
|
||||||
|
{
|
||||||
|
"type": "",
|
||||||
|
"tag": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Fields
|
||||||
|
|
||||||
|
| Type | Format |
|
||||||
|
|------------|------------------------|
|
||||||
|
| `derp` | [DERP](./derp) |
|
||||||
|
| `resolved` | [Resolved](./resolved) |
|
||||||
|
| `ssm-api` | [SSM API](./ssm-api) |
|
||||||
|
|
||||||
|
#### tag
|
||||||
|
|
||||||
|
The tag of the endpoint.
|
44
docs/configuration/service/resolved.md
Normal file
44
docs/configuration/service/resolved.md
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
---
|
||||||
|
icon: material/new-box
|
||||||
|
---
|
||||||
|
|
||||||
|
!!! question "Since sing-box 1.12.0"
|
||||||
|
|
||||||
|
# Resolved
|
||||||
|
|
||||||
|
Resolved service is a fake systemd-resolved DBUS service to receive DNS settings from other programs
|
||||||
|
(e.g. NetworkManager) and provide DNS resolution.
|
||||||
|
|
||||||
|
See also: [Resolved DNS Server](/configuration/dns/server/resolved/)
|
||||||
|
|
||||||
|
### Structure
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "resolved",
|
||||||
|
|
||||||
|
... // Listen Fields
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Listen Fields
|
||||||
|
|
||||||
|
See [Listen Fields](/configuration/shared/listen/) for details.
|
||||||
|
|
||||||
|
### Fields
|
||||||
|
|
||||||
|
#### listen
|
||||||
|
|
||||||
|
==Required==
|
||||||
|
|
||||||
|
Listen address.
|
||||||
|
|
||||||
|
`127.0.0.53` will be used by default.
|
||||||
|
|
||||||
|
#### listen_port
|
||||||
|
|
||||||
|
==Required==
|
||||||
|
|
||||||
|
Listen port.
|
||||||
|
|
||||||
|
`53` will be used by default.
|
52
docs/configuration/service/ssm-api.md
Normal file
52
docs/configuration/service/ssm-api.md
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
---
|
||||||
|
icon: material/new-box
|
||||||
|
---
|
||||||
|
|
||||||
|
!!! question "Since sing-box 1.12.0"
|
||||||
|
|
||||||
|
# SSM API
|
||||||
|
|
||||||
|
SSM API service is a RESTful API server for managing Shadowsocks servers.
|
||||||
|
|
||||||
|
See https://github.com/Shadowsocks-NET/shadowsocks-specs/blob/main/2023-1-shadowsocks-server-management-api-v1.md
|
||||||
|
|
||||||
|
### Structure
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "ssm-api",
|
||||||
|
|
||||||
|
... // Listen Fields
|
||||||
|
|
||||||
|
"servers": {},
|
||||||
|
"tls": {}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Listen Fields
|
||||||
|
|
||||||
|
See [Listen Fields](/configuration/shared/listen/) for details.
|
||||||
|
|
||||||
|
### Fields
|
||||||
|
|
||||||
|
#### servers
|
||||||
|
|
||||||
|
==Required==
|
||||||
|
|
||||||
|
A mapping Object from HTTP endpoints to [Shadowsocks Inbound](/configuration/inbound/shadowsocks) tags.
|
||||||
|
|
||||||
|
Selected Shadowsocks inbounds must be configured with [managed](/configuration/inbound/shadowsocks#managed) enabled.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"servers": {
|
||||||
|
"/": "ss-in"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### tls
|
||||||
|
|
||||||
|
TLS configuration, see [TLS](/configuration/shared/tls/#inbound).
|
@ -25,11 +25,12 @@ icon: material/new-box
|
|||||||
"inet6_bind_address": "",
|
"inet6_bind_address": "",
|
||||||
"routing_mark": 0,
|
"routing_mark": 0,
|
||||||
"reuse_addr": false,
|
"reuse_addr": false,
|
||||||
|
"netns": "",
|
||||||
"connect_timeout": "",
|
"connect_timeout": "",
|
||||||
"tcp_fast_open": false,
|
"tcp_fast_open": false,
|
||||||
"tcp_multi_path": false,
|
"tcp_multi_path": false,
|
||||||
"udp_fragment": false,
|
"udp_fragment": false,
|
||||||
"netns": "",
|
|
||||||
"domain_resolver": "", // or {}
|
"domain_resolver": "", // or {}
|
||||||
"network_strategy": "",
|
"network_strategy": "",
|
||||||
"network_type": [],
|
"network_type": [],
|
||||||
@ -37,6 +38,7 @@ icon: material/new-box
|
|||||||
"fallback_delay": "",
|
"fallback_delay": "",
|
||||||
|
|
||||||
// Deprecated
|
// Deprecated
|
||||||
|
|
||||||
"domain_strategy": ""
|
"domain_strategy": ""
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -73,10 +75,22 @@ The IPv6 address to bind to.
|
|||||||
|
|
||||||
Set netfilter routing mark.
|
Set netfilter routing mark.
|
||||||
|
|
||||||
|
Integers (e.g. `1234`) and string hexadecimals (e.g. `"0x1234"`) are supported.
|
||||||
|
|
||||||
#### reuse_addr
|
#### reuse_addr
|
||||||
|
|
||||||
Reuse listener address.
|
Reuse listener address.
|
||||||
|
|
||||||
|
#### netns
|
||||||
|
|
||||||
|
!!! question "Since sing-box 1.12.0"
|
||||||
|
|
||||||
|
!!! quote ""
|
||||||
|
|
||||||
|
Only supported on Linux.
|
||||||
|
|
||||||
|
Set network namespace, name or path.
|
||||||
|
|
||||||
#### connect_timeout
|
#### connect_timeout
|
||||||
|
|
||||||
Connect timeout, in golang's Duration format.
|
Connect timeout, in golang's Duration format.
|
||||||
@ -102,16 +116,6 @@ Enable TCP Multi Path.
|
|||||||
|
|
||||||
Enable UDP fragmentation.
|
Enable UDP fragmentation.
|
||||||
|
|
||||||
#### netns
|
|
||||||
|
|
||||||
!!! question "Since sing-box 1.12.0"
|
|
||||||
|
|
||||||
!!! quote ""
|
|
||||||
|
|
||||||
Only supported on Linux.
|
|
||||||
|
|
||||||
Set network namespace, name or path.
|
|
||||||
|
|
||||||
#### domain_resolver
|
#### domain_resolver
|
||||||
|
|
||||||
!!! warning ""
|
!!! warning ""
|
||||||
|
@ -25,11 +25,11 @@ icon: material/new-box
|
|||||||
"inet6_bind_address": "",
|
"inet6_bind_address": "",
|
||||||
"routing_mark": 0,
|
"routing_mark": 0,
|
||||||
"reuse_addr": false,
|
"reuse_addr": false,
|
||||||
|
"netns": "",
|
||||||
"connect_timeout": "",
|
"connect_timeout": "",
|
||||||
"tcp_fast_open": false,
|
"tcp_fast_open": false,
|
||||||
"tcp_multi_path": false,
|
"tcp_multi_path": false,
|
||||||
"udp_fragment": false,
|
"udp_fragment": false,
|
||||||
"netns": "",
|
|
||||||
"domain_resolver": "", // 或 {}
|
"domain_resolver": "", // 或 {}
|
||||||
"network_strategy": "",
|
"network_strategy": "",
|
||||||
"network_type": [],
|
"network_type": [],
|
||||||
@ -74,10 +74,22 @@ icon: material/new-box
|
|||||||
|
|
||||||
设置 netfilter 路由标记。
|
设置 netfilter 路由标记。
|
||||||
|
|
||||||
|
支持数字 (如 `1234`) 和十六进制字符串 (如 `"0x1234"`)。
|
||||||
|
|
||||||
#### reuse_addr
|
#### reuse_addr
|
||||||
|
|
||||||
重用监听地址。
|
重用监听地址。
|
||||||
|
|
||||||
|
#### netns
|
||||||
|
|
||||||
|
!!! question "自 sing-box 1.12.0 起"
|
||||||
|
|
||||||
|
!!! quote ""
|
||||||
|
|
||||||
|
仅支持 Linux。
|
||||||
|
|
||||||
|
设置网络命名空间,名称或路径。
|
||||||
|
|
||||||
#### connect_timeout
|
#### connect_timeout
|
||||||
|
|
||||||
连接超时,采用 golang 的 Duration 格式。
|
连接超时,采用 golang 的 Duration 格式。
|
||||||
@ -101,16 +113,6 @@ icon: material/new-box
|
|||||||
|
|
||||||
启用 UDP 分段。
|
启用 UDP 分段。
|
||||||
|
|
||||||
#### netns
|
|
||||||
|
|
||||||
!!! question "自 sing-box 1.12.0 起"
|
|
||||||
|
|
||||||
!!! quote ""
|
|
||||||
|
|
||||||
仅支持 Linux。
|
|
||||||
|
|
||||||
设置网络命名空间,名称或路径。
|
|
||||||
|
|
||||||
#### domain_resolver
|
#### domain_resolver
|
||||||
|
|
||||||
!!! warning ""
|
!!! warning ""
|
||||||
|
@ -4,7 +4,10 @@ icon: material/new-box
|
|||||||
|
|
||||||
!!! quote "Changes in sing-box 1.12.0"
|
!!! quote "Changes in sing-box 1.12.0"
|
||||||
|
|
||||||
:material-plus: [netns](#netns)
|
:material-plus: [netns](#netns)
|
||||||
|
:material-plus: [bind_interface](#bind_interface)
|
||||||
|
:material-plus: [routing_mark](#routing_mark)
|
||||||
|
:material-plus: [reuse_addr](#reuse_addr)
|
||||||
|
|
||||||
!!! quote "Changes in sing-box 1.11.0"
|
!!! quote "Changes in sing-box 1.11.0"
|
||||||
|
|
||||||
@ -20,12 +23,18 @@ icon: material/new-box
|
|||||||
{
|
{
|
||||||
"listen": "",
|
"listen": "",
|
||||||
"listen_port": 0,
|
"listen_port": 0,
|
||||||
|
"bind_interface": "",
|
||||||
|
"routing_mark": 0,
|
||||||
|
"reuse_addr": false,
|
||||||
|
"netns": "",
|
||||||
"tcp_fast_open": false,
|
"tcp_fast_open": false,
|
||||||
"tcp_multi_path": false,
|
"tcp_multi_path": false,
|
||||||
"udp_fragment": false,
|
"udp_fragment": false,
|
||||||
"udp_timeout": "",
|
"udp_timeout": "",
|
||||||
"netns": "",
|
|
||||||
"detour": "",
|
"detour": "",
|
||||||
|
|
||||||
|
// Deprecated
|
||||||
|
|
||||||
"sniff": false,
|
"sniff": false,
|
||||||
"sniff_override_destination": false,
|
"sniff_override_destination": false,
|
||||||
"sniff_timeout": "",
|
"sniff_timeout": "",
|
||||||
@ -36,15 +45,6 @@ icon: material/new-box
|
|||||||
|
|
||||||
### Fields
|
### Fields
|
||||||
|
|
||||||
| Field | Available Context |
|
|
||||||
|--------------------------------|---------------------------------------------------------|
|
|
||||||
| `listen` | Needs to listen on TCP or UDP. |
|
|
||||||
| `listen_port` | Needs to listen on TCP or UDP. |
|
|
||||||
| `tcp_fast_open` | Needs to listen on TCP. |
|
|
||||||
| `tcp_multi_path` | Needs to listen on TCP. |
|
|
||||||
| `udp_timeout` | Needs to assemble UDP connections. |
|
|
||||||
| `udp_disable_domain_unmapping` | Needs to listen on UDP and accept domain UDP addresses. |
|
|
||||||
|
|
||||||
#### listen
|
#### listen
|
||||||
|
|
||||||
==Required==
|
==Required==
|
||||||
@ -55,6 +55,40 @@ Listen address.
|
|||||||
|
|
||||||
Listen port.
|
Listen port.
|
||||||
|
|
||||||
|
#### bind_interface
|
||||||
|
|
||||||
|
!!! question "Since sing-box 1.12.0"
|
||||||
|
|
||||||
|
The network interface to bind to.
|
||||||
|
|
||||||
|
#### routing_mark
|
||||||
|
|
||||||
|
!!! question "Since sing-box 1.12.0"
|
||||||
|
|
||||||
|
!!! quote ""
|
||||||
|
|
||||||
|
Only supported on Linux.
|
||||||
|
|
||||||
|
Set netfilter routing mark.
|
||||||
|
|
||||||
|
Integers (e.g. `1234`) and string hexadecimals (e.g. `"0x1234"`) are supported.
|
||||||
|
|
||||||
|
#### reuse_addr
|
||||||
|
|
||||||
|
!!! question "Since sing-box 1.12.0"
|
||||||
|
|
||||||
|
Reuse listener address.
|
||||||
|
|
||||||
|
#### netns
|
||||||
|
|
||||||
|
!!! question "Since sing-box 1.12.0"
|
||||||
|
|
||||||
|
!!! quote ""
|
||||||
|
|
||||||
|
Only supported on Linux.
|
||||||
|
|
||||||
|
Set network namespace, name or path.
|
||||||
|
|
||||||
#### tcp_fast_open
|
#### tcp_fast_open
|
||||||
|
|
||||||
Enable TCP Fast Open.
|
Enable TCP Fast Open.
|
||||||
@ -77,16 +111,6 @@ UDP NAT expiration time.
|
|||||||
|
|
||||||
`5m` will be used by default.
|
`5m` will be used by default.
|
||||||
|
|
||||||
#### netns
|
|
||||||
|
|
||||||
!!! question "Since sing-box 1.12.0"
|
|
||||||
|
|
||||||
!!! quote ""
|
|
||||||
|
|
||||||
Only supported on Linux.
|
|
||||||
|
|
||||||
Set network namespace, name or path.
|
|
||||||
|
|
||||||
#### detour
|
#### detour
|
||||||
|
|
||||||
If set, connections will be forwarded to the specified inbound.
|
If set, connections will be forwarded to the specified inbound.
|
||||||
|
@ -4,7 +4,10 @@ icon: material/new-box
|
|||||||
|
|
||||||
!!! quote "Changes in sing-box 1.12.0"
|
!!! quote "Changes in sing-box 1.12.0"
|
||||||
|
|
||||||
:material-plus: [netns](#netns)
|
:material-plus: [netns](#netns)
|
||||||
|
:material-plus: [bind_interface](#bind_interface)
|
||||||
|
:material-plus: [routing_mark](#routing_mark)
|
||||||
|
:material-plus: [reuse_addr](#reuse_addr)
|
||||||
|
|
||||||
!!! quote "sing-box 1.11.0 中的更改"
|
!!! quote "sing-box 1.11.0 中的更改"
|
||||||
|
|
||||||
@ -20,12 +23,18 @@ icon: material/new-box
|
|||||||
{
|
{
|
||||||
"listen": "",
|
"listen": "",
|
||||||
"listen_port": 0,
|
"listen_port": 0,
|
||||||
|
"bind_interface": "",
|
||||||
|
"routing_mark": 0,
|
||||||
|
"reuse_addr": false,
|
||||||
|
"netns": "",
|
||||||
"tcp_fast_open": false,
|
"tcp_fast_open": false,
|
||||||
"tcp_multi_path": false,
|
"tcp_multi_path": false,
|
||||||
"udp_fragment": false,
|
"udp_fragment": false,
|
||||||
"udp_timeout": "",
|
"udp_timeout": "",
|
||||||
"netns": "",
|
|
||||||
"detour": "",
|
"detour": "",
|
||||||
|
|
||||||
|
// 废弃的
|
||||||
|
|
||||||
"sniff": false,
|
"sniff": false,
|
||||||
"sniff_override_destination": false,
|
"sniff_override_destination": false,
|
||||||
"sniff_timeout": "",
|
"sniff_timeout": "",
|
||||||
@ -34,16 +43,6 @@ icon: material/new-box
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
| 字段 | 可用上下文 |
|
|
||||||
|------------------|-----------------|
|
|
||||||
| `listen` | 需要监听 TCP 或 UDP。 |
|
|
||||||
| `listen_port` | 需要监听 TCP 或 UDP。 |
|
|
||||||
| `tcp_fast_open` | 需要监听 TCP。 |
|
|
||||||
| `tcp_multi_path` | 需要监听 TCP。 |
|
|
||||||
| `udp_timeout` | 需要组装 UDP 连接。 |
|
|
||||||
|
|
|
||||||
|
|
||||||
### 字段
|
### 字段
|
||||||
|
|
||||||
#### listen
|
#### listen
|
||||||
@ -56,6 +55,40 @@ icon: material/new-box
|
|||||||
|
|
||||||
监听端口。
|
监听端口。
|
||||||
|
|
||||||
|
#### bind_interface
|
||||||
|
|
||||||
|
!!! question "自 sing-box 1.12.0 起"
|
||||||
|
|
||||||
|
要绑定到的网络接口。
|
||||||
|
|
||||||
|
#### routing_mark
|
||||||
|
|
||||||
|
!!! question "自 sing-box 1.12.0 起"
|
||||||
|
|
||||||
|
!!! quote ""
|
||||||
|
|
||||||
|
仅支持 Linux。
|
||||||
|
|
||||||
|
设置 netfilter 路由标记。
|
||||||
|
|
||||||
|
支持数字 (如 `1234`) 和十六进制字符串 (如 `"0x1234"`)。
|
||||||
|
|
||||||
|
#### reuse_addr
|
||||||
|
|
||||||
|
!!! question "自 sing-box 1.12.0 起"
|
||||||
|
|
||||||
|
重用监听地址。
|
||||||
|
|
||||||
|
#### netns
|
||||||
|
|
||||||
|
!!! question "自 sing-box 1.12.0 起"
|
||||||
|
|
||||||
|
!!! quote ""
|
||||||
|
|
||||||
|
仅支持 Linux。
|
||||||
|
|
||||||
|
设置网络命名空间,名称或路径。
|
||||||
|
|
||||||
#### tcp_fast_open
|
#### tcp_fast_open
|
||||||
|
|
||||||
启用 TCP Fast Open。
|
启用 TCP Fast Open。
|
||||||
@ -78,16 +111,6 @@ UDP NAT 过期时间。
|
|||||||
|
|
||||||
默认使用 `5m`。
|
默认使用 `5m`。
|
||||||
|
|
||||||
#### netns
|
|
||||||
|
|
||||||
!!! question "自 sing-box 1.12.0 起"
|
|
||||||
|
|
||||||
!!! quote ""
|
|
||||||
|
|
||||||
仅支持 Linux。
|
|
||||||
|
|
||||||
设置网络命名空间,名称或路径。
|
|
||||||
|
|
||||||
#### detour
|
#### detour
|
||||||
|
|
||||||
如果设置,连接将被转发到指定的入站。
|
如果设置,连接将被转发到指定的入站。
|
||||||
|
@ -52,7 +52,6 @@ go build -tags "tag_a tag_b" ./cmd/sing-box
|
|||||||
| `with_dhcp` | :material-check: | Build with DHCP support, see [DHCP DNS transport](/configuration/dns/server/). |
|
| `with_dhcp` | :material-check: | Build with DHCP support, see [DHCP DNS transport](/configuration/dns/server/). |
|
||||||
| `with_wireguard` | :material-check: | Build with WireGuard support, see [WireGuard outbound](/configuration/outbound/wireguard/). |
|
| `with_wireguard` | :material-check: | Build with WireGuard support, see [WireGuard outbound](/configuration/outbound/wireguard/). |
|
||||||
| `with_utls` | :material-check: | Build with [uTLS](https://github.com/refraction-networking/utls) support for TLS outbound, see [TLS](/configuration/shared/tls#utls). |
|
| `with_utls` | :material-check: | Build with [uTLS](https://github.com/refraction-networking/utls) support for TLS outbound, see [TLS](/configuration/shared/tls#utls). |
|
||||||
| `with_reality_server` | :material-check: | Build with reality TLS server support, see [TLS](/configuration/shared/tls/). |
|
|
||||||
| `with_acme` | :material-check: | Build with ACME TLS certificate issuer support, see [TLS](/configuration/shared/tls/). |
|
| `with_acme` | :material-check: | Build with ACME TLS certificate issuer support, see [TLS](/configuration/shared/tls/). |
|
||||||
| `with_clash_api` | :material-check: | Build with Clash API support, see [Experimental](/configuration/experimental#clash-api-fields). |
|
| `with_clash_api` | :material-check: | Build with Clash API support, see [Experimental](/configuration/experimental#clash-api-fields). |
|
||||||
| `with_v2ray_api` | :material-close:️ | Build with V2Ray API support, see [Experimental](/configuration/experimental#v2ray-api-fields). |
|
| `with_v2ray_api` | :material-close:️ | Build with V2Ray API support, see [Experimental](/configuration/experimental#v2ray-api-fields). |
|
||||||
|
@ -56,7 +56,6 @@ go build -tags "tag_a tag_b" ./cmd/sing-box
|
|||||||
| `with_dhcp` | :material-check: | Build with DHCP support, see [DHCP DNS transport](/configuration/dns/server/). |
|
| `with_dhcp` | :material-check: | Build with DHCP support, see [DHCP DNS transport](/configuration/dns/server/). |
|
||||||
| `with_wireguard` | :material-check: | Build with WireGuard support, see [WireGuard outbound](/configuration/outbound/wireguard/). |
|
| `with_wireguard` | :material-check: | Build with WireGuard support, see [WireGuard outbound](/configuration/outbound/wireguard/). |
|
||||||
| `with_utls` | :material-check: | Build with [uTLS](https://github.com/refraction-networking/utls) support for TLS outbound, see [TLS](/configuration/shared/tls#utls). |
|
| `with_utls` | :material-check: | Build with [uTLS](https://github.com/refraction-networking/utls) support for TLS outbound, see [TLS](/configuration/shared/tls#utls). |
|
||||||
| `with_reality_server` | :material-check: | Build with reality TLS server support, see [TLS](/configuration/shared/tls/). |
|
|
||||||
| `with_acme` | :material-check: | Build with ACME TLS certificate issuer support, see [TLS](/configuration/shared/tls/). |
|
| `with_acme` | :material-check: | Build with ACME TLS certificate issuer support, see [TLS](/configuration/shared/tls/). |
|
||||||
| `with_clash_api` | :material-check: | Build with Clash API support, see [Experimental](/configuration/experimental#clash-api-fields). |
|
| `with_clash_api` | :material-check: | Build with Clash API support, see [Experimental](/configuration/experimental#clash-api-fields). |
|
||||||
| `with_v2ray_api` | :material-close:️ | Build with V2Ray API support, see [Experimental](/configuration/experimental#v2ray-api-fields). |
|
| `with_v2ray_api` | :material-close:️ | Build with V2Ray API support, see [Experimental](/configuration/experimental#v2ray-api-fields). |
|
||||||
|
@ -33,7 +33,7 @@ func BaseContext(platformInterface PlatformInterface) context.Context {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return box.Context(context.Background(), include.InboundRegistry(), include.OutboundRegistry(), include.EndpointRegistry(), dnsRegistry)
|
return box.Context(context.Background(), include.InboundRegistry(), include.OutboundRegistry(), include.EndpointRegistry(), dnsRegistry, include.ServiceRegistry())
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseConfig(ctx context.Context, configContent string) (option.Options, error) {
|
func parseConfig(ctx context.Context, configContent string) (option.Options, error) {
|
||||||
|
@ -433,78 +433,44 @@ func (x *SysStatsResponse) GetUptime() uint32 {
|
|||||||
|
|
||||||
var File_experimental_v2rayapi_stats_proto protoreflect.FileDescriptor
|
var File_experimental_v2rayapi_stats_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
var file_experimental_v2rayapi_stats_proto_rawDesc = string([]byte{
|
const file_experimental_v2rayapi_stats_proto_rawDesc = "" +
|
||||||
0x0a, 0x21, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2f, 0x76,
|
"\n" +
|
||||||
0x32, 0x72, 0x61, 0x79, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x70, 0x72,
|
"!experimental/v2rayapi/stats.proto\x12\x15experimental.v2rayapi\";\n" +
|
||||||
0x6f, 0x74, 0x6f, 0x12, 0x15, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61,
|
"\x0fGetStatsRequest\x12\x12\n" +
|
||||||
0x6c, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x61, 0x70, 0x69, 0x22, 0x3b, 0x0a, 0x0f, 0x47, 0x65,
|
"\x04name\x18\x01 \x01(\tR\x04name\x12\x14\n" +
|
||||||
0x74, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a,
|
"\x05reset\x18\x02 \x01(\bR\x05reset\"0\n" +
|
||||||
0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d,
|
"\x04Stat\x12\x12\n" +
|
||||||
0x65, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x65, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08,
|
"\x04name\x18\x01 \x01(\tR\x04name\x12\x14\n" +
|
||||||
0x52, 0x05, 0x72, 0x65, 0x73, 0x65, 0x74, 0x22, 0x30, 0x0a, 0x04, 0x53, 0x74, 0x61, 0x74, 0x12,
|
"\x05value\x18\x02 \x01(\x03R\x05value\"C\n" +
|
||||||
0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e,
|
"\x10GetStatsResponse\x12/\n" +
|
||||||
0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01,
|
"\x04stat\x18\x01 \x01(\v2\x1b.experimental.v2rayapi.StatR\x04stat\"w\n" +
|
||||||
0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x43, 0x0a, 0x10, 0x47, 0x65, 0x74,
|
"\x11QueryStatsRequest\x12\x18\n" +
|
||||||
0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a,
|
"\apattern\x18\x01 \x01(\tR\apattern\x12\x14\n" +
|
||||||
0x04, 0x73, 0x74, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x65, 0x78,
|
"\x05reset\x18\x02 \x01(\bR\x05reset\x12\x1a\n" +
|
||||||
0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79,
|
"\bpatterns\x18\x03 \x03(\tR\bpatterns\x12\x16\n" +
|
||||||
0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x52, 0x04, 0x73, 0x74, 0x61, 0x74, 0x22, 0x77,
|
"\x06regexp\x18\x04 \x01(\bR\x06regexp\"E\n" +
|
||||||
0x0a, 0x11, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75,
|
"\x12QueryStatsResponse\x12/\n" +
|
||||||
0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x18, 0x01,
|
"\x04stat\x18\x01 \x03(\v2\x1b.experimental.v2rayapi.StatR\x04stat\"\x11\n" +
|
||||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x12, 0x14, 0x0a,
|
"\x0fSysStatsRequest\"\xa2\x02\n" +
|
||||||
0x05, 0x72, 0x65, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x72, 0x65,
|
"\x10SysStatsResponse\x12\"\n" +
|
||||||
0x73, 0x65, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x73, 0x18,
|
"\fNumGoroutine\x18\x01 \x01(\rR\fNumGoroutine\x12\x14\n" +
|
||||||
0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x73, 0x12,
|
"\x05NumGC\x18\x02 \x01(\rR\x05NumGC\x12\x14\n" +
|
||||||
0x16, 0x0a, 0x06, 0x72, 0x65, 0x67, 0x65, 0x78, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52,
|
"\x05Alloc\x18\x03 \x01(\x04R\x05Alloc\x12\x1e\n" +
|
||||||
0x06, 0x72, 0x65, 0x67, 0x65, 0x78, 0x70, 0x22, 0x45, 0x0a, 0x12, 0x51, 0x75, 0x65, 0x72, 0x79,
|
"\n" +
|
||||||
0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a,
|
"TotalAlloc\x18\x04 \x01(\x04R\n" +
|
||||||
0x04, 0x73, 0x74, 0x61, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x65, 0x78,
|
"TotalAlloc\x12\x10\n" +
|
||||||
0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79,
|
"\x03Sys\x18\x05 \x01(\x04R\x03Sys\x12\x18\n" +
|
||||||
0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x52, 0x04, 0x73, 0x74, 0x61, 0x74, 0x22, 0x11,
|
"\aMallocs\x18\x06 \x01(\x04R\aMallocs\x12\x14\n" +
|
||||||
0x0a, 0x0f, 0x53, 0x79, 0x73, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
"\x05Frees\x18\a \x01(\x04R\x05Frees\x12 \n" +
|
||||||
0x74, 0x22, 0xa2, 0x02, 0x0a, 0x10, 0x53, 0x79, 0x73, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65,
|
"\vLiveObjects\x18\b \x01(\x04R\vLiveObjects\x12\"\n" +
|
||||||
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x4e, 0x75, 0x6d, 0x47, 0x6f, 0x72,
|
"\fPauseTotalNs\x18\t \x01(\x04R\fPauseTotalNs\x12\x16\n" +
|
||||||
0x6f, 0x75, 0x74, 0x69, 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x4e, 0x75,
|
"\x06Uptime\x18\n" +
|
||||||
0x6d, 0x47, 0x6f, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x4e, 0x75,
|
" \x01(\rR\x06Uptime2\xb4\x02\n" +
|
||||||
0x6d, 0x47, 0x43, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x4e, 0x75, 0x6d, 0x47, 0x43,
|
"\fStatsService\x12]\n" +
|
||||||
0x12, 0x14, 0x0a, 0x05, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52,
|
"\bGetStats\x12&.experimental.v2rayapi.GetStatsRequest\x1a'.experimental.v2rayapi.GetStatsResponse\"\x00\x12c\n" +
|
||||||
0x05, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x12, 0x1e, 0x0a, 0x0a, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x41,
|
"\n" +
|
||||||
0x6c, 0x6c, 0x6f, 0x63, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x54, 0x6f, 0x74, 0x61,
|
"QueryStats\x12(.experimental.v2rayapi.QueryStatsRequest\x1a).experimental.v2rayapi.QueryStatsResponse\"\x00\x12`\n" +
|
||||||
0x6c, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x12, 0x10, 0x0a, 0x03, 0x53, 0x79, 0x73, 0x18, 0x05, 0x20,
|
"\vGetSysStats\x12&.experimental.v2rayapi.SysStatsRequest\x1a'.experimental.v2rayapi.SysStatsResponse\"\x00B4Z2github.com/sagernet/sing-box/experimental/v2rayapib\x06proto3"
|
||||||
0x01, 0x28, 0x04, 0x52, 0x03, 0x53, 0x79, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x4d, 0x61, 0x6c, 0x6c,
|
|
||||||
0x6f, 0x63, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x4d, 0x61, 0x6c, 0x6c, 0x6f,
|
|
||||||
0x63, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x46, 0x72, 0x65, 0x65, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28,
|
|
||||||
0x04, 0x52, 0x05, 0x46, 0x72, 0x65, 0x65, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x4c, 0x69, 0x76, 0x65,
|
|
||||||
0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x4c,
|
|
||||||
0x69, 0x76, 0x65, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x50, 0x61,
|
|
||||||
0x75, 0x73, 0x65, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x4e, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04,
|
|
||||||
0x52, 0x0c, 0x50, 0x61, 0x75, 0x73, 0x65, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x4e, 0x73, 0x12, 0x16,
|
|
||||||
0x0a, 0x06, 0x55, 0x70, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06,
|
|
||||||
0x55, 0x70, 0x74, 0x69, 0x6d, 0x65, 0x32, 0xb4, 0x02, 0x0a, 0x0c, 0x53, 0x74, 0x61, 0x74, 0x73,
|
|
||||||
0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5d, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x53, 0x74,
|
|
||||||
0x61, 0x74, 0x73, 0x12, 0x26, 0x2e, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74,
|
|
||||||
0x61, 0x6c, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x53,
|
|
||||||
0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x65, 0x78,
|
|
||||||
0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79,
|
|
||||||
0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70,
|
|
||||||
0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x63, 0x0a, 0x0a, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53,
|
|
||||||
0x74, 0x61, 0x74, 0x73, 0x12, 0x28, 0x2e, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e,
|
|
||||||
0x74, 0x61, 0x6c, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x61, 0x70, 0x69, 0x2e, 0x51, 0x75, 0x65,
|
|
||||||
0x72, 0x79, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29,
|
|
||||||
0x2e, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x32,
|
|
||||||
0x72, 0x61, 0x79, 0x61, 0x70, 0x69, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x61, 0x74,
|
|
||||||
0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x60, 0x0a, 0x0b, 0x47,
|
|
||||||
0x65, 0x74, 0x53, 0x79, 0x73, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x26, 0x2e, 0x65, 0x78, 0x70,
|
|
||||||
0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x61,
|
|
||||||
0x70, 0x69, 0x2e, 0x53, 0x79, 0x73, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65,
|
|
||||||
0x73, 0x74, 0x1a, 0x27, 0x2e, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61,
|
|
||||||
0x6c, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x79, 0x73, 0x53, 0x74,
|
|
||||||
0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x34, 0x5a,
|
|
||||||
0x32, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x61, 0x67, 0x65,
|
|
||||||
0x72, 0x6e, 0x65, 0x74, 0x2f, 0x73, 0x69, 0x6e, 0x67, 0x2d, 0x62, 0x6f, 0x78, 0x2f, 0x65, 0x78,
|
|
||||||
0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79,
|
|
||||||
0x61, 0x70, 0x69, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
|
||||||
})
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
file_experimental_v2rayapi_stats_proto_rawDescOnce sync.Once
|
file_experimental_v2rayapi_stats_proto_rawDescOnce sync.Once
|
||||||
|
85
go.mod
85
go.mod
@ -4,54 +4,55 @@ go 1.23.1
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/anytls/sing-anytls v0.0.8
|
github.com/anytls/sing-anytls v0.0.8
|
||||||
github.com/caddyserver/certmagic v0.21.7
|
github.com/caddyserver/certmagic v0.23.0
|
||||||
github.com/cloudflare/circl v1.6.0
|
github.com/cloudflare/circl v1.6.1
|
||||||
|
github.com/coder/websocket v1.8.12
|
||||||
github.com/cretz/bine v0.2.0
|
github.com/cretz/bine v0.2.0
|
||||||
github.com/go-chi/chi/v5 v5.2.1
|
github.com/go-chi/chi/v5 v5.2.1
|
||||||
github.com/go-chi/render v1.0.3
|
github.com/go-chi/render v1.0.3
|
||||||
|
github.com/godbus/dbus/v5 v5.1.1-0.20230522191255-76236955d466
|
||||||
github.com/gofrs/uuid/v5 v5.3.2
|
github.com/gofrs/uuid/v5 v5.3.2
|
||||||
github.com/insomniacslk/dhcp v0.0.0-20250109001534-8abf58130905
|
github.com/insomniacslk/dhcp v0.0.0-20250417080101-5f8cf70e8c5f
|
||||||
github.com/libdns/alidns v1.0.3
|
github.com/libdns/alidns v1.0.4-libdns.v1.beta1
|
||||||
github.com/libdns/cloudflare v0.1.1
|
github.com/libdns/cloudflare v0.2.2-0.20250430151523-b46a2b0885f6
|
||||||
github.com/logrusorgru/aurora v2.0.3+incompatible
|
github.com/logrusorgru/aurora v2.0.3+incompatible
|
||||||
github.com/metacubex/tfo-go v0.0.0-20241231083714-66613d49c422
|
github.com/metacubex/tfo-go v0.0.0-20241231083714-66613d49c422
|
||||||
github.com/mholt/acmez/v3 v3.0.1
|
github.com/metacubex/utls v1.7.0-alpha.3
|
||||||
github.com/miekg/dns v1.1.63
|
github.com/mholt/acmez/v3 v3.1.2
|
||||||
|
github.com/miekg/dns v1.1.66
|
||||||
github.com/oschwald/maxminddb-golang v1.13.1
|
github.com/oschwald/maxminddb-golang v1.13.1
|
||||||
github.com/sagernet/asc-go v0.0.0-20241217030726-d563060fe4e1
|
github.com/sagernet/asc-go v0.0.0-20241217030726-d563060fe4e1
|
||||||
github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a
|
github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a
|
||||||
github.com/sagernet/cors v1.2.1
|
github.com/sagernet/cors v1.2.1
|
||||||
github.com/sagernet/fswatch v0.1.1
|
github.com/sagernet/fswatch v0.1.1
|
||||||
github.com/sagernet/gomobile v0.1.4
|
github.com/sagernet/gomobile v0.1.6
|
||||||
github.com/sagernet/gvisor v0.0.0-20250325023245-7a9c0f5725fb
|
github.com/sagernet/gvisor v0.0.0-20250325023245-7a9c0f5725fb
|
||||||
github.com/sagernet/quic-go v0.49.0-beta.1
|
github.com/sagernet/quic-go v0.52.0-beta.1
|
||||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691
|
github.com/sagernet/sing v0.6.11-0.20250521033217-30d675ea099b
|
||||||
github.com/sagernet/sing v0.6.8-0.20250429124449-59dfe1dbfdbf
|
github.com/sagernet/sing-mux v0.3.2
|
||||||
github.com/sagernet/sing-mux v0.3.1
|
github.com/sagernet/sing-quic v0.5.0-beta.2
|
||||||
github.com/sagernet/sing-quic v0.4.1-0.20250423030647-0eb05f373a76
|
github.com/sagernet/sing-shadowsocks v0.2.8
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.7
|
github.com/sagernet/sing-shadowsocks2 v0.2.1
|
||||||
github.com/sagernet/sing-shadowsocks2 v0.2.0
|
github.com/sagernet/sing-shadowtls v0.2.1-0.20250503051639-fcd445d33c11
|
||||||
github.com/sagernet/sing-shadowtls v0.2.1-0.20250316154757-6f9e732e5056
|
|
||||||
github.com/sagernet/sing-tun v0.6.6-0.20250428031943-0686f8c4f210
|
github.com/sagernet/sing-tun v0.6.6-0.20250428031943-0686f8c4f210
|
||||||
github.com/sagernet/sing-vmess v0.2.1
|
github.com/sagernet/sing-vmess v0.2.4-0.20250605032146-38cc72672c88
|
||||||
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7
|
github.com/sagernet/smux v1.5.34-mod.2
|
||||||
github.com/sagernet/tailscale v1.80.3-mod.4
|
github.com/sagernet/tailscale v1.80.3-mod.5
|
||||||
github.com/sagernet/utls v1.6.7
|
|
||||||
github.com/sagernet/wireguard-go v0.0.1-beta.7
|
github.com/sagernet/wireguard-go v0.0.1-beta.7
|
||||||
github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854
|
github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854
|
||||||
github.com/spf13/cobra v1.8.1
|
github.com/spf13/cobra v1.9.1
|
||||||
github.com/stretchr/testify v1.10.0
|
github.com/stretchr/testify v1.10.0
|
||||||
github.com/vishvananda/netns v0.0.4
|
github.com/vishvananda/netns v0.0.5
|
||||||
go.uber.org/zap v1.27.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.33.0
|
golang.org/x/crypto v0.38.0
|
||||||
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8
|
golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6
|
||||||
golang.org/x/mod v0.23.0
|
golang.org/x/mod v0.24.0
|
||||||
golang.org/x/net v0.35.0
|
golang.org/x/net v0.40.0
|
||||||
golang.org/x/sys v0.30.0
|
golang.org/x/sys v0.33.0
|
||||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20241231184526-a9ab2273dd10
|
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20241231184526-a9ab2273dd10
|
||||||
google.golang.org/grpc v1.70.0
|
google.golang.org/grpc v1.72.0
|
||||||
google.golang.org/protobuf v1.36.5
|
google.golang.org/protobuf v1.36.6
|
||||||
howett.net/plist v1.0.1
|
howett.net/plist v1.0.1
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -66,7 +67,6 @@ require (
|
|||||||
github.com/bits-and-blooms/bitset v1.13.0 // indirect
|
github.com/bits-and-blooms/bitset v1.13.0 // indirect
|
||||||
github.com/caddyserver/zerossl v0.1.3 // indirect
|
github.com/caddyserver/zerossl v0.1.3 // indirect
|
||||||
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||||
github.com/coder/websocket v1.8.12 // indirect
|
|
||||||
github.com/coreos/go-iptables v0.7.1-0.20240112124308-65c67c9f46e6 // indirect
|
github.com/coreos/go-iptables v0.7.1-0.20240112124308-65c67c9f46e6 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||||
github.com/dblohm7/wingoes v0.0.0-20240119213807-a09d6be7affa // indirect
|
github.com/dblohm7/wingoes v0.0.0-20240119213807-a09d6be7affa // indirect
|
||||||
@ -77,16 +77,13 @@ require (
|
|||||||
github.com/gaissmai/bart v0.11.1 // indirect
|
github.com/gaissmai/bart v0.11.1 // indirect
|
||||||
github.com/go-json-experiment/json v0.0.0-20250103232110-6a9a0fde9288 // indirect
|
github.com/go-json-experiment/json v0.0.0-20250103232110-6a9a0fde9288 // indirect
|
||||||
github.com/go-ole/go-ole v1.3.0 // indirect
|
github.com/go-ole/go-ole v1.3.0 // indirect
|
||||||
github.com/go-task/slim-sprig/v3 v3.0.0 // 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/godbus/dbus/v5 v5.1.1-0.20230522191255-76236955d466 // indirect
|
|
||||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||||
github.com/google/btree v1.1.3 // indirect
|
github.com/google/btree v1.1.3 // indirect
|
||||||
github.com/google/go-cmp v0.6.0 // indirect
|
github.com/google/go-cmp v0.6.0 // indirect
|
||||||
github.com/google/go-querystring v1.1.0 // indirect
|
github.com/google/go-querystring v1.1.0 // indirect
|
||||||
github.com/google/nftables v0.2.1-0.20240414091927-5e242ec57806 // indirect
|
github.com/google/nftables v0.2.1-0.20240414091927-5e242ec57806 // indirect
|
||||||
github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 // indirect
|
|
||||||
github.com/google/uuid v1.6.0 // indirect
|
github.com/google/uuid v1.6.0 // indirect
|
||||||
github.com/gorilla/csrf v1.7.3-0.20250123201450-9dd6af1f6d30 // indirect
|
github.com/gorilla/csrf v1.7.3-0.20250123201450-9dd6af1f6d30 // indirect
|
||||||
github.com/gorilla/securecookie v1.1.2 // indirect
|
github.com/gorilla/securecookie v1.1.2 // indirect
|
||||||
@ -96,24 +93,22 @@ require (
|
|||||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||||
github.com/jsimonetti/rtnetlink v1.4.0 // indirect
|
github.com/jsimonetti/rtnetlink v1.4.0 // indirect
|
||||||
github.com/klauspost/compress v1.17.11 // indirect
|
github.com/klauspost/compress v1.17.11 // indirect
|
||||||
github.com/klauspost/cpuid/v2 v2.2.9 // indirect
|
github.com/klauspost/cpuid/v2 v2.2.10 // indirect
|
||||||
github.com/kortschak/wol v0.0.0-20200729010619-da482cc4850a // indirect
|
github.com/kortschak/wol v0.0.0-20200729010619-da482cc4850a // indirect
|
||||||
github.com/libdns/libdns v0.2.2 // indirect
|
github.com/libdns/libdns v1.0.0-beta.1 // indirect
|
||||||
github.com/mdlayher/genetlink v1.3.2 // indirect
|
github.com/mdlayher/genetlink v1.3.2 // indirect
|
||||||
github.com/mdlayher/netlink v1.7.3-0.20250113171957-fbb4dce95f42 // indirect
|
github.com/mdlayher/netlink v1.7.3-0.20250113171957-fbb4dce95f42 // indirect
|
||||||
github.com/mdlayher/sdnotify v1.0.0 // indirect
|
github.com/mdlayher/sdnotify v1.0.0 // indirect
|
||||||
github.com/mdlayher/socket v0.5.1 // indirect
|
github.com/mdlayher/socket v0.5.1 // indirect
|
||||||
github.com/mitchellh/go-ps v1.0.0 // indirect
|
github.com/mitchellh/go-ps v1.0.0 // indirect
|
||||||
github.com/onsi/ginkgo/v2 v2.17.2 // indirect
|
|
||||||
github.com/pierrec/lz4/v4 v4.1.21 // indirect
|
github.com/pierrec/lz4/v4 v4.1.21 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||||
github.com/prometheus-community/pro-bing v0.4.0 // indirect
|
github.com/prometheus-community/pro-bing v0.4.0 // indirect
|
||||||
github.com/quic-go/qpack v0.4.0 // indirect
|
github.com/quic-go/qpack v0.5.1 // indirect
|
||||||
github.com/quic-go/qtls-go1-20 v0.4.1 // indirect
|
|
||||||
github.com/safchain/ethtool v0.3.0 // indirect
|
github.com/safchain/ethtool v0.3.0 // indirect
|
||||||
github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a // indirect
|
github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a // indirect
|
||||||
github.com/sagernet/nftables v0.3.0-beta.4 // indirect
|
github.com/sagernet/nftables v0.3.0-beta.4 // indirect
|
||||||
github.com/spf13/pflag v1.0.5 // indirect
|
github.com/spf13/pflag v1.0.6 // indirect
|
||||||
github.com/tailscale/certstore v0.1.1-0.20231202035212-d3fa0460f47e // indirect
|
github.com/tailscale/certstore v0.1.1-0.20231202035212-d3fa0460f47e // indirect
|
||||||
github.com/tailscale/go-winio v0.0.0-20231025203758-c4f33415bf55 // indirect
|
github.com/tailscale/go-winio v0.0.0-20231025203758-c4f33415bf55 // indirect
|
||||||
github.com/tailscale/golang-x-crypto v0.0.0-20240604161659-3fde5e568aa4 // indirect
|
github.com/tailscale/golang-x-crypto v0.0.0-20240604161659-3fde5e568aa4 // indirect
|
||||||
@ -128,16 +123,14 @@ require (
|
|||||||
go.uber.org/multierr v1.11.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
go.uber.org/zap/exp v0.3.0 // indirect
|
go.uber.org/zap/exp v0.3.0 // indirect
|
||||||
go4.org/mem v0.0.0-20240501181205-ae6ca9944745 // indirect
|
go4.org/mem v0.0.0-20240501181205-ae6ca9944745 // indirect
|
||||||
golang.org/x/sync v0.11.0 // indirect
|
golang.org/x/sync v0.14.0 // indirect
|
||||||
golang.org/x/term v0.29.0 // indirect
|
golang.org/x/term v0.32.0 // indirect
|
||||||
golang.org/x/text v0.22.0 // indirect
|
golang.org/x/text v0.25.0 // indirect
|
||||||
golang.org/x/time v0.9.0 // indirect
|
golang.org/x/time v0.9.0 // indirect
|
||||||
golang.org/x/tools v0.29.0 // indirect
|
golang.org/x/tools v0.33.0 // indirect
|
||||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
|
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
|
||||||
golang.zx2c4.com/wireguard/windows v0.5.3 // indirect
|
golang.zx2c4.com/wireguard/windows v0.5.3 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
lukechampine.com/blake3 v1.3.0 // indirect
|
lukechampine.com/blake3 v1.3.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
//replace github.com/sagernet/sing => ../sing
|
|
||||||
|
197
go.sum
197
go.sum
@ -12,24 +12,25 @@ github.com/anytls/sing-anytls v0.0.8 h1:1u/fnH1HoeeMV5mX7/eUOjLBvPdkd1UJRmXiRi6V
|
|||||||
github.com/anytls/sing-anytls v0.0.8/go.mod h1:7rjN6IukwysmdusYsrV51Fgu1uW6vsrdd6ctjnEAln8=
|
github.com/anytls/sing-anytls v0.0.8/go.mod h1:7rjN6IukwysmdusYsrV51Fgu1uW6vsrdd6ctjnEAln8=
|
||||||
github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJRUA0wFAVE=
|
github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJRUA0wFAVE=
|
||||||
github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
|
github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
|
||||||
github.com/caddyserver/certmagic v0.21.7 h1:66KJioPFJwttL43KYSWk7ErSmE6LfaJgCQuhm8Sg6fg=
|
github.com/caddyserver/certmagic v0.23.0 h1:CfpZ/50jMfG4+1J/u2LV6piJq4HOfO6ppOnOf7DkFEU=
|
||||||
github.com/caddyserver/certmagic v0.21.7/go.mod h1:LCPG3WLxcnjVKl/xpjzM0gqh0knrKKKiO5WVttX2eEI=
|
github.com/caddyserver/certmagic v0.23.0/go.mod h1:9mEZIWqqWoI+Gf+4Trh04MOVPD0tGSxtqsxg87hAIH4=
|
||||||
github.com/caddyserver/zerossl v0.1.3 h1:onS+pxp3M8HnHpN5MMbOMyNjmTheJyWRaZYwn+YTAyA=
|
github.com/caddyserver/zerossl v0.1.3 h1:onS+pxp3M8HnHpN5MMbOMyNjmTheJyWRaZYwn+YTAyA=
|
||||||
github.com/caddyserver/zerossl v0.1.3/go.mod h1:CxA0acn7oEGO6//4rtrRjYgEoa4MFw/XofZnrYwGqG4=
|
github.com/caddyserver/zerossl v0.1.3/go.mod h1:CxA0acn7oEGO6//4rtrRjYgEoa4MFw/XofZnrYwGqG4=
|
||||||
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
|
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
|
||||||
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
|
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
|
||||||
github.com/cilium/ebpf v0.15.0 h1:7NxJhNiBT3NG8pZJ3c+yfrVdHY8ScgKD27sScgjLMMk=
|
github.com/cilium/ebpf v0.15.0 h1:7NxJhNiBT3NG8pZJ3c+yfrVdHY8ScgKD27sScgjLMMk=
|
||||||
github.com/cilium/ebpf v0.15.0/go.mod h1:DHp1WyrLeiBh19Cf/tfiSMhqheEiK8fXFZ4No0P1Hso=
|
github.com/cilium/ebpf v0.15.0/go.mod h1:DHp1WyrLeiBh19Cf/tfiSMhqheEiK8fXFZ4No0P1Hso=
|
||||||
github.com/cloudflare/circl v1.6.0 h1:cr5JKic4HI+LkINy2lg3W2jF8sHCVTBncJr5gIIq7qk=
|
github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0=
|
||||||
github.com/cloudflare/circl v1.6.0/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
|
github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
|
||||||
github.com/coder/websocket v1.8.12 h1:5bUXkEPPIbewrnkU8LTCLVaxi4N4J8ahufH2vlo4NAo=
|
github.com/coder/websocket v1.8.12 h1:5bUXkEPPIbewrnkU8LTCLVaxi4N4J8ahufH2vlo4NAo=
|
||||||
github.com/coder/websocket v1.8.12/go.mod h1:LNVeNrXQZfe5qhS9ALED3uA+l5pPqvwXg3CKoDBB2gs=
|
github.com/coder/websocket v1.8.12/go.mod h1:LNVeNrXQZfe5qhS9ALED3uA+l5pPqvwXg3CKoDBB2gs=
|
||||||
github.com/coreos/go-iptables v0.7.1-0.20240112124308-65c67c9f46e6 h1:8h5+bWd7R6AYUslN6c6iuZWTKsKxUFDlpnmilO6R2n0=
|
github.com/coreos/go-iptables v0.7.1-0.20240112124308-65c67c9f46e6 h1:8h5+bWd7R6AYUslN6c6iuZWTKsKxUFDlpnmilO6R2n0=
|
||||||
github.com/coreos/go-iptables v0.7.1-0.20240112124308-65c67c9f46e6/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFETJConOQ//Q=
|
github.com/coreos/go-iptables v0.7.1-0.20240112124308-65c67c9f46e6/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFETJConOQ//Q=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||||
github.com/cretz/bine v0.2.0 h1:8GiDRGlTgz+o8H9DSnsl+5MeBK4HsExxgl6WgzOCuZo=
|
github.com/cretz/bine v0.2.0 h1:8GiDRGlTgz+o8H9DSnsl+5MeBK4HsExxgl6WgzOCuZo=
|
||||||
github.com/cretz/bine v0.2.0/go.mod h1:WU4o9QR9wWp8AVKtTM1XD5vUHkEqnf2vVSo6dBqbetI=
|
github.com/cretz/bine v0.2.0/go.mod h1:WU4o9QR9wWp8AVKtTM1XD5vUHkEqnf2vVSo6dBqbetI=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/dblohm7/wingoes v0.0.0-20240119213807-a09d6be7affa h1:h8TfIT1xc8FWbwwpmHn1J5i43Y0uZP97GqasGCzSRJk=
|
github.com/dblohm7/wingoes v0.0.0-20240119213807-a09d6be7affa h1:h8TfIT1xc8FWbwwpmHn1J5i43Y0uZP97GqasGCzSRJk=
|
||||||
@ -58,8 +59,6 @@ github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
|||||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||||
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
|
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
|
||||||
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
|
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
|
||||||
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
|
|
||||||
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
|
|
||||||
github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU=
|
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=
|
||||||
@ -83,8 +82,6 @@ github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
|||||||
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/nftables v0.2.1-0.20240414091927-5e242ec57806 h1:wG8RYIyctLhdFk6Vl1yPGtSRtwGpVkWyZww1OCil2MI=
|
github.com/google/nftables v0.2.1-0.20240414091927-5e242ec57806 h1:wG8RYIyctLhdFk6Vl1yPGtSRtwGpVkWyZww1OCil2MI=
|
||||||
github.com/google/nftables v0.2.1-0.20240414091927-5e242ec57806/go.mod h1:Beg6V6zZ3oEn0JuiUQ4wqwuyqqzasOltcoXPtgLbFp4=
|
github.com/google/nftables v0.2.1-0.20240414091927-5e242ec57806/go.mod h1:Beg6V6zZ3oEn0JuiUQ4wqwuyqqzasOltcoXPtgLbFp4=
|
||||||
github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 h1:k7nVchz72niMH6YLQNvHSdIE7iqsQxK1P41mySCvssg=
|
|
||||||
github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw=
|
|
||||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/gorilla/csrf v1.7.3-0.20250123201450-9dd6af1f6d30 h1:fiJdrgVBkjZ5B1HJ2WQwNOaXB+QyYcNXTA3t1XYLz0M=
|
github.com/gorilla/csrf v1.7.3-0.20250123201450-9dd6af1f6d30 h1:fiJdrgVBkjZ5B1HJ2WQwNOaXB+QyYcNXTA3t1XYLz0M=
|
||||||
@ -99,24 +96,23 @@ github.com/illarion/gonotify/v2 v2.0.3 h1:B6+SKPo/0Sw8cRJh1aLzNEeNVFfzE3c6N+o+vy
|
|||||||
github.com/illarion/gonotify/v2 v2.0.3/go.mod h1:38oIJTgFqupkEydkkClkbL6i5lXV/bxdH9do5TALPEE=
|
github.com/illarion/gonotify/v2 v2.0.3/go.mod h1:38oIJTgFqupkEydkkClkbL6i5lXV/bxdH9do5TALPEE=
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||||
github.com/insomniacslk/dhcp v0.0.0-20250109001534-8abf58130905 h1:q3OEI9RaN/wwcx+qgGo6ZaoJkCiDYe/gjDLfq7lQQF4=
|
github.com/insomniacslk/dhcp v0.0.0-20250417080101-5f8cf70e8c5f h1:dd33oobuIv9PcBVqvbEiCXEbNTomOHyj3WFuC5YiPRU=
|
||||||
github.com/insomniacslk/dhcp v0.0.0-20250109001534-8abf58130905/go.mod h1:VvGYjkZoJyKqlmT1yzakUs4mfKMNB0XdODP0+rdml6k=
|
github.com/insomniacslk/dhcp v0.0.0-20250417080101-5f8cf70e8c5f/go.mod h1:zhFlBeJssZ1YBCMZ5Lzu1pX4vhftDvU10WUVb1uXKtM=
|
||||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||||
github.com/jsimonetti/rtnetlink v1.4.0 h1:Z1BF0fRgcETPEa0Kt0MRk3yV5+kF1FWTni6KUFKrq2I=
|
github.com/jsimonetti/rtnetlink v1.4.0 h1:Z1BF0fRgcETPEa0Kt0MRk3yV5+kF1FWTni6KUFKrq2I=
|
||||||
github.com/jsimonetti/rtnetlink v1.4.0/go.mod h1:5W1jDvWdnthFJ7fxYX1GMK07BUpI4oskfOqvPteYS6E=
|
github.com/jsimonetti/rtnetlink v1.4.0/go.mod h1:5W1jDvWdnthFJ7fxYX1GMK07BUpI4oskfOqvPteYS6E=
|
||||||
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
|
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
|
||||||
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
|
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
|
||||||
github.com/klauspost/cpuid/v2 v2.2.9 h1:66ze0taIn2H33fBvCkXuv9BmCwDfafmiIVpKV9kKGuY=
|
github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE=
|
||||||
github.com/klauspost/cpuid/v2 v2.2.9/go.mod h1:rqkxqrZ1EhYM9G+hXH7YdowN5R5RGN6NK4QwQ3WMXF8=
|
github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
|
||||||
github.com/kortschak/wol v0.0.0-20200729010619-da482cc4850a h1:+RR6SqnTkDLWyICxS1xpjCi/3dhyV+TgZwA6Ww3KncQ=
|
github.com/kortschak/wol v0.0.0-20200729010619-da482cc4850a h1:+RR6SqnTkDLWyICxS1xpjCi/3dhyV+TgZwA6Ww3KncQ=
|
||||||
github.com/kortschak/wol v0.0.0-20200729010619-da482cc4850a/go.mod h1:YTtCCM3ryyfiu4F7t8HQ1mxvp1UBdWM2r6Xa+nGWvDk=
|
github.com/kortschak/wol v0.0.0-20200729010619-da482cc4850a/go.mod h1:YTtCCM3ryyfiu4F7t8HQ1mxvp1UBdWM2r6Xa+nGWvDk=
|
||||||
github.com/libdns/alidns v1.0.3 h1:LFHuGnbseq5+HCeGa1aW8awyX/4M2psB9962fdD2+yQ=
|
github.com/libdns/alidns v1.0.4-libdns.v1.beta1 h1:ods22gD4PcT0g4qRX77ucykjz7Rppnkz3vQoxDbbKTM=
|
||||||
github.com/libdns/alidns v1.0.3/go.mod h1:e18uAG6GanfRhcJj6/tps2rCMzQJaYVcGKT+ELjdjGE=
|
github.com/libdns/alidns v1.0.4-libdns.v1.beta1/go.mod h1:ystHmPwcGoWjPrGpensQSMY9VoCx4cpR2hXNlwk9H/g=
|
||||||
github.com/libdns/cloudflare v0.1.1 h1:FVPfWwP8zZCqj268LZjmkDleXlHPlFU9KC4OJ3yn054=
|
github.com/libdns/cloudflare v0.2.2-0.20250430151523-b46a2b0885f6 h1:0dlpPjNr8TaYZbkpwCiee4udBNrYrWG8EZPYEbjHEn8=
|
||||||
github.com/libdns/cloudflare v0.1.1/go.mod h1:9VK91idpOjg6v7/WbjkEW49bSCxj00ALesIFDhJ8PBU=
|
github.com/libdns/cloudflare v0.2.2-0.20250430151523-b46a2b0885f6/go.mod h1:Aq4IXdjalB6mD0ELvKqJiIGim8zSC6mlIshRPMOAb5w=
|
||||||
github.com/libdns/libdns v0.2.0/go.mod h1:yQCXzk1lEZmmCPa857bnk4TsOiqYasqpyOEeSObbb40=
|
github.com/libdns/libdns v1.0.0-beta.1 h1:KIf4wLfsrEpXpZ3vmc/poM8zCATXT2klbdPe6hyOBjQ=
|
||||||
github.com/libdns/libdns v0.2.2 h1:O6ws7bAfRPaBsgAYt8MDe2HcNBGC29hkZ9MX2eUSX3s=
|
github.com/libdns/libdns v1.0.0-beta.1/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ=
|
||||||
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/mdlayher/genetlink v1.3.2 h1:KdrNKe+CTu+IbZnm/GVUMXSqBBLqcGpRDa0xkQy56gw=
|
github.com/mdlayher/genetlink v1.3.2 h1:KdrNKe+CTu+IbZnm/GVUMXSqBBLqcGpRDa0xkQy56gw=
|
||||||
@ -129,18 +125,16 @@ github.com/mdlayher/socket v0.5.1 h1:VZaqt6RkGkt2OE9l3GcC6nZkqD3xKeQLyfleW/uBcos
|
|||||||
github.com/mdlayher/socket v0.5.1/go.mod h1:TjPLHI1UgwEv5J1B5q0zTZq12A/6H7nKmtTanQE37IQ=
|
github.com/mdlayher/socket v0.5.1/go.mod h1:TjPLHI1UgwEv5J1B5q0zTZq12A/6H7nKmtTanQE37IQ=
|
||||||
github.com/metacubex/tfo-go v0.0.0-20241231083714-66613d49c422 h1:zGeQt3UyNydIVrMRB97AA5WsYEau/TyCnRtTf1yUmJY=
|
github.com/metacubex/tfo-go v0.0.0-20241231083714-66613d49c422 h1:zGeQt3UyNydIVrMRB97AA5WsYEau/TyCnRtTf1yUmJY=
|
||||||
github.com/metacubex/tfo-go v0.0.0-20241231083714-66613d49c422/go.mod h1:l9oLnLoEXyGZ5RVLsh7QCC5XsouTUyKk4F2nLm2DHLw=
|
github.com/metacubex/tfo-go v0.0.0-20241231083714-66613d49c422/go.mod h1:l9oLnLoEXyGZ5RVLsh7QCC5XsouTUyKk4F2nLm2DHLw=
|
||||||
github.com/mholt/acmez/v3 v3.0.1 h1:4PcjKjaySlgXK857aTfDuRbmnM5gb3Ruz3tvoSJAUp8=
|
github.com/metacubex/utls v1.7.0-alpha.3 h1:cp1cEMUnoifiWrGHRzo+nCwPRveN9yPD8QaRFmfcYxA=
|
||||||
github.com/mholt/acmez/v3 v3.0.1/go.mod h1:L1wOU06KKvq7tswuMDwKdcHeKpFFgkppZy/y0DFxagQ=
|
github.com/metacubex/utls v1.7.0-alpha.3/go.mod h1:oknYT0qTOwE4hjPmZOEpzVdefnW7bAdGLvZcqmk4TLU=
|
||||||
github.com/miekg/dns v1.1.63 h1:8M5aAw6OMZfFXTT7K5V0Eu5YiiL8l7nUAkyN6C9YwaY=
|
github.com/mholt/acmez/v3 v3.1.2 h1:auob8J/0FhmdClQicvJvuDavgd5ezwLBfKuYmynhYzc=
|
||||||
github.com/miekg/dns v1.1.63/go.mod h1:6NGHfjhpmr5lt3XPLuyfDJi5AXbNIPM9PY6H6sF1Nfs=
|
github.com/mholt/acmez/v3 v3.1.2/go.mod h1:L1wOU06KKvq7tswuMDwKdcHeKpFFgkppZy/y0DFxagQ=
|
||||||
|
github.com/miekg/dns v1.1.66 h1:FeZXOS3VCVsKnEAd+wBkjMC3D2K+ww66Cq3VnCINuJE=
|
||||||
|
github.com/miekg/dns v1.1.66/go.mod h1:jGFzBsSNbJw6z1HYut1RKBKHA9PBdxeHrZG8J+gC2WE=
|
||||||
github.com/mitchellh/go-ps v1.0.0 h1:i6ampVEEF4wQFF+bkYfwYgY+F/uYJDktmvLPf7qIgjc=
|
github.com/mitchellh/go-ps v1.0.0 h1:i6ampVEEF4wQFF+bkYfwYgY+F/uYJDktmvLPf7qIgjc=
|
||||||
github.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg=
|
github.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg=
|
||||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
|
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
|
||||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
|
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
|
||||||
github.com/onsi/ginkgo/v2 v2.17.2 h1:7eMhcy3GimbsA3hEnVKdw/PQM9XN9krpKVXsZdph0/g=
|
|
||||||
github.com/onsi/ginkgo/v2 v2.17.2/go.mod h1:nP2DPOQoNsQmsVyv5rDA8JkXQoCs6goXIvr/PRJ1eCc=
|
|
||||||
github.com/onsi/gomega v1.33.0 h1:snPCflnZrpMsy94p4lXVEkHo12lmPnc3vY5XBbreexE=
|
|
||||||
github.com/onsi/gomega v1.33.0/go.mod h1:+925n5YtiFsLzzafLUHzVMBpvvRAzrydIBiSIxjX3wY=
|
|
||||||
github.com/oschwald/maxminddb-golang v1.13.1 h1:G3wwjdN9JmIK2o/ermkHM+98oX5fS+k5MbwsmL4MRQE=
|
github.com/oschwald/maxminddb-golang v1.13.1 h1:G3wwjdN9JmIK2o/ermkHM+98oX5fS+k5MbwsmL4MRQE=
|
||||||
github.com/oschwald/maxminddb-golang v1.13.1/go.mod h1:K4pgV9N/GcK694KSTmVSDTODk4IsCNThNdTmnaBZ/F8=
|
github.com/oschwald/maxminddb-golang v1.13.1/go.mod h1:K4pgV9N/GcK694KSTmVSDTODk4IsCNThNdTmnaBZ/F8=
|
||||||
github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ=
|
github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ=
|
||||||
@ -150,10 +144,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI
|
|||||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/prometheus-community/pro-bing v0.4.0 h1:YMbv+i08gQz97OZZBwLyvmmQEEzyfyrrjEaAchdy3R4=
|
github.com/prometheus-community/pro-bing v0.4.0 h1:YMbv+i08gQz97OZZBwLyvmmQEEzyfyrrjEaAchdy3R4=
|
||||||
github.com/prometheus-community/pro-bing v0.4.0/go.mod h1:b7wRYZtCcPmt4Sz319BykUU241rWLe1VFXyiyWK/dH4=
|
github.com/prometheus-community/pro-bing v0.4.0/go.mod h1:b7wRYZtCcPmt4Sz319BykUU241rWLe1VFXyiyWK/dH4=
|
||||||
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
|
github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
|
||||||
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
|
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
|
||||||
github.com/quic-go/qtls-go1-20 v0.4.1 h1:D33340mCNDAIKBqXuAvexTNMUByrYmFYVfKfDN5nfFs=
|
|
||||||
github.com/quic-go/qtls-go1-20 v0.4.1/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
|
|
||||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/safchain/ethtool v0.3.0 h1:gimQJpsI6sc1yIqP/y8GYgiXn/NjgvpM0RNoWLVVmP0=
|
github.com/safchain/ethtool v0.3.0 h1:gimQJpsI6sc1yIqP/y8GYgiXn/NjgvpM0RNoWLVVmP0=
|
||||||
github.com/safchain/ethtool v0.3.0/go.mod h1:SA9BwrgyAqNo7M+uaL6IYbxpm5wk3L7Mm6ocLW+CJUs=
|
github.com/safchain/ethtool v0.3.0/go.mod h1:SA9BwrgyAqNo7M+uaL6IYbxpm5wk3L7Mm6ocLW+CJUs=
|
||||||
@ -165,51 +157,54 @@ github.com/sagernet/cors v1.2.1 h1:Cv5Z8y9YSD6Gm+qSpNrL3LO4lD3eQVvbFYJSG7JCMHQ=
|
|||||||
github.com/sagernet/cors v1.2.1/go.mod h1:O64VyOjjhrkLmQIjF4KGRrJO/5dVXFdpEmCW/eISRAI=
|
github.com/sagernet/cors v1.2.1/go.mod h1:O64VyOjjhrkLmQIjF4KGRrJO/5dVXFdpEmCW/eISRAI=
|
||||||
github.com/sagernet/fswatch v0.1.1 h1:YqID+93B7VRfqIH3PArW/XpJv5H4OLEVWDfProGoRQs=
|
github.com/sagernet/fswatch v0.1.1 h1:YqID+93B7VRfqIH3PArW/XpJv5H4OLEVWDfProGoRQs=
|
||||||
github.com/sagernet/fswatch v0.1.1/go.mod h1:nz85laH0mkQqJfaOrqPpkwtU1znMFNVTpT/5oRsVz/o=
|
github.com/sagernet/fswatch v0.1.1/go.mod h1:nz85laH0mkQqJfaOrqPpkwtU1znMFNVTpT/5oRsVz/o=
|
||||||
github.com/sagernet/gomobile v0.1.4 h1:WzX9ka+iHdupMgy2Vdich+OAt7TM8C2cZbIbzNjBrJY=
|
github.com/sagernet/gomobile v0.1.6 h1:JkR1ToKOrdoiwULte4pYS5HYdPBzl2N+JNuuwVuLs0k=
|
||||||
github.com/sagernet/gomobile v0.1.4/go.mod h1:Pqq2+ZVvs10U7xK+UwJgwYWUykewi8H6vlslAO73n9E=
|
github.com/sagernet/gomobile v0.1.6/go.mod h1:Pqq2+ZVvs10U7xK+UwJgwYWUykewi8H6vlslAO73n9E=
|
||||||
github.com/sagernet/gvisor v0.0.0-20250325023245-7a9c0f5725fb h1:pprQtDqNgqXkRsXn+0E8ikKOemzmum8bODjSfDene38=
|
github.com/sagernet/gvisor v0.0.0-20250325023245-7a9c0f5725fb h1:pprQtDqNgqXkRsXn+0E8ikKOemzmum8bODjSfDene38=
|
||||||
github.com/sagernet/gvisor v0.0.0-20250325023245-7a9c0f5725fb/go.mod h1:QkkPEJLw59/tfxgapHta14UL5qMUah5NXhO0Kw2Kan4=
|
github.com/sagernet/gvisor v0.0.0-20250325023245-7a9c0f5725fb/go.mod h1:QkkPEJLw59/tfxgapHta14UL5qMUah5NXhO0Kw2Kan4=
|
||||||
github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a h1:ObwtHN2VpqE0ZNjr6sGeT00J8uU7JF4cNUdb44/Duis=
|
github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a h1:ObwtHN2VpqE0ZNjr6sGeT00J8uU7JF4cNUdb44/Duis=
|
||||||
github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM=
|
github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM=
|
||||||
github.com/sagernet/nftables v0.3.0-beta.4 h1:kbULlAwAC3jvdGAC1P5Fa3GSxVwQJibNenDW2zaXr8I=
|
github.com/sagernet/nftables v0.3.0-beta.4 h1:kbULlAwAC3jvdGAC1P5Fa3GSxVwQJibNenDW2zaXr8I=
|
||||||
github.com/sagernet/nftables v0.3.0-beta.4/go.mod h1:OQXAjvjNGGFxaTgVCSTRIhYB5/llyVDeapVoENYBDS8=
|
github.com/sagernet/nftables v0.3.0-beta.4/go.mod h1:OQXAjvjNGGFxaTgVCSTRIhYB5/llyVDeapVoENYBDS8=
|
||||||
github.com/sagernet/quic-go v0.49.0-beta.1 h1:3LdoCzVVfYRibZns1tYWSIoB65fpTmrwy+yfK8DQ8Jk=
|
github.com/sagernet/quic-go v0.52.0-beta.1 h1:hWkojLg64zjV+MJOvJU/kOeWndm3tiEfBLx5foisszs=
|
||||||
github.com/sagernet/quic-go v0.49.0-beta.1/go.mod h1:uesWD1Ihrldq1M3XtjuEvIUqi8WHNsRs71b3Lt1+p/U=
|
github.com/sagernet/quic-go v0.52.0-beta.1/go.mod h1:OV+V5kEBb8kJS7k29MzDu6oj9GyMc7HA07sE1tedxz4=
|
||||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 h1:5Th31OC6yj8byLGkEnIYp6grlXfo1QYUfiYFGjewIdc=
|
github.com/sagernet/sing v0.6.9/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
|
||||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691/go.mod h1:B8lp4WkQ1PwNnrVMM6KyuFR20pU8jYBD+A4EhJovEXU=
|
github.com/sagernet/sing v0.6.11-0.20250521033217-30d675ea099b h1:ZjTCYPb5f7aHdf1UpUvE22dVmf7BL8eQ/zLZhjgh7Wo=
|
||||||
github.com/sagernet/sing v0.2.18/go.mod h1:OL6k2F0vHmEzXz2KW19qQzu172FDgSbUSODylighuVo=
|
github.com/sagernet/sing v0.6.11-0.20250521033217-30d675ea099b/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
|
||||||
github.com/sagernet/sing v0.6.8-0.20250429124449-59dfe1dbfdbf h1:WLlIJ2+Z4ZjQQAJlxYvASMIopFFk5aQBbq7fwIPS3u0=
|
github.com/sagernet/sing-mux v0.3.2 h1:meZVFiiStvHThb/trcpAkCrmtJOuItG5Dzl1RRP5/NE=
|
||||||
github.com/sagernet/sing v0.6.8-0.20250429124449-59dfe1dbfdbf/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
|
github.com/sagernet/sing-mux v0.3.2/go.mod h1:pht8iFY4c9Xltj7rhVd208npkNaeCxzyXCgulDPLUDA=
|
||||||
github.com/sagernet/sing-mux v0.3.1 h1:kvCc8HyGAskDHDQ0yQvoTi/7J4cZPB/VJMsAM3MmdQI=
|
github.com/sagernet/sing-quic v0.5.0-beta.2 h1:j7KAbBuGmsKwSxVAQL5soJ+wDqxim4/llK2kxB0hSKk=
|
||||||
github.com/sagernet/sing-mux v0.3.1/go.mod h1:Mkdz8LnDstthz0HWuA/5foncnDIdcNN5KZ6AdJX+x78=
|
github.com/sagernet/sing-quic v0.5.0-beta.2/go.mod h1:SAv/qdeDN+75msGG5U5ZIwG+3Ua50jVIKNrRSY8pkx0=
|
||||||
github.com/sagernet/sing-quic v0.4.1-0.20250423030647-0eb05f373a76 h1:iwpCX6H3nZEOGUGwx0q5azcgYOA9f6v9YssihXoRKHk=
|
github.com/sagernet/sing-shadowsocks v0.2.8 h1:PURj5PRoAkqeHh2ZW205RWzN9E9RtKCVCzByXruQWfE=
|
||||||
github.com/sagernet/sing-quic v0.4.1-0.20250423030647-0eb05f373a76/go.mod h1:tqPa0/Wqa19MkkSlKVZZX5sHxtiDR9BROcn4ufcbVdY=
|
github.com/sagernet/sing-shadowsocks v0.2.8/go.mod h1:lo7TWEMDcN5/h5B8S0ew+r78ZODn6SwVaFhvB6H+PTI=
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.7 h1:zaopR1tbHEw5Nk6FAkM05wCslV6ahVegEZaKMv9ipx8=
|
github.com/sagernet/sing-shadowsocks2 v0.2.1 h1:dWV9OXCeFPuYGHb6IRqlSptVnSzOelnqqs2gQ2/Qioo=
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.7/go.mod h1:0rIKJZBR65Qi0zwdKezt4s57y/Tl1ofkaq6NlkzVuyE=
|
github.com/sagernet/sing-shadowsocks2 v0.2.1/go.mod h1:RnXS0lExcDAovvDeniJ4IKa2IuChrdipolPYWBv9hWQ=
|
||||||
github.com/sagernet/sing-shadowsocks2 v0.2.0 h1:wpZNs6wKnR7mh1wV9OHwOyUr21VkS3wKFHi+8XwgADg=
|
github.com/sagernet/sing-shadowtls v0.2.1-0.20250503051639-fcd445d33c11 h1:tK+75l64tm9WvEFrYRE1t0YxoFdWQqw/h7Uhzj0vJ+w=
|
||||||
github.com/sagernet/sing-shadowsocks2 v0.2.0/go.mod h1:RnXS0lExcDAovvDeniJ4IKa2IuChrdipolPYWBv9hWQ=
|
github.com/sagernet/sing-shadowtls v0.2.1-0.20250503051639-fcd445d33c11/go.mod h1:sWqKnGlMipCHaGsw1sTTlimyUpgzP4WP3pjhCsYt9oA=
|
||||||
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-tun v0.6.6-0.20250428031943-0686f8c4f210 h1:6H4BZaTqKI3YcDMyTV3E576LuJM4S4wY99xoq2T1ECw=
|
github.com/sagernet/sing-tun v0.6.6-0.20250428031943-0686f8c4f210 h1:6H4BZaTqKI3YcDMyTV3E576LuJM4S4wY99xoq2T1ECw=
|
||||||
github.com/sagernet/sing-tun v0.6.6-0.20250428031943-0686f8c4f210/go.mod h1:fisFCbC4Vfb6HqQNcwPJi2CDK2bf0Xapyz3j3t4cnHE=
|
github.com/sagernet/sing-tun v0.6.6-0.20250428031943-0686f8c4f210/go.mod h1:fisFCbC4Vfb6HqQNcwPJi2CDK2bf0Xapyz3j3t4cnHE=
|
||||||
github.com/sagernet/sing-vmess v0.2.1 h1:6izHC2+B68aQCxTagki6eZZc+g5eh4dYwxOV5a2Lhug=
|
github.com/sagernet/sing-vmess v0.2.4-0.20250605032146-38cc72672c88 h1:0pVm8sPOel+BoiCddW3pV3cKDKEaSioVTYDdTSKjyFI=
|
||||||
github.com/sagernet/sing-vmess v0.2.1/go.mod h1:jDAZ0A0St1zVRkyvhAPRySOFfhC+4SQtO5VYyeFotgA=
|
github.com/sagernet/sing-vmess v0.2.4-0.20250605032146-38cc72672c88/go.mod h1:IL8Rr+EGwuqijszZkNrEFTQDKhilEpkqFqOlvdpS6/w=
|
||||||
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ=
|
github.com/sagernet/smux v1.5.34-mod.2 h1:gkmBjIjlJ2zQKpLigOkFur5kBKdV6bNRoFu2WkltRQ4=
|
||||||
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7/go.mod h1:FP9X2xjT/Az1EsG/orYYoC+5MojWnuI7hrffz8fGwwo=
|
github.com/sagernet/smux v1.5.34-mod.2/go.mod h1:0KW0+R+ycvA2INW4gbsd7BNyg+HEfLIAxa5N02/28Zc=
|
||||||
github.com/sagernet/tailscale v1.80.3-mod.4 h1:9UgYq8m9mwX5dbTbueVxbRh+bq7AayxemJGM2PkJQnE=
|
github.com/sagernet/tailscale v1.80.3-mod.5 h1:7V7z+p2C//TGtff20pPnDCt3qP6uFyY62peJoKF9z/A=
|
||||||
github.com/sagernet/tailscale v1.80.3-mod.4/go.mod h1:EBxXsWu4OH2ELbQLq32WoBeIubG8KgDrg4/Oaxjs6lI=
|
github.com/sagernet/tailscale v1.80.3-mod.5/go.mod h1:EBxXsWu4OH2ELbQLq32WoBeIubG8KgDrg4/Oaxjs6lI=
|
||||||
github.com/sagernet/utls v1.6.7 h1:Ep3+aJ8FUGGta+II2IEVNUc3EDhaRCZINWkj/LloIA8=
|
|
||||||
github.com/sagernet/utls v1.6.7/go.mod h1:Uua1TKO/FFuAhLr9rkaVnnrTmmiItzDjv1BUb2+ERwM=
|
|
||||||
github.com/sagernet/wireguard-go v0.0.1-beta.7 h1:ltgBwYHfr+9Wz1eG59NiWnHrYEkDKHG7otNZvu85DXI=
|
github.com/sagernet/wireguard-go v0.0.1-beta.7 h1:ltgBwYHfr+9Wz1eG59NiWnHrYEkDKHG7otNZvu85DXI=
|
||||||
github.com/sagernet/wireguard-go v0.0.1-beta.7/go.mod h1:jGXij2Gn2wbrWuYNUmmNhf1dwcZtvyAvQoe8Xd8MbUo=
|
github.com/sagernet/wireguard-go v0.0.1-beta.7/go.mod h1:jGXij2Gn2wbrWuYNUmmNhf1dwcZtvyAvQoe8Xd8MbUo=
|
||||||
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/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
|
github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
|
||||||
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
|
github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
|
||||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
|
||||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
|
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||||
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.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
|
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/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
github.com/tailscale/certstore v0.1.1-0.20231202035212-d3fa0460f47e h1:PtWT87weP5LWHEY//SWsYkSO3RWRZo4OSWagh3YD2vQ=
|
github.com/tailscale/certstore v0.1.1-0.20231202035212-d3fa0460f47e h1:PtWT87weP5LWHEY//SWsYkSO3RWRZo4OSWagh3YD2vQ=
|
||||||
@ -233,8 +228,8 @@ github.com/tc-hib/winres v0.2.1/go.mod h1:C/JaNhH3KBvhNKVbvdlDWkbMDO9H4fKKDaN7/0
|
|||||||
github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701 h1:pyC9PaHYZFgEKFdlp3G8RaCKgVpHZnecvArXvPXcFkM=
|
github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701 h1:pyC9PaHYZFgEKFdlp3G8RaCKgVpHZnecvArXvPXcFkM=
|
||||||
github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701/go.mod h1:P3a5rG4X7tI17Nn3aOIAYr5HbIMukwXG0urG0WuL8OA=
|
github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701/go.mod h1:P3a5rG4X7tI17Nn3aOIAYr5HbIMukwXG0urG0WuL8OA=
|
||||||
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
||||||
github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8=
|
github.com/vishvananda/netns v0.0.5 h1:DfiHV+j8bA32MFM7bfEunvT8IAqQ/NzSJHtcmW5zdEY=
|
||||||
github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
|
github.com/vishvananda/netns v0.0.5/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
|
||||||
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
||||||
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
||||||
github.com/zeebo/assert v1.1.0 h1:hU1L1vLTHsnO8x8c9KAR5GmM5QscxHg5RNU5z5qbUWY=
|
github.com/zeebo/assert v1.1.0 h1:hU1L1vLTHsnO8x8c9KAR5GmM5QscxHg5RNU5z5qbUWY=
|
||||||
@ -243,16 +238,18 @@ github.com/zeebo/blake3 v0.2.4 h1:KYQPkhpRtcqh0ssGYcKLG1JYvddkEA8QwCM/yBqhaZI=
|
|||||||
github.com/zeebo/blake3 v0.2.4/go.mod h1:7eeQ6d2iXWRGF6npfaxl2CU+xy2Fjo2gxeyZGCRUjcE=
|
github.com/zeebo/blake3 v0.2.4/go.mod h1:7eeQ6d2iXWRGF6npfaxl2CU+xy2Fjo2gxeyZGCRUjcE=
|
||||||
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.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U=
|
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
||||||
go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg=
|
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||||
go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M=
|
go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY=
|
||||||
go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8=
|
go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI=
|
||||||
go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4=
|
go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ=
|
||||||
go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU=
|
go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE=
|
||||||
go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU=
|
go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A=
|
||||||
go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ=
|
go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU=
|
||||||
go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM=
|
go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk=
|
||||||
go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8=
|
go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w=
|
||||||
|
go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k=
|
||||||
|
go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE=
|
||||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||||
@ -266,21 +263,21 @@ go4.org/mem v0.0.0-20240501181205-ae6ca9944745/go.mod h1:reUoABIJ9ikfM5sgtSF3Wus
|
|||||||
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-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.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus=
|
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
|
||||||
golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
|
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
|
||||||
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 h1:yqrTHse8TCMW1M1ZCP+VAR/l0kKxwaAIqN/il7x4voA=
|
golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 h1:y5zboxd6LQAqYIhHnB48p0ByQ/GnQx2BE33L8BOHQkI=
|
||||||
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8/go.mod h1:tujkw807nyEEAamNbDrEGzRav+ilXA7PCRAd6xsmwiU=
|
golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6/go.mod h1:U6Lno4MTRCDY+Ba7aCcauB9T60gsv5s4ralQzP72ZoQ=
|
||||||
golang.org/x/image v0.23.0 h1:HseQ7c2OpPKTPVzNjG5fwJsOTCiiwS4QdsYi5XU6H68=
|
golang.org/x/image v0.23.0 h1:HseQ7c2OpPKTPVzNjG5fwJsOTCiiwS4QdsYi5XU6H68=
|
||||||
golang.org/x/image v0.23.0/go.mod h1:wJJBTdLfCCf3tiHa1fNxpZmUI4mmoZvwMCPP0ddoNKY=
|
golang.org/x/image v0.23.0/go.mod h1:wJJBTdLfCCf3tiHa1fNxpZmUI4mmoZvwMCPP0ddoNKY=
|
||||||
golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM=
|
golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
|
||||||
golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
|
||||||
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.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
|
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
|
||||||
golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
|
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
|
golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
|
||||||
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||||
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-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/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=
|
||||||
@ -288,21 +285,21 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20220817070843-5a390386f1f2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220817070843-5a390386f1f2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.1.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.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
|
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
||||||
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||||
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.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU=
|
golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg=
|
||||||
golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s=
|
golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ=
|
||||||
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.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
|
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
|
||||||
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
|
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
|
||||||
golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
|
golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
|
||||||
golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
golang.org/x/time v0.9.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.29.0 h1:Xx0h3TtM9rzQpQuR4dKLrdglAmCEN5Oi+P74JdhdzXE=
|
golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc=
|
||||||
golang.org/x/tools v0.29.0/go.mod h1:KMQVMRsVxU6nHCFXrBPhDB8XncLNLM0lIy/F14RP588=
|
golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
@ -312,12 +309,12 @@ golang.zx2c4.com/wireguard/wgctrl v0.0.0-20241231184526-a9ab2273dd10 h1:3GDAcqdI
|
|||||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20241231184526-a9ab2273dd10/go.mod h1:T97yPqesLiNrOYxkwmhMI0ZIlJDm+p0PMR8eRVeR5tQ=
|
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20241231184526-a9ab2273dd10/go.mod h1:T97yPqesLiNrOYxkwmhMI0ZIlJDm+p0PMR8eRVeR5tQ=
|
||||||
golang.zx2c4.com/wireguard/windows v0.5.3 h1:On6j2Rpn3OEMXqBq00QEDC7bWSZrPIHKIus8eIuExIE=
|
golang.zx2c4.com/wireguard/windows v0.5.3 h1:On6j2Rpn3OEMXqBq00QEDC7bWSZrPIHKIus8eIuExIE=
|
||||||
golang.zx2c4.com/wireguard/windows v0.5.3/go.mod h1:9TEe8TJmtwyQebdFwAkEWOPr3prrtqm+REGFifP60hI=
|
golang.zx2c4.com/wireguard/windows v0.5.3/go.mod h1:9TEe8TJmtwyQebdFwAkEWOPr3prrtqm+REGFifP60hI=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a h1:51aaUVRocpvUOSQKM6Q7VuoaktNIaMCLuhZB6DKksq4=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a/go.mod h1:uRxBH1mhmO8PGhU89cMcHaXKZqO+OfakD8QQO0oYwlQ=
|
||||||
google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ=
|
google.golang.org/grpc v1.72.0 h1:S7UkcVa60b5AAQTaO6ZKamFp1zMZSU0fGDK2WZLbBnM=
|
||||||
google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw=
|
google.golang.org/grpc v1.72.0/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM=
|
||||||
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
|
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
||||||
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
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/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa3CI79GS0ol3YnhVnKP89i0kNg=
|
gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa3CI79GS0ol3YnhVnKP89i0kNg=
|
||||||
|
@ -3,10 +3,12 @@ package include
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing-box"
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
"github.com/sagernet/sing-box/adapter/endpoint"
|
"github.com/sagernet/sing-box/adapter/endpoint"
|
||||||
"github.com/sagernet/sing-box/adapter/inbound"
|
"github.com/sagernet/sing-box/adapter/inbound"
|
||||||
"github.com/sagernet/sing-box/adapter/outbound"
|
"github.com/sagernet/sing-box/adapter/outbound"
|
||||||
|
"github.com/sagernet/sing-box/adapter/service"
|
||||||
C "github.com/sagernet/sing-box/constant"
|
C "github.com/sagernet/sing-box/constant"
|
||||||
"github.com/sagernet/sing-box/dns"
|
"github.com/sagernet/sing-box/dns"
|
||||||
"github.com/sagernet/sing-box/dns/transport"
|
"github.com/sagernet/sing-box/dns/transport"
|
||||||
@ -33,9 +35,15 @@ import (
|
|||||||
"github.com/sagernet/sing-box/protocol/tun"
|
"github.com/sagernet/sing-box/protocol/tun"
|
||||||
"github.com/sagernet/sing-box/protocol/vless"
|
"github.com/sagernet/sing-box/protocol/vless"
|
||||||
"github.com/sagernet/sing-box/protocol/vmess"
|
"github.com/sagernet/sing-box/protocol/vmess"
|
||||||
|
"github.com/sagernet/sing-box/service/resolved"
|
||||||
|
"github.com/sagernet/sing-box/service/ssmapi"
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func Context(ctx context.Context) context.Context {
|
||||||
|
return box.Context(ctx, InboundRegistry(), OutboundRegistry(), EndpointRegistry(), DNSTransportRegistry(), ServiceRegistry())
|
||||||
|
}
|
||||||
|
|
||||||
func InboundRegistry() *inbound.Registry {
|
func InboundRegistry() *inbound.Registry {
|
||||||
registry := inbound.NewRegistry()
|
registry := inbound.NewRegistry()
|
||||||
|
|
||||||
@ -110,6 +118,7 @@ func DNSTransportRegistry() *dns.TransportRegistry {
|
|||||||
hosts.RegisterTransport(registry)
|
hosts.RegisterTransport(registry)
|
||||||
local.RegisterTransport(registry)
|
local.RegisterTransport(registry)
|
||||||
fakeip.RegisterTransport(registry)
|
fakeip.RegisterTransport(registry)
|
||||||
|
resolved.RegisterTransport(registry)
|
||||||
|
|
||||||
registerQUICTransports(registry)
|
registerQUICTransports(registry)
|
||||||
registerDHCPTransport(registry)
|
registerDHCPTransport(registry)
|
||||||
@ -118,6 +127,17 @@ func DNSTransportRegistry() *dns.TransportRegistry {
|
|||||||
return registry
|
return registry
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ServiceRegistry() *service.Registry {
|
||||||
|
registry := service.NewRegistry()
|
||||||
|
|
||||||
|
resolved.RegisterService(registry)
|
||||||
|
ssmapi.RegisterService(registry)
|
||||||
|
|
||||||
|
registerDERPService(registry)
|
||||||
|
|
||||||
|
return registry
|
||||||
|
}
|
||||||
|
|
||||||
func registerStubForRemovedInbounds(registry *inbound.Registry) {
|
func registerStubForRemovedInbounds(registry *inbound.Registry) {
|
||||||
inbound.Register[option.ShadowsocksInboundOptions](registry, C.TypeShadowsocksR, func(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.ShadowsocksInboundOptions) (adapter.Inbound, error) {
|
inbound.Register[option.ShadowsocksInboundOptions](registry, C.TypeShadowsocksR, func(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.ShadowsocksInboundOptions) (adapter.Inbound, error) {
|
||||||
return nil, E.New("ShadowsocksR is deprecated and removed in sing-box 1.6.0")
|
return nil, E.New("ShadowsocksR is deprecated and removed in sing-box 1.6.0")
|
||||||
|
@ -4,8 +4,10 @@ package include
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/sagernet/sing-box/adapter/endpoint"
|
"github.com/sagernet/sing-box/adapter/endpoint"
|
||||||
|
"github.com/sagernet/sing-box/adapter/service"
|
||||||
"github.com/sagernet/sing-box/dns"
|
"github.com/sagernet/sing-box/dns"
|
||||||
"github.com/sagernet/sing-box/protocol/tailscale"
|
"github.com/sagernet/sing-box/protocol/tailscale"
|
||||||
|
"github.com/sagernet/sing-box/service/derp"
|
||||||
)
|
)
|
||||||
|
|
||||||
func registerTailscaleEndpoint(registry *endpoint.Registry) {
|
func registerTailscaleEndpoint(registry *endpoint.Registry) {
|
||||||
@ -15,3 +17,7 @@ func registerTailscaleEndpoint(registry *endpoint.Registry) {
|
|||||||
func registerTailscaleTransport(registry *dns.TransportRegistry) {
|
func registerTailscaleTransport(registry *dns.TransportRegistry) {
|
||||||
tailscale.RegistryTransport(registry)
|
tailscale.RegistryTransport(registry)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func registerDERPService(registry *service.Registry) {
|
||||||
|
derp.Register(registry)
|
||||||
|
}
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
"github.com/sagernet/sing-box/adapter/endpoint"
|
"github.com/sagernet/sing-box/adapter/endpoint"
|
||||||
|
"github.com/sagernet/sing-box/adapter/service"
|
||||||
C "github.com/sagernet/sing-box/constant"
|
C "github.com/sagernet/sing-box/constant"
|
||||||
"github.com/sagernet/sing-box/dns"
|
"github.com/sagernet/sing-box/dns"
|
||||||
"github.com/sagernet/sing-box/log"
|
"github.com/sagernet/sing-box/log"
|
||||||
@ -25,3 +26,9 @@ func registerTailscaleTransport(registry *dns.TransportRegistry) {
|
|||||||
return nil, E.New(`Tailscale is not included in this build, rebuild with -tags with_tailscale`)
|
return nil, E.New(`Tailscale is not included in this build, rebuild with -tags with_tailscale`)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func registerDERPService(registry *service.Registry) {
|
||||||
|
service.Register[option.DERPServiceOptions](registry, C.TypeDERP, func(ctx context.Context, logger log.ContextLogger, tag string, options option.DERPServiceOptions) (adapter.Service, error) {
|
||||||
|
return nil, E.New(`DERP is not included in this build, rebuild with -tags with_tailscale`)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
@ -94,6 +94,7 @@ nav:
|
|||||||
- DHCP: configuration/dns/server/dhcp.md
|
- DHCP: configuration/dns/server/dhcp.md
|
||||||
- FakeIP: configuration/dns/server/fakeip.md
|
- FakeIP: configuration/dns/server/fakeip.md
|
||||||
- Tailscale: configuration/dns/server/tailscale.md
|
- Tailscale: configuration/dns/server/tailscale.md
|
||||||
|
- Resolved: configuration/dns/server/resolved.md
|
||||||
- DNS Rule: configuration/dns/rule.md
|
- DNS Rule: configuration/dns/rule.md
|
||||||
- DNS Rule Action: configuration/dns/rule_action.md
|
- DNS Rule Action: configuration/dns/rule_action.md
|
||||||
- FakeIP: configuration/dns/fakeip.md
|
- FakeIP: configuration/dns/fakeip.md
|
||||||
@ -169,6 +170,11 @@ nav:
|
|||||||
- DNS: configuration/outbound/dns.md
|
- DNS: configuration/outbound/dns.md
|
||||||
- Selector: configuration/outbound/selector.md
|
- Selector: configuration/outbound/selector.md
|
||||||
- URLTest: configuration/outbound/urltest.md
|
- URLTest: configuration/outbound/urltest.md
|
||||||
|
- Service:
|
||||||
|
- configuration/service/index.md
|
||||||
|
- DERP: configuration/service/derp.md
|
||||||
|
- Resolved: configuration/service/resolved.md
|
||||||
|
- SSM API: configuration/service/ssm-api.md
|
||||||
markdown_extensions:
|
markdown_extensions:
|
||||||
- pymdownx.inlinehilite
|
- pymdownx.inlinehilite
|
||||||
- pymdownx.snippets
|
- pymdownx.snippets
|
||||||
|
@ -121,7 +121,6 @@ type LegacyDNSFakeIPOptions struct {
|
|||||||
type DNSTransportOptionsRegistry interface {
|
type DNSTransportOptionsRegistry interface {
|
||||||
CreateOptions(transportType string) (any, bool)
|
CreateOptions(transportType string) (any, bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
type _DNSServerOptions struct {
|
type _DNSServerOptions struct {
|
||||||
Type string `json:"type,omitempty"`
|
Type string `json:"type,omitempty"`
|
||||||
Tag string `json:"tag,omitempty"`
|
Tag string `json:"tag,omitempty"`
|
||||||
|
@ -32,11 +32,11 @@ func (h *Endpoint) UnmarshalJSONContext(ctx context.Context, content []byte) err
|
|||||||
}
|
}
|
||||||
registry := service.FromContext[EndpointOptionsRegistry](ctx)
|
registry := service.FromContext[EndpointOptionsRegistry](ctx)
|
||||||
if registry == nil {
|
if registry == nil {
|
||||||
return E.New("missing Endpoint fields registry in context")
|
return E.New("missing endpoint fields registry in context")
|
||||||
}
|
}
|
||||||
options, loaded := registry.CreateOptions(h.Type)
|
options, loaded := registry.CreateOptions(h.Type)
|
||||||
if !loaded {
|
if !loaded {
|
||||||
return E.New("unknown inbound type: ", h.Type)
|
return E.New("unknown endpoint type: ", h.Type)
|
||||||
}
|
}
|
||||||
err = badjson.UnmarshallExcludedContext(ctx, content, (*_Endpoint)(h), options)
|
err = badjson.UnmarshallExcludedContext(ctx, content, (*_Endpoint)(h), options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -34,7 +34,7 @@ func (h *Inbound) UnmarshalJSONContext(ctx context.Context, content []byte) erro
|
|||||||
}
|
}
|
||||||
registry := service.FromContext[InboundOptionsRegistry](ctx)
|
registry := service.FromContext[InboundOptionsRegistry](ctx)
|
||||||
if registry == nil {
|
if registry == nil {
|
||||||
return E.New("missing Inbound fields registry in context")
|
return E.New("missing inbound fields registry in context")
|
||||||
}
|
}
|
||||||
options, loaded := registry.CreateOptions(h.Type)
|
options, loaded := registry.CreateOptions(h.Type)
|
||||||
if !loaded {
|
if !loaded {
|
||||||
@ -61,6 +61,10 @@ type InboundOptions struct {
|
|||||||
type ListenOptions struct {
|
type ListenOptions struct {
|
||||||
Listen *badoption.Addr `json:"listen,omitempty"`
|
Listen *badoption.Addr `json:"listen,omitempty"`
|
||||||
ListenPort uint16 `json:"listen_port,omitempty"`
|
ListenPort uint16 `json:"listen_port,omitempty"`
|
||||||
|
BindInterface string `json:"bind_interface,omitempty"`
|
||||||
|
RoutingMark FwMark `json:"routing_mark,omitempty"`
|
||||||
|
ReuseAddr bool `json:"reuse_addr,omitempty"`
|
||||||
|
NetNs string `json:"netns,omitempty"`
|
||||||
TCPKeepAlive badoption.Duration `json:"tcp_keep_alive,omitempty"`
|
TCPKeepAlive badoption.Duration `json:"tcp_keep_alive,omitempty"`
|
||||||
TCPKeepAliveInterval badoption.Duration `json:"tcp_keep_alive_interval,omitempty"`
|
TCPKeepAliveInterval badoption.Duration `json:"tcp_keep_alive_interval,omitempty"`
|
||||||
TCPFastOpen bool `json:"tcp_fast_open,omitempty"`
|
TCPFastOpen bool `json:"tcp_fast_open,omitempty"`
|
||||||
@ -68,7 +72,6 @@ type ListenOptions struct {
|
|||||||
UDPFragment *bool `json:"udp_fragment,omitempty"`
|
UDPFragment *bool `json:"udp_fragment,omitempty"`
|
||||||
UDPFragmentDefault bool `json:"-"`
|
UDPFragmentDefault bool `json:"-"`
|
||||||
UDPTimeout UDPTimeoutCompat `json:"udp_timeout,omitempty"`
|
UDPTimeout UDPTimeoutCompat `json:"udp_timeout,omitempty"`
|
||||||
NetNs string `json:"netns,omitempty"`
|
|
||||||
|
|
||||||
// Deprecated: removed
|
// Deprecated: removed
|
||||||
ProxyProtocol bool `json:"proxy_protocol,omitempty"`
|
ProxyProtocol bool `json:"proxy_protocol,omitempty"`
|
||||||
|
@ -19,6 +19,7 @@ type _Options struct {
|
|||||||
Inbounds []Inbound `json:"inbounds,omitempty"`
|
Inbounds []Inbound `json:"inbounds,omitempty"`
|
||||||
Outbounds []Outbound `json:"outbounds,omitempty"`
|
Outbounds []Outbound `json:"outbounds,omitempty"`
|
||||||
Route *RouteOptions `json:"route,omitempty"`
|
Route *RouteOptions `json:"route,omitempty"`
|
||||||
|
Services []Service `json:"services,omitempty"`
|
||||||
Experimental *ExperimentalOptions `json:"experimental,omitempty"`
|
Experimental *ExperimentalOptions `json:"experimental,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ func (h *Outbound) UnmarshalJSONContext(ctx context.Context, content []byte) err
|
|||||||
return E.New("missing outbound options registry in context")
|
return E.New("missing outbound options registry in context")
|
||||||
}
|
}
|
||||||
switch h.Type {
|
switch h.Type {
|
||||||
case C.TypeBlock, C.TypeDNS:
|
case C.TypeDNS:
|
||||||
deprecated.Report(ctx, deprecated.OptionSpecialOutbounds)
|
deprecated.Report(ctx, deprecated.OptionSpecialOutbounds)
|
||||||
}
|
}
|
||||||
options, loaded := registry.CreateOptions(h.Type)
|
options, loaded := registry.CreateOptions(h.Type)
|
||||||
@ -72,12 +72,12 @@ type DialerOptions struct {
|
|||||||
ProtectPath string `json:"protect_path,omitempty"`
|
ProtectPath string `json:"protect_path,omitempty"`
|
||||||
RoutingMark FwMark `json:"routing_mark,omitempty"`
|
RoutingMark FwMark `json:"routing_mark,omitempty"`
|
||||||
ReuseAddr bool `json:"reuse_addr,omitempty"`
|
ReuseAddr bool `json:"reuse_addr,omitempty"`
|
||||||
|
NetNs string `json:"netns,omitempty"`
|
||||||
ConnectTimeout badoption.Duration `json:"connect_timeout,omitempty"`
|
ConnectTimeout badoption.Duration `json:"connect_timeout,omitempty"`
|
||||||
TCPFastOpen bool `json:"tcp_fast_open,omitempty"`
|
TCPFastOpen bool `json:"tcp_fast_open,omitempty"`
|
||||||
TCPMultiPath bool `json:"tcp_multi_path,omitempty"`
|
TCPMultiPath bool `json:"tcp_multi_path,omitempty"`
|
||||||
UDPFragment *bool `json:"udp_fragment,omitempty"`
|
UDPFragment *bool `json:"udp_fragment,omitempty"`
|
||||||
UDPFragmentDefault bool `json:"-"`
|
UDPFragmentDefault bool `json:"-"`
|
||||||
NetNs string `json:"netns,omitempty"`
|
|
||||||
DomainResolver *DomainResolveOptions `json:"domain_resolver,omitempty"`
|
DomainResolver *DomainResolveOptions `json:"domain_resolver,omitempty"`
|
||||||
NetworkStrategy *NetworkStrategy `json:"network_strategy,omitempty"`
|
NetworkStrategy *NetworkStrategy `json:"network_strategy,omitempty"`
|
||||||
NetworkType badoption.Listable[InterfaceType] `json:"network_type,omitempty"`
|
NetworkType badoption.Listable[InterfaceType] `json:"network_type,omitempty"`
|
||||||
|
49
option/resolved.go
Normal file
49
option/resolved.go
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
package option
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/netip"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing/common"
|
||||||
|
"github.com/sagernet/sing/common/json"
|
||||||
|
"github.com/sagernet/sing/common/json/badoption"
|
||||||
|
)
|
||||||
|
|
||||||
|
type _ResolvedServiceOptions struct {
|
||||||
|
ListenOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
type ResolvedServiceOptions _ResolvedServiceOptions
|
||||||
|
|
||||||
|
func (r ResolvedServiceOptions) MarshalJSONContext(ctx context.Context) ([]byte, error) {
|
||||||
|
if r.Listen != nil && netip.Addr(*r.Listen) == (netip.AddrFrom4([4]byte{127, 0, 0, 53})) {
|
||||||
|
r.Listen = nil
|
||||||
|
}
|
||||||
|
if r.ListenPort == 53 {
|
||||||
|
r.ListenPort = 0
|
||||||
|
}
|
||||||
|
return json.MarshalContext(ctx, (*_ResolvedServiceOptions)(&r))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *ResolvedServiceOptions) UnmarshalJSONContext(ctx context.Context, bytes []byte) error {
|
||||||
|
err := json.UnmarshalContextDisallowUnknownFields(ctx, bytes, (*_ResolvedServiceOptions)(r))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if r.Listen == nil {
|
||||||
|
r.Listen = (*badoption.Addr)(common.Ptr(netip.AddrFrom4([4]byte{127, 0, 0, 53})))
|
||||||
|
}
|
||||||
|
if r.ListenPort == 0 {
|
||||||
|
r.ListenPort = 53
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type ResolvedDNSServerOptions struct {
|
||||||
|
Service string `json:"service"`
|
||||||
|
AcceptDefaultResolvers bool `json:"accept_default_resolvers,omitempty"`
|
||||||
|
// NDots int `json:"ndots,omitempty"`
|
||||||
|
// Timeout badoption.Duration `json:"timeout,omitempty"`
|
||||||
|
// Attempts int `json:"attempts,omitempty"`
|
||||||
|
// Rotate bool `json:"rotate,omitempty"`
|
||||||
|
}
|
@ -158,6 +158,7 @@ type RawRouteOptionsActionOptions struct {
|
|||||||
|
|
||||||
TLSFragment bool `json:"tls_fragment,omitempty"`
|
TLSFragment bool `json:"tls_fragment,omitempty"`
|
||||||
TLSFragmentFallbackDelay badoption.Duration `json:"tls_fragment_fallback_delay,omitempty"`
|
TLSFragmentFallbackDelay badoption.Duration `json:"tls_fragment_fallback_delay,omitempty"`
|
||||||
|
TLSRecordFragment bool `json:"tls_record_fragment,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type RouteOptionsActionOptions RawRouteOptionsActionOptions
|
type RouteOptionsActionOptions RawRouteOptionsActionOptions
|
||||||
@ -170,6 +171,9 @@ func (r *RouteOptionsActionOptions) UnmarshalJSON(data []byte) error {
|
|||||||
if *r == (RouteOptionsActionOptions{}) {
|
if *r == (RouteOptionsActionOptions{}) {
|
||||||
return E.New("empty route option action")
|
return E.New("empty route option action")
|
||||||
}
|
}
|
||||||
|
if r.TLSFragment && r.TLSRecordFragment {
|
||||||
|
return E.New("`tls_fragment` and `tls_record_fragment` are mutually exclusive")
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package option
|
package option
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"net/url"
|
||||||
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
C "github.com/sagernet/sing-box/constant"
|
C "github.com/sagernet/sing-box/constant"
|
||||||
@ -27,6 +29,18 @@ type _RuleSet struct {
|
|||||||
type RuleSet _RuleSet
|
type RuleSet _RuleSet
|
||||||
|
|
||||||
func (r RuleSet) MarshalJSON() ([]byte, error) {
|
func (r RuleSet) MarshalJSON() ([]byte, error) {
|
||||||
|
if r.Type != C.RuleSetTypeInline {
|
||||||
|
var defaultFormat string
|
||||||
|
switch r.Type {
|
||||||
|
case C.RuleSetTypeLocal:
|
||||||
|
defaultFormat = ruleSetDefaultFormat(r.LocalOptions.Path)
|
||||||
|
case C.RuleSetTypeRemote:
|
||||||
|
defaultFormat = ruleSetDefaultFormat(r.RemoteOptions.URL)
|
||||||
|
}
|
||||||
|
if r.Format == defaultFormat {
|
||||||
|
r.Format = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
var v any
|
var v any
|
||||||
switch r.Type {
|
switch r.Type {
|
||||||
case "", C.RuleSetTypeInline:
|
case "", C.RuleSetTypeInline:
|
||||||
@ -62,7 +76,19 @@ func (r *RuleSet) UnmarshalJSON(bytes []byte) error {
|
|||||||
default:
|
default:
|
||||||
return E.New("unknown rule-set type: " + r.Type)
|
return E.New("unknown rule-set type: " + r.Type)
|
||||||
}
|
}
|
||||||
|
err = badjson.UnmarshallExcluded(bytes, (*_RuleSet)(r), v)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
if r.Type != C.RuleSetTypeInline {
|
if r.Type != C.RuleSetTypeInline {
|
||||||
|
if r.Format == "" {
|
||||||
|
switch r.Type {
|
||||||
|
case C.RuleSetTypeLocal:
|
||||||
|
r.Format = ruleSetDefaultFormat(r.LocalOptions.Path)
|
||||||
|
case C.RuleSetTypeRemote:
|
||||||
|
r.Format = ruleSetDefaultFormat(r.RemoteOptions.URL)
|
||||||
|
}
|
||||||
|
}
|
||||||
switch r.Format {
|
switch r.Format {
|
||||||
case "":
|
case "":
|
||||||
return E.New("missing format")
|
return E.New("missing format")
|
||||||
@ -73,13 +99,23 @@ func (r *RuleSet) UnmarshalJSON(bytes []byte) error {
|
|||||||
} else {
|
} else {
|
||||||
r.Format = ""
|
r.Format = ""
|
||||||
}
|
}
|
||||||
err = badjson.UnmarshallExcluded(bytes, (*_RuleSet)(r), v)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ruleSetDefaultFormat(path string) string {
|
||||||
|
if pathURL, err := url.Parse(path); err == nil {
|
||||||
|
path = pathURL.Path
|
||||||
|
}
|
||||||
|
switch filepath.Ext(path) {
|
||||||
|
case ".json":
|
||||||
|
return C.RuleSetFormatSource
|
||||||
|
case ".srs":
|
||||||
|
return C.RuleSetFormatBinary
|
||||||
|
default:
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type LocalRuleSet struct {
|
type LocalRuleSet struct {
|
||||||
Path string `json:"path,omitempty"`
|
Path string `json:"path,omitempty"`
|
||||||
}
|
}
|
||||||
|
47
option/service.go
Normal file
47
option/service.go
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
package option
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
|
"github.com/sagernet/sing/common/json"
|
||||||
|
"github.com/sagernet/sing/common/json/badjson"
|
||||||
|
"github.com/sagernet/sing/service"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ServiceOptionsRegistry interface {
|
||||||
|
CreateOptions(serviceType string) (any, bool)
|
||||||
|
}
|
||||||
|
|
||||||
|
type _Service struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
Tag string `json:"tag,omitempty"`
|
||||||
|
Options any `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Service _Service
|
||||||
|
|
||||||
|
func (h *Service) MarshalJSONContext(ctx context.Context) ([]byte, error) {
|
||||||
|
return badjson.MarshallObjectsContext(ctx, (*_Service)(h), h.Options)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Service) UnmarshalJSONContext(ctx context.Context, content []byte) error {
|
||||||
|
err := json.UnmarshalContext(ctx, content, (*_Service)(h))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
registry := service.FromContext[ServiceOptionsRegistry](ctx)
|
||||||
|
if registry == nil {
|
||||||
|
return E.New("missing service fields registry in context")
|
||||||
|
}
|
||||||
|
options, loaded := registry.CreateOptions(h.Type)
|
||||||
|
if !loaded {
|
||||||
|
return E.New("unknown inbound type: ", h.Type)
|
||||||
|
}
|
||||||
|
err = badjson.UnmarshallExcludedContext(ctx, content, (*_Service)(h), options)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
h.Options = options
|
||||||
|
return nil
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user