Compare commits

..

22 Commits

Author SHA1 Message Date
Shtorm
dec3f0713f Update sing-box core 2026-08-09 16:32:34 +03:00
Shtorm
21a23d7488 Fix OpenStream dropping connection errors 2026-08-09 15:03:14 +03:00
Shtorm
cb664d1a4b Fix DNS Fallback 2026-08-09 15:01:36 +03:00
世界
45ca32dcb9 Bump version 2026-08-09 14:57:01 +08:00
世界
93df3ef612 Fix slow open connection declaring lazy headroom 2026-08-09 13:13:24 +08:00
Shtorm
f682ceb8e2 Update packages 2026-08-08 22:56:39 +03:00
Shtorm
545424b86b Fix wireguard 2026-08-08 20:49:55 +03:00
Shtorm
1d10636a5f Fix mieru outbound with fqdn server address 2026-08-08 20:46:52 +03:00
Shtorm
9f34cdb2f8 Fix DefaultGateway 2026-08-08 20:43:13 +03:00
Shtorm
da4c532efb Merge branch 'extended' of https://github.com/shtorm-7/sing-box-extended into extended 2026-08-08 10:33:36 +03:00
Shtorm
97c981764d Add DefaultGateway 2026-08-08 10:33:31 +03:00
Shtorm
3310474137 Fix limiters 2026-08-08 10:11:10 +03:00
Shtorm
6c81ddd00f Fix Wireguard options 2026-08-08 10:11:01 +03:00
Shtorm
da50e2969d Fix XHTTP dialing 2026-08-08 10:10:05 +03:00
世界
7afc0aa2ba Update naiveproxy to v150.0.7871.63-1 2026-08-08 11:27:55 +08:00
Shtorm
1e35987658 Fix typo in Rmux description in README.md
Signed-off-by: Shtorm <108103062+shtorm-7@users.noreply.github.com>
2026-08-07 06:33:09 +03:00
Shtorm
44c9c36c65 Fix typo
Signed-off-by: Shtorm <108103062+shtorm-7@users.noreply.github.com>
2026-08-06 17:14:08 +03:00
Ofek Lev
4c02326989 Fix route_address_set duplicated IP sets causing route creation failure 2026-08-05 14:13:43 +08:00
世界
af40956e58 Update sing 2026-08-04 22:50:40 +08:00
世界
3b22615aec tailscale: Match bare hostnames in preferred_by when search domains exist
MagicDNS resolves single-label names via tailnet search domains, so
route preferred_by should treat them as tailscale domains, matching
official client behavior.
2026-08-04 22:29:14 +08:00
世界
cc1c891400 tailscale: Fix preferred_by matching all addresses with exit node
Exit node peers carry default routes (0.0.0.0/0, ::/0) in their allowed
IPs, so including them in routePrefixes made PreferredAddress report
every address as preferred.
2026-08-04 22:17:04 +08:00
世界
3d85cbd7f0 tailscale: Fix handle peer DNS query 2026-08-04 21:08:00 +08:00
38 changed files with 705 additions and 327 deletions

View File

@@ -1 +1 @@
617d38f41f935b46a68f550d9add2e38abb3f168
ec9a39c5ba3b4a8d625ede04deaf3c9020afb916

View File

@@ -10,4 +10,4 @@ git -C $PROJECTS/cronet-go fetch origin go_dev
go get -x github.com/sagernet/cronet-go/all@$(git -C $PROJECTS/cronet-go rev-parse origin/go_dev)
go get -x github.com/sagernet/cronet-go@$(git -C $PROJECTS/cronet-go rev-parse origin/go_dev)
go mod tidy
git -C $PROJECTS/cronet-go rev-parse origin/dev > "$SCRIPT_DIR/CRONET_GO_VERSION"
git -C $PROJECTS/cronet-go rev-parse origin/go_dev > "$SCRIPT_DIR/CRONET_GO_VERSION"

View File

@@ -175,24 +175,25 @@ jobs:
with:
ndk-version: r28
- name: Clone cronet-go
if: matrix.naive
if: matrix.naive && matrix.variant != 'purego'
run: |
set -xeuo pipefail
CRONET_GO_VERSION=$(cat .github/CRONET_GO_VERSION)
git init ~/cronet-go
git -C ~/cronet-go remote add origin https://github.com/sagernet/cronet-go.git
git -C ~/cronet-go fetch --depth=1 origin "$CRONET_GO_VERSION"
git -C ~/cronet-go sparse-checkout set --no-cone '/*' '!/lib'
git -C ~/cronet-go fetch --depth=1 --filter=blob:none origin "$CRONET_GO_VERSION"
git -C ~/cronet-go checkout FETCH_HEAD
git -C ~/cronet-go submodule update --init --recursive --depth=1
- name: Regenerate Debian keyring
if: matrix.naive
if: matrix.naive && matrix.variant != 'purego'
run: |
set -xeuo pipefail
rm -f ~/cronet-go/naiveproxy/src/build/linux/sysroot_scripts/keyring.gpg
cd ~/cronet-go
GPG_TTY=/dev/null ./naiveproxy/src/build/linux/sysroot_scripts/generate_keyring.sh
- name: Download Chromium toolchain
if: matrix.naive
if: matrix.naive && matrix.variant != 'purego'
run: |
set -xeuo pipefail
cd ~/cronet-go
@@ -202,7 +203,7 @@ jobs:
go run ./cmd/build-naive --target=linux/${{ matrix.arch }} download-toolchain
fi
- name: Set Chromium toolchain environment
if: matrix.naive
if: matrix.naive && matrix.variant != 'purego'
run: |
set -xeuo pipefail
cd ~/cronet-go
@@ -252,9 +253,15 @@ jobs:
- name: Extract libcronet.so
if: matrix.variant == 'purego' && matrix.naive
run: |
cd ~/cronet-go
CGO_ENABLED=0 go build -v -o "$RUNNER_TEMP/build-naive" ./cmd/build-naive
GOPROXY=direct GOSUMDB=off "$RUNNER_TEMP/build-naive" extract-lib --target ${{ matrix.os }}/${{ matrix.arch }} -o $GITHUB_WORKSPACE/dist
set -xeuo pipefail
CRONET_GO_VERSION=$(cat .github/CRONET_GO_VERSION)
LIBRARY_PATH="lib/${{ matrix.os }}_${{ matrix.arch }}/libcronet.so"
git init "$RUNNER_TEMP/cronet-go-lib"
git -C "$RUNNER_TEMP/cronet-go-lib" remote add origin https://github.com/sagernet/cronet-go.git
git -C "$RUNNER_TEMP/cronet-go-lib" sparse-checkout set --no-cone "/$LIBRARY_PATH"
git -C "$RUNNER_TEMP/cronet-go-lib" fetch --depth=1 --filter=blob:none origin "$CRONET_GO_VERSION"
git -C "$RUNNER_TEMP/cronet-go-lib" checkout FETCH_HEAD
cp "$RUNNER_TEMP/cronet-go-lib/$LIBRARY_PATH" dist/
- name: Build (glibc)
if: matrix.variant == 'glibc'
run: |
@@ -621,15 +628,13 @@ jobs:
if: matrix.naive
run: |
$CRONET_GO_VERSION = Get-Content .github/CRONET_GO_VERSION
git init "$env:RUNNER_TEMP/cronet-go"
git -C "$env:RUNNER_TEMP/cronet-go" remote add origin https://github.com/sagernet/cronet-go.git
git -C "$env:RUNNER_TEMP/cronet-go" fetch --depth=1 origin "$CRONET_GO_VERSION"
git -C "$env:RUNNER_TEMP/cronet-go" checkout FETCH_HEAD
$env:CGO_ENABLED = "0"
go -C "$env:RUNNER_TEMP/cronet-go" build -v -o "$env:RUNNER_TEMP/build-naive.exe" ./cmd/build-naive
$env:GOPROXY = "direct"
$env:GOSUMDB = "off"
& "$env:RUNNER_TEMP/build-naive.exe" extract-lib --target windows/${{ matrix.arch }} -o dist
$LIBRARY_PATH = "lib/windows_${{ matrix.arch }}/libcronet.dll"
git init "$env:RUNNER_TEMP/cronet-go-lib"
git -C "$env:RUNNER_TEMP/cronet-go-lib" remote add origin https://github.com/sagernet/cronet-go.git
git -C "$env:RUNNER_TEMP/cronet-go-lib" sparse-checkout set --no-cone "/$LIBRARY_PATH"
git -C "$env:RUNNER_TEMP/cronet-go-lib" fetch --depth=1 --filter=blob:none origin "$CRONET_GO_VERSION"
git -C "$env:RUNNER_TEMP/cronet-go-lib" checkout FETCH_HEAD
Copy-Item "$env:RUNNER_TEMP/cronet-go-lib/$LIBRARY_PATH" dist
- name: Archive
if: matrix.naive
run: |

View File

@@ -63,7 +63,8 @@ jobs:
CRONET_GO_VERSION=$(cat .github/CRONET_GO_VERSION)
git init ~/cronet-go
git -C ~/cronet-go remote add origin https://github.com/sagernet/cronet-go.git
git -C ~/cronet-go fetch --depth=1 origin "$CRONET_GO_VERSION"
git -C ~/cronet-go sparse-checkout set --no-cone '/*' '!/lib'
git -C ~/cronet-go fetch --depth=1 --filter=blob:none origin "$CRONET_GO_VERSION"
git -C ~/cronet-go checkout FETCH_HEAD
git -C ~/cronet-go submodule update --init --recursive --depth=1
- name: Regenerate Debian keyring

View File

@@ -80,7 +80,8 @@ jobs:
CRONET_GO_VERSION=$(cat .github/CRONET_GO_VERSION)
git init ~/cronet-go
git -C ~/cronet-go remote add origin https://github.com/sagernet/cronet-go.git
git -C ~/cronet-go fetch --depth=1 origin "$CRONET_GO_VERSION"
git -C ~/cronet-go sparse-checkout set --no-cone '/*' '!/lib'
git -C ~/cronet-go fetch --depth=1 --filter=blob:none origin "$CRONET_GO_VERSION"
git -C ~/cronet-go checkout FETCH_HEAD
git -C ~/cronet-go submodule update --init --recursive --depth=1
- name: Regenerate Debian keyring

View File

@@ -42,7 +42,7 @@ Sing-box with extended features.
### Transports
- **mKCP** — Reliable UDP-based transport
- **XHTTP** — Modern XRAY transport
- **rmux** — Improved smux multiplex protocol
- **Rmux** — Improved smux multiplexer
### Services
- **Admin Panel** — Web-based management interface

View File

@@ -156,10 +156,6 @@ func (c *slowOpenConn) WriterReplaceable() bool {
return c.conn.Load() != nil
}
func (c *slowOpenConn) LazyHeadroom() bool {
return c.conn.Load() == nil
}
func (c *slowOpenConn) NeedHandshake() bool {
return c.conn.Load() == nil
}

View File

@@ -43,7 +43,7 @@ func NewTransport(ctx context.Context, logger log.ContextLogger, tag string, opt
}
servers[i] = server
}
strategy, err := CreateStrategy(options.Strategy, servers, logger)
strategy, err := CreateStrategy(options.Strategy, servers, logger, options.Timeout.Build())
if err != nil {
return nil, err
}

View File

@@ -2,18 +2,20 @@ package fallback
import (
"context"
"time"
mDNS "github.com/miekg/dns"
"github.com/sagernet/sing-box/adapter"
C "github.com/sagernet/sing-box/constant"
E "github.com/sagernet/sing/common/exceptions"
"github.com/sagernet/sing/common/logger"
)
type ExchangeStrategy = func(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg, error)
func parallelStrategy(servers []adapter.DNSTransport, logger logger.ContextLogger) ExchangeStrategy {
func parallelStrategy(servers []adapter.DNSTransport, logger logger.ContextLogger, timeout time.Duration) ExchangeStrategy {
return func(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg, error) {
queryCtx, cancel := context.WithCancel(ctx)
ctx, cancel := context.WithTimeout(ctx, timeout)
defer cancel()
type result struct {
response *mDNS.Msg
@@ -22,10 +24,13 @@ func parallelStrategy(servers []adapter.DNSTransport, logger logger.ContextLogge
results := make(chan result)
for _, server := range servers {
go func() {
response, err := server.Exchange(queryCtx, message)
response, err := checkExchangeResponse(server.Exchange(ctx, message))
if err != nil {
logger.InfoContext(ctx, E.Cause(err, "resolve failed for server ", server.Tag()))
}
select {
case results <- result{response, err}:
case <-queryCtx.Done():
case <-ctx.Done():
}
}()
}
@@ -46,12 +51,17 @@ func parallelStrategy(servers []adapter.DNSTransport, logger logger.ContextLogge
}
}
func sequentialStrategy(servers []adapter.DNSTransport, logger logger.ContextLogger) ExchangeStrategy {
func sequentialStrategy(servers []adapter.DNSTransport, logger logger.ContextLogger, timeout time.Duration) ExchangeStrategy {
return func(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg, error) {
ctx, cancel := context.WithTimeout(ctx, timeout)
defer cancel()
var lastErr error
for _, server := range servers {
response, err := server.Exchange(ctx, message)
for index, server := range servers {
exchangeCtx, exchangeCancel := context.WithTimeout(ctx, perAttemptTimeout(ctx, len(servers)-index))
response, err := checkExchangeResponse(server.Exchange(exchangeCtx, message))
exchangeCancel()
if err != nil {
logger.InfoContext(ctx, E.Cause(err, "resolve failed for server ", server.Tag()))
lastErr = err
continue
}
@@ -61,12 +71,30 @@ func sequentialStrategy(servers []adapter.DNSTransport, logger logger.ContextLog
}
}
func CreateStrategy(strategy string, servers []adapter.DNSTransport, logger logger.ContextLogger) (ExchangeStrategy, error) {
func checkExchangeResponse(response *mDNS.Msg, err error) (*mDNS.Msg, error) {
if err != nil {
return nil, err
}
if response.Rcode != mDNS.RcodeSuccess && response.Rcode != mDNS.RcodeNameError {
return nil, E.New("bad response rcode: ", mDNS.RcodeToString[response.Rcode])
}
return response, nil
}
func perAttemptTimeout(ctx context.Context, remaining int) time.Duration {
deadline, _ := ctx.Deadline()
return time.Until(deadline) / time.Duration(remaining)
}
func CreateStrategy(strategy string, servers []adapter.DNSTransport, logger logger.ContextLogger, timeout time.Duration) (ExchangeStrategy, error) {
if timeout <= 0 {
timeout = C.DNSTimeout
}
switch strategy {
case "parallel":
return parallelStrategy(servers, logger), nil
return parallelStrategy(servers, logger, timeout), nil
case "", "sequential":
return sequentialStrategy(servers, logger), nil
return sequentialStrategy(servers, logger, timeout), nil
default:
return nil, E.New("strategy not found: ", strategy)
}

View File

@@ -2,6 +2,11 @@
icon: material/alert-decagram
---
#### 1.13.18
* Update naiveproxy to v150.0.7871.63-1
* Fixes and improvements
#### 1.13.16
* Remove client metadata from AnyTLS requests by default **1**

View File

@@ -44,10 +44,13 @@
"i3": "<b 0xc70000000108...",
"i4": "<b 0xc70000000108...",
"i5": "<b 0xc70000000108...",
"j1": "<b 0xc70000000108...",
"j2": "<b 0xc70000000108...",
"j3": "<b 0xc70000000108...",
"itime": 50,
"header_protection_key": "QGg8AFRn6qKfTB7cT3FWH1WGx3np+OKzlNuQUrqIBmI=",
"content_padding_addition": "50-100",
"rekey_after_time": 120,
"rekey_timeout": 5,
"reject_after_time": 180,
"keepalive_timeout": 10,
"max_handshake_attempts": 20
}
}
],

View File

@@ -34,7 +34,8 @@
// - "parallel": query all servers concurrently. Returns
// the first successful response (cancelling the rest), or the last
// error if all servers failed.
"strategy": "sequential"
"strategy": "sequential",
"timeout": "10s" // overall budget for the whole fallback exchange
}
],
"disable_cache": true,

View File

@@ -19,11 +19,7 @@
"amnezia": {
"jc": 120,
"jmin": 23,
"jmax": 911,
"h1": 1,
"h2": 2,
"h3": 3,
"h4": 4
"jmax": 911
},
"profile": {
"detour": "direct"

View File

@@ -0,0 +1,53 @@
{
"log": {
"level": "error"
},
"dns": {
"servers": [
{
"type": "local",
"tag": "default"
}
]
},
"endpoints": [
{
"type": "vpn-client",
"tag": "vpn",
"address": "10.0.0.2",
"key": "1c9b2ccf-b0c0-4c26-868d-a55a4edad3fe",
"outbound": {
"type": "vless",
"tag": "vless-out",
"server": "0.0.0.0",
"server_port": 8000,
"uuid": "9b65b7e1-04c8-4717-8f45-2aa61fd25937",
"network": "tcp"
}
}
],
"inbounds": [
{
"type": "mixed",
"tag": "mixed-in",
"listen_port": 7897
}
],
"outbounds": [
{
"type": "direct",
"tag": "direct-out"
}
],
"route": {
"rules": [
{
"domain_suffix": ".internal",
"outbound": "vpn",
"override_gateway": "10.0.0.3"
}
],
"final": "direct-out",
"auto_detect_interface": true
}
}

View File

@@ -0,0 +1,40 @@
{
"log": {
"level": "error"
},
"dns": {
"servers": [
{
"type": "local",
"tag": "default"
}
]
},
"endpoints": [
{
"type": "vpn-client",
"tag": "vpn",
"address": "10.0.0.3",
"key": "3d74d616-2502-4c17-9cc3-92c366550f4f",
"outbound": {
"type": "vless",
"tag": "vless-out",
"server": "0.0.0.0",
"server_port": 8000,
"uuid": "9b65b7e1-04c8-4717-8f45-2aa61fd25937",
"network": "tcp"
}
}
],
"outbounds": [
{
"type": "direct",
"tag": "direct-out"
}
],
"route": {
"final": "direct-out",
"default_domain_resolver": "default",
"auto_detect_interface": true
}
}

View File

@@ -0,0 +1,61 @@
{
"log": {
"level": "error"
},
"dns": {
"servers": [
{
"type": "local",
"tag": "default"
}
]
},
"endpoints": [
{
"type": "vpn-server",
"tag": "vpn",
"address": "10.0.0.1",
"users": [
{
"address": "10.0.0.2",
"key": "1c9b2ccf-b0c0-4c26-868d-a55a4edad3fe"
},
{
"address": "10.0.0.3",
"key": "3d74d616-2502-4c17-9cc3-92c366550f4f"
}
],
"inbounds": [
{
"type": "vless",
"tag": "vless-in",
"listen": "0.0.0.0",
"listen_port": 8000,
"users": [
{
"name": "vless",
"uuid": "9b65b7e1-04c8-4717-8f45-2aa61fd25937"
}
]
}
]
}
],
"outbounds": [
{
"type": "direct",
"tag": "direct-out"
}
],
"route": {
"rules": [
{
"source_ip_cidr": "10.0.0.0/24",
"outbound": "vpn"
}
],
"final": "direct-out",
"default_domain_resolver": "default",
"auto_detect_interface": true
}
}

View File

@@ -16,6 +16,7 @@
"tag": "vpn",
"address": "10.0.0.2",
"key": "1c9b2ccf-b0c0-4c26-868d-a55a4edad3fe",
"default_gateway": "10.0.0.3",
"outbound": {
"type": "vless",
"tag": "vless-out",
@@ -40,13 +41,7 @@
}
],
"route": {
"rules": [
{
"outbound": "vpn",
"override_gateway": "10.0.0.3"
}
],
"final": "direct-out",
"final": "vpn",
"auto_detect_interface": true
}
}

View File

@@ -15,6 +15,7 @@
"type": "vpn-server",
"tag": "vpn",
"address": "10.0.0.1",
"default_gateway": "10.0.0.2",
"users": [
{
"address": "10.0.0.2",
@@ -47,8 +48,7 @@
"rules": [
{
"inbound": "vless-in",
"outbound": "vpn",
"override_gateway": "10.0.0.2"
"outbound": "vpn"
}
],
"final": "direct-out",

View File

@@ -15,6 +15,7 @@
"type": "vpn-server",
"tag": "vpn",
"address": "10.0.0.1",
"default_gateway": "10.0.0.2",
"users": [
{
"address": "10.0.0.2",
@@ -51,13 +52,7 @@
}
],
"route": {
"rules": [
{
"outbound": "vpn",
"override_gateway": "10.0.0.2"
}
],
"final": "direct-out",
"final": "vpn",
"default_domain_resolver": "default",
"auto_detect_interface": true
}

View File

@@ -26,23 +26,17 @@
"jc": 120,
"jmin": 23,
"jmax": 911,
"s1": 1,
"s2": 2,
"s3": 3,
"s4": 4,
"h1": 1,
"h2": 2,
"h3": 3,
"h4": 4,
"i1": "<b 0xc70000000108...",
"i2": "<b 0xc70000000108...",
"i3": "<b 0xc70000000108...",
"i4": "<b 0xc70000000108...",
"i5": "<b 0xc70000000108...",
"j1": "<b 0xc70000000108...",
"j2": "<b 0xc70000000108...",
"j3": "<b 0xc70000000108...",
"itime": 50
"content_padding_addition": "50-100",
"rekey_after_time": 120,
"rekey_timeout": 5,
"reject_after_time": 180,
"keepalive_timeout": 10,
"max_handshake_attempts": 20
},
"profile": {
"detour": "direct",

78
go.mod
View File

@@ -44,13 +44,13 @@ require (
github.com/sagernet/asc-go v0.0.0-20241217030726-d563060fe4e1
github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a
github.com/sagernet/cors v1.2.1
github.com/sagernet/cronet-go v0.0.0-20260712143338-d22f2ea3630e
github.com/sagernet/cronet-go/all v0.0.0-20260712143338-d22f2ea3630e
github.com/sagernet/cronet-go v0.0.0-20260807162344-ec9a39c5ba3b
github.com/sagernet/cronet-go/all v0.0.0-20260807162344-ec9a39c5ba3b
github.com/sagernet/fswatch v0.1.2
github.com/sagernet/gomobile v0.1.12
github.com/sagernet/gvisor v0.0.0-20250811.0-sing-box-mod.1
github.com/sagernet/quic-go v0.59.0-sing-box-mod.4
github.com/sagernet/sing v0.8.12-0.20260726145744-ef2df370afca
github.com/sagernet/sing v0.8.12
github.com/sagernet/sing-mux v0.3.5
github.com/sagernet/sing-quic v0.6.4-0.20260803041914-d83826c306d7
github.com/sagernet/sing-shadowsocks v0.2.8
@@ -59,8 +59,8 @@ require (
github.com/sagernet/sing-tun v0.8.12-0.20260727151122-3a09076491df
github.com/sagernet/sing-vmess v0.2.8-0.20250909125414-3aed155119a1
github.com/sagernet/smux v1.5.50-sing-box-mod.1
github.com/sagernet/tailscale v1.92.4-sing-box-1.13-mod.8
github.com/sagernet/wireguard-go v0.0.2-beta.1.0.20260224074747-506b7631853c
github.com/sagernet/tailscale v1.92.4-sing-box-1.13-mod.9
github.com/sagernet/wireguard-go v0.0.4
github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854
github.com/shtorm-7/go-cache/v2 v2.1.0-extended-1.0.2
github.com/shtorm-7/workerpool v0.5.0
@@ -122,7 +122,7 @@ require (
go.opentelemetry.io/otel v1.44.0 // indirect
go.opentelemetry.io/otel/sdk/metric v1.44.0 // indirect
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect
gvisor.dev/gvisor v0.0.0-20260408064518-65a410b0d584 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
modernc.org/libc v1.72.0 // indirect
modernc.org/mathutil v1.7.1 // indirect
modernc.org/memory v1.11.0 // indirect
@@ -184,35 +184,35 @@ require (
github.com/prometheus-community/pro-bing v0.4.0 // indirect
github.com/quic-go/qpack v0.6.0 // indirect
github.com/safchain/ethtool v0.3.0 // indirect
github.com/sagernet/cronet-go/lib/android_386 v0.0.0-20260712142643-1e5048bd5587 // indirect
github.com/sagernet/cronet-go/lib/android_amd64 v0.0.0-20260712142643-1e5048bd5587 // indirect
github.com/sagernet/cronet-go/lib/android_arm v0.0.0-20260712142643-1e5048bd5587 // indirect
github.com/sagernet/cronet-go/lib/android_arm64 v0.0.0-20260712142643-1e5048bd5587 // indirect
github.com/sagernet/cronet-go/lib/darwin_amd64 v0.0.0-20260712142643-1e5048bd5587 // indirect
github.com/sagernet/cronet-go/lib/darwin_arm64 v0.0.0-20260712142643-1e5048bd5587 // indirect
github.com/sagernet/cronet-go/lib/ios_amd64_simulator v0.0.0-20260712142643-1e5048bd5587 // indirect
github.com/sagernet/cronet-go/lib/ios_arm64 v0.0.0-20260712142643-1e5048bd5587 // indirect
github.com/sagernet/cronet-go/lib/ios_arm64_simulator v0.0.0-20260712142643-1e5048bd5587 // indirect
github.com/sagernet/cronet-go/lib/linux_386 v0.0.0-20260712142643-1e5048bd5587 // indirect
github.com/sagernet/cronet-go/lib/linux_386_musl v0.0.0-20260712142643-1e5048bd5587 // indirect
github.com/sagernet/cronet-go/lib/linux_amd64 v0.0.0-20260712142643-1e5048bd5587 // indirect
github.com/sagernet/cronet-go/lib/linux_amd64_musl v0.0.0-20260712142643-1e5048bd5587 // indirect
github.com/sagernet/cronet-go/lib/linux_arm v0.0.0-20260712142643-1e5048bd5587 // indirect
github.com/sagernet/cronet-go/lib/linux_arm64 v0.0.0-20260712142643-1e5048bd5587 // indirect
github.com/sagernet/cronet-go/lib/linux_arm64_musl v0.0.0-20260712142643-1e5048bd5587 // indirect
github.com/sagernet/cronet-go/lib/linux_arm_musl v0.0.0-20260712142643-1e5048bd5587 // indirect
github.com/sagernet/cronet-go/lib/linux_loong64 v0.0.0-20260712142643-1e5048bd5587 // indirect
github.com/sagernet/cronet-go/lib/linux_loong64_musl v0.0.0-20260712142643-1e5048bd5587 // indirect
github.com/sagernet/cronet-go/lib/linux_mips64le v0.0.0-20260712142643-1e5048bd5587 // indirect
github.com/sagernet/cronet-go/lib/linux_mipsle v0.0.0-20260712142643-1e5048bd5587 // indirect
github.com/sagernet/cronet-go/lib/linux_mipsle_musl v0.0.0-20260712142643-1e5048bd5587 // indirect
github.com/sagernet/cronet-go/lib/linux_riscv64 v0.0.0-20260712142643-1e5048bd5587 // indirect
github.com/sagernet/cronet-go/lib/linux_riscv64_musl v0.0.0-20260712142643-1e5048bd5587 // indirect
github.com/sagernet/cronet-go/lib/tvos_amd64_simulator v0.0.0-20260712142643-1e5048bd5587 // indirect
github.com/sagernet/cronet-go/lib/tvos_arm64 v0.0.0-20260712142643-1e5048bd5587 // indirect
github.com/sagernet/cronet-go/lib/tvos_arm64_simulator v0.0.0-20260712142643-1e5048bd5587 // indirect
github.com/sagernet/cronet-go/lib/windows_amd64 v0.0.0-20260712142643-1e5048bd5587 // indirect
github.com/sagernet/cronet-go/lib/windows_arm64 v0.0.0-20260712142643-1e5048bd5587 // indirect
github.com/sagernet/cronet-go/lib/android_386 v0.0.0-20260807161529-8d42107dcdfc // indirect
github.com/sagernet/cronet-go/lib/android_amd64 v0.0.0-20260807161529-8d42107dcdfc // indirect
github.com/sagernet/cronet-go/lib/android_arm v0.0.0-20260807161529-8d42107dcdfc // indirect
github.com/sagernet/cronet-go/lib/android_arm64 v0.0.0-20260807161529-8d42107dcdfc // indirect
github.com/sagernet/cronet-go/lib/darwin_amd64 v0.0.0-20260807161529-8d42107dcdfc // indirect
github.com/sagernet/cronet-go/lib/darwin_arm64 v0.0.0-20260807161529-8d42107dcdfc // indirect
github.com/sagernet/cronet-go/lib/ios_amd64_simulator v0.0.0-20260807161529-8d42107dcdfc // indirect
github.com/sagernet/cronet-go/lib/ios_arm64 v0.0.0-20260807161529-8d42107dcdfc // indirect
github.com/sagernet/cronet-go/lib/ios_arm64_simulator v0.0.0-20260807161529-8d42107dcdfc // indirect
github.com/sagernet/cronet-go/lib/linux_386 v0.0.0-20260807161529-8d42107dcdfc // indirect
github.com/sagernet/cronet-go/lib/linux_386_musl v0.0.0-20260807161529-8d42107dcdfc // indirect
github.com/sagernet/cronet-go/lib/linux_amd64 v0.0.0-20260807161529-8d42107dcdfc // indirect
github.com/sagernet/cronet-go/lib/linux_amd64_musl v0.0.0-20260807161529-8d42107dcdfc // indirect
github.com/sagernet/cronet-go/lib/linux_arm v0.0.0-20260807161529-8d42107dcdfc // indirect
github.com/sagernet/cronet-go/lib/linux_arm64 v0.0.0-20260807161529-8d42107dcdfc // indirect
github.com/sagernet/cronet-go/lib/linux_arm64_musl v0.0.0-20260807161529-8d42107dcdfc // indirect
github.com/sagernet/cronet-go/lib/linux_arm_musl v0.0.0-20260807161529-8d42107dcdfc // indirect
github.com/sagernet/cronet-go/lib/linux_loong64 v0.0.0-20260807161529-8d42107dcdfc // indirect
github.com/sagernet/cronet-go/lib/linux_loong64_musl v0.0.0-20260807161529-8d42107dcdfc // indirect
github.com/sagernet/cronet-go/lib/linux_mips64le v0.0.0-20260807161529-8d42107dcdfc // indirect
github.com/sagernet/cronet-go/lib/linux_mipsle v0.0.0-20260807161529-8d42107dcdfc // indirect
github.com/sagernet/cronet-go/lib/linux_mipsle_musl v0.0.0-20260807161529-8d42107dcdfc // indirect
github.com/sagernet/cronet-go/lib/linux_riscv64 v0.0.0-20260807161529-8d42107dcdfc // indirect
github.com/sagernet/cronet-go/lib/linux_riscv64_musl v0.0.0-20260807161529-8d42107dcdfc // indirect
github.com/sagernet/cronet-go/lib/tvos_amd64_simulator v0.0.0-20260807161529-8d42107dcdfc // indirect
github.com/sagernet/cronet-go/lib/tvos_arm64 v0.0.0-20260807161529-8d42107dcdfc // indirect
github.com/sagernet/cronet-go/lib/tvos_arm64_simulator v0.0.0-20260807161529-8d42107dcdfc // indirect
github.com/sagernet/cronet-go/lib/windows_amd64 v0.0.0-20260807161529-8d42107dcdfc // indirect
github.com/sagernet/cronet-go/lib/windows_arm64 v0.0.0-20260807161529-8d42107dcdfc // indirect
github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a // indirect
github.com/sagernet/nftables v0.3.0-mod.2 // indirect
github.com/shtorm-7/rmux v1.0.0 // indirect
@@ -246,9 +246,9 @@ require (
lukechampine.com/blake3 v1.4.1
)
replace github.com/sagernet/wireguard-go => github.com/shtorm-7/wireguard-go v0.0.2-beta.1-extended-1.5.0
replace github.com/sagernet/wireguard-go => github.com/shtorm-7/wireguard-go v0.0.4-extended-1.5.1
replace github.com/sagernet/tailscale => github.com/shtorm-7/tailscale v1.92.4-sing-box-1.13-mod.7-extended-1.0.2
replace github.com/sagernet/tailscale => github.com/shtorm-7/tailscale v1.92.4-sing-box-1.13-mod.9-extended-1.0.2
replace github.com/ameshkov/dnscrypt/v2 => github.com/shtorm-7/dnscrypt/v2 v2.4.0-extended-1.0.0
@@ -260,6 +260,6 @@ replace github.com/Diniboy1123/connect-ip-go => github.com/shtorm-7/connect-ip-g
replace github.com/shtorm-7/go-cache/v2 => github.com/shtorm-7/go-cache/v2 v2.1.0-extended-1.2.0
replace github.com/sagernet/sing => github.com/shtorm-7/sing v0.8.10-extended-1.2.0
replace github.com/sagernet/sing => github.com/shtorm-7/sing v0.8.12-extended-1.2.0
replace github.com/sagernet/sing-mux => github.com/shtorm-7/sing-mux v0.3.4-extended-1.1.0
replace github.com/sagernet/sing-mux => github.com/shtorm-7/sing-mux v0.3.5-extended-1.0.0

142
go.sum
View File

@@ -351,68 +351,68 @@ github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a h1:+NkI2670SQpQWvkk
github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a/go.mod h1:63s7jpZqcDAIpj8oI/1v4Izok+npJOHACFCU6+huCkM=
github.com/sagernet/cors v1.2.1 h1:Cv5Z8y9YSD6Gm+qSpNrL3LO4lD3eQVvbFYJSG7JCMHQ=
github.com/sagernet/cors v1.2.1/go.mod h1:O64VyOjjhrkLmQIjF4KGRrJO/5dVXFdpEmCW/eISRAI=
github.com/sagernet/cronet-go v0.0.0-20260712143338-d22f2ea3630e h1:Y5mhsZrYuZ9jraIqg7hg1fw4zoVreae81fWvmozbCsQ=
github.com/sagernet/cronet-go v0.0.0-20260712143338-d22f2ea3630e/go.mod h1:T/mwtrpC4JlWfScw73CmSBvHzIvc7BatQ1MhRr+cYNw=
github.com/sagernet/cronet-go/all v0.0.0-20260712143338-d22f2ea3630e h1:rdNlS1dRSi7jQe/ingFf7QmV9ZCUZMbxAfHnBrdVW7g=
github.com/sagernet/cronet-go/all v0.0.0-20260712143338-d22f2ea3630e/go.mod h1:WNl4xfTNuR+f7SObmuBtrk0p4MhlmvuuiWYoty3U52E=
github.com/sagernet/cronet-go/lib/android_386 v0.0.0-20260712142643-1e5048bd5587 h1:ENmDXbGH92/jsMwhjIxK2a0URkA8ILC3npjqmTGj0Yc=
github.com/sagernet/cronet-go/lib/android_386 v0.0.0-20260712142643-1e5048bd5587/go.mod h1:XXDwdjX/T8xftoeJxQmbBoYXZp8MAPFR2CwbFuTpEtw=
github.com/sagernet/cronet-go/lib/android_amd64 v0.0.0-20260712142643-1e5048bd5587 h1:5xn/EZOO5LriSEih91thvTuR+gxb59jNxNQiB/KQPEc=
github.com/sagernet/cronet-go/lib/android_amd64 v0.0.0-20260712142643-1e5048bd5587/go.mod h1:iNiUGoLtnr8/JTuVNj7XJbmpOAp2C6+B81KDrPxwaZM=
github.com/sagernet/cronet-go/lib/android_arm v0.0.0-20260712142643-1e5048bd5587 h1:2/UN0LvWnAM0Sc9B/zE2qWylGrX2hQXhknyQyTlvz4k=
github.com/sagernet/cronet-go/lib/android_arm v0.0.0-20260712142643-1e5048bd5587/go.mod h1:19ILNUOGIzRdOqa2mq+iY0JoHxuieB7/lnjYeaA2vEc=
github.com/sagernet/cronet-go/lib/android_arm64 v0.0.0-20260712142643-1e5048bd5587 h1:SDULc9o0HkneJD38H1G+HRLby69zfdtyQk5qaKtn/tU=
github.com/sagernet/cronet-go/lib/android_arm64 v0.0.0-20260712142643-1e5048bd5587/go.mod h1:JxzGyQf94Cr6sBShKqODGDyRUlESfJK/Njcz9Lz6qMQ=
github.com/sagernet/cronet-go/lib/darwin_amd64 v0.0.0-20260712142643-1e5048bd5587 h1:hfcM9YccWN4O2LENHN16Jgm4g1/1PRouV0RmvvrS1f0=
github.com/sagernet/cronet-go/lib/darwin_amd64 v0.0.0-20260712142643-1e5048bd5587/go.mod h1:KN+9T9TBycGOLzmKU4QdcHAJEj6Nlx48ifnlTvvHMvs=
github.com/sagernet/cronet-go/lib/darwin_arm64 v0.0.0-20260712142643-1e5048bd5587 h1:arY9CL3C7lwJfG2Cdz2ZLvHLzT1wnzCVyAomNER6CrY=
github.com/sagernet/cronet-go/lib/darwin_arm64 v0.0.0-20260712142643-1e5048bd5587/go.mod h1:kojvtUc29KKnk8hs2QIANynVR59921SnGWA9kXohHc0=
github.com/sagernet/cronet-go/lib/ios_amd64_simulator v0.0.0-20260712142643-1e5048bd5587 h1:HrtCf6KPJsW9KJ4L4T8HMW1vx+3xefLRLObpjZEtzF4=
github.com/sagernet/cronet-go/lib/ios_amd64_simulator v0.0.0-20260712142643-1e5048bd5587/go.mod h1:hkQzRE5GDbaH1/ioqYh0Taho4L6i0yLRCVEZ5xHz5M0=
github.com/sagernet/cronet-go/lib/ios_arm64 v0.0.0-20260712142643-1e5048bd5587 h1:Inzzp4hyvcC0lawhndaK8iwEN0vGLDJLCThbaKZpksg=
github.com/sagernet/cronet-go/lib/ios_arm64 v0.0.0-20260712142643-1e5048bd5587/go.mod h1:tzVJFTOm66UxLxy6K0ZN5Ic2PC79e+sKKnt+V9puEa4=
github.com/sagernet/cronet-go/lib/ios_arm64_simulator v0.0.0-20260712142643-1e5048bd5587 h1:qN6vqr9nFnZqjZXhLez+7tMcbm3FMfhaJRWNMlK3SLI=
github.com/sagernet/cronet-go/lib/ios_arm64_simulator v0.0.0-20260712142643-1e5048bd5587/go.mod h1:M/pN6m3j0HFU6/y83n0HU6GLYys3tYdr/xTE8hVEGMo=
github.com/sagernet/cronet-go/lib/linux_386 v0.0.0-20260712142643-1e5048bd5587 h1:Zwzpw6555p3rWw844JxNZ+5iRqli6ZBOEtMH3qq1c7s=
github.com/sagernet/cronet-go/lib/linux_386 v0.0.0-20260712142643-1e5048bd5587/go.mod h1:cGh5hO6eljCo6KMQ/Cel8Xgq4+etL0awZLRBDVG1EZQ=
github.com/sagernet/cronet-go/lib/linux_386_musl v0.0.0-20260712142643-1e5048bd5587 h1:CwsGHfo1HwvEhA2Wnh3O8WxazN3d4Un44LXhiuIvA/w=
github.com/sagernet/cronet-go/lib/linux_386_musl v0.0.0-20260712142643-1e5048bd5587/go.mod h1:JFE0/cxaKkx0wqPMZU7MgaplQlU0zudv82dROJjClKU=
github.com/sagernet/cronet-go/lib/linux_amd64 v0.0.0-20260712142643-1e5048bd5587 h1:Pn6vsVFOJkj9q/XKBOZosfuDLB6luNMLkqq6YLUPXEk=
github.com/sagernet/cronet-go/lib/linux_amd64 v0.0.0-20260712142643-1e5048bd5587/go.mod h1:vU8VftFeSt7fURCa3JXD6+k6ss1YAX+idQjPvHmJ2tI=
github.com/sagernet/cronet-go/lib/linux_amd64_musl v0.0.0-20260712142643-1e5048bd5587 h1:vgRWcEr2jlgICj28XwDMXPQcy8mTob1ZcO+tPdiZjes=
github.com/sagernet/cronet-go/lib/linux_amd64_musl v0.0.0-20260712142643-1e5048bd5587/go.mod h1:vCe4OUuL+XOUge9v3MyTD45BnuAXiH+DkjN9quDXJzQ=
github.com/sagernet/cronet-go/lib/linux_arm v0.0.0-20260712142643-1e5048bd5587 h1:uiO62HvSAdRJR3d1Jc4duxWig3kkdwHBSQ3TmUFqw48=
github.com/sagernet/cronet-go/lib/linux_arm v0.0.0-20260712142643-1e5048bd5587/go.mod h1:w9amBWrvjtohQzBGCKJ7LCh22LhTIJs4sE7cYaKQzM0=
github.com/sagernet/cronet-go/lib/linux_arm64 v0.0.0-20260712142643-1e5048bd5587 h1:mXioRdq9h2YlIr9XGM51kXgIkToywwVfnGmJiaz/uzM=
github.com/sagernet/cronet-go/lib/linux_arm64 v0.0.0-20260712142643-1e5048bd5587/go.mod h1:TqlsFtcYS/etTeck46kHBeT8Le0Igw1Q/AV88UnMS3s=
github.com/sagernet/cronet-go/lib/linux_arm64_musl v0.0.0-20260712142643-1e5048bd5587 h1:oOlfOL+sq0KNZRsk06+5KgvtKw2TEXl2EZnLakTx+WM=
github.com/sagernet/cronet-go/lib/linux_arm64_musl v0.0.0-20260712142643-1e5048bd5587/go.mod h1:B6Qd0vys8sv9OKVRN6J9RqDzYRGE938Fb2zrYdBDyTQ=
github.com/sagernet/cronet-go/lib/linux_arm_musl v0.0.0-20260712142643-1e5048bd5587 h1:UDCa0lYiSUXD4wbxA/G5pGPSXhJaesCQCh5IEiZKb3M=
github.com/sagernet/cronet-go/lib/linux_arm_musl v0.0.0-20260712142643-1e5048bd5587/go.mod h1:3tXMMFY7AHugOVBZ5Al7cL7JKsnFOe5bMVr0hZPk3ow=
github.com/sagernet/cronet-go/lib/linux_loong64 v0.0.0-20260712142643-1e5048bd5587 h1:Yg2Ut7mPs0GK4W6p9LDh8RrDOnhTe4YpvG/WeJyUqMo=
github.com/sagernet/cronet-go/lib/linux_loong64 v0.0.0-20260712142643-1e5048bd5587/go.mod h1:Wt5uFdU3tnmm8YzobYewwdF7Mt6SucRQg6xeTNWC3Tk=
github.com/sagernet/cronet-go/lib/linux_loong64_musl v0.0.0-20260712142643-1e5048bd5587 h1:NtagC/YHvucD0Azh86aVghOk4z5f7oOAAy25Uw4knXQ=
github.com/sagernet/cronet-go/lib/linux_loong64_musl v0.0.0-20260712142643-1e5048bd5587/go.mod h1:lyIF6wKBLwWa5ZXaAKbAoewewl+yCHo2iYev39Mbj4E=
github.com/sagernet/cronet-go/lib/linux_mips64le v0.0.0-20260712142643-1e5048bd5587 h1:INzfLHBKjgJxoUDBeCaiB9hYqjhn5yfudkMz2phYypA=
github.com/sagernet/cronet-go/lib/linux_mips64le v0.0.0-20260712142643-1e5048bd5587/go.mod h1:H46PnSTTZNcZokLLiDeMDaHiS1l14PH3tzWi0eykjD8=
github.com/sagernet/cronet-go/lib/linux_mipsle v0.0.0-20260712142643-1e5048bd5587 h1:IX5NCEV9nojHdjpOkxKVN4L5FUuA5nwawXlSTdFXjCE=
github.com/sagernet/cronet-go/lib/linux_mipsle v0.0.0-20260712142643-1e5048bd5587/go.mod h1:RBhSUDAKWq7fswtV4nQUQhuaTLcX3ettR7teA7/yf2w=
github.com/sagernet/cronet-go/lib/linux_mipsle_musl v0.0.0-20260712142643-1e5048bd5587 h1:pzgA94sR7kvrP+H86/to2oN3efYORQmh0Q3b6AyfRJQ=
github.com/sagernet/cronet-go/lib/linux_mipsle_musl v0.0.0-20260712142643-1e5048bd5587/go.mod h1:wRzoIOGG4xbpp3Gh3triLKwMwYriScXzFtunLYhY4w0=
github.com/sagernet/cronet-go/lib/linux_riscv64 v0.0.0-20260712142643-1e5048bd5587 h1:nkS6jhF90E24PW37Xemhs6+hUM0l2iRcQcZFhPJL8R8=
github.com/sagernet/cronet-go/lib/linux_riscv64 v0.0.0-20260712142643-1e5048bd5587/go.mod h1:LNiZXmWil1OPwKCheqQjtakZlJuKGFz+iv2eGF76Hhs=
github.com/sagernet/cronet-go/lib/linux_riscv64_musl v0.0.0-20260712142643-1e5048bd5587 h1:EbydHlp6vWdqhb8e8zBPVJv/F3HPob+FgO6rsSdNSr0=
github.com/sagernet/cronet-go/lib/linux_riscv64_musl v0.0.0-20260712142643-1e5048bd5587/go.mod h1:YFDGKTkpkJGc5+hnX/RYosZyTWg9h+68VB55fYRRLYc=
github.com/sagernet/cronet-go/lib/tvos_amd64_simulator v0.0.0-20260712142643-1e5048bd5587 h1:sSfVTswgqQZJqh9wTP0Acvvo5/qYARAoHegRYwZ+gyU=
github.com/sagernet/cronet-go/lib/tvos_amd64_simulator v0.0.0-20260712142643-1e5048bd5587/go.mod h1:aaX0YGl8nhGmfRWI8bc3BtDjY8Vzx6O0cS/e1uqxDq4=
github.com/sagernet/cronet-go/lib/tvos_arm64 v0.0.0-20260712142643-1e5048bd5587 h1:lHqqbALbKdJdq/1rcI4yyg3zvibHDw7wmhDYVbjy498=
github.com/sagernet/cronet-go/lib/tvos_arm64 v0.0.0-20260712142643-1e5048bd5587/go.mod h1:EdzMKA96xITc42QEI+ct4SwqX8Dn3ltKK8wzdkLWpSc=
github.com/sagernet/cronet-go/lib/tvos_arm64_simulator v0.0.0-20260712142643-1e5048bd5587 h1:23GyWjb58Nk9a7WXgRfFUiTrMD9kvYSRHx73AaBthYc=
github.com/sagernet/cronet-go/lib/tvos_arm64_simulator v0.0.0-20260712142643-1e5048bd5587/go.mod h1:qix4kv1TTAJ5tY4lJ9vjhe9EY4mM+B7H5giOhbxDVcc=
github.com/sagernet/cronet-go/lib/windows_amd64 v0.0.0-20260712142643-1e5048bd5587 h1:64EMjgVuZMD4TX5b7oWUfWRVp8aVl3hg4aWrriQKOWo=
github.com/sagernet/cronet-go/lib/windows_amd64 v0.0.0-20260712142643-1e5048bd5587/go.mod h1:lm9w/oCCRyBiUa3G8lDQTT8x/ONUvgVR2iV9fVzUZB8=
github.com/sagernet/cronet-go/lib/windows_arm64 v0.0.0-20260712142643-1e5048bd5587 h1:x8cvgMQUs0EgVwt3iT/isRQ9KImvXvPobLKO5bHTN4o=
github.com/sagernet/cronet-go/lib/windows_arm64 v0.0.0-20260712142643-1e5048bd5587/go.mod h1:n34YyLgapgjWdKa0IoeczjAFCwD3/dxbsH5sucKw0bw=
github.com/sagernet/cronet-go v0.0.0-20260807162344-ec9a39c5ba3b h1:SfX10lRxbq9ixHm4OZ4/7q+TSpK4Gh0lEVrPaIAB/K0=
github.com/sagernet/cronet-go v0.0.0-20260807162344-ec9a39c5ba3b/go.mod h1:T/mwtrpC4JlWfScw73CmSBvHzIvc7BatQ1MhRr+cYNw=
github.com/sagernet/cronet-go/all v0.0.0-20260807162344-ec9a39c5ba3b h1:ilEtBdfFgdHmCY3q/Gzp3wRDILYAT8wOh+jVAEAT77U=
github.com/sagernet/cronet-go/all v0.0.0-20260807162344-ec9a39c5ba3b/go.mod h1:Mr2MlNGQYovxvSPGo0+HEgXJ+uITwvPMtp7kdZO8T9w=
github.com/sagernet/cronet-go/lib/android_386 v0.0.0-20260807161529-8d42107dcdfc h1:JxjIRahHFgA766NTMNoQH5FHcSjo3OVdQbqMuqqvOSQ=
github.com/sagernet/cronet-go/lib/android_386 v0.0.0-20260807161529-8d42107dcdfc/go.mod h1:XXDwdjX/T8xftoeJxQmbBoYXZp8MAPFR2CwbFuTpEtw=
github.com/sagernet/cronet-go/lib/android_amd64 v0.0.0-20260807161529-8d42107dcdfc h1:U1M7GkzYchNnahyGiSGD1xAHJXoCiae3E8DDPWaeliA=
github.com/sagernet/cronet-go/lib/android_amd64 v0.0.0-20260807161529-8d42107dcdfc/go.mod h1:iNiUGoLtnr8/JTuVNj7XJbmpOAp2C6+B81KDrPxwaZM=
github.com/sagernet/cronet-go/lib/android_arm v0.0.0-20260807161529-8d42107dcdfc h1:Vtm7UuE69wKPNUakYjlxscX16LkQTEX1Uh6qf2YZj3Y=
github.com/sagernet/cronet-go/lib/android_arm v0.0.0-20260807161529-8d42107dcdfc/go.mod h1:19ILNUOGIzRdOqa2mq+iY0JoHxuieB7/lnjYeaA2vEc=
github.com/sagernet/cronet-go/lib/android_arm64 v0.0.0-20260807161529-8d42107dcdfc h1:w48m0+ic4Y4pmW9ZIAo7o70fq/ioL1pgIKCggvvZiOU=
github.com/sagernet/cronet-go/lib/android_arm64 v0.0.0-20260807161529-8d42107dcdfc/go.mod h1:JxzGyQf94Cr6sBShKqODGDyRUlESfJK/Njcz9Lz6qMQ=
github.com/sagernet/cronet-go/lib/darwin_amd64 v0.0.0-20260807161529-8d42107dcdfc h1:1XkXOj47J9kPTBYZXIPraLG8V3vtQ2p6kI+EuLkNQVs=
github.com/sagernet/cronet-go/lib/darwin_amd64 v0.0.0-20260807161529-8d42107dcdfc/go.mod h1:KN+9T9TBycGOLzmKU4QdcHAJEj6Nlx48ifnlTvvHMvs=
github.com/sagernet/cronet-go/lib/darwin_arm64 v0.0.0-20260807161529-8d42107dcdfc h1:++dHyER9VY0KIfN18i0J2uQcp/DMySqVsUtSEso6mcU=
github.com/sagernet/cronet-go/lib/darwin_arm64 v0.0.0-20260807161529-8d42107dcdfc/go.mod h1:kojvtUc29KKnk8hs2QIANynVR59921SnGWA9kXohHc0=
github.com/sagernet/cronet-go/lib/ios_amd64_simulator v0.0.0-20260807161529-8d42107dcdfc h1:Jd84+nEjqapOYqxbbRaYD9WsqV/+UacrPngpzT3JOW4=
github.com/sagernet/cronet-go/lib/ios_amd64_simulator v0.0.0-20260807161529-8d42107dcdfc/go.mod h1:hkQzRE5GDbaH1/ioqYh0Taho4L6i0yLRCVEZ5xHz5M0=
github.com/sagernet/cronet-go/lib/ios_arm64 v0.0.0-20260807161529-8d42107dcdfc h1:2q/pUYTulaxitrk+Uuwu+nnPeJCwoWCI8YB0b5JU5Pg=
github.com/sagernet/cronet-go/lib/ios_arm64 v0.0.0-20260807161529-8d42107dcdfc/go.mod h1:tzVJFTOm66UxLxy6K0ZN5Ic2PC79e+sKKnt+V9puEa4=
github.com/sagernet/cronet-go/lib/ios_arm64_simulator v0.0.0-20260807161529-8d42107dcdfc h1:KuR8ZjycdnaHpdlwER2BJcyQxFV89+Ci1MC7hQuDQtM=
github.com/sagernet/cronet-go/lib/ios_arm64_simulator v0.0.0-20260807161529-8d42107dcdfc/go.mod h1:M/pN6m3j0HFU6/y83n0HU6GLYys3tYdr/xTE8hVEGMo=
github.com/sagernet/cronet-go/lib/linux_386 v0.0.0-20260807161529-8d42107dcdfc h1:5oWj5iZn7tg9wOC4VMltItUE87FDxubwICgtjSp+HAM=
github.com/sagernet/cronet-go/lib/linux_386 v0.0.0-20260807161529-8d42107dcdfc/go.mod h1:cGh5hO6eljCo6KMQ/Cel8Xgq4+etL0awZLRBDVG1EZQ=
github.com/sagernet/cronet-go/lib/linux_386_musl v0.0.0-20260807161529-8d42107dcdfc h1:EZBIqNjit9xGM1w9xKcQVzU3gtyNdEcgXPfmeVuTinM=
github.com/sagernet/cronet-go/lib/linux_386_musl v0.0.0-20260807161529-8d42107dcdfc/go.mod h1:JFE0/cxaKkx0wqPMZU7MgaplQlU0zudv82dROJjClKU=
github.com/sagernet/cronet-go/lib/linux_amd64 v0.0.0-20260807161529-8d42107dcdfc h1:yOIHOVXOlmbvcs1Gm2xfcr84+mvAVN0zdXycfLgr3DE=
github.com/sagernet/cronet-go/lib/linux_amd64 v0.0.0-20260807161529-8d42107dcdfc/go.mod h1:vU8VftFeSt7fURCa3JXD6+k6ss1YAX+idQjPvHmJ2tI=
github.com/sagernet/cronet-go/lib/linux_amd64_musl v0.0.0-20260807161529-8d42107dcdfc h1:4uVapCorUiSKJ2xTi8BNLOTq878kFv3l+6+aDeYpuiE=
github.com/sagernet/cronet-go/lib/linux_amd64_musl v0.0.0-20260807161529-8d42107dcdfc/go.mod h1:vCe4OUuL+XOUge9v3MyTD45BnuAXiH+DkjN9quDXJzQ=
github.com/sagernet/cronet-go/lib/linux_arm v0.0.0-20260807161529-8d42107dcdfc h1:fm2GA6JTp48rigyUtuzgu/G9WbMZ+o5QBylks1Noss0=
github.com/sagernet/cronet-go/lib/linux_arm v0.0.0-20260807161529-8d42107dcdfc/go.mod h1:w9amBWrvjtohQzBGCKJ7LCh22LhTIJs4sE7cYaKQzM0=
github.com/sagernet/cronet-go/lib/linux_arm64 v0.0.0-20260807161529-8d42107dcdfc h1:kWx/l/TCx2hdUKnNn2uyKZAGkCeqm+vkhr84wZJkSgU=
github.com/sagernet/cronet-go/lib/linux_arm64 v0.0.0-20260807161529-8d42107dcdfc/go.mod h1:TqlsFtcYS/etTeck46kHBeT8Le0Igw1Q/AV88UnMS3s=
github.com/sagernet/cronet-go/lib/linux_arm64_musl v0.0.0-20260807161529-8d42107dcdfc h1:XnHUep8+amHCWW3WWCD6/QAZYAXkcLUeCZqs0SnXp7M=
github.com/sagernet/cronet-go/lib/linux_arm64_musl v0.0.0-20260807161529-8d42107dcdfc/go.mod h1:B6Qd0vys8sv9OKVRN6J9RqDzYRGE938Fb2zrYdBDyTQ=
github.com/sagernet/cronet-go/lib/linux_arm_musl v0.0.0-20260807161529-8d42107dcdfc h1:F7rgwvKytTxeU3G3RpZlH0o77J6OmbZpxaUkTWk1+cE=
github.com/sagernet/cronet-go/lib/linux_arm_musl v0.0.0-20260807161529-8d42107dcdfc/go.mod h1:3tXMMFY7AHugOVBZ5Al7cL7JKsnFOe5bMVr0hZPk3ow=
github.com/sagernet/cronet-go/lib/linux_loong64 v0.0.0-20260807161529-8d42107dcdfc h1:lpq6aztgg4Luspo4V4SresrCg7+bXlpZ45EfAwpWabg=
github.com/sagernet/cronet-go/lib/linux_loong64 v0.0.0-20260807161529-8d42107dcdfc/go.mod h1:Wt5uFdU3tnmm8YzobYewwdF7Mt6SucRQg6xeTNWC3Tk=
github.com/sagernet/cronet-go/lib/linux_loong64_musl v0.0.0-20260807161529-8d42107dcdfc h1:o66baLwgg/aI14jCX6lrQ+1EPkn7RS4cFWJQRKXYXqM=
github.com/sagernet/cronet-go/lib/linux_loong64_musl v0.0.0-20260807161529-8d42107dcdfc/go.mod h1:lyIF6wKBLwWa5ZXaAKbAoewewl+yCHo2iYev39Mbj4E=
github.com/sagernet/cronet-go/lib/linux_mips64le v0.0.0-20260807161529-8d42107dcdfc h1:7tSY8HPMvf/piEi0TywA/dQWyp1lAJH9U/qyn4+DKY8=
github.com/sagernet/cronet-go/lib/linux_mips64le v0.0.0-20260807161529-8d42107dcdfc/go.mod h1:H46PnSTTZNcZokLLiDeMDaHiS1l14PH3tzWi0eykjD8=
github.com/sagernet/cronet-go/lib/linux_mipsle v0.0.0-20260807161529-8d42107dcdfc h1:zgHBT1uv5UQ/GHVMn4j6NXelH7ukIo0IQQLsntV+VfA=
github.com/sagernet/cronet-go/lib/linux_mipsle v0.0.0-20260807161529-8d42107dcdfc/go.mod h1:RBhSUDAKWq7fswtV4nQUQhuaTLcX3ettR7teA7/yf2w=
github.com/sagernet/cronet-go/lib/linux_mipsle_musl v0.0.0-20260807161529-8d42107dcdfc h1:HNzghnPzq2RK5TXjl5QIVPm44FKzw6pds1GQINAYD80=
github.com/sagernet/cronet-go/lib/linux_mipsle_musl v0.0.0-20260807161529-8d42107dcdfc/go.mod h1:wRzoIOGG4xbpp3Gh3triLKwMwYriScXzFtunLYhY4w0=
github.com/sagernet/cronet-go/lib/linux_riscv64 v0.0.0-20260807161529-8d42107dcdfc h1:xAaqyzbYqGPJbKCa6onmX7Bs2HXM1mvbEdMtdAiXplA=
github.com/sagernet/cronet-go/lib/linux_riscv64 v0.0.0-20260807161529-8d42107dcdfc/go.mod h1:LNiZXmWil1OPwKCheqQjtakZlJuKGFz+iv2eGF76Hhs=
github.com/sagernet/cronet-go/lib/linux_riscv64_musl v0.0.0-20260807161529-8d42107dcdfc h1:dHay8gOPaH4kwcTnxQeAEZaIw88Y0V6Gmef3HkdX31U=
github.com/sagernet/cronet-go/lib/linux_riscv64_musl v0.0.0-20260807161529-8d42107dcdfc/go.mod h1:YFDGKTkpkJGc5+hnX/RYosZyTWg9h+68VB55fYRRLYc=
github.com/sagernet/cronet-go/lib/tvos_amd64_simulator v0.0.0-20260807161529-8d42107dcdfc h1:NLAel/XTGYWExz5gpFzlsX+BZba3/6Wgz1xwOzux9r0=
github.com/sagernet/cronet-go/lib/tvos_amd64_simulator v0.0.0-20260807161529-8d42107dcdfc/go.mod h1:aaX0YGl8nhGmfRWI8bc3BtDjY8Vzx6O0cS/e1uqxDq4=
github.com/sagernet/cronet-go/lib/tvos_arm64 v0.0.0-20260807161529-8d42107dcdfc h1:/k71v3Hs2m6mpDTWVm2W6spZNd+do9U+1jBYTOIPj3g=
github.com/sagernet/cronet-go/lib/tvos_arm64 v0.0.0-20260807161529-8d42107dcdfc/go.mod h1:EdzMKA96xITc42QEI+ct4SwqX8Dn3ltKK8wzdkLWpSc=
github.com/sagernet/cronet-go/lib/tvos_arm64_simulator v0.0.0-20260807161529-8d42107dcdfc h1:HUB2CvXtgggtQNW5ix670s9Qd+vCiy5aFKEFJO5/UL8=
github.com/sagernet/cronet-go/lib/tvos_arm64_simulator v0.0.0-20260807161529-8d42107dcdfc/go.mod h1:qix4kv1TTAJ5tY4lJ9vjhe9EY4mM+B7H5giOhbxDVcc=
github.com/sagernet/cronet-go/lib/windows_amd64 v0.0.0-20260807161529-8d42107dcdfc h1:rWdo0pRYdrGvZ0turVxLqsXsizj+AS/nivMHX0RHtLw=
github.com/sagernet/cronet-go/lib/windows_amd64 v0.0.0-20260807161529-8d42107dcdfc/go.mod h1:lm9w/oCCRyBiUa3G8lDQTT8x/ONUvgVR2iV9fVzUZB8=
github.com/sagernet/cronet-go/lib/windows_arm64 v0.0.0-20260807161529-8d42107dcdfc h1:+3Fe+RdrbyEGyi66Kt8BromMTFGVw6+8ZTEqKF4kCaU=
github.com/sagernet/cronet-go/lib/windows_arm64 v0.0.0-20260807161529-8d42107dcdfc/go.mod h1:n34YyLgapgjWdKa0IoeczjAFCwD3/dxbsH5sucKw0bw=
github.com/sagernet/fswatch v0.1.2 h1:/TT7k4mkce1qFPxamLO842WjqBgbTBiXP2mlUjp9PFk=
github.com/sagernet/fswatch v0.1.2/go.mod h1:5BpGmpUQVd3Mc5r313HRpvADHRg3/rKn5QbwFteB880=
github.com/sagernet/gomobile v0.1.12 h1:XwzjZaclFF96deLqwAgK8gU3w0M2A8qxgDmhV+A0wjg=
@@ -449,16 +449,16 @@ github.com/shtorm-7/mtg-multi v1.11.0-extended-1.0.0 h1:iBLll4ZZG8ULQcHWs6gGslZW
github.com/shtorm-7/mtg-multi v1.11.0-extended-1.0.0/go.mod h1:3rvdhwdPABkwKBdvgMt3VwMn9uSq8hpoHRezZ5jRJU0=
github.com/shtorm-7/rmux v1.0.0 h1:oNXshcZVUEDU9u5ylqh3VBFQwus5LFH5yZD9KMTkSSw=
github.com/shtorm-7/rmux v1.0.0/go.mod h1:6tVwUpgjMcCTi3iami7le2/rqhfR6aFPhwuyFzGNQcw=
github.com/shtorm-7/sing v0.8.10-extended-1.2.0 h1:5yw9j0+P2QkRWvxBvb71wvNdpAlHmmpBv4hj2gqvass=
github.com/shtorm-7/sing v0.8.10-extended-1.2.0/go.mod h1:olXxWQNqRW/l2Q6JI3b2Qmz8iQnIFlOeeH8bx6JhgUA=
github.com/shtorm-7/sing-mux v0.3.4-extended-1.1.0 h1:rSDID4on/Z9OherBpvsvKqyuj7dM2b4q+YBJFcpLGpI=
github.com/shtorm-7/sing-mux v0.3.4-extended-1.1.0/go.mod h1:1qHy7cnbDQSY2OWL7CybproWC0t5Ia/DIuNHAzB6ZCA=
github.com/shtorm-7/sing v0.8.12-extended-1.2.0 h1:/CYLFBi+Xrj0R6hFvYoqmDfcLe3WB6McZq5t9UvVhrc=
github.com/shtorm-7/sing v0.8.12-extended-1.2.0/go.mod h1:olXxWQNqRW/l2Q6JI3b2Qmz8iQnIFlOeeH8bx6JhgUA=
github.com/shtorm-7/sing-mux v0.3.5-extended-1.0.0 h1:AfCNqpQlrdWnEd64wXN+cmoHlPMAszre+Wpkg/O8wvA=
github.com/shtorm-7/sing-mux v0.3.5-extended-1.0.0/go.mod h1:1qHy7cnbDQSY2OWL7CybproWC0t5Ia/DIuNHAzB6ZCA=
github.com/shtorm-7/sing-vmess v0.2.8-extended-1.0.0 h1:OjvqZOhYSi9eIJGYC0iPDPqvgo/asujvhAGkFzbZ5/Y=
github.com/shtorm-7/sing-vmess v0.2.8-extended-1.0.0/go.mod h1:P11scgTxMxVVQ8dlM27yNm3Cro40mD0+gHbnqrNGDuY=
github.com/shtorm-7/tailscale v1.92.4-sing-box-1.13-mod.7-extended-1.0.2 h1:hSMjh97OszszOd8HrzpaYUQH9dWRRBluJCbwQyz8ZOk=
github.com/shtorm-7/tailscale v1.92.4-sing-box-1.13-mod.7-extended-1.0.2/go.mod h1:TYIIqO5sZpWq873rLIeO2usszSMUpR3h6WdqVVs65ug=
github.com/shtorm-7/wireguard-go v0.0.2-beta.1-extended-1.5.0 h1:7YhTkPhDUK81OV9mRMH26Efobh0VCGlig/HgHAlsf5U=
github.com/shtorm-7/wireguard-go v0.0.2-beta.1-extended-1.5.0/go.mod h1:Me2JlCDYHxnd0mnuX7L5LXAeDHCltI7vSKq3eTE6SVE=
github.com/shtorm-7/tailscale v1.92.4-sing-box-1.13-mod.9-extended-1.0.2 h1:ho7bMq/aUFnNhFbdtrqlW3gyZAsnCtYMXEcyoSNo65Q=
github.com/shtorm-7/tailscale v1.92.4-sing-box-1.13-mod.9-extended-1.0.2/go.mod h1:rPn4ZaNbMdbCNBRj3bYCTFCHqB2LcxDgJJrFoaTavTc=
github.com/shtorm-7/wireguard-go v0.0.4-extended-1.5.1 h1:TJ8tinN4A2DRy33RiYiK3ST10Q93O2G/9ZabSUnb2iQ=
github.com/shtorm-7/wireguard-go v0.0.4-extended-1.5.1/go.mod h1:1VZmkU7yPAZVE0XKufUqqAhEY1RnWUcyZLmry85y+7A=
github.com/shtorm-7/workerpool v0.5.0 h1:NPZuNgyH0EUm4aQsTL09xR1iV+7GCFw6jX9Z4aAVp2s=
github.com/shtorm-7/workerpool v0.5.0/go.mod h1:NI0pUZgmGu0BdKO9j3mct1DNZmgXbyTS9foorljdH6E=
github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU=
@@ -668,8 +668,6 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gvisor.dev/gvisor v0.0.0-20260408064518-65a410b0d584 h1:QyFROp5Ew7XZWKPtp8ap78z4gpY6xHpJIEdHgVA4bzA=
gvisor.dev/gvisor v0.0.0-20260408064518-65a410b0d584/go.mod h1:xQ2PWgHmWJA/Ph4i1q1jBm39BKhc3W0DXqWoDSyuBOY=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
howett.net/plist v1.0.1 h1:37GdZ8tP09Q35o9ych3ehygcsL+HqKSwzctveSlarvM=

View File

@@ -427,6 +427,7 @@ type SDNSDNSServerOptions struct {
}
type FallbackDNSServerOptions struct {
Servers []string `json:"servers"`
Strategy string `json:"strategy,omitempty"`
Servers []string `json:"servers"`
Strategy string `json:"strategy,omitempty"`
Timeout badoption.Duration `json:"timeout,omitempty"`
}

View File

@@ -11,7 +11,24 @@ type WARPEndpointOptions struct {
Workers int `json:"workers,omitempty"`
PreallocatedBuffersPerPool uint32 `json:"preallocated_buffers_per_pool,omitempty"`
DisablePauses bool `json:"disable_pauses,omitempty"`
Amnezia *WireGuardAmnezia `json:"amnezia,omitempty"`
Amnezia *WARPAmnezia `json:"amnezia,omitempty"`
Profile CloudflareProfile `json:"profile,omitempty"`
DialerOptions
}
type WARPAmnezia struct {
JC int `json:"jc,omitempty"`
JMin int `json:"jmin,omitempty"`
JMax int `json:"jmax,omitempty"`
I1 string `json:"i1,omitempty"`
I2 string `json:"i2,omitempty"`
I3 string `json:"i3,omitempty"`
I4 string `json:"i4,omitempty"`
I5 string `json:"i5,omitempty"`
ContentPaddingAddition *badoption.Range[uint32] `json:"content_padding_addition,omitempty"`
RekeyAfterTime *badoption.Range[uint32] `json:"rekey_after_time,omitempty"`
RekeyTimeout *badoption.Range[uint32] `json:"rekey_timeout,omitempty"`
RejectAfterTime *badoption.Range[uint32] `json:"reject_after_time,omitempty"`
KeepaliveTimeout *badoption.Range[uint32] `json:"keepalive_timeout,omitempty"`
MaxHandshakeAttempts *badoption.Range[uint32] `json:"max_handshake_attempts,omitempty"`
}

View File

@@ -32,24 +32,27 @@ type WireGuardPeer struct {
}
type WireGuardAmnezia struct {
JC int `json:"jc,omitempty"`
JMin int `json:"jmin,omitempty"`
JMax int `json:"jmax,omitempty"`
S1 int `json:"s1,omitempty"`
S2 int `json:"s2,omitempty"`
S3 int `json:"s3,omitempty"`
S4 int `json:"s4,omitempty"`
H1 *badoption.Range[uint32] `json:"h1,omitempty"`
H2 *badoption.Range[uint32] `json:"h2,omitempty"`
H3 *badoption.Range[uint32] `json:"h3,omitempty"`
H4 *badoption.Range[uint32] `json:"h4,omitempty"`
I1 string `json:"i1,omitempty"`
I2 string `json:"i2,omitempty"`
I3 string `json:"i3,omitempty"`
I4 string `json:"i4,omitempty"`
I5 string `json:"i5,omitempty"`
J1 string `json:"j1,omitempty"`
J2 string `json:"j2,omitempty"`
J3 string `json:"j3,omitempty"`
ITime int64 `json:"itime,omitempty"`
JC int `json:"jc,omitempty"`
JMin int `json:"jmin,omitempty"`
JMax int `json:"jmax,omitempty"`
S1 int `json:"s1,omitempty"`
S2 int `json:"s2,omitempty"`
S3 int `json:"s3,omitempty"`
S4 int `json:"s4,omitempty"`
H1 *badoption.Range[uint32] `json:"h1,omitempty"`
H2 *badoption.Range[uint32] `json:"h2,omitempty"`
H3 *badoption.Range[uint32] `json:"h3,omitempty"`
H4 *badoption.Range[uint32] `json:"h4,omitempty"`
I1 string `json:"i1,omitempty"`
I2 string `json:"i2,omitempty"`
I3 string `json:"i3,omitempty"`
I4 string `json:"i4,omitempty"`
I5 string `json:"i5,omitempty"`
HeaderProtectionKey string `json:"header_protection_key,omitempty"`
ContentPaddingAddition *badoption.Range[uint32] `json:"content_padding_addition,omitempty"`
RekeyAfterTime *badoption.Range[uint32] `json:"rekey_after_time,omitempty"`
RekeyTimeout *badoption.Range[uint32] `json:"rekey_timeout,omitempty"`
RejectAfterTime *badoption.Range[uint32] `json:"reject_after_time,omitempty"`
KeepaliveTimeout *badoption.Range[uint32] `json:"keepalive_timeout,omitempty"`
MaxHandshakeAttempts *badoption.Range[uint32] `json:"max_handshake_attempts,omitempty"`
}

View File

@@ -106,7 +106,12 @@ func (h *Outbound) DialContext(ctx context.Context, network string, destination
if err != nil {
return nil, err
}
return h.strategy.wrapConn(ctx, conn, adapter.ContextFrom(ctx), true)
wrappedConn, err := h.strategy.wrapConn(ctx, conn, adapter.ContextFrom(ctx), true)
if err != nil {
conn.Close()
return nil, err
}
return wrappedConn, nil
}
func (h *Outbound) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
@@ -114,12 +119,17 @@ func (h *Outbound) ListenPacket(ctx context.Context, destination M.Socksaddr) (n
if err != nil {
return nil, err
}
return h.strategy.wrapPacketConn(ctx, conn, adapter.ContextFrom(ctx), true)
wrappedConn, err := h.strategy.wrapPacketConn(ctx, conn, adapter.ContextFrom(ctx), true)
if err != nil {
conn.Close()
return nil, err
}
return wrappedConn, nil
}
func (h *Outbound) NewConnectionEx(ctx context.Context, conn net.Conn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) {
ctx = adapter.WithContext(ctx, &metadata)
conn, err := h.strategy.wrapConn(ctx, conn, &metadata, false)
wrappedConn, err := h.strategy.wrapConn(ctx, conn, &metadata, false)
if err != nil {
h.logger.ErrorContext(ctx, err)
N.CloseOnHandshakeFailure(conn, onClose, err)
@@ -127,7 +137,7 @@ func (h *Outbound) NewConnectionEx(ctx context.Context, conn net.Conn, metadata
}
metadata.Inbound = h.Tag()
metadata.InboundType = h.Type()
h.router.RouteConnectionEx(ctx, conn, metadata, onClose)
h.router.RouteConnectionEx(ctx, wrappedConn, metadata, onClose)
return
}

View File

@@ -2,6 +2,7 @@ package bandwidth
import (
"context"
"io"
"net"
"strconv"
"sync"
@@ -191,7 +192,7 @@ func (s *UsersBandwidthStrategy) getStrategy(ctx context.Context, metadata *adap
}
type bwConnEntry struct {
conn net.Conn
conn io.Closer
}
type ManagerBandwidthStrategy struct {
@@ -251,7 +252,25 @@ func (s *ManagerBandwidthStrategy) wrapPacketConn(ctx context.Context, conn net.
if !ok {
return nil, E.New("user strategy not found: ", user)
}
return strategy.wrapPacketConn(ctx, conn, metadata, reverse)
wrapped, err := strategy.wrapPacketConn(ctx, conn, metadata, reverse)
if err != nil {
return nil, err
}
entry := &bwConnEntry{conn: conn}
s.mtx.Lock()
s.conns[user] = append(s.conns[user], entry)
s.mtx.Unlock()
return onclose.NewPacketConn(wrapped, func() {
s.mtx.Lock()
entries := s.conns[user]
for i, e := range entries {
if e == entry {
s.conns[user] = append(entries[:i], entries[i+1:]...)
break
}
}
s.mtx.Unlock()
}), nil
}
func (s *ManagerBandwidthStrategy) UpdateStrategies(strategies map[string]BandwidthStrategy) {

View File

@@ -82,7 +82,12 @@ func (h *Outbound) DialContext(ctx context.Context, network string, destination
if err != nil {
return nil, err
}
return h.strategy.wrapConn(ctx, conn, adapter.ContextFrom(ctx), true)
wrappedConn, err := h.strategy.wrapConn(ctx, conn, adapter.ContextFrom(ctx), true)
if err != nil {
conn.Close()
return nil, err
}
return wrappedConn, nil
}
func (h *Outbound) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
@@ -90,11 +95,16 @@ func (h *Outbound) ListenPacket(ctx context.Context, destination M.Socksaddr) (n
if err != nil {
return nil, err
}
return h.strategy.wrapPacketConn(ctx, conn, adapter.ContextFrom(ctx), true)
wrappedConn, err := h.strategy.wrapPacketConn(ctx, conn, adapter.ContextFrom(ctx), true)
if err != nil {
conn.Close()
return nil, err
}
return wrappedConn, nil
}
func (h *Outbound) NewConnectionEx(ctx context.Context, conn net.Conn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) {
conn, err := h.strategy.wrapConn(ctx, conn, &metadata, false)
wrappedConn, err := h.strategy.wrapConn(ctx, conn, &metadata, false)
if err != nil {
if err.Error() != "traffic limit exceeded" {
h.logger.ErrorContext(ctx, err)
@@ -104,7 +114,7 @@ func (h *Outbound) NewConnectionEx(ctx context.Context, conn net.Conn, metadata
}
metadata.Inbound = h.Tag()
metadata.InboundType = h.Type()
h.router.RouteConnectionEx(ctx, conn, metadata, onClose)
h.router.RouteConnectionEx(ctx, wrappedConn, metadata, onClose)
}
func (h *Outbound) NewPacketConnectionEx(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) {

View File

@@ -2,6 +2,7 @@ package traffic
import (
"context"
"io"
"net"
"sync"
@@ -37,11 +38,11 @@ func NewDefaultWrapStrategy(limiterStrategy TrafficLimiterStrategy, connWrapper
func (s *DefaultWrapStrategy) wrapConn(ctx context.Context, conn net.Conn, metadata *adapter.InboundContext, reverse bool) (net.Conn, error) {
limiter, err := s.limiterStrategy.getLimiter(ctx, metadata)
if err != nil {
return conn, err
return nil, err
}
_, err = limiter.Reserve(0)
if err != nil {
return conn, err
return nil, err
}
return s.connWrapper(ctx, conn, limiter, reverse), nil
}
@@ -49,11 +50,11 @@ func (s *DefaultWrapStrategy) wrapConn(ctx context.Context, conn net.Conn, metad
func (s *DefaultWrapStrategy) wrapPacketConn(ctx context.Context, conn net.PacketConn, metadata *adapter.InboundContext, reverse bool) (net.PacketConn, error) {
limiter, err := s.limiterStrategy.getLimiter(ctx, metadata)
if err != nil {
return conn, err
return nil, err
}
_, err = limiter.Reserve(0)
if err != nil {
return conn, err
return nil, err
}
return s.packetConnWrapper(ctx, conn, limiter, reverse), nil
}
@@ -73,7 +74,7 @@ func (s *GlobalTrafficStrategy) getLimiter(ctx context.Context, metadata *adapte
}
type connEntry struct {
conn net.Conn
conn io.Closer
}
type ManagerTrafficStrategy struct {
@@ -94,7 +95,7 @@ func (s *ManagerTrafficStrategy) wrapConn(ctx context.Context, conn net.Conn, me
if err != nil {
return nil, err
}
wrapped, err := strategy.wrapConn(ctx, conn, metadata, reverse)
wrappedConn, err := strategy.wrapConn(ctx, conn, metadata, reverse)
if err != nil {
return nil, err
}
@@ -102,7 +103,7 @@ func (s *ManagerTrafficStrategy) wrapConn(ctx context.Context, conn net.Conn, me
s.mtx.Lock()
s.conns[user] = append(s.conns[user], entry)
s.mtx.Unlock()
return onclose.NewConn(wrapped, func() {
return onclose.NewConn(wrappedConn, func() {
s.mtx.Lock()
entries := s.conns[user]
for i, e := range entries {
@@ -116,11 +117,29 @@ func (s *ManagerTrafficStrategy) wrapConn(ctx context.Context, conn net.Conn, me
}
func (s *ManagerTrafficStrategy) wrapPacketConn(ctx context.Context, conn net.PacketConn, metadata *adapter.InboundContext, reverse bool) (net.PacketConn, error) {
strategy, _, err := s.getStrategy(ctx, metadata)
strategy, user, err := s.getStrategy(ctx, metadata)
if err != nil {
return nil, err
}
return strategy.wrapPacketConn(ctx, conn, metadata, reverse)
wrappedConn, err := strategy.wrapPacketConn(ctx, conn, metadata, reverse)
if err != nil {
return nil, err
}
entry := &connEntry{conn: conn}
s.mtx.Lock()
s.conns[user] = append(s.conns[user], entry)
s.mtx.Unlock()
return onclose.NewPacketConn(wrappedConn, func() {
s.mtx.Lock()
entries := s.conns[user]
for i, e := range entries {
if e == entry {
s.conns[user] = append(entries[:i], entries[i+1:]...)
break
}
}
s.mtx.Unlock()
}), nil
}
func (s *ManagerTrafficStrategy) getStrategy(ctx context.Context, metadata *adapter.InboundContext) (TrafficStrategy, string, error) {

View File

@@ -16,6 +16,7 @@ import (
E "github.com/sagernet/sing/common/exceptions"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
"github.com/sagernet/sing/service"
mieruclient "github.com/enfein/mieru/v3/apis/client"
mierucommon "github.com/enfein/mieru/v3/apis/common"
@@ -27,9 +28,12 @@ import (
type Outbound struct {
outbound.Adapter
dialer N.Dialer
logger log.ContextLogger
client mieruclient.Client
ctx context.Context
dnsRouter adapter.DNSRouter
dialer N.Dialer
logger log.ContextLogger
options option.MieruOutboundOptions
client mieruclient.Client
}
func RegisterOutbound(registry *outbound.Registry) {
@@ -41,26 +45,42 @@ func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextL
if err != nil {
return nil, err
}
return &Outbound{
Adapter: outbound.NewAdapterWithDialerOptions(C.TypeMieru, tag, []string{N.NetworkTCP, N.NetworkUDP}, options.DialerOptions),
ctx: ctx,
dnsRouter: service.FromContext[adapter.DNSRouter](ctx),
dialer: outboundDialer,
logger: logger,
options: options,
}, nil
}
config, err := buildMieruClientConfig(options, mieruDialer{dialer: outboundDialer})
func (o *Outbound) Start(stage adapter.StartStage) error {
if stage != adapter.StartStatePostStart {
return nil
}
serverOptions := o.options
if M.IsDomainName(serverOptions.Server) {
addresses, err := o.dnsRouter.Lookup(o.ctx, serverOptions.Server, adapter.DNSQueryOptions{})
if err != nil {
return fmt.Errorf("failed to resolve mieru server address: %w", err)
}
serverOptions.Server = addresses[0].String()
}
config, err := buildMieruClientConfig(serverOptions, mieruDialer{dialer: o.dialer})
if err != nil {
return nil, fmt.Errorf("failed to build mieru client config: %w", err)
return fmt.Errorf("failed to build mieru client config: %w", err)
}
c := mieruclient.NewClient()
if err := c.Store(config); err != nil {
return nil, fmt.Errorf("failed to store mieru client config: %w", err)
return fmt.Errorf("failed to store mieru client config: %w", err)
}
if err := c.Start(); err != nil {
return nil, fmt.Errorf("failed to start mieru client: %w", err)
return fmt.Errorf("failed to start mieru client: %w", err)
}
logger.NoticeContext(ctx, "mieru client is started")
return &Outbound{
Adapter: outbound.NewAdapterWithDialerOptions(C.TypeMieru, tag, []string{N.NetworkTCP, N.NetworkUDP}, options.DialerOptions),
dialer: outboundDialer,
logger: logger,
client: c,
}, nil
o.logger.NoticeContext(o.ctx, "mieru client is started")
o.client = c
return nil
}
func (o *Outbound) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {

View File

@@ -27,9 +27,10 @@ import (
"github.com/sagernet/sing-box/adapter/endpoint"
"github.com/sagernet/sing-box/common/dialer"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/dns"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/option"
"github.com/sagernet/sing-box/route/rule"
R "github.com/sagernet/sing-box/route/rule"
"github.com/sagernet/sing-tun"
"github.com/sagernet/sing-tun/ping"
"github.com/sagernet/sing/common"
@@ -60,6 +61,7 @@ import (
"github.com/sagernet/tailscale/wgengine/router"
"github.com/sagernet/tailscale/wgengine/wgcfg"
mDNS "github.com/miekg/dns"
"go4.org/netipx"
)
@@ -96,6 +98,7 @@ type Endpoint struct {
routerCfg *router.Config
dnsCfg *tsDNS.Config
routeDomains common.TypedValue[map[string]bool]
searchDomains atomic.Bool
routePrefixes atomic.Pointer[netipx.IPSet]
acceptRoutes bool
@@ -260,6 +263,8 @@ func NewEndpoint(ctx context.Context, router adapter.Router, logger log.ContextL
func (t *Endpoint) Start(stage adapter.StartStage) error {
switch stage {
case adapter.StartStateInitialize:
t.server.PeerDNSQueryHandler = (*peerDNSQueryHandler)(t)
case adapter.StartStateStart:
return t.start()
case adapter.StartStatePostStart:
@@ -678,9 +683,9 @@ func (t *Endpoint) PrepareConnection(network string, source M.Socksaddr, destina
}, routeContext, timeout, false)
if err != nil {
switch {
case rule.IsBypassed(err):
case R.IsBypassed(err):
err = nil
case rule.IsRejected(err):
case R.IsRejected(err):
t.logger.Trace("reject ", network, " connection from ", source.AddrString(), " to ", destination.AddrString())
default:
if network == N.NetworkICMP {
@@ -781,7 +786,11 @@ func (t *Endpoint) PreferredDomain(domain string) bool {
if routeDomains == nil {
return false
}
return routeDomains[strings.ToLower(domain)]
domain = strings.ToLower(domain)
if routeDomains[domain] {
return true
}
return !strings.Contains(domain, ".") && t.searchDomains.Load()
}
func (t *Endpoint) PreferredAddress(address netip.Addr) bool {
@@ -826,10 +835,14 @@ func (t *Endpoint) onReconfig(cfg *wgcfg.Config, routerCfg *router.Config, dnsCf
routeDomains[fqdn.WithoutTrailingDot()] = true
}
t.routeDomains.Store(routeDomains)
t.searchDomains.Store(len(dnsCfg.SearchDomains) > 0)
var builder netipx.IPSetBuilder
for _, peer := range cfg.Peers {
for _, allowedIP := range peer.AllowedIPs {
if allowedIP.Bits() == 0 {
continue
}
builder.AddPrefix(allowedIP)
}
}
@@ -888,3 +901,30 @@ func (c *dnsConfigurtor) GetBaseConfig() (tsDNS.OSConfig, error) {
func (c *dnsConfigurtor) Close() error {
return nil
}
type peerDNSQueryHandler Endpoint
func (t *peerDNSQueryHandler) HandlePeerDNSQuery(ctx context.Context, query []byte, sourceAddress netip.AddrPort, allowName func(name string) bool) ([]byte, error) {
var message mDNS.Msg
err := message.Unpack(query)
if err != nil {
return nil, err
}
for _, question := range message.Question {
if allowName != nil && !allowName(question.Name) {
return dns.FixedResponseStatus(&message, mDNS.RcodeRefused).Pack()
}
}
var metadata adapter.InboundContext
metadata.Inbound = t.Tag()
metadata.InboundType = t.Type()
metadata.Source = M.SocksaddrFromNetIP(sourceAddress)
response, err := t.dnsRouter.Exchange(adapter.WithContext(ctx, &metadata), &message, adapter.DNSQueryOptions{})
if err != nil {
if !R.IsRejected(err) && !E.IsClosedOrCanceled(err) {
t.logger.ErrorContext(ctx, E.Cause(err, "process peer DNS query"))
}
return nil, err
}
return response.Pack()
}

View File

@@ -29,13 +29,14 @@ func RegisterClientEndpoint(registry *endpoint.Registry) {
type ClientEndpoint struct {
outbound.Adapter
ctx context.Context
outbound adapter.Outbound
router adapter.ConnectionRouterEx
logger logger.ContextLogger
address IPv4
key uuid.UUID
uotClient *uot.Client
ctx context.Context
outbound adapter.Outbound
router adapter.ConnectionRouterEx
logger logger.ContextLogger
address IPv4
key uuid.UUID
defaultGateway IPv4
uotClient *uot.Client
}
func NewClientEndpoint(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.VPNClientEndpointOptions) (adapter.Endpoint, error) {
@@ -47,13 +48,21 @@ func NewClientEndpoint(ctx context.Context, router adapter.Router, logger log.Co
if err != nil {
return nil, err
}
defaultGateway := Loopback.As4()
if options.DefaultGateway.IsValid() {
if !options.DefaultGateway.Is4() {
return nil, E.New("invalid default_gateway: ", options.DefaultGateway)
}
defaultGateway = options.DefaultGateway.As4()
}
client := &ClientEndpoint{
Adapter: outbound.NewAdapter(C.TypeVPNClient, tag, []string{N.NetworkTCP, N.NetworkUDP}, []string{}),
ctx: ctx,
router: sbUot.NewRouter(router, logger),
logger: logger,
address: address.As4(),
key: key,
Adapter: outbound.NewAdapter(C.TypeVPNClient, tag, []string{N.NetworkTCP, N.NetworkUDP}, []string{}),
ctx: ctx,
router: sbUot.NewRouter(router, logger),
logger: logger,
address: address.As4(),
key: key,
defaultGateway: defaultGateway,
}
outboundRegistry := service.FromContext[adapter.OutboundRegistry](ctx)
outbound, err := outboundRegistry.CreateOutbound(ctx, router, logger, options.Outbound.Tag, options.Outbound.Type, options.Outbound.Options)
@@ -102,7 +111,7 @@ func (c *ClientEndpoint) DialContext(ctx context.Context, network string, destin
if err != nil {
return nil, err
}
gateway := Loopback.As4()
gateway := c.defaultGateway
if metadata := adapter.ContextFrom(ctx); metadata != nil {
if metadata.Gateway != nil {
gateway = metadata.Gateway.As4()

View File

@@ -29,15 +29,16 @@ func RegisterServerEndpoint(registry *endpoint.Registry) {
type ServerEndpoint struct {
outbound.Adapter
logger logger.ContextLogger
inbounds []adapter.Inbound
router adapter.ConnectionRouterEx
address IPv4
addresses map[uuid.UUID]IPv4
keys map[IPv4]uuid.UUID
conns map[IPv4]chan net.Conn
timeout time.Duration
uotClient *uot.Client
logger logger.ContextLogger
inbounds []adapter.Inbound
router adapter.ConnectionRouterEx
address IPv4
addresses map[uuid.UUID]IPv4
keys map[IPv4]uuid.UUID
conns map[IPv4]chan net.Conn
timeout time.Duration
defaultGateway *netip.Addr
uotClient *uot.Client
}
func NewServerEndpoint(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.VPNServerEndpointOptions) (adapter.Endpoint, error) {
@@ -51,6 +52,13 @@ func NewServerEndpoint(ctx context.Context, router adapter.Router, logger log.Co
router: sbUot.NewRouter(router, logger),
address: address.As4(),
}
if options.DefaultGateway.IsValid() {
if !options.DefaultGateway.Is4() {
return nil, E.New("invalid default_gateway: ", options.DefaultGateway)
}
defaultGateway := options.DefaultGateway
server.defaultGateway = &defaultGateway
}
router = NewRouter(router, logger, server.connHandler)
inboundRegistry := service.FromContext[adapter.InboundRegistry](ctx)
inbounds := make([]adapter.Inbound, len(options.Inbounds))
@@ -118,7 +126,9 @@ func (s *ServerEndpoint) DialContext(ctx context.Context, network string, destin
}
}
if gateway == nil {
if destination.IsIPv4() {
if s.defaultGateway != nil {
gateway = s.defaultGateway
} else if destination.IsIPv4() {
gateway = &destination.Addr
destination = M.Socksaddr{
Addr: Loopback,
@@ -127,7 +137,8 @@ func (s *ServerEndpoint) DialContext(ctx context.Context, network string, destin
} else {
return nil, E.New("missing gateway")
}
} else if destination.Addr.Compare(*gateway) == 0 {
}
if destination.Addr.Compare(*gateway) == 0 {
destination = M.Socksaddr{
Addr: Loopback,
Port: destination.Port,

View File

@@ -88,6 +88,25 @@ func NewEndpoint(ctx context.Context, router adapter.Router, logger log.ContextL
}
peer := config.Peers[0]
hostParts := strings.Split(peer.Endpoint.Host, ":")
var amnezia *option.WireGuardAmnezia
if options.Amnezia != nil {
amnezia = &option.WireGuardAmnezia{
JC: options.Amnezia.JC,
JMin: options.Amnezia.JMin,
JMax: options.Amnezia.JMax,
I1: options.Amnezia.I1,
I2: options.Amnezia.I2,
I3: options.Amnezia.I3,
I4: options.Amnezia.I4,
I5: options.Amnezia.I5,
ContentPaddingAddition: options.Amnezia.ContentPaddingAddition,
RekeyAfterTime: options.Amnezia.RekeyAfterTime,
RekeyTimeout: options.Amnezia.RekeyTimeout,
RejectAfterTime: options.Amnezia.RejectAfterTime,
KeepaliveTimeout: options.Amnezia.KeepaliveTimeout,
MaxHandshakeAttempts: options.Amnezia.MaxHandshakeAttempts,
}
}
endpoint.endpoint, err = wireguard.NewEndpoint(
ctx,
router,
@@ -101,7 +120,7 @@ func NewEndpoint(ctx context.Context, router adapter.Router, logger log.ContextL
Workers: options.Workers,
PreallocatedBuffersPerPool: options.PreallocatedBuffersPerPool,
DisablePauses: options.DisablePauses,
Amnezia: options.Amnezia,
Amnezia: amnezia,
DialerOptions: options.DialerOptions,
Address: badoption.Listable[netip.Prefix]{

View File

@@ -77,26 +77,29 @@ func NewEndpoint(ctx context.Context, router adapter.Router, logger log.ContextL
var amnezia *wireguard.AmneziaOptions
if options.Amnezia != nil {
amnezia = &wireguard.AmneziaOptions{
JC: options.Amnezia.JC,
JMin: options.Amnezia.JMin,
JMax: options.Amnezia.JMax,
S1: options.Amnezia.S1,
S2: options.Amnezia.S2,
S3: options.Amnezia.S3,
S4: options.Amnezia.S4,
H1: options.Amnezia.H1,
H2: options.Amnezia.H2,
H3: options.Amnezia.H3,
H4: options.Amnezia.H4,
I1: options.Amnezia.I1,
I2: options.Amnezia.I2,
I3: options.Amnezia.I3,
I4: options.Amnezia.I4,
I5: options.Amnezia.I5,
J1: options.Amnezia.J1,
J2: options.Amnezia.J2,
J3: options.Amnezia.J3,
ITime: options.Amnezia.ITime,
JC: options.Amnezia.JC,
JMin: options.Amnezia.JMin,
JMax: options.Amnezia.JMax,
S1: options.Amnezia.S1,
S2: options.Amnezia.S2,
S3: options.Amnezia.S3,
S4: options.Amnezia.S4,
H1: options.Amnezia.H1,
H2: options.Amnezia.H2,
H3: options.Amnezia.H3,
H4: options.Amnezia.H4,
I1: options.Amnezia.I1,
I2: options.Amnezia.I2,
I3: options.Amnezia.I3,
I4: options.Amnezia.I4,
I5: options.Amnezia.I5,
HeaderProtectionKey: options.Amnezia.HeaderProtectionKey,
ContentPaddingAddition: options.Amnezia.ContentPaddingAddition,
RekeyAfterTime: options.Amnezia.RekeyAfterTime,
RekeyTimeout: options.Amnezia.RekeyTimeout,
RejectAfterTime: options.Amnezia.RejectAfterTime,
KeepaliveTimeout: options.Amnezia.KeepaliveTimeout,
MaxHandshakeAttempts: options.Amnezia.MaxHandshakeAttempts,
}
}
wgEndpoint, err := wireguard.NewEndpoint(wireguard.EndpointOptions{

View File

@@ -3,6 +3,7 @@ package xhttp
import (
"bytes"
"context"
"errors"
"fmt"
"io"
"net"
@@ -110,15 +111,18 @@ func (c *DefaultDialerClient) OpenStream(ctx context.Context, url string, sessio
if body != nil {
method = c.options.GetNormalizedUplinkHTTPMethod() // stream-up/one
}
req, _ := http.NewRequestWithContext(context.WithoutCancel(ctx), method, url, body)
reqCtx, cancel := context.WithCancel(context.WithoutCancel(ctx))
req, _ := http.NewRequestWithContext(reqCtx, method, url, body)
FillStreamRequest(req, sessionId, "", c.options)
wrc = &WaitReadCloser{Wait: make(chan struct{})}
wrc = &WaitReadCloser{Wait: make(chan struct{}), Cancel: cancel}
go func() {
resp, err := c.client.Do(req)
var resp *http.Response
resp, err = c.client.Do(req)
if err != nil {
if !uploadOnly { // stream-down is enough
if !uploadOnly && !errors.Is(err, context.Canceled) { // stream-down is enough
c.Close()
}
cancel()
gotConn.Close()
common.Close(body)
wrc.Close()
@@ -128,6 +132,7 @@ func (c *DefaultDialerClient) OpenStream(ctx context.Context, url string, sessio
io.Copy(io.Discard, resp.Body)
resp.Body.Close() // if it is called immediately, the upload will be interrupted also
common.Close(body)
cancel()
wrc.Close()
return
}
@@ -210,7 +215,8 @@ func (c *DefaultDialerClient) PostPacket(ctx context.Context, url string, sessio
}
type WaitReadCloser struct {
Wait chan struct{}
Wait chan struct{}
Cancel context.CancelFunc
io.ReadCloser
}
@@ -233,6 +239,9 @@ func (w *WaitReadCloser) Read(b []byte) (int, error) {
}
func (w *WaitReadCloser) Close() error {
if w.Cancel != nil {
w.Cancel()
}
if w.ReadCloser != nil {
return w.ReadCloser.Close()
}

View File

@@ -235,17 +235,30 @@ func (e *Endpoint) Start(resolve bool) error {
if e.options.Amnezia.I5 != "" {
ipcConf.WriteString("\ni5=" + e.options.Amnezia.I5)
}
if e.options.Amnezia.J1 != "" {
ipcConf.WriteString("\nj1=" + e.options.Amnezia.J1)
if e.options.Amnezia.HeaderProtectionKey != "" {
headerProtectionKeyBytes, err := base64.StdEncoding.DecodeString(e.options.Amnezia.HeaderProtectionKey)
if err != nil {
return E.Cause(err, "decode header protection key")
}
ipcConf.WriteString("\nheader_protection_key=" + hex.EncodeToString(headerProtectionKeyBytes))
}
if e.options.Amnezia.J2 != "" {
ipcConf.WriteString("\nj2=" + e.options.Amnezia.J2)
if e.options.Amnezia.ContentPaddingAddition != nil {
ipcConf.WriteString("\ncontent_padding_addition=" + e.options.Amnezia.ContentPaddingAddition.String())
}
if e.options.Amnezia.J3 != "" {
ipcConf.WriteString("\nj3=" + e.options.Amnezia.J3)
if e.options.Amnezia.RekeyAfterTime != nil {
ipcConf.WriteString("\nrekey_after_time=" + e.options.Amnezia.RekeyAfterTime.String())
}
if e.options.Amnezia.ITime > 0 {
ipcConf.WriteString("\nitime=" + strconv.FormatInt(e.options.Amnezia.ITime, 10))
if e.options.Amnezia.RekeyTimeout != nil {
ipcConf.WriteString("\nrekey_timeout=" + e.options.Amnezia.RekeyTimeout.String())
}
if e.options.Amnezia.RejectAfterTime != nil {
ipcConf.WriteString("\nreject_after_time=" + e.options.Amnezia.RejectAfterTime.String())
}
if e.options.Amnezia.KeepaliveTimeout != nil {
ipcConf.WriteString("\nkeepalive_timeout=" + e.options.Amnezia.KeepaliveTimeout.String())
}
if e.options.Amnezia.MaxHandshakeAttempts != nil {
ipcConf.WriteString("\nmax_handshake_attempts=" + e.options.Amnezia.MaxHandshakeAttempts.String())
}
}
for _, peer := range e.peers {

View File

@@ -5,8 +5,8 @@ import (
"net/netip"
"time"
"github.com/sagernet/sing/common/json/badoption"
tun "github.com/sagernet/sing-tun"
"github.com/sagernet/sing/common/json/badoption"
"github.com/sagernet/sing/common/logger"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
@@ -43,24 +43,27 @@ type PeerOptions struct {
}
type AmneziaOptions struct {
JC int
JMin int
JMax int
S1 int
S2 int
S3 int
S4 int
H1 *badoption.Range[uint32]
H2 *badoption.Range[uint32]
H3 *badoption.Range[uint32]
H4 *badoption.Range[uint32]
I1 string
I2 string
I3 string
I4 string
I5 string
J1 string
J2 string
J3 string
ITime int64
JC int
JMin int
JMax int
S1 int
S2 int
S3 int
S4 int
H1 *badoption.Range[uint32]
H2 *badoption.Range[uint32]
H3 *badoption.Range[uint32]
H4 *badoption.Range[uint32]
I1 string
I2 string
I3 string
I4 string
I5 string
HeaderProtectionKey string
ContentPaddingAddition *badoption.Range[uint32]
RekeyAfterTime *badoption.Range[uint32]
RekeyTimeout *badoption.Range[uint32]
RejectAfterTime *badoption.Range[uint32]
KeepaliveTimeout *badoption.Range[uint32]
MaxHandshakeAttempts *badoption.Range[uint32]
}