Compare commits

..

17 Commits

Author SHA1 Message Date
世界
ebe75d89ab documentation: Bump version 2025-02-11 01:35:42 +08:00
世界
1a4b316186 badjson: Fix merge objects 2025-02-11 01:35:42 +08:00
ReleTor
e0869a7ba6 documentation: Fixes 2025-02-11 01:35:41 +08:00
世界
442a13bcfe Fix crash in exchangeParallel 2025-02-11 01:35:41 +08:00
世界
5da866f1c0 Fix match DNS rule for fqdn 2025-02-11 01:35:40 +08:00
世界
874cba47ff Fix WireGuard panic 2025-02-11 01:35:40 +08:00
世界
81df32e200 Fix domain resolver for DNS server 2025-02-11 01:35:40 +08:00
世界
835bbe3a96 documentation: Fix fakeip example 2025-02-11 01:35:40 +08:00
世界
ec47668d1b documentation: Remove outdated icons 2025-02-11 01:35:39 +08:00
世界
f5faa66b71 documentation: Certificate store 2025-02-11 01:35:39 +08:00
世界
4acb5b3987 documentation: TLS fragment 2025-02-11 01:35:39 +08:00
世界
b63247f627 documentation: Outbound domain resolver 2025-02-11 01:35:38 +08:00
世界
b3c78487de documentation: Refactor DNS 2025-02-11 01:35:38 +08:00
世界
cc068195f0 Add certificate store 2025-02-11 01:35:38 +08:00
世界
e819c3a0b6 Add TLS fragment support 2025-02-11 01:35:37 +08:00
世界
b8f6670453 refactor: Outbound domain resolver 2025-02-11 01:35:37 +08:00
世界
3ab4c97178 refactor: DNS 2025-02-11 01:35:36 +08:00
77 changed files with 896 additions and 2629 deletions

View File

@@ -1,22 +0,0 @@
#!/usr/bin/env bash
VERSION="1.23.6"
wget "https://dl.google.com/go/go${VERSION}.linux-amd64.tar.gz"
tar -xzf "go${VERSION}.linux-amd64.tar.gz"
mv go $HOME/go/go_legacy
cd $HOME/go/go_legacy
# modify from https://github.com/restic/restic/issues/4636#issuecomment-1896455557
# this patch file only works on golang1.23.x
# that means after golang1.24 release it must be changed
# see: https://github.com/MetaCubeX/go/commits/release-branch.go1.23/
# revert:
# 693def151adff1af707d82d28f55dba81ceb08e1: "crypto/rand,runtime: switch RtlGenRandom for ProcessPrng"
# 7c1157f9544922e96945196b47b95664b1e39108: "net: remove sysSocket fallback for Windows 7"
# 48042aa09c2f878c4faa576948b07fe625c4707a: "syscall: remove Windows 7 console handle workaround"
# a17d959debdb04cd550016a3501dd09d50cd62e7: "runtime: always use LoadLibraryEx to load system libraries"
curl https://github.com/MetaCubeX/go/commit/9ac42137ef6730e8b7daca016ece831297a1d75b.diff | patch --verbose -p 1
curl https://github.com/MetaCubeX/go/commit/21290de8a4c91408de7c2b5b68757b1e90af49dd.diff | patch --verbose -p 1
curl https://github.com/MetaCubeX/go/commit/6a31d3fa8e47ddabc10bd97bff10d9a85f4cfb76.diff | patch --verbose -p 1
curl https://github.com/MetaCubeX/go/commit/69e2eed6dd0f6d815ebf15797761c13f31213dd6.diff | patch --verbose -p 1

View File

@@ -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 go-version: ^1.23
- name: Check input version - name: Check input version
if: github.event_name == 'workflow_dispatch' if: github.event_name == 'workflow_dispatch'
run: |- run: |-
@@ -112,6 +112,7 @@ jobs:
- name: darwin_amd64 - name: darwin_amd64
goos: darwin goos: darwin
goarch: amd64 goarch: amd64
require_legacy_go: true
- name: android_arm64 - name: android_arm64
goos: android goos: android
goarch: arm64 goarch: arm64
@@ -133,18 +134,21 @@ jobs:
- name: Setup Go - name: Setup Go
uses: actions/setup-go@v5 uses: actions/setup-go@v5
with: with:
go-version: ^1.24 go-version: ^1.23
- 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
uses: actions/cache@v4 uses: actions/cache@v4
with: with:
path: | path: |
~/go/go_legacy ~/go/go1.20.14
key: go_legacy_1236 key: go120
- name: Setup legacy Go - name: Setup legacy Go
if: matrix.require_legacy_go && steps.cache-legacy-go.outputs.cache-hit != 'true' if: matrix.require_legacy_go && steps.cache-legacy-go.outputs.cache-hit != 'true'
run: bash .github/setup_legacy_go.sh run: |-
wget https://dl.google.com/go/go1.20.14.linux-amd64.tar.gz
tar -xzf go1.20.14.linux-amd64.tar.gz
mv go $HOME/go/go1.20.14
- name: Setup Android NDK - name: Setup Android NDK
if: matrix.goos == 'android' if: matrix.goos == 'android'
uses: nttld/setup-ndk@v1 uses: nttld/setup-ndk@v1
@@ -215,7 +219,7 @@ jobs:
- name: Setup Go - name: Setup Go
uses: actions/setup-go@v5 uses: actions/setup-go@v5
with: with:
go-version: ^1.24 go-version: ^1.23
- name: Setup Android NDK - name: Setup Android NDK
id: setup-ndk id: setup-ndk
uses: nttld/setup-ndk@v1 uses: nttld/setup-ndk@v1
@@ -252,16 +256,9 @@ jobs:
with: with:
path: ~/.gradle path: ~/.gradle
key: gradle-${{ hashFiles('**/*.gradle') }} key: gradle-${{ hashFiles('**/*.gradle') }}
- name: Update version
if: github.event_name == 'workflow_dispatch'
run: |-
go run -v ./cmd/internal/update_android_version --ci
- name: Update nightly version
if: github.event_name != 'workflow_dispatch'
run: |-
go run -v ./cmd/internal/update_android_version --ci --nightly
- name: Build - name: Build
run: |- run: |-
go run -v ./cmd/internal/update_android_version --ci
mkdir clients/android/app/libs mkdir clients/android/app/libs
cp libbox.aar clients/android/app/libs cp libbox.aar clients/android/app/libs
cd clients/android cd clients/android
@@ -297,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 go-version: ^1.23
- name: Setup Android NDK - name: Setup Android NDK
id: setup-ndk id: setup-ndk
uses: nttld/setup-ndk@v1 uses: nttld/setup-ndk@v1
@@ -395,7 +392,7 @@ jobs:
if: matrix.if if: matrix.if
uses: actions/setup-go@v5 uses: actions/setup-go@v5
with: with:
go-version: ^1.24 go-version: ^1.23
- 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: |-

View File

@@ -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 go-version: ^1.23
- name: golangci-lint - name: golangci-lint
uses: golangci/golangci-lint-action@v6 uses: golangci/golangci-lint-action@v6
with: with:

View File

@@ -16,7 +16,7 @@ jobs:
- name: Setup Go - name: Setup Go
uses: actions/setup-go@v5 uses: actions/setup-go@v5
with: with:
go-version: ^1.24 go-version: ^1.23
- name: Extract signing key - name: Extract signing key
run: |- run: |-
mkdir -p $HOME/.gnupg mkdir -p $HOME/.gnupg

View File

@@ -21,7 +21,7 @@ linters-settings:
- -SA1003 - -SA1003
run: run:
go: "1.24" go: "1.23"
build-tags: build-tags:
- with_gvisor - with_gvisor
- with_quic - with_quic

View File

@@ -19,7 +19,6 @@ builds:
- with_reality_server - with_reality_server
- with_acme - with_acme
- with_clash_api - with_clash_api
- with_tailscale
env: env:
- CGO_ENABLED=0 - CGO_ENABLED=0
targets: targets:

View File

@@ -21,7 +21,6 @@ builds:
- with_reality_server - with_reality_server
- with_acme - with_acme
- with_clash_api - with_clash_api
- with_tailscale
env: env:
- CGO_ENABLED=0 - CGO_ENABLED=0
targets: targets:
@@ -50,14 +49,14 @@ builds:
- with_reality_server - with_reality_server
- with_acme - with_acme
- with_clash_api - with_clash_api
- with_tailscale
env: env:
- CGO_ENABLED=0 - CGO_ENABLED=0
- GOROOT={{ .Env.GOPATH }}/go_legacy - GOROOT={{ .Env.GOPATH }}/go1.20.14
tool: "{{ .Env.GOPATH }}/go_legacy/bin/go" tool: "{{ .Env.GOPATH }}/go1.20.14/bin/go"
targets: targets:
- windows_amd64_v1 - windows_amd64_v1
- windows_386 - windows_386
- darwin_amd64_v1
- id: android - id: android
<<: *template <<: *template
env: env:
@@ -123,8 +122,8 @@ nfpms:
- deb - deb
- rpm - rpm
- archlinux - archlinux
# - apk # - apk
# - ipk # - ipk
priority: extra priority: extra
contents: contents:
- src: release/config/config.json - src: release/config/config.json

View File

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

View File

@@ -2,8 +2,7 @@ NAME = sing-box
COMMIT = $(shell git rev-parse --short HEAD) COMMIT = $(shell git rev-parse --short HEAD)
TAGS_GO120 = with_gvisor,with_dhcp,with_wireguard,with_reality_server,with_clash_api,with_quic,with_utls TAGS_GO120 = with_gvisor,with_dhcp,with_wireguard,with_reality_server,with_clash_api,with_quic,with_utls
TAGS_GO121 = with_ech TAGS_GO121 = with_ech
TAGS_GO123 = with_tailscale TAGS ?= $(TAGS_GO118),$(TAGS_GO120),$(TAGS_GO121)
TAGS ?= $(TAGS_GO118),$(TAGS_GO120),$(TAGS_GO121),$(TAGS_GO123)
TAGS_TEST ?= with_gvisor,with_quic,with_wireguard,with_grpc,with_ech,with_utls,with_reality_server TAGS_TEST ?= with_gvisor,with_quic,with_wireguard,with_grpc,with_ech,with_utls,with_reality_server
GOHOSTOS = $(shell go env GOHOSTOS) GOHOSTOS = $(shell go env GOHOSTOS)

View File

@@ -5,7 +5,6 @@ import (
"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-tun"
N "github.com/sagernet/sing/common/network" N "github.com/sagernet/sing/common/network"
) )
@@ -19,11 +18,6 @@ type Outbound interface {
N.Dialer N.Dialer
} }
type DirectRouteOutbound interface {
Outbound
NewDirectRouteConnection(metadata InboundContext, routeContext tun.DirectRouteContext) (tun.DirectRouteDestination, error)
}
type OutboundRegistry interface { type OutboundRegistry interface {
option.OutboundOptionsRegistry option.OutboundOptionsRegistry
CreateOutbound(ctx context.Context, router Router, logger log.ContextLogger, tag string, outboundType string, options any) (Outbound, error) CreateOutbound(ctx context.Context, router Router, logger log.ContextLogger, tag string, outboundType string, options any) (Outbound, error)

View File

@@ -8,7 +8,6 @@ import (
"sync" "sync"
C "github.com/sagernet/sing-box/constant" C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-tun"
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"
@@ -20,7 +19,7 @@ import (
type Router interface { type Router interface {
Lifecycle Lifecycle
ConnectionRouter ConnectionRouter
PreMatch(metadata InboundContext, context tun.DirectRouteContext) (tun.DirectRouteDestination, error) PreMatch(metadata InboundContext) error
ConnectionRouterEx ConnectionRouterEx
RuleSet(tag string) (RuleSet, bool) RuleSet(tag string) (RuleSet, bool)
NeedWIFIState() bool NeedWIFIState() bool

View File

@@ -58,7 +58,7 @@ 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_ech", "with_utls", "with_clash_api", "with_tailscale") sharedTags = append(sharedTags, "with_gvisor", "with_quic", "with_wireguard", "with_ech", "with_utls", "with_clash_api")
iosTags = append(iosTags, "with_dhcp", "with_low_memory", "with_conntrack") iosTags = append(iosTags, "with_dhcp", "with_low_memory", "with_conntrack")
debugTags = append(debugTags, "debug") debugTags = append(debugTags, "debug")
} }

View File

@@ -13,14 +13,10 @@ import (
"github.com/sagernet/sing/common" "github.com/sagernet/sing/common"
) )
var ( var flagRunInCI bool
flagRunInCI bool
flagRunNightly bool
)
func init() { func init() {
flag.BoolVar(&flagRunInCI, "ci", false, "Run in CI") flag.BoolVar(&flagRunInCI, "ci", false, "Run in CI")
flag.BoolVar(&flagRunNightly, "nightly", false, "Run nightly")
} }
func main() { func main() {
@@ -50,23 +46,21 @@ func main() {
switch propPair[0] { switch propPair[0] {
case "VERSION_NAME": case "VERSION_NAME":
if propPair[1] != newVersion { if propPair[1] != newVersion {
log.Info("updated version from ", propPair[1], " to ", newVersion)
versionUpdated = true versionUpdated = true
propPair[1] = newVersion propPair[1] = newVersion
log.Info("updated version to ", newVersion)
} }
case "GO_VERSION": case "GO_VERSION":
if propPair[1] != runtime.Version() { if propPair[1] != runtime.Version() {
log.Info("updated Go version from ", propPair[1], " to ", runtime.Version())
goVersionUpdated = true goVersionUpdated = true
propPair[1] = runtime.Version() propPair[1] = runtime.Version()
log.Info("updated Go version to ", runtime.Version())
} }
} }
} }
if !(versionUpdated || goVersionUpdated) { if !(versionUpdated || goVersionUpdated) {
log.Info("version not changed") log.Info("version not changed")
return return
} else if flagRunInCI && !flagRunNightly {
log.Fatal("version changed, commit changes first.")
} }
for _, propPair := range propsList { for _, propPair := range propsList {
switch propPair[0] { switch propPair[0] {

View File

@@ -60,10 +60,7 @@ func init() {
generated.WriteString(record[nameIndex]) generated.WriteString(record[nameIndex])
generated.WriteString("\n") generated.WriteString("\n")
generated.WriteString(" mozillaIncluded.AppendCertsFromPEM([]byte(`") generated.WriteString(" mozillaIncluded.AppendCertsFromPEM([]byte(`")
cert := record[certIndex] generated.WriteString(record[certIndex])
// Remove single quotes
cert = cert[1 : len(cert)-1]
generated.WriteString(cert)
generated.WriteString("`))\n") generated.WriteString("`))\n")
} }
generated.WriteString("}\n") generated.WriteString("}\n")

File diff suppressed because it is too large Load Diff

View File

@@ -33,14 +33,16 @@ func NewStore(ctx context.Context, logger logger.Logger, options option.Certific
var systemPool *x509.CertPool var systemPool *x509.CertPool
switch options.Store { switch options.Store {
case C.CertificateStoreSystem, "": case C.CertificateStoreSystem, "":
systemPool = x509.NewCertPool() platformInterface := service.FromContext[platform.Interface](ctx)
var systemValid bool systemCertificates := platformInterface.SystemCertificates()
for _, cert := range service.FromContext[platform.Interface](ctx).SystemCertificates() { if len(systemCertificates) > 0 {
if systemPool.AppendCertsFromPEM([]byte(cert)) { systemPool = x509.NewCertPool()
systemValid = true for _, cert := range systemCertificates {
if !systemPool.AppendCertsFromPEM([]byte(cert)) {
return nil, E.New("invalid system certificate PEM: ", cert)
}
} }
} } else {
if !systemValid {
certPool, err := x509.SystemCertPool() certPool, err := x509.SystemCertPool()
if err != nil { if err != nil {
return nil, err return nil, err

View File

@@ -22,7 +22,6 @@ type Options struct {
RemoteIsDomain bool RemoteIsDomain bool
DirectResolver bool DirectResolver bool
ResolverOnDetour bool ResolverOnDetour bool
NewDialer bool
} }
// TODO: merge with NewWithOptions // TODO: merge with NewWithOptions
@@ -101,8 +100,6 @@ func NewWithOptions(options Options) (N.Dialer, error) {
} }
dnsQueryOptions.Transport = transport dnsQueryOptions.Transport = transport
resolveFallbackDelay = time.Duration(dialOptions.FallbackDelay) resolveFallbackDelay = time.Duration(dialOptions.FallbackDelay)
} else if options.NewDialer {
return nil, E.New("missing domain resolver for domain server address")
} else { } else {
deprecated.Report(options.Context, deprecated.OptionMissingDomainResolver) deprecated.Report(options.Context, deprecated.OptionMissingDomainResolver)
} }

View File

@@ -16,7 +16,7 @@ import (
"github.com/caddyserver/certmagic" "github.com/caddyserver/certmagic"
"github.com/libdns/alidns" "github.com/libdns/alidns"
"github.com/libdns/cloudflare" "github.com/libdns/cloudflare"
"github.com/mholt/acmez/v3/acme" "github.com/mholt/acmez/acme"
"go.uber.org/zap" "go.uber.org/zap"
"go.uber.org/zap/zapcore" "go.uber.org/zap/zapcore"
) )

View File

@@ -27,7 +27,6 @@ const (
DNSTypePreDefined = "predefined" DNSTypePreDefined = "predefined"
DNSTypeFakeIP = "fakeip" DNSTypeFakeIP = "fakeip"
DNSTypeDHCP = "dhcp" DNSTypeDHCP = "dhcp"
DNSTypeTailscale = "tailscale"
) )
const ( const (

View File

@@ -23,7 +23,6 @@ const (
TypeVLESS = "vless" TypeVLESS = "vless"
TypeTUIC = "tuic" TypeTUIC = "tuic"
TypeHysteria2 = "hysteria2" TypeHysteria2 = "hysteria2"
TypeTailscale = "tailscale"
) )
const ( const (

View File

@@ -174,6 +174,7 @@ func (r *Router) matchDNS(ctx context.Context, allowFakeIP bool, ruleIndex int,
options.ClientSubnet = legacyTransport.LegacyClientSubnet() options.ClientSubnet = legacyTransport.LegacyClientSubnet()
} }
} }
r.logger.DebugContext(ctx, "match[", displayRuleIndex, "] => ", currentRule.Action())
return transport, currentRule, currentRuleIndex return transport, currentRule, currentRuleIndex
case *R.RuleActionDNSRouteOptions: case *R.RuleActionDNSRouteOptions:
if action.Strategy != C.DomainStrategyAsIS { if action.Strategy != C.DomainStrategyAsIS {
@@ -188,7 +189,9 @@ func (r *Router) matchDNS(ctx context.Context, allowFakeIP bool, ruleIndex int,
if action.ClientSubnet.IsValid() { if action.ClientSubnet.IsValid() {
options.ClientSubnet = action.ClientSubnet options.ClientSubnet = action.ClientSubnet
} }
r.logger.DebugContext(ctx, "match[", displayRuleIndex, "] => ", currentRule.Action())
case *R.RuleActionReject: case *R.RuleActionReject:
r.logger.DebugContext(ctx, "match[", displayRuleIndex, "] => ", currentRule.Action())
return nil, currentRule, currentRuleIndex return nil, currentRule, currentRuleIndex
} }
} }

View File

@@ -2,45 +2,14 @@
icon: material/alert-decagram icon: material/alert-decagram
--- ---
#### 1.12.0-alpha.8
* Fixes and improvements
#### 1.12.0-alpha.7
* Add Tailscale DNS server **1**
* Fixes and improvements
**1**:
See [Tailscale](/configuration/dns/server/tailscale/).
#### 1.12.0-alpha.6
* Add Tailscale endpoint **1**
* Drop support for go1.22 **2**
* Fixes and improvements
**1**:
See [Tailscale](/configuration/endpoint/tailscale/).
**2**:
Due to maintenance difficulties, sing-box 1.12.0 requires at least Go 1.23 to compile.
For Windows 7 users, legacy binaries now continue to compile with Go 1.23 and patches from [MetaCubeX/go](https://github.com/MetaCubeX/go).
### 1.11.3
* Fixes and improvements
_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
* Fixes and improvements * Fixes and improvements
### 1.11.2
* Fixes and improvements
### 1.11.1 ### 1.11.1
* Fixes and improvements * Fixes and improvements

View File

@@ -1,83 +0,0 @@
---
icon: material/new-box
---
!!! question "Since sing-box 1.12.0"
# Tailscale
### Structure
```json
{
"dns": {
"servers": [
{
"type": "tailscale",
"tag": "",
"endpoint": "ts-ep",
"accept_default_resolvers": false
}
]
}
}
```
### Fields
#### endpoint
==Required==
The tag of the Tailscale endpoint.
#### accept_default_resolvers
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.
### Examples
=== "MagicDNS only"
```json
{
"dns": {
"servers": [
{
"type": "local",
"tag": "local"
},
{
"type": "tailscale",
"tag": "ts",
"endpoint": "ts-ep"
}
],
"rules": [
{
"ip_accept_any": true,
"server": "ts"
}
]
}
}
```
=== "Use as global DNS"
```json
{
"dns": {
"servers": [
{
"type": "tailscale",
"endpoint": "ts-ep",
"accept_default_resolvers": true
}
]
}
}
```

View File

@@ -1,99 +0,0 @@
---
icon: material/new-box
---
!!! question "Since sing-box 1.12.0"
### Structure
```json
{
"type": "tailscale",
"tag": "ts-ep",
"state_directory": "",
"auth_key": "",
"control_url": "",
"ephemeral": false,
"hostname": "",
"exit_node": "",
"exit_node_allow_lan_access": false,
"advertise_routes": [],
"advertise_exit_node": false,
"udp_timeout": "5m",
... // Dial Fields
}
```
### Fields
#### state_directory
The directory where the Tailscale state is stored.
`tailscale` is used by default.
Example: `$HOME/.tailscale`
#### auth_key
!!! note
Auth key is not required. By default, sing-box will log the login URL (or popup a notification on graphical clients).
The auth key to create the node. If the node is already created (from state previously stored), then this field is not
used.
#### control_url
The coordination server URL.
`https://controlplane.tailscale.com` is used by default.
#### ephemeral
Indicates whether the instance should register as an Ephemeral node (https://tailscale.com/s/ephemeral-nodes).
#### hostname
The hostname of the node.
System hostname is used by default.
Example: `localhost`
#### exit_node
The exit node name or IP address to use.
#### exit_node_allow_lan_access
!!! note
When the exit node does not have a corresponding advertised route, private traffics cannot be routed to the exit node even if `exit_node_allow_lan_access is` set.
Indicates whether locally accessible subnets should be routed directly or via the exit node.
#### advertise_routes
CIDR prefixes to advertise into the Tailscale network as reachable through the current node.
Example: `["192.168.1.1/24"]`
#### advertise_exit_node
Indicates whether the node should advertise itself as an exit node.
#### udp_timeout
UDP NAT expiration time.
`5m` will be used by default.
### Dial Fields
!!! note
Dial Fields in Tailscale endpoints only control how it connects to the control plane and have nothing to do with actual connections.
See [Dial Fields](/configuration/shared/dial/) for details.

View File

@@ -1,12 +1,3 @@
---
icon: material/new-box
---
!!! quote "Changes in sing-box 1.12.0"
:material-plus: [server_ports](#server_ports)
:material-plus: [hop_interval](#hop_interval)
### Structure ### Structure
```json ```json
@@ -16,10 +7,6 @@ icon: material/new-box
"server": "127.0.0.1", "server": "127.0.0.1",
"server_port": 1080, "server_port": 1080,
"server_ports": [
"2080:3000"
],
"hop_interval": "",
"up": "100 Mbps", "up": "100 Mbps",
"up_mbps": 100, "up_mbps": 100,
"down": "100 Mbps", "down": "100 Mbps",
@@ -51,22 +38,6 @@ The server address.
The server port. The server port.
#### server_ports
!!! question "Since sing-box 1.12.0"
Server port range list.
Conflicts with `server_port`.
#### hop_interval
!!! question "Since sing-box 1.12.0"
Port hopping interval.
`30s` is used by default.
#### up, down #### up, down
==Required== ==Required==

View File

@@ -1,12 +1,3 @@
---
icon: material/new-box
---
!!! quote "sing-box 1.12.0 中的更改"
:material-plus: [server_ports](#server_ports)
:material-plus: [hop_interval](#hop_interval)
### 结构 ### 结构
```json ```json
@@ -16,10 +7,6 @@ icon: material/new-box
"server": "127.0.0.1", "server": "127.0.0.1",
"server_port": 1080, "server_port": 1080,
"server_ports": [
"2080:3000"
],
"hop_interval": "",
"up": "100 Mbps", "up": "100 Mbps",
"up_mbps": 100, "up_mbps": 100,
"down": "100 Mbps", "down": "100 Mbps",
@@ -51,22 +38,6 @@ icon: material/new-box
服务器端口。 服务器端口。
#### server_ports
!!! question "自 sing-box 1.12.0 起"
服务器端口范围列表。
`server_port` 冲突。
#### hop_interval
!!! question "自 sing-box 1.12.0 起"
端口跳跃间隔。
默认使用 `30s`
#### up, down #### up, down
==必填== ==必填==

View File

@@ -60,6 +60,5 @@ go build -tags "tag_a tag_b" ./cmd/sing-box
| `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). |
| `with_gvisor` | :material-check: | Build with gVisor support, see [Tun inbound](/configuration/inbound/tun#stack) and [WireGuard outbound](/configuration/outbound/wireguard#system_interface). | | `with_gvisor` | :material-check: | Build with gVisor support, see [Tun inbound](/configuration/inbound/tun#stack) and [WireGuard outbound](/configuration/outbound/wireguard#system_interface). |
| `with_embedded_tor` (CGO required) | :material-close: | Build with embedded Tor support, see [Tor outbound](/configuration/outbound/tor/). | | `with_embedded_tor` (CGO required) | :material-close: | Build with embedded Tor support, see [Tor outbound](/configuration/outbound/tor/). |
| `with_tailscale` | :material-check: | Build with Tailscale support, see [Tailscale endpoint](/configuration/endpoint/tailscale) |
It is not recommended to change the default build tag list unless you really know what you are adding. It is not recommended to change the default build tag list unless you really know what you are adding.

View File

@@ -60,6 +60,5 @@ go build -tags "tag_a tag_b" ./cmd/sing-box
| `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). |
| `with_gvisor` | :material-check: | Build with gVisor support, see [Tun inbound](/configuration/inbound/tun#stack) and [WireGuard outbound](/configuration/outbound/wireguard#system_interface). | | `with_gvisor` | :material-check: | Build with gVisor support, see [Tun inbound](/configuration/inbound/tun#stack) and [WireGuard outbound](/configuration/outbound/wireguard#system_interface). |
| `with_embedded_tor` (CGO required) | :material-close: | Build with embedded Tor support, see [Tor outbound](/configuration/outbound/tor/). | | `with_embedded_tor` (CGO required) | :material-close: | Build with embedded Tor support, see [Tor outbound](/configuration/outbound/tor/). |
| `with_tailscale` | :material-check: | Build with Tailscale support, see [Tailscale endpoint](/configuration/endpoint/tailscale) |
除非您确实知道您正在启用什么,否则不建议更改默认构建标签列表。 除非您确实知道您正在启用什么,否则不建议更改默认构建标签列表。

View File

@@ -3,7 +3,6 @@ package v2rayapi
import ( import (
reflect "reflect" reflect "reflect"
sync "sync" sync "sync"
unsafe "unsafe"
protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl" protoimpl "google.golang.org/protobuf/runtime/protoimpl"
@@ -17,20 +16,23 @@ const (
) )
type GetStatsRequest struct { type GetStatsRequest struct {
state protoimpl.MessageState `protogen:"open.v1"` state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// Name of the stat counter. // Name of the stat counter.
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
// Whether or not to reset the counter to fetching its value. // Whether or not to reset the counter to fetching its value.
Reset_ bool `protobuf:"varint,2,opt,name=reset,proto3" json:"reset,omitempty"` Reset_ bool `protobuf:"varint,2,opt,name=reset,proto3" json:"reset,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
} }
func (x *GetStatsRequest) Reset() { func (x *GetStatsRequest) Reset() {
*x = GetStatsRequest{} *x = GetStatsRequest{}
mi := &file_experimental_v2rayapi_stats_proto_msgTypes[0] if protoimpl.UnsafeEnabled {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) mi := &file_experimental_v2rayapi_stats_proto_msgTypes[0]
ms.StoreMessageInfo(mi) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
} }
func (x *GetStatsRequest) String() string { func (x *GetStatsRequest) String() string {
@@ -41,7 +43,7 @@ func (*GetStatsRequest) ProtoMessage() {}
func (x *GetStatsRequest) ProtoReflect() protoreflect.Message { func (x *GetStatsRequest) ProtoReflect() protoreflect.Message {
mi := &file_experimental_v2rayapi_stats_proto_msgTypes[0] mi := &file_experimental_v2rayapi_stats_proto_msgTypes[0]
if x != nil { if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -71,18 +73,21 @@ func (x *GetStatsRequest) GetReset_() bool {
} }
type Stat struct { type Stat struct {
state protoimpl.MessageState `protogen:"open.v1"` state protoimpl.MessageState
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
Value int64 `protobuf:"varint,2,opt,name=value,proto3" json:"value,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
Value int64 `protobuf:"varint,2,opt,name=value,proto3" json:"value,omitempty"`
} }
func (x *Stat) Reset() { func (x *Stat) Reset() {
*x = Stat{} *x = Stat{}
mi := &file_experimental_v2rayapi_stats_proto_msgTypes[1] if protoimpl.UnsafeEnabled {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) mi := &file_experimental_v2rayapi_stats_proto_msgTypes[1]
ms.StoreMessageInfo(mi) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
} }
func (x *Stat) String() string { func (x *Stat) String() string {
@@ -93,7 +98,7 @@ func (*Stat) ProtoMessage() {}
func (x *Stat) ProtoReflect() protoreflect.Message { func (x *Stat) ProtoReflect() protoreflect.Message {
mi := &file_experimental_v2rayapi_stats_proto_msgTypes[1] mi := &file_experimental_v2rayapi_stats_proto_msgTypes[1]
if x != nil { if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -123,17 +128,20 @@ func (x *Stat) GetValue() int64 {
} }
type GetStatsResponse struct { type GetStatsResponse struct {
state protoimpl.MessageState `protogen:"open.v1"` state protoimpl.MessageState
Stat *Stat `protobuf:"bytes,1,opt,name=stat,proto3" json:"stat,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Stat *Stat `protobuf:"bytes,1,opt,name=stat,proto3" json:"stat,omitempty"`
} }
func (x *GetStatsResponse) Reset() { func (x *GetStatsResponse) Reset() {
*x = GetStatsResponse{} *x = GetStatsResponse{}
mi := &file_experimental_v2rayapi_stats_proto_msgTypes[2] if protoimpl.UnsafeEnabled {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) mi := &file_experimental_v2rayapi_stats_proto_msgTypes[2]
ms.StoreMessageInfo(mi) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
} }
func (x *GetStatsResponse) String() string { func (x *GetStatsResponse) String() string {
@@ -144,7 +152,7 @@ func (*GetStatsResponse) ProtoMessage() {}
func (x *GetStatsResponse) ProtoReflect() protoreflect.Message { func (x *GetStatsResponse) ProtoReflect() protoreflect.Message {
mi := &file_experimental_v2rayapi_stats_proto_msgTypes[2] mi := &file_experimental_v2rayapi_stats_proto_msgTypes[2]
if x != nil { if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -167,21 +175,24 @@ func (x *GetStatsResponse) GetStat() *Stat {
} }
type QueryStatsRequest struct { type QueryStatsRequest struct {
state protoimpl.MessageState `protogen:"open.v1"` state protoimpl.MessageState
// Deprecated, use Patterns instead
Pattern string `protobuf:"bytes,1,opt,name=pattern,proto3" json:"pattern,omitempty"`
Reset_ bool `protobuf:"varint,2,opt,name=reset,proto3" json:"reset,omitempty"`
Patterns []string `protobuf:"bytes,3,rep,name=patterns,proto3" json:"patterns,omitempty"`
Regexp bool `protobuf:"varint,4,opt,name=regexp,proto3" json:"regexp,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// Deprecated, use Patterns instead
Pattern string `protobuf:"bytes,1,opt,name=pattern,proto3" json:"pattern,omitempty"`
Reset_ bool `protobuf:"varint,2,opt,name=reset,proto3" json:"reset,omitempty"`
Patterns []string `protobuf:"bytes,3,rep,name=patterns,proto3" json:"patterns,omitempty"`
Regexp bool `protobuf:"varint,4,opt,name=regexp,proto3" json:"regexp,omitempty"`
} }
func (x *QueryStatsRequest) Reset() { func (x *QueryStatsRequest) Reset() {
*x = QueryStatsRequest{} *x = QueryStatsRequest{}
mi := &file_experimental_v2rayapi_stats_proto_msgTypes[3] if protoimpl.UnsafeEnabled {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) mi := &file_experimental_v2rayapi_stats_proto_msgTypes[3]
ms.StoreMessageInfo(mi) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
} }
func (x *QueryStatsRequest) String() string { func (x *QueryStatsRequest) String() string {
@@ -192,7 +203,7 @@ func (*QueryStatsRequest) ProtoMessage() {}
func (x *QueryStatsRequest) ProtoReflect() protoreflect.Message { func (x *QueryStatsRequest) ProtoReflect() protoreflect.Message {
mi := &file_experimental_v2rayapi_stats_proto_msgTypes[3] mi := &file_experimental_v2rayapi_stats_proto_msgTypes[3]
if x != nil { if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -236,17 +247,20 @@ func (x *QueryStatsRequest) GetRegexp() bool {
} }
type QueryStatsResponse struct { type QueryStatsResponse struct {
state protoimpl.MessageState `protogen:"open.v1"` state protoimpl.MessageState
Stat []*Stat `protobuf:"bytes,1,rep,name=stat,proto3" json:"stat,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Stat []*Stat `protobuf:"bytes,1,rep,name=stat,proto3" json:"stat,omitempty"`
} }
func (x *QueryStatsResponse) Reset() { func (x *QueryStatsResponse) Reset() {
*x = QueryStatsResponse{} *x = QueryStatsResponse{}
mi := &file_experimental_v2rayapi_stats_proto_msgTypes[4] if protoimpl.UnsafeEnabled {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) mi := &file_experimental_v2rayapi_stats_proto_msgTypes[4]
ms.StoreMessageInfo(mi) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
} }
func (x *QueryStatsResponse) String() string { func (x *QueryStatsResponse) String() string {
@@ -257,7 +271,7 @@ func (*QueryStatsResponse) ProtoMessage() {}
func (x *QueryStatsResponse) ProtoReflect() protoreflect.Message { func (x *QueryStatsResponse) ProtoReflect() protoreflect.Message {
mi := &file_experimental_v2rayapi_stats_proto_msgTypes[4] mi := &file_experimental_v2rayapi_stats_proto_msgTypes[4]
if x != nil { if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -280,16 +294,18 @@ func (x *QueryStatsResponse) GetStat() []*Stat {
} }
type SysStatsRequest struct { type SysStatsRequest struct {
state protoimpl.MessageState `protogen:"open.v1"` state protoimpl.MessageState
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
} }
func (x *SysStatsRequest) Reset() { func (x *SysStatsRequest) Reset() {
*x = SysStatsRequest{} *x = SysStatsRequest{}
mi := &file_experimental_v2rayapi_stats_proto_msgTypes[5] if protoimpl.UnsafeEnabled {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) mi := &file_experimental_v2rayapi_stats_proto_msgTypes[5]
ms.StoreMessageInfo(mi) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
} }
func (x *SysStatsRequest) String() string { func (x *SysStatsRequest) String() string {
@@ -300,7 +316,7 @@ func (*SysStatsRequest) ProtoMessage() {}
func (x *SysStatsRequest) ProtoReflect() protoreflect.Message { func (x *SysStatsRequest) ProtoReflect() protoreflect.Message {
mi := &file_experimental_v2rayapi_stats_proto_msgTypes[5] mi := &file_experimental_v2rayapi_stats_proto_msgTypes[5]
if x != nil { if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -316,26 +332,29 @@ func (*SysStatsRequest) Descriptor() ([]byte, []int) {
} }
type SysStatsResponse struct { type SysStatsResponse struct {
state protoimpl.MessageState `protogen:"open.v1"` state protoimpl.MessageState
NumGoroutine uint32 `protobuf:"varint,1,opt,name=NumGoroutine,proto3" json:"NumGoroutine,omitempty"`
NumGC uint32 `protobuf:"varint,2,opt,name=NumGC,proto3" json:"NumGC,omitempty"`
Alloc uint64 `protobuf:"varint,3,opt,name=Alloc,proto3" json:"Alloc,omitempty"`
TotalAlloc uint64 `protobuf:"varint,4,opt,name=TotalAlloc,proto3" json:"TotalAlloc,omitempty"`
Sys uint64 `protobuf:"varint,5,opt,name=Sys,proto3" json:"Sys,omitempty"`
Mallocs uint64 `protobuf:"varint,6,opt,name=Mallocs,proto3" json:"Mallocs,omitempty"`
Frees uint64 `protobuf:"varint,7,opt,name=Frees,proto3" json:"Frees,omitempty"`
LiveObjects uint64 `protobuf:"varint,8,opt,name=LiveObjects,proto3" json:"LiveObjects,omitempty"`
PauseTotalNs uint64 `protobuf:"varint,9,opt,name=PauseTotalNs,proto3" json:"PauseTotalNs,omitempty"`
Uptime uint32 `protobuf:"varint,10,opt,name=Uptime,proto3" json:"Uptime,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
NumGoroutine uint32 `protobuf:"varint,1,opt,name=NumGoroutine,proto3" json:"NumGoroutine,omitempty"`
NumGC uint32 `protobuf:"varint,2,opt,name=NumGC,proto3" json:"NumGC,omitempty"`
Alloc uint64 `protobuf:"varint,3,opt,name=Alloc,proto3" json:"Alloc,omitempty"`
TotalAlloc uint64 `protobuf:"varint,4,opt,name=TotalAlloc,proto3" json:"TotalAlloc,omitempty"`
Sys uint64 `protobuf:"varint,5,opt,name=Sys,proto3" json:"Sys,omitempty"`
Mallocs uint64 `protobuf:"varint,6,opt,name=Mallocs,proto3" json:"Mallocs,omitempty"`
Frees uint64 `protobuf:"varint,7,opt,name=Frees,proto3" json:"Frees,omitempty"`
LiveObjects uint64 `protobuf:"varint,8,opt,name=LiveObjects,proto3" json:"LiveObjects,omitempty"`
PauseTotalNs uint64 `protobuf:"varint,9,opt,name=PauseTotalNs,proto3" json:"PauseTotalNs,omitempty"`
Uptime uint32 `protobuf:"varint,10,opt,name=Uptime,proto3" json:"Uptime,omitempty"`
} }
func (x *SysStatsResponse) Reset() { func (x *SysStatsResponse) Reset() {
*x = SysStatsResponse{} *x = SysStatsResponse{}
mi := &file_experimental_v2rayapi_stats_proto_msgTypes[6] if protoimpl.UnsafeEnabled {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) mi := &file_experimental_v2rayapi_stats_proto_msgTypes[6]
ms.StoreMessageInfo(mi) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
} }
func (x *SysStatsResponse) String() string { func (x *SysStatsResponse) String() string {
@@ -346,7 +365,7 @@ func (*SysStatsResponse) ProtoMessage() {}
func (x *SysStatsResponse) ProtoReflect() protoreflect.Message { func (x *SysStatsResponse) ProtoReflect() protoreflect.Message {
mi := &file_experimental_v2rayapi_stats_proto_msgTypes[6] mi := &file_experimental_v2rayapi_stats_proto_msgTypes[6]
if x != nil { if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -433,7 +452,7 @@ 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{ var file_experimental_v2rayapi_stats_proto_rawDesc = []byte{
0x0a, 0x21, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2f, 0x76, 0x0a, 0x21, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2f, 0x76,
0x32, 0x72, 0x61, 0x79, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x70, 0x72, 0x32, 0x72, 0x61, 0x79, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x12, 0x15, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6f, 0x74, 0x6f, 0x12, 0x15, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61,
@@ -504,23 +523,23 @@ var file_experimental_v2rayapi_stats_proto_rawDesc = string([]byte{
0x72, 0x6e, 0x65, 0x74, 0x2f, 0x73, 0x69, 0x6e, 0x67, 0x2d, 0x62, 0x6f, 0x78, 0x2f, 0x65, 0x78, 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, 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, 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
file_experimental_v2rayapi_stats_proto_rawDescData []byte file_experimental_v2rayapi_stats_proto_rawDescData = file_experimental_v2rayapi_stats_proto_rawDesc
) )
func file_experimental_v2rayapi_stats_proto_rawDescGZIP() []byte { func file_experimental_v2rayapi_stats_proto_rawDescGZIP() []byte {
file_experimental_v2rayapi_stats_proto_rawDescOnce.Do(func() { file_experimental_v2rayapi_stats_proto_rawDescOnce.Do(func() {
file_experimental_v2rayapi_stats_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_experimental_v2rayapi_stats_proto_rawDesc), len(file_experimental_v2rayapi_stats_proto_rawDesc))) file_experimental_v2rayapi_stats_proto_rawDescData = protoimpl.X.CompressGZIP(file_experimental_v2rayapi_stats_proto_rawDescData)
}) })
return file_experimental_v2rayapi_stats_proto_rawDescData return file_experimental_v2rayapi_stats_proto_rawDescData
} }
var ( var (
file_experimental_v2rayapi_stats_proto_msgTypes = make([]protoimpl.MessageInfo, 7) file_experimental_v2rayapi_stats_proto_msgTypes = make([]protoimpl.MessageInfo, 7)
file_experimental_v2rayapi_stats_proto_goTypes = []any{ file_experimental_v2rayapi_stats_proto_goTypes = []interface{}{
(*GetStatsRequest)(nil), // 0: experimental.v2rayapi.GetStatsRequest (*GetStatsRequest)(nil), // 0: experimental.v2rayapi.GetStatsRequest
(*Stat)(nil), // 1: experimental.v2rayapi.Stat (*Stat)(nil), // 1: experimental.v2rayapi.Stat
(*GetStatsResponse)(nil), // 2: experimental.v2rayapi.GetStatsResponse (*GetStatsResponse)(nil), // 2: experimental.v2rayapi.GetStatsResponse
@@ -552,11 +571,97 @@ func file_experimental_v2rayapi_stats_proto_init() {
if File_experimental_v2rayapi_stats_proto != nil { if File_experimental_v2rayapi_stats_proto != nil {
return return
} }
if !protoimpl.UnsafeEnabled {
file_experimental_v2rayapi_stats_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetStatsRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_experimental_v2rayapi_stats_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Stat); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_experimental_v2rayapi_stats_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetStatsResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_experimental_v2rayapi_stats_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*QueryStatsRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_experimental_v2rayapi_stats_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*QueryStatsResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_experimental_v2rayapi_stats_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*SysStatsRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_experimental_v2rayapi_stats_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*SysStatsResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{} type x struct{}
out := protoimpl.TypeBuilder{ out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{ File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(), GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_experimental_v2rayapi_stats_proto_rawDesc), len(file_experimental_v2rayapi_stats_proto_rawDesc)), RawDescriptor: file_experimental_v2rayapi_stats_proto_rawDesc,
NumEnums: 0, NumEnums: 0,
NumMessages: 7, NumMessages: 7,
NumExtensions: 0, NumExtensions: 0,
@@ -567,6 +672,7 @@ func file_experimental_v2rayapi_stats_proto_init() {
MessageInfos: file_experimental_v2rayapi_stats_proto_msgTypes, MessageInfos: file_experimental_v2rayapi_stats_proto_msgTypes,
}.Build() }.Build()
File_experimental_v2rayapi_stats_proto = out.File File_experimental_v2rayapi_stats_proto = out.File
file_experimental_v2rayapi_stats_proto_rawDesc = nil
file_experimental_v2rayapi_stats_proto_goTypes = nil file_experimental_v2rayapi_stats_proto_goTypes = nil
file_experimental_v2rayapi_stats_proto_depIdxs = nil file_experimental_v2rayapi_stats_proto_depIdxs = nil
} }

View File

@@ -10,8 +10,8 @@ import (
// This is a compile-time assertion to ensure that this generated file // This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against. // is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.64.0 or later. // Requires gRPC-Go v1.32.0 or later.
const _ = grpc.SupportPackageIsVersion9 const _ = grpc.SupportPackageIsVersion7
const ( const (
StatsService_GetStats_FullMethodName = "/experimental.v2rayapi.StatsService/GetStats" StatsService_GetStats_FullMethodName = "/experimental.v2rayapi.StatsService/GetStats"
@@ -37,9 +37,8 @@ func NewStatsServiceClient(cc grpc.ClientConnInterface) StatsServiceClient {
} }
func (c *statsServiceClient) GetStats(ctx context.Context, in *GetStatsRequest, opts ...grpc.CallOption) (*GetStatsResponse, error) { func (c *statsServiceClient) GetStats(ctx context.Context, in *GetStatsRequest, opts ...grpc.CallOption) (*GetStatsResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(GetStatsResponse) out := new(GetStatsResponse)
err := c.cc.Invoke(ctx, StatsService_GetStats_FullMethodName, in, out, cOpts...) err := c.cc.Invoke(ctx, StatsService_GetStats_FullMethodName, in, out, opts...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -47,9 +46,8 @@ func (c *statsServiceClient) GetStats(ctx context.Context, in *GetStatsRequest,
} }
func (c *statsServiceClient) QueryStats(ctx context.Context, in *QueryStatsRequest, opts ...grpc.CallOption) (*QueryStatsResponse, error) { func (c *statsServiceClient) QueryStats(ctx context.Context, in *QueryStatsRequest, opts ...grpc.CallOption) (*QueryStatsResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(QueryStatsResponse) out := new(QueryStatsResponse)
err := c.cc.Invoke(ctx, StatsService_QueryStats_FullMethodName, in, out, cOpts...) err := c.cc.Invoke(ctx, StatsService_QueryStats_FullMethodName, in, out, opts...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -57,9 +55,8 @@ func (c *statsServiceClient) QueryStats(ctx context.Context, in *QueryStatsReque
} }
func (c *statsServiceClient) GetSysStats(ctx context.Context, in *SysStatsRequest, opts ...grpc.CallOption) (*SysStatsResponse, error) { func (c *statsServiceClient) GetSysStats(ctx context.Context, in *SysStatsRequest, opts ...grpc.CallOption) (*SysStatsResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(SysStatsResponse) out := new(SysStatsResponse)
err := c.cc.Invoke(ctx, StatsService_GetSysStats_FullMethodName, in, out, cOpts...) err := c.cc.Invoke(ctx, StatsService_GetSysStats_FullMethodName, in, out, opts...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -68,7 +65,7 @@ func (c *statsServiceClient) GetSysStats(ctx context.Context, in *SysStatsReques
// StatsServiceServer is the server API for StatsService service. // StatsServiceServer is the server API for StatsService service.
// All implementations must embed UnimplementedStatsServiceServer // All implementations must embed UnimplementedStatsServiceServer
// for forward compatibility. // for forward compatibility
type StatsServiceServer interface { type StatsServiceServer interface {
GetStats(context.Context, *GetStatsRequest) (*GetStatsResponse, error) GetStats(context.Context, *GetStatsRequest) (*GetStatsResponse, error)
QueryStats(context.Context, *QueryStatsRequest) (*QueryStatsResponse, error) QueryStats(context.Context, *QueryStatsRequest) (*QueryStatsResponse, error)
@@ -76,11 +73,7 @@ type StatsServiceServer interface {
mustEmbedUnimplementedStatsServiceServer() mustEmbedUnimplementedStatsServiceServer()
} }
// UnimplementedStatsServiceServer must be embedded to have // UnimplementedStatsServiceServer must be embedded to have forward compatible implementations.
// forward compatible implementations.
//
// NOTE: this should be embedded by value instead of pointer to avoid a nil
// pointer dereference when methods are called.
type UnimplementedStatsServiceServer struct{} type UnimplementedStatsServiceServer struct{}
func (UnimplementedStatsServiceServer) GetStats(context.Context, *GetStatsRequest) (*GetStatsResponse, error) { func (UnimplementedStatsServiceServer) GetStats(context.Context, *GetStatsRequest) (*GetStatsResponse, error) {
@@ -95,7 +88,6 @@ func (UnimplementedStatsServiceServer) GetSysStats(context.Context, *SysStatsReq
return nil, status.Errorf(codes.Unimplemented, "method GetSysStats not implemented") return nil, status.Errorf(codes.Unimplemented, "method GetSysStats not implemented")
} }
func (UnimplementedStatsServiceServer) mustEmbedUnimplementedStatsServiceServer() {} func (UnimplementedStatsServiceServer) mustEmbedUnimplementedStatsServiceServer() {}
func (UnimplementedStatsServiceServer) testEmbeddedByValue() {}
// UnsafeStatsServiceServer may be embedded to opt out of forward compatibility for this service. // UnsafeStatsServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to StatsServiceServer will // Use of this interface is not recommended, as added methods to StatsServiceServer will
@@ -105,13 +97,6 @@ type UnsafeStatsServiceServer interface {
} }
func RegisterStatsServiceServer(s grpc.ServiceRegistrar, srv StatsServiceServer) { func RegisterStatsServiceServer(s grpc.ServiceRegistrar, srv StatsServiceServer) {
// If the following call pancis, it indicates UnimplementedStatsServiceServer was
// embedded by pointer and is nil. This will cause panics if an
// unimplemented method is ever invoked, so we test this at initialization
// time to prevent it from happening at runtime later due to I/O.
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
t.testEmbeddedByValue()
}
s.RegisterService(&StatsService_ServiceDesc, srv) s.RegisterService(&StatsService_ServiceDesc, srv)
} }

110
go.mod
View File

@@ -1,43 +1,40 @@
module github.com/sagernet/sing-box module github.com/sagernet/sing-box
go 1.23.1 go 1.20
toolchain go1.24.0
require ( require (
github.com/caddyserver/certmagic v0.21.7 github.com/caddyserver/certmagic v0.20.0
github.com/cloudflare/circl v1.6.0 github.com/cloudflare/circl v1.3.7
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/gofrs/uuid/v5 v5.3.1 github.com/gofrs/uuid/v5 v5.3.0
github.com/insomniacslk/dhcp v0.0.0-20250109001534-8abf58130905 github.com/insomniacslk/dhcp v0.0.0-20250109001534-8abf58130905
github.com/libdns/alidns v1.0.3 github.com/libdns/alidns v1.0.3
github.com/libdns/cloudflare v0.1.1 github.com/libdns/cloudflare v0.1.1
github.com/logrusorgru/aurora v2.0.3+incompatible github.com/logrusorgru/aurora v2.0.3+incompatible
github.com/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/mholt/acmez v1.2.0
github.com/miekg/dns v1.1.63 github.com/miekg/dns v1.1.63
github.com/oschwald/maxminddb-golang v1.13.1 github.com/oschwald/maxminddb-golang v1.12.0
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/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1 github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1
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.4
github.com/sagernet/gvisor v0.0.0-20250217052116-ed66b6946f72 github.com/sagernet/gvisor v0.0.0-20241123041152-536d05261cff
github.com/sagernet/quic-go v0.49.0-beta.1 github.com/sagernet/quic-go v0.49.0-beta.1
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691
github.com/sagernet/sing v0.6.2-0.20250210105917-3464ed3babc0 github.com/sagernet/sing v0.6.2-0.20250210105917-3464ed3babc0
github.com/sagernet/sing-mux v0.3.1 github.com/sagernet/sing-mux v0.3.1
github.com/sagernet/sing-quic v0.4.1-beta.1 github.com/sagernet/sing-quic v0.4.0
github.com/sagernet/sing-shadowsocks v0.2.7 github.com/sagernet/sing-shadowsocks v0.2.7
github.com/sagernet/sing-shadowsocks2 v0.2.0 github.com/sagernet/sing-shadowsocks2 v0.2.0
github.com/sagernet/sing-shadowtls v0.2.0 github.com/sagernet/sing-shadowtls v0.2.0
github.com/sagernet/sing-tun v0.6.2-0.20250217135654-784bb584392f github.com/sagernet/sing-tun v0.6.1
github.com/sagernet/sing-vmess v0.2.0 github.com/sagernet/sing-vmess v0.2.0
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7
github.com/sagernet/tailscale v1.79.0-mod.1
github.com/sagernet/utls v1.6.7 github.com/sagernet/utls v1.6.7
github.com/sagernet/wireguard-go v0.0.1-beta.5 github.com/sagernet/wireguard-go v0.0.1-beta.5
github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854 github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854
@@ -45,103 +42,62 @@ require (
github.com/stretchr/testify v1.10.0 github.com/stretchr/testify v1.10.0
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.32.0
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56
golang.org/x/mod v0.23.0 golang.org/x/mod v0.20.0
golang.org/x/net v0.35.0 golang.org/x/net v0.34.0
golang.org/x/sys v0.30.0 golang.org/x/sys v0.30.0
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20241231184526-a9ab2273dd10 golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6
google.golang.org/grpc v1.70.0 google.golang.org/grpc v1.63.2
google.golang.org/protobuf v1.36.5 google.golang.org/protobuf v1.33.0
howett.net/plist v1.0.1 howett.net/plist v1.0.1
) )
//replace github.com/sagernet/sing => ../sing //replace github.com/sagernet/sing => ../sing
require ( require (
filippo.io/edwards25519 v1.1.0 // indirect
github.com/ajg/form v1.5.1 // indirect github.com/ajg/form v1.5.1 // indirect
github.com/akutz/memconn v0.1.0 // indirect github.com/andybalholm/brotli v1.0.6 // indirect
github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa // indirect
github.com/andybalholm/brotli v1.1.0 // indirect
github.com/bits-and-blooms/bitset v1.13.0 // 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/davecgh/go-spew v1.1.1 // 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/dblohm7/wingoes v0.0.0-20240119213807-a09d6be7affa // indirect
github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1 // indirect github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1 // indirect
github.com/digitalocean/go-smbios v0.0.0-20180907143718-390a4f403a8e // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/fxamacker/cbor/v2 v2.6.0 // indirect
github.com/gaissmai/bart v0.11.1 // indirect
github.com/go-json-experiment/json v0.0.0-20231102232822-2e55bd4e08b0 // 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/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/gobwas/httphead v0.1.0 // indirect github.com/gobwas/httphead v0.1.0 // indirect
github.com/gobwas/pool v0.2.1 // indirect github.com/gobwas/pool v0.2.1 // indirect
github.com/godbus/dbus/v5 v5.1.1-0.20230522191255-76236955d466 // 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/pprof v0.0.0-20231101202521-4ca4178f5c7a // indirect
github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/csrf v1.7.2 // indirect
github.com/gorilla/securecookie v1.1.2 // indirect
github.com/hashicorp/yamux v0.1.2 // indirect github.com/hashicorp/yamux v0.1.2 // indirect
github.com/hdevalence/ed25519consensus v0.2.0 // indirect
github.com/illarion/gonotify/v2 v2.0.3 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/josharian/native v1.1.1-0.20230202152459-5c7d0dd6ab86 // indirect github.com/josharian/native v1.1.0 // indirect
github.com/jsimonetti/rtnetlink v1.4.0 // indirect github.com/klauspost/compress v1.17.4 // indirect
github.com/klauspost/compress v1.17.11 // indirect github.com/klauspost/cpuid/v2 v2.2.5 // indirect
github.com/klauspost/cpuid/v2 v2.2.9 // indirect
github.com/kortschak/wol v0.0.0-20200729010619-da482cc4850a // indirect
github.com/libdns/libdns v0.2.2 // indirect github.com/libdns/libdns v0.2.2 // indirect
github.com/mdlayher/genetlink v1.3.2 // indirect
github.com/mdlayher/netlink v1.7.2 // indirect github.com/mdlayher/netlink v1.7.2 // indirect
github.com/mdlayher/sdnotify v1.0.0 // indirect github.com/mdlayher/socket v0.4.1 // indirect
github.com/mdlayher/socket v0.5.1 // indirect github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
github.com/mitchellh/go-ps v1.0.0 // indirect github.com/onsi/ginkgo/v2 v2.9.7 // indirect
github.com/onsi/ginkgo/v2 v2.17.2 // indirect github.com/pierrec/lz4/v4 v4.1.14 // indirect
github.com/pierrec/lz4/v4 v4.1.21 // indirect github.com/pmezard/go-difflib v1.0.0 // 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/quic-go/qpack v0.4.0 // indirect github.com/quic-go/qpack v0.4.0 // indirect
github.com/quic-go/qtls-go1-20 v0.4.1 // indirect github.com/quic-go/qtls-go1-20 v0.4.1 // indirect
github.com/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.5 // indirect
github.com/tailscale/certstore v0.1.1-0.20231202035212-d3fa0460f47e // indirect github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 // 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/goupnp v1.0.1-0.20210804011211-c64d0f06ea05 // indirect
github.com/tailscale/hujson v0.0.0-20221223112325-20486734a56a // indirect
github.com/tailscale/netlink v1.1.1-0.20240822203006-4d49adab4de7 // indirect
github.com/tailscale/peercred v0.0.0-20240214030740-b535050b2aa4 // indirect
github.com/tailscale/web-client-prebuilt v0.0.0-20240226180453-5db17b287bf1 // indirect
github.com/tcnksm/go-httpstat v0.2.0 // indirect
github.com/u-root/uio v0.0.0-20240118234441-a3c409a6018e // indirect
github.com/vishvananda/netns v0.0.4 // indirect github.com/vishvananda/netns v0.0.4 // indirect
github.com/x448/float16 v0.8.4 // indirect github.com/zeebo/blake3 v0.2.3 // indirect
github.com/zeebo/blake3 v0.2.4 // indirect
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 golang.org/x/sync v0.10.0 // indirect
go4.org/mem v0.0.0-20220726221520-4f986261bf13 // indirect golang.org/x/text v0.21.0 // indirect
golang.org/x/sync v0.11.0 // indirect
golang.org/x/term v0.29.0 // indirect
golang.org/x/text v0.22.0 // indirect
golang.org/x/time v0.7.0 // indirect golang.org/x/time v0.7.0 // indirect
golang.org/x/tools v0.24.0 // indirect golang.org/x/tools v0.24.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 google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
lukechampine.com/blake3 v1.3.0 // indirect lukechampine.com/blake3 v1.3.0 // indirect
) )
//replace github.com/sagernet/sing => ../sing

257
go.sum
View File

@@ -1,75 +1,39 @@
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU=
github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
github.com/akutz/memconn v0.1.0 h1:NawI0TORU4hcOMsMr11g7vwlCdkYeLKXBcxWu2W/P8A= github.com/andybalholm/brotli v1.0.6 h1:Yf9fFpf49Zrxb9NlQaluyE92/+X7UVHlhMNJN2sxfOI=
github.com/akutz/memconn v0.1.0/go.mod h1:Jo8rI7m0NieZyLI5e2CDlRdRqRRB4S7Xp77ukDjH+Fw= github.com/andybalholm/brotli v1.0.6/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa h1:LHTHcTQiSGT7VVbI0o4wBRNQIgn917usHWOd6VAffYI= github.com/caddyserver/certmagic v0.20.0 h1:bTw7LcEZAh9ucYCRXyCpIrSAGplplI0vGYJ4BpCQ/Fc=
github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4= github.com/caddyserver/certmagic v0.20.0/go.mod h1:N4sXgpICQUskEWpj7zVzvWD41p3NYacrNoZYiRM2jTg=
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
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/caddyserver/certmagic v0.21.7 h1:66KJioPFJwttL43KYSWk7ErSmE6LfaJgCQuhm8Sg6fg=
github.com/caddyserver/certmagic v0.21.7/go.mod h1:LCPG3WLxcnjVKl/xpjzM0gqh0knrKKKiO5WVttX2eEI=
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/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/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU=
github.com/cilium/ebpf v0.15.0/go.mod h1:DHp1WyrLeiBh19Cf/tfiSMhqheEiK8fXFZ4No0P1Hso= github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA=
github.com/cloudflare/circl v1.6.0 h1:cr5JKic4HI+LkINy2lg3W2jF8sHCVTBncJr5gIIq7qk=
github.com/cloudflare/circl v1.6.0/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
github.com/coder/websocket v1.8.12 h1:5bUXkEPPIbewrnkU8LTCLVaxi4N4J8ahufH2vlo4NAo=
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/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.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
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.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
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.1/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/go.mod h1:Nx87SkVqTKd8UtT+xu7sM/l+LgXs6c0aHrlKusR+2EQ=
github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1 h1:CaO/zOnF8VvUfEbhRatPcwKVWamvbYd8tQGRWacE9kU= github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1 h1:CaO/zOnF8VvUfEbhRatPcwKVWamvbYd8tQGRWacE9kU=
github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1/go.mod h1:+hnT3ywWDTAFrW5aE+u2Sa/wT555ZqwoCS+pk3p6ry4= github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1/go.mod h1:+hnT3ywWDTAFrW5aE+u2Sa/wT555ZqwoCS+pk3p6ry4=
github.com/digitalocean/go-smbios v0.0.0-20180907143718-390a4f403a8e h1:vUmf0yezR0y7jJ5pceLHthLaYf4bA5T14B6q39S4q2Q=
github.com/digitalocean/go-smbios v0.0.0-20180907143718-390a4f403a8e/go.mod h1:YTIHhz/QFSYnu/EhlF2SpU2Uk+32abacUYA5ZPljz1A=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/fxamacker/cbor/v2 v2.6.0 h1:sU6J2usfADwWlYDAFhZBQ6TnLFBHxgesMrQfQgk1tWA=
github.com/fxamacker/cbor/v2 v2.6.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
github.com/gaissmai/bart v0.11.1 h1:5Uv5XwsaFBRo4E5VBcb9TzY8B7zxFf+U7isDxqOrRfc=
github.com/gaissmai/bart v0.11.1/go.mod h1:KHeYECXQiBjTzQz/om2tqn3sZF1J7hw9m6z41ftj3fg=
github.com/github/fakeca v0.1.0 h1:Km/MVOFvclqxPM9dZBC4+QE564nU4gz4iZ0D9pMw28I=
github.com/github/fakeca v0.1.0/go.mod h1:+bormgoGMMuamOscx7N91aOuUST7wdaJ2rNjeohylyo=
github.com/go-chi/chi/v5 v5.2.1 h1:KOIHODQj58PmL80G2Eak4WdvUzjSJSm0vG72crDCqb8= github.com/go-chi/chi/v5 v5.2.1 h1:KOIHODQj58PmL80G2Eak4WdvUzjSJSm0vG72crDCqb8=
github.com/go-chi/chi/v5 v5.2.1/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops= github.com/go-chi/chi/v5 v5.2.1/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops=
github.com/go-chi/render v1.0.3 h1:AsXqd2a1/INaIfUSKq3G5uA8weYx20FOsM7uSoCyyt4= github.com/go-chi/render v1.0.3 h1:AsXqd2a1/INaIfUSKq3G5uA8weYx20FOsM7uSoCyyt4=
github.com/go-chi/render v1.0.3/go.mod h1:/gr3hVkmYR0YlEy3LxCuVRFzEu9Ruok+gFqbIofjao0= github.com/go-chi/render v1.0.3/go.mod h1:/gr3hVkmYR0YlEy3LxCuVRFzEu9Ruok+gFqbIofjao0=
github.com/go-json-experiment/json v0.0.0-20231102232822-2e55bd4e08b0 h1:ymLjT4f35nQbASLnvxEde4XOBL+Sn7rFuV+FOJqkljg= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
github.com/go-json-experiment/json v0.0.0-20231102232822-2e55bd4e08b0/go.mod h1:6daplAwHHGbUGib4990V3Il26O0OC4aRyvewaaAihaA=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
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-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 v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
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=
github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
github.com/godbus/dbus/v5 v5.1.1-0.20230522191255-76236955d466 h1:sQspH8M4niEijh3PFscJRLDnkL547IeP7kpPe3uUhEg= github.com/gofrs/uuid/v5 v5.3.0 h1:m0mUMr+oVYUdxpMLgSYCZiXe7PuVPnI94+OMeVBNedk=
github.com/godbus/dbus/v5 v5.1.1-0.20230522191255-76236955d466/go.mod h1:ZiQxhyQ+bbbfxUKVvjfO498oPYvtYhZzycal3G/NHmU= github.com/gofrs/uuid/v5 v5.3.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8=
github.com/gofrs/uuid/v5 v5.3.1 h1:aPx49MwJbekCzOyhZDjJVb0hx3A0KLjlbLx6p2gY0p0=
github.com/gofrs/uuid/v5 v5.3.1/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg=
github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
@@ -77,40 +41,26 @@ github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a h1:fEBsGL/sjAuJrgah5XqmmYsTLzJp/TO9Lhy39gkverk=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
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/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/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/csrf v1.7.2 h1:oTUjx0vyf2T+wkrx09Trsev1TE+/EbDAeHtSTbtC2eI=
github.com/gorilla/csrf v1.7.2/go.mod h1:F1Fj3KG23WYHE6gozCmBAezKookxbIvUJT+121wTuLk=
github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA=
github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo=
github.com/hashicorp/yamux v0.1.2 h1:XtB8kyFOyHXYVFnwT5C3+Bdo8gArse7j2AQ0DA0Uey8= github.com/hashicorp/yamux v0.1.2 h1:XtB8kyFOyHXYVFnwT5C3+Bdo8gArse7j2AQ0DA0Uey8=
github.com/hashicorp/yamux v0.1.2/go.mod h1:C+zze2n6e/7wshOZep2A70/aQU6QBRWJO/G6FT1wIns= github.com/hashicorp/yamux v0.1.2/go.mod h1:C+zze2n6e/7wshOZep2A70/aQU6QBRWJO/G6FT1wIns=
github.com/hdevalence/ed25519consensus v0.2.0 h1:37ICyZqdyj0lAZ8P4D1d1id3HqbbG1N3iBb1Tb4rdcU=
github.com/hdevalence/ed25519consensus v0.2.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3sus+7FctEyM4RqDxYNzo=
github.com/illarion/gonotify/v2 v2.0.3 h1:B6+SKPo/0Sw8cRJh1aLzNEeNVFfzE3c6N+o+vyxM+9A=
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-20250109001534-8abf58130905 h1:q3OEI9RaN/wwcx+qgGo6ZaoJkCiDYe/gjDLfq7lQQF4=
github.com/insomniacslk/dhcp v0.0.0-20250109001534-8abf58130905/go.mod h1:VvGYjkZoJyKqlmT1yzakUs4mfKMNB0XdODP0+rdml6k= github.com/insomniacslk/dhcp v0.0.0-20250109001534-8abf58130905/go.mod h1:VvGYjkZoJyKqlmT1yzakUs4mfKMNB0XdODP0+rdml6k=
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/josharian/native v1.0.1-0.20221213033349-c1e37c09b531/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= github.com/josharian/native v1.0.1-0.20221213033349-c1e37c09b531/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
github.com/josharian/native v1.1.1-0.20230202152459-5c7d0dd6ab86 h1:elKwZS1OcdQ0WwEDBeqxKwb7WB62QX8bvZ/FJnVXIfk= github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA=
github.com/josharian/native v1.1.1-0.20230202152459-5c7d0dd6ab86/go.mod h1:aFAMtuldEgx/4q7iSGazk22+IcgvtiC+HIimFO9XlS8= github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
github.com/jsimonetti/rtnetlink v1.4.0 h1:Z1BF0fRgcETPEa0Kt0MRk3yV5+kF1FWTni6KUFKrq2I= github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4=
github.com/jsimonetti/rtnetlink v1.4.0/go.mod h1:5W1jDvWdnthFJ7fxYX1GMK07BUpI4oskfOqvPteYS6E= github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
github.com/klauspost/cpuid/v2 v2.2.9 h1:66ze0taIn2H33fBvCkXuv9BmCwDfafmiIVpKV9kKGuY= github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/klauspost/cpuid/v2 v2.2.9/go.mod h1:rqkxqrZ1EhYM9G+hXH7YdowN5R5RGN6NK4QwQ3WMXF8= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kortschak/wol v0.0.0-20200729010619-da482cc4850a h1:+RR6SqnTkDLWyICxS1xpjCi/3dhyV+TgZwA6Ww3KncQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kortschak/wol v0.0.0-20200729010619-da482cc4850a/go.mod h1:YTtCCM3ryyfiu4F7t8HQ1mxvp1UBdWM2r6Xa+nGWvDk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/libdns/alidns v1.0.3 h1:LFHuGnbseq5+HCeGa1aW8awyX/4M2psB9962fdD2+yQ= github.com/libdns/alidns v1.0.3 h1:LFHuGnbseq5+HCeGa1aW8awyX/4M2psB9962fdD2+yQ=
github.com/libdns/alidns v1.0.3/go.mod h1:e18uAG6GanfRhcJj6/tps2rCMzQJaYVcGKT+ELjdjGE= github.com/libdns/alidns v1.0.3/go.mod h1:e18uAG6GanfRhcJj6/tps2rCMzQJaYVcGKT+ELjdjGE=
github.com/libdns/cloudflare v0.1.1 h1:FVPfWwP8zZCqj268LZjmkDleXlHPlFU9KC4OJ3yn054= github.com/libdns/cloudflare v0.1.1 h1:FVPfWwP8zZCqj268LZjmkDleXlHPlFU9KC4OJ3yn054=
@@ -120,45 +70,32 @@ github.com/libdns/libdns v0.2.2 h1:O6ws7bAfRPaBsgAYt8MDe2HcNBGC29hkZ9MX2eUSX3s=
github.com/libdns/libdns v0.2.2/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ= github.com/libdns/libdns v0.2.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/go.mod h1:tcC3pkCrPUGIKKsCsp0B3AdaaKuHtaxoJRz3cc+528o=
github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/g= github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/g=
github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw= github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw=
github.com/mdlayher/sdnotify v1.0.0 h1:Ma9XeLVN/l0qpyx1tNeMSeTjCPH6NtuD6/N9XdTlQ3c= github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U=
github.com/mdlayher/sdnotify v1.0.0/go.mod h1:HQUmpM4XgYkhDLtd+Uad8ZFK1T9D5+pNxnXQjCeJlGE= github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA=
github.com/mdlayher/socket v0.5.1 h1:VZaqt6RkGkt2OE9l3GcC6nZkqD3xKeQLyfleW/uBcos=
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/mholt/acmez v1.2.0 h1:1hhLxSgY5FvH5HCnGUuwbKY2VQVo8IU7rxXKSnZ7F30=
github.com/mholt/acmez/v3 v3.0.1/go.mod h1:L1wOU06KKvq7tswuMDwKdcHeKpFFgkppZy/y0DFxagQ= github.com/mholt/acmez v1.2.0/go.mod h1:VT9YwH1xgNX1kmYY89gY8xPJC84BFAisjo8Egigt4kE=
github.com/miekg/dns v1.1.63 h1:8M5aAw6OMZfFXTT7K5V0Eu5YiiL8l7nUAkyN6C9YwaY= github.com/miekg/dns v1.1.63 h1:8M5aAw6OMZfFXTT7K5V0Eu5YiiL8l7nUAkyN6C9YwaY=
github.com/miekg/dns v1.1.63/go.mod h1:6NGHfjhpmr5lt3XPLuyfDJi5AXbNIPM9PY6H6sF1Nfs= github.com/miekg/dns v1.1.63/go.mod h1:6NGHfjhpmr5lt3XPLuyfDJi5AXbNIPM9PY6H6sF1Nfs=
github.com/mitchellh/go-ps v1.0.0 h1:i6ampVEEF4wQFF+bkYfwYgY+F/uYJDktmvLPf7qIgjc= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ= github.com/onsi/ginkgo/v2 v2.9.7 h1:06xGQy5www2oN160RtEZoTvnP2sPhEfePYmCDc2szss=
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= github.com/onsi/ginkgo/v2 v2.9.7/go.mod h1:cxrmXWykAwTwhQsJOPfdIDiJ+l2RYq7U8hFU+M/1uw0=
github.com/onsi/ginkgo/v2 v2.17.2 h1:7eMhcy3GimbsA3hEnVKdw/PQM9XN9krpKVXsZdph0/g= github.com/onsi/gomega v1.27.7 h1:fVih9JD6ogIiHUN6ePK7HJidyEDpWGVB5mzM7cWNXoU=
github.com/onsi/ginkgo/v2 v2.17.2/go.mod h1:nP2DPOQoNsQmsVyv5rDA8JkXQoCs6goXIvr/PRJ1eCc= github.com/oschwald/maxminddb-golang v1.12.0 h1:9FnTOD0YOhP7DGxGsq4glzpGy5+w7pq50AS6wALUMYs=
github.com/onsi/gomega v1.33.0 h1:snPCflnZrpMsy94p4lXVEkHo12lmPnc3vY5XBbreexE= github.com/oschwald/maxminddb-golang v1.12.0/go.mod h1:q0Nob5lTCqyQ8WT6FYgS1L7PXKVVbgiymefNwIjPzgY=
github.com/onsi/gomega v1.33.0/go.mod h1:+925n5YtiFsLzzafLUHzVMBpvvRAzrydIBiSIxjX3wY= github.com/pierrec/lz4/v4 v4.1.14 h1:+fL8AQEZtz/ijeNnpduH0bROTu0O3NZAlPjQxGn8LwE=
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/pierrec/lz4/v4 v4.1.14/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pierrec/lz4/v4 v4.1.14/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
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/go.mod h1:b7wRYZtCcPmt4Sz319BykUU241rWLe1VFXyiyWK/dH4=
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo= github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A= github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
github.com/quic-go/qtls-go1-20 v0.4.1 h1:D33340mCNDAIKBqXuAvexTNMUByrYmFYVfKfDN5nfFs= 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/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/go.mod h1:SA9BwrgyAqNo7M+uaL6IYbxpm5wk3L7Mm6ocLW+CJUs=
github.com/sagernet/asc-go v0.0.0-20241217030726-d563060fe4e1 h1:qi+ijeREa0yfAaO+NOcZ81gv4uzOfALUIdhkiIFvmG4= github.com/sagernet/asc-go v0.0.0-20241217030726-d563060fe4e1 h1:qi+ijeREa0yfAaO+NOcZ81gv4uzOfALUIdhkiIFvmG4=
github.com/sagernet/asc-go v0.0.0-20241217030726-d563060fe4e1/go.mod h1:JULDuzTMn2gyZFcjpTVZP4/UuwAdbHJ0bum2RdjXojU= github.com/sagernet/asc-go v0.0.0-20241217030726-d563060fe4e1/go.mod h1:JULDuzTMn2gyZFcjpTVZP4/UuwAdbHJ0bum2RdjXojU=
github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a h1:+NkI2670SQpQWvkkD2QgdTuzQG263YZ+2emfpeyGqW0= github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a h1:+NkI2670SQpQWvkkD2QgdTuzQG263YZ+2emfpeyGqW0=
@@ -171,8 +108,8 @@ github.com/sagernet/fswatch v0.1.1 h1:YqID+93B7VRfqIH3PArW/XpJv5H4OLEVWDfProGoRQ
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.4 h1:WzX9ka+iHdupMgy2Vdich+OAt7TM8C2cZbIbzNjBrJY=
github.com/sagernet/gomobile v0.1.4/go.mod h1:Pqq2+ZVvs10U7xK+UwJgwYWUykewi8H6vlslAO73n9E= github.com/sagernet/gomobile v0.1.4/go.mod h1:Pqq2+ZVvs10U7xK+UwJgwYWUykewi8H6vlslAO73n9E=
github.com/sagernet/gvisor v0.0.0-20250217052116-ed66b6946f72 h1:Jgv6N59yiVMEwimTcFV1EVcu2Aa7R2Wh1ZAYNzWP2qA= github.com/sagernet/gvisor v0.0.0-20241123041152-536d05261cff h1:mlohw3360Wg1BNGook/UHnISXhUx4Gd/3tVLs5T0nSs=
github.com/sagernet/gvisor v0.0.0-20250217052116-ed66b6946f72/go.mod h1:ehZwnT2UpmOWAHFL48XdBhnd4Qu4hN2O3Ji0us3ZHMw= github.com/sagernet/gvisor v0.0.0-20241123041152-536d05261cff/go.mod h1:ehZwnT2UpmOWAHFL48XdBhnd4Qu4hN2O3Ji0us3ZHMw=
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=
@@ -186,22 +123,20 @@ github.com/sagernet/sing v0.6.2-0.20250210105917-3464ed3babc0 h1:8gTBdpb2JeNq4oA
github.com/sagernet/sing v0.6.2-0.20250210105917-3464ed3babc0/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak= github.com/sagernet/sing v0.6.2-0.20250210105917-3464ed3babc0/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
github.com/sagernet/sing-mux v0.3.1 h1:kvCc8HyGAskDHDQ0yQvoTi/7J4cZPB/VJMsAM3MmdQI= github.com/sagernet/sing-mux v0.3.1 h1:kvCc8HyGAskDHDQ0yQvoTi/7J4cZPB/VJMsAM3MmdQI=
github.com/sagernet/sing-mux v0.3.1/go.mod h1:Mkdz8LnDstthz0HWuA/5foncnDIdcNN5KZ6AdJX+x78= github.com/sagernet/sing-mux v0.3.1/go.mod h1:Mkdz8LnDstthz0HWuA/5foncnDIdcNN5KZ6AdJX+x78=
github.com/sagernet/sing-quic v0.4.1-beta.1 h1:V2VfMckT3EQR3ZdfSzJgZZDsvfZZH42QAZpnOnHKa0s= github.com/sagernet/sing-quic v0.4.0 h1:E4geazHk/UrJTXMlT+CBCKmn8V86RhtNeczWtfeoEFc=
github.com/sagernet/sing-quic v0.4.1-beta.1/go.mod h1:c+CytOEyeN20KCTFIP8YQUkNDVFLSzjrEPqP7Hlnxys= github.com/sagernet/sing-quic v0.4.0/go.mod h1:c+CytOEyeN20KCTFIP8YQUkNDVFLSzjrEPqP7Hlnxys=
github.com/sagernet/sing-shadowsocks v0.2.7 h1:zaopR1tbHEw5Nk6FAkM05wCslV6ahVegEZaKMv9ipx8= github.com/sagernet/sing-shadowsocks v0.2.7 h1:zaopR1tbHEw5Nk6FAkM05wCslV6ahVegEZaKMv9ipx8=
github.com/sagernet/sing-shadowsocks v0.2.7/go.mod h1:0rIKJZBR65Qi0zwdKezt4s57y/Tl1ofkaq6NlkzVuyE= github.com/sagernet/sing-shadowsocks v0.2.7/go.mod h1:0rIKJZBR65Qi0zwdKezt4s57y/Tl1ofkaq6NlkzVuyE=
github.com/sagernet/sing-shadowsocks2 v0.2.0 h1:wpZNs6wKnR7mh1wV9OHwOyUr21VkS3wKFHi+8XwgADg= github.com/sagernet/sing-shadowsocks2 v0.2.0 h1:wpZNs6wKnR7mh1wV9OHwOyUr21VkS3wKFHi+8XwgADg=
github.com/sagernet/sing-shadowsocks2 v0.2.0/go.mod h1:RnXS0lExcDAovvDeniJ4IKa2IuChrdipolPYWBv9hWQ= github.com/sagernet/sing-shadowsocks2 v0.2.0/go.mod h1:RnXS0lExcDAovvDeniJ4IKa2IuChrdipolPYWBv9hWQ=
github.com/sagernet/sing-shadowtls v0.2.0 h1:cLKe4OAOFwuhmAIuPLj//CIL7Q9js+pIDardhJ+/osk= github.com/sagernet/sing-shadowtls v0.2.0 h1:cLKe4OAOFwuhmAIuPLj//CIL7Q9js+pIDardhJ+/osk=
github.com/sagernet/sing-shadowtls v0.2.0/go.mod h1:agU+Fw5X+xnWVyRHyFthoZCX3MfWKCFPm4JUf+1oaxo= github.com/sagernet/sing-shadowtls v0.2.0/go.mod h1:agU+Fw5X+xnWVyRHyFthoZCX3MfWKCFPm4JUf+1oaxo=
github.com/sagernet/sing-tun v0.6.2-0.20250217135654-784bb584392f h1:VEtmCNfk8RuZcYz/Xx63F2QjcgG3z/7Pa0uiJciQo+Y= github.com/sagernet/sing-tun v0.6.1 h1:4l0+gnEKcGjlWfUVTD+W0BRApqIny/lU2ZliurE+VMo=
github.com/sagernet/sing-tun v0.6.2-0.20250217135654-784bb584392f/go.mod h1:UiOi1ombGaAzWkGSgH4qcP7Zpq8FjWc1uQmleK8oPCE= github.com/sagernet/sing-tun v0.6.1/go.mod h1:fisFCbC4Vfb6HqQNcwPJi2CDK2bf0Xapyz3j3t4cnHE=
github.com/sagernet/sing-vmess v0.2.0 h1:pCMGUXN2k7RpikQV65/rtXtDHzb190foTfF9IGTMZrI= github.com/sagernet/sing-vmess v0.2.0 h1:pCMGUXN2k7RpikQV65/rtXtDHzb190foTfF9IGTMZrI=
github.com/sagernet/sing-vmess v0.2.0/go.mod h1:jDAZ0A0St1zVRkyvhAPRySOFfhC+4SQtO5VYyeFotgA= github.com/sagernet/sing-vmess v0.2.0/go.mod h1:jDAZ0A0St1zVRkyvhAPRySOFfhC+4SQtO5VYyeFotgA=
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ= github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ=
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7/go.mod h1:FP9X2xjT/Az1EsG/orYYoC+5MojWnuI7hrffz8fGwwo= github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7/go.mod h1:FP9X2xjT/Az1EsG/orYYoC+5MojWnuI7hrffz8fGwwo=
github.com/sagernet/tailscale v1.79.0-mod.1 h1:wIuAH7VqBYJNk0h2+bTyk4F0OlSqHvyLDCBrD3i+XNI=
github.com/sagernet/tailscale v1.79.0-mod.1/go.mod h1:RKY5WjYLj3JJ7VO/8ZCw8eAFa4+kWU6A1Ftdk84uB14=
github.com/sagernet/utls v1.6.7 h1:Ep3+aJ8FUGGta+II2IEVNUc3EDhaRCZINWkj/LloIA8= 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/utls v1.6.7/go.mod h1:Uua1TKO/FFuAhLr9rkaVnnrTmmiItzDjv1BUb2+ERwM=
github.com/sagernet/wireguard-go v0.0.1-beta.5 h1:aBEsxJUMEONwOZqKPIkuAcv4zJV5p6XlzEN04CF0FXc= github.com/sagernet/wireguard-go v0.0.1-beta.5 h1:aBEsxJUMEONwOZqKPIkuAcv4zJV5p6XlzEN04CF0FXc=
@@ -213,121 +148,75 @@ github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3k
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.5/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/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.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/u-root/uio v0.0.0-20230220225925-ffce2a382923 h1:tHNk7XK9GkmKUR6Gh8gVBKXc2MVSZ4G/NnWLtzw4gNA=
github.com/tailscale/certstore v0.1.1-0.20231202035212-d3fa0460f47e/go.mod h1:XrBNfAFN+pwoWuksbFS9Ccxnopa15zJGgXRFN90l3K4= github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923/go.mod h1:eLL9Nub3yfAho7qB0MzZizFhTU2QkLeoVsWdHtDW264=
github.com/tailscale/go-winio v0.0.0-20231025203758-c4f33415bf55 h1:Gzfnfk2TWrk8Jj4P4c1a3CtQyMaTVCznlkLZI++hok4=
github.com/tailscale/go-winio v0.0.0-20231025203758-c4f33415bf55/go.mod h1:4k4QO+dQ3R5FofL+SanAUZe+/QfeK0+OIuwDIRu2vSg=
github.com/tailscale/golang-x-crypto v0.0.0-20240604161659-3fde5e568aa4 h1:rXZGgEa+k2vJM8xT0PoSKfVXwFGPQ3z3CJfmnHJkZZw=
github.com/tailscale/golang-x-crypto v0.0.0-20240604161659-3fde5e568aa4/go.mod h1:ikbF+YT089eInTp9f2vmvy4+ZVnW5hzX1q2WknxSprQ=
github.com/tailscale/goupnp v1.0.1-0.20210804011211-c64d0f06ea05 h1:4chzWmimtJPxRs2O36yuGRW3f9SYV+bMTTvMBI0EKio=
github.com/tailscale/goupnp v1.0.1-0.20210804011211-c64d0f06ea05/go.mod h1:PdCqy9JzfWMJf1H5UJW2ip33/d4YkoKN0r67yKH1mG8=
github.com/tailscale/hujson v0.0.0-20221223112325-20486734a56a h1:SJy1Pu0eH1C29XwJucQo73FrleVK6t4kYz4NVhp34Yw=
github.com/tailscale/hujson v0.0.0-20221223112325-20486734a56a/go.mod h1:DFSS3NAGHthKo1gTlmEcSBiZrRJXi28rLNd/1udP1c8=
github.com/tailscale/netlink v1.1.1-0.20240822203006-4d49adab4de7 h1:uFsXVBE9Qr4ZoF094vE6iYTLDl0qCiKzYXlL6UeWObU=
github.com/tailscale/netlink v1.1.1-0.20240822203006-4d49adab4de7/go.mod h1:NzVQi3Mleb+qzq8VmcWpSkcSYxXIg0DkI6XDzpVkhJ0=
github.com/tailscale/peercred v0.0.0-20240214030740-b535050b2aa4 h1:Gz0rz40FvFVLTBk/K8UNAenb36EbDSnh+q7Z9ldcC8w=
github.com/tailscale/peercred v0.0.0-20240214030740-b535050b2aa4/go.mod h1:phI29ccmHQBc+wvroosENp1IF9195449VDnFDhJ4rJU=
github.com/tailscale/web-client-prebuilt v0.0.0-20240226180453-5db17b287bf1 h1:tdUdyPqJ0C97SJfjB9tW6EylTtreyee9C44de+UBG0g=
github.com/tailscale/web-client-prebuilt v0.0.0-20240226180453-5db17b287bf1/go.mod h1:agQPE6y6ldqCOui2gkIh7ZMztTkIQKH049tv8siLuNQ=
github.com/tc-hib/winres v0.2.1 h1:YDE0FiP0VmtRaDn7+aaChp1KiF4owBiJa5l964l5ujA=
github.com/tc-hib/winres v0.2.1/go.mod h1:C/JaNhH3KBvhNKVbvdlDWkbMDO9H4fKKDaN7/07SSuk=
github.com/tcnksm/go-httpstat v0.2.0 h1:rP7T5e5U2HfmOBmZzGgGZjBQ5/GluWUylujl0tJ04I0=
github.com/tcnksm/go-httpstat v0.2.0/go.mod h1:s3JVJFtQxtBEBC9dwcdTTXS9xFnM3SXAZwPG41aurT8=
github.com/u-root/uio v0.0.0-20240118234441-a3c409a6018e h1:BA9O3BmlTmpjbvajAwzWx4Wo2TRVdpPXZEeemGQcajw=
github.com/u-root/uio v0.0.0-20240118234441-a3c409a6018e/go.mod h1:eLL9Nub3yfAho7qB0MzZizFhTU2QkLeoVsWdHtDW264=
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.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8=
github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
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/zeebo/assert v1.1.0 h1:hU1L1vLTHsnO8x8c9KAR5GmM5QscxHg5RNU5z5qbUWY= github.com/zeebo/assert v1.1.0 h1:hU1L1vLTHsnO8x8c9KAR5GmM5QscxHg5RNU5z5qbUWY=
github.com/zeebo/assert v1.1.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= github.com/zeebo/assert v1.1.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
github.com/zeebo/blake3 v0.2.4 h1:KYQPkhpRtcqh0ssGYcKLG1JYvddkEA8QwCM/yBqhaZI= github.com/zeebo/blake3 v0.2.3 h1:TFoLXsjeXqRNFxSbk35Dk4YtszE/MQQGK10BH4ptoTg=
github.com/zeebo/blake3 v0.2.4/go.mod h1:7eeQ6d2iXWRGF6npfaxl2CU+xy2Fjo2gxeyZGCRUjcE= github.com/zeebo/blake3 v0.2.3/go.mod h1:mjJjZpnsyIVtVgTOSpJ9vmRE4wgDeyt2HU3qXvvKCaQ=
github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo= github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo=
github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4= github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4=
go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U=
go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg=
go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M=
go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8=
go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4=
go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU=
go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU=
go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ=
go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM=
go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8=
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/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
go.uber.org/zap/exp v0.3.0 h1:6JYzdifzYkGmTdRR59oYH+Ng7k49H9qVpWwNSsGJj3U=
go.uber.org/zap/exp v0.3.0/go.mod h1:5I384qq7XGxYyByIhHm6jg5CHkGY0nsTfbDLgDDlgJQ=
go4.org/mem v0.0.0-20220726221520-4f986261bf13 h1:CbZeCBZ0aZj8EfVgnqQcYZgf0lpZ3H9rmp5nkDTAst8=
go4.org/mem v0.0.0-20220726221520-4f986261bf13/go.mod h1:reUoABIJ9ikfM5sgtSF3Wushcza7+WeD01VB9Lirh3g=
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.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
golang.org/x/image v0.18.0 h1:jGzIakQa/ZXI1I0Fxvaa9W7yP25TqT6cHIHn+6CqvSQ= golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0=
golang.org/x/image v0.18.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E= golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM=
golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
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.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
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-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20220622161953-175b2fd9d664/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220622161953-175b2fd9d664/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.4.1-0.20230131160137-e7d7f63158de/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU= golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg=
golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s=
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.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ= golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ=
golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/time v0.7.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.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=
golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
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/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeunTOisW56dUokqW/FOteYJJ/yg= golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeunTOisW56dUokqW/FOteYJJ/yg=
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI= golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI=
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20241231184526-a9ab2273dd10 h1:3GDAcqdIg1ozBNLgPy4SLT84nfcBjr6rhGtXYtrkWLU= golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6 h1:CawjfCvYQH2OU3/TnxLx97WDSUDRABfT18pCOYwc2GE=
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20241231184526-a9ab2273dd10/go.mod h1:T97yPqesLiNrOYxkwmhMI0ZIlJDm+p0PMR8eRVeR5tQ= golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6/go.mod h1:3rxYc4HtVcSG9gVaTs2GEBdehh+sYPOwKtyUWEOTb80=
golang.zx2c4.com/wireguard/windows v0.5.3 h1:On6j2Rpn3OEMXqBq00QEDC7bWSZrPIHKIus8eIuExIE= google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de h1:cZGRis4/ot9uVm639a+rHCUaG0JJHEsdyzSQTMX+suY=
golang.zx2c4.com/wireguard/windows v0.5.3/go.mod h1:9TEe8TJmtwyQebdFwAkEWOPr3prrtqm+REGFifP60hI= google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY=
google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM=
google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA=
google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
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/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/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=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 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 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
@@ -336,5 +225,3 @@ howett.net/plist v1.0.1 h1:37GdZ8tP09Q35o9ych3ehygcsL+HqKSwzctveSlarvM=
howett.net/plist v1.0.1/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g= howett.net/plist v1.0.1/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g=
lukechampine.com/blake3 v1.3.0 h1:sJ3XhFINmHSrYCgl958hscfIa3bw8x4DqMP3u1YvoYE= lukechampine.com/blake3 v1.3.0 h1:sJ3XhFINmHSrYCgl958hscfIa3bw8x4DqMP3u1YvoYE=
lukechampine.com/blake3 v1.3.0/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= lukechampine.com/blake3 v1.3.0/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k=
software.sslmate.com/src/go-pkcs12 v0.4.0 h1:H2g08FrTvSFKUj+D309j1DPfk5APnIdAQAB8aEykJ5k=
software.sslmate.com/src/go-pkcs12 v0.4.0/go.mod h1:Qiz0EyvDRJjjxGyUQa2cCNZn/wMyzrRJ/qcDXOQazLI=

View File

@@ -92,7 +92,6 @@ func EndpointRegistry() *endpoint.Registry {
registry := endpoint.NewRegistry() registry := endpoint.NewRegistry()
registerWireGuardEndpoint(registry) registerWireGuardEndpoint(registry)
registerTailscaleEndpoint(registry)
return registry return registry
} }
@@ -111,7 +110,6 @@ func DNSTransportRegistry() *dns.TransportRegistry {
registerQUICTransports(registry) registerQUICTransports(registry)
registerDHCPTransport(registry) registerDHCPTransport(registry)
registerTailscaleTransport(registry)
return registry return registry
} }

View File

@@ -1,17 +0,0 @@
//go:build with_tailscale
package include
import (
"github.com/sagernet/sing-box/adapter/endpoint"
"github.com/sagernet/sing-box/dns"
"github.com/sagernet/sing-box/protocol/tailscale"
)
func registerTailscaleEndpoint(registry *endpoint.Registry) {
tailscale.RegisterEndpoint(registry)
}
func registerTailscaleTransport(registry *dns.TransportRegistry) {
tailscale.RegistryTransport(registry)
}

View File

@@ -1,27 +0,0 @@
//go:build !with_tailscale
package include
import (
"context"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/adapter/endpoint"
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"
E "github.com/sagernet/sing/common/exceptions"
)
func registerTailscaleEndpoint(registry *endpoint.Registry) {
endpoint.Register[option.TailscaleEndpointOptions](registry, C.TypeTailscale, func(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.TailscaleEndpointOptions) (adapter.Endpoint, error) {
return nil, E.New(`Tailscale is not included in this build, rebuild with -tags with_tailscale`)
})
}
func registerTailscaleTransport(registry *dns.TransportRegistry) {
dns.RegisterTransport[option.TailscaleDNSServerOptions](registry, C.DNSTypeTailscale, func(ctx context.Context, logger log.ContextLogger, tag string, options option.TailscaleDNSServerOptions) (adapter.DNSTransport, error) {
return nil, E.New(`Tailscale is not included in this build, rebuild with -tags with_tailscale`)
})
}

View File

@@ -93,7 +93,6 @@ nav:
- Predefined: configuration/dns/server/predefined.md - Predefined: configuration/dns/server/predefined.md
- 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
- 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
@@ -128,7 +127,6 @@ nav:
- Endpoint: - Endpoint:
- configuration/endpoint/index.md - configuration/endpoint/index.md
- WireGuard: configuration/endpoint/wireguard.md - WireGuard: configuration/endpoint/wireguard.md
- Tailscale: configuration/endpoint/tailscale.md
- Inbound: - Inbound:
- configuration/inbound/index.md - configuration/inbound/index.md
- Direct: configuration/inbound/direct.md - Direct: configuration/inbound/direct.md

View File

@@ -126,12 +126,7 @@ func (o *NewDNSServerOptions) Upgrade(ctx context.Context) error {
if serverURL.Scheme != "" { if serverURL.Scheme != "" {
serverType = serverURL.Scheme serverType = serverURL.Scheme
} else { } else {
switch options.Address { serverType = C.DNSTypeUDP
case "local", "fakeip":
serverType = options.Address
default:
serverType = C.DNSTypeUDP
}
} }
var remoteOptions RemoteDNSServerOptions var remoteOptions RemoteDNSServerOptions
if options.Detour == "" { if options.Detour == "" {
@@ -163,9 +158,6 @@ func (o *NewDNSServerOptions) Upgrade(ctx context.Context) error {
} }
} }
switch serverType { switch serverType {
case C.DNSTypeLocal:
o.Type = C.DNSTypeLocal
o.Options = &remoteOptions.LocalDNSServerOptions
case C.DNSTypeUDP: case C.DNSTypeUDP:
o.Type = C.DNSTypeUDP o.Type = C.DNSTypeUDP
o.Options = &remoteOptions o.Options = &remoteOptions
@@ -182,8 +174,6 @@ func (o *NewDNSServerOptions) Upgrade(ctx context.Context) error {
if serverAddr.Port != 0 && serverAddr.Port != 53 { if serverAddr.Port != 0 && serverAddr.Port != 53 {
remoteOptions.ServerPort = serverAddr.Port remoteOptions.ServerPort = serverAddr.Port
} }
remoteOptions.Server = serverAddr.AddrString()
remoteOptions.ServerPort = serverAddr.Port
case C.DNSTypeTCP: case C.DNSTypeTCP:
o.Type = C.DNSTypeTCP o.Type = C.DNSTypeTCP
o.Options = &remoteOptions o.Options = &remoteOptions
@@ -195,20 +185,19 @@ func (o *NewDNSServerOptions) Upgrade(ctx context.Context) error {
if serverAddr.Port != 0 && serverAddr.Port != 53 { if serverAddr.Port != 0 && serverAddr.Port != 53 {
remoteOptions.ServerPort = serverAddr.Port remoteOptions.ServerPort = serverAddr.Port
} }
remoteOptions.Server = serverAddr.AddrString()
remoteOptions.ServerPort = serverAddr.Port
case C.DNSTypeTLS, C.DNSTypeQUIC: case C.DNSTypeTLS, C.DNSTypeQUIC:
o.Type = serverType o.Type = serverType
tlsOptions := RemoteTLSDNSServerOptions{
RemoteDNSServerOptions: remoteOptions,
}
o.Options = &tlsOptions
serverAddr := M.ParseSocksaddr(serverURL.Host) serverAddr := M.ParseSocksaddr(serverURL.Host)
if !serverAddr.IsValid() { if !serverAddr.IsValid() {
return E.New("invalid server address") return E.New("invalid server address")
} }
remoteOptions.Server = serverAddr.Addr.String() tlsOptions.Server = serverAddr.Addr.String()
if serverAddr.Port != 0 && serverAddr.Port != 853 { if serverAddr.Port != 0 && serverAddr.Port != 853 {
remoteOptions.ServerPort = serverAddr.Port tlsOptions.ServerPort = serverAddr.Port
}
o.Options = &RemoteTLSDNSServerOptions{
RemoteDNSServerOptions: remoteOptions,
} }
case C.DNSTypeHTTPS, C.DNSTypeHTTP3: case C.DNSTypeHTTPS, C.DNSTypeHTTP3:
o.Type = serverType o.Type = serverType
@@ -255,14 +244,14 @@ func (o *NewDNSServerOptions) Upgrade(ctx context.Context) error {
}, },
}, },
} }
case C.DNSTypeDHCP: case "dhcp":
o.Type = C.DNSTypeDHCP o.Type = C.DNSTypeDHCP
dhcpOptions := DHCPDNSServerOptions{} dhcpOptions := DHCPDNSServerOptions{}
if serverURL.Host != "" && serverURL.Host != "auto" { if serverURL.Host != "" && serverURL.Host != "auto" {
dhcpOptions.Interface = serverURL.Host dhcpOptions.Interface = serverURL.Host
} }
o.Options = &dhcpOptions o.Options = &dhcpOptions
case C.DNSTypeFakeIP: case "fakeip":
o.Type = C.DNSTypeFakeIP o.Type = C.DNSTypeFakeIP
fakeipOptions := FakeIPDNSServerOptions{} fakeipOptions := FakeIPDNSServerOptions{}
if legacyOptions, loaded := ctx.Value((*LegacyDNSFakeIPOptions)(nil)).(*LegacyDNSFakeIPOptions); loaded { if legacyOptions, loaded := ctx.Value((*LegacyDNSFakeIPOptions)(nil)).(*LegacyDNSFakeIPOptions); loaded {

View File

@@ -1,7 +1,5 @@
package option package option
import "github.com/sagernet/sing/common/json/badoption"
type HysteriaInboundOptions struct { type HysteriaInboundOptions struct {
ListenOptions ListenOptions
Up string `json:"up,omitempty"` Up string `json:"up,omitempty"`
@@ -26,18 +24,16 @@ type HysteriaUser struct {
type HysteriaOutboundOptions struct { type HysteriaOutboundOptions struct {
DialerOptions DialerOptions
ServerOptions ServerOptions
ServerPorts badoption.Listable[string] `json:"server_ports,omitempty"` Up string `json:"up,omitempty"`
HopInterval badoption.Duration `json:"hop_interval,omitempty"` UpMbps int `json:"up_mbps,omitempty"`
Up string `json:"up,omitempty"` Down string `json:"down,omitempty"`
UpMbps int `json:"up_mbps,omitempty"` DownMbps int `json:"down_mbps,omitempty"`
Down string `json:"down,omitempty"` Obfs string `json:"obfs,omitempty"`
DownMbps int `json:"down_mbps,omitempty"` Auth []byte `json:"auth,omitempty"`
Obfs string `json:"obfs,omitempty"` AuthString string `json:"auth_str,omitempty"`
Auth []byte `json:"auth,omitempty"` ReceiveWindowConn uint64 `json:"recv_window_conn,omitempty"`
AuthString string `json:"auth_str,omitempty"` ReceiveWindow uint64 `json:"recv_window,omitempty"`
ReceiveWindowConn uint64 `json:"recv_window_conn,omitempty"` DisableMTUDiscovery bool `json:"disable_mtu_discovery,omitempty"`
ReceiveWindow uint64 `json:"recv_window,omitempty"` Network NetworkList `json:"network,omitempty"`
DisableMTUDiscovery bool `json:"disable_mtu_discovery,omitempty"`
Network NetworkList `json:"network,omitempty"`
OutboundTLSOptionsContainer OutboundTLSOptionsContainer
} }

View File

@@ -1,24 +0,0 @@
package option
import (
"net/netip"
)
type TailscaleEndpointOptions struct {
DialerOptions
StateDirectory string `json:"state_directory,omitempty"`
AuthKey string `json:"auth_key,omitempty"`
ControlURL string `json:"control_url,omitempty"`
Ephemeral bool `json:"ephemeral,omitempty"`
Hostname string `json:"hostname,omitempty"`
ExitNode string `json:"exit_node,omitempty"`
ExitNodeAllowLANAccess bool `json:"exit_node_allow_lan_access,omitempty"`
AdvertiseRoutes []netip.Prefix `json:"advertise_routes,omitempty"`
AdvertiseExitNode bool `json:"advertise_exit_node,omitempty"`
UDPTimeout UDPTimeoutCompat `json:"udp_timeout,omitempty"`
}
type TailscaleDNSServerOptions struct {
Endpoint string `json:"endpoint,omitempty"`
AcceptDefaultResolvers bool `json:"accept_default_resolvers,omitempty"`
}

View File

@@ -12,11 +12,6 @@ import (
mDNS "github.com/miekg/dns" mDNS "github.com/miekg/dns"
) )
var (
DefaultNetworks = []string{N.NetworkTCP, N.NetworkUDP}
DefaultIPNetworks = []string{N.NetworkTCP, N.NetworkUDP, N.NetworkICMPv4, N.NetworkICMPv6}
)
type NetworkList string type NetworkList string
func (v *NetworkList) UnmarshalJSON(content []byte) error { func (v *NetworkList) UnmarshalJSON(content []byte) error {
@@ -42,9 +37,9 @@ func (v *NetworkList) UnmarshalJSON(content []byte) error {
return nil return nil
} }
func (v NetworkList) Build(defaultNetworks []string) []string { func (v NetworkList) Build() []string {
if v == "" { if v == "" {
return defaultNetworks return []string{N.NetworkTCP, N.NetworkUDP}
} }
return strings.Split(string(v), "\n") return strings.Split(string(v), "\n")
} }

View File

@@ -60,7 +60,7 @@ func NewInbound(ctx context.Context, router adapter.Router, logger log.ContextLo
inbound.listener = listener.New(listener.Options{ inbound.listener = listener.New(listener.Options{
Context: ctx, Context: ctx,
Logger: logger, Logger: logger,
Network: options.Network.Build(option.DefaultIPNetworks), Network: options.Network.Build(),
Listen: options.ListenOptions, Listen: options.ListenOptions,
ConnectionHandler: inbound, ConnectionHandler: inbound,
PacketHandler: inbound, PacketHandler: inbound,

View File

@@ -2,7 +2,6 @@ package direct
import ( import (
"context" "context"
"github.com/sagernet/sing-tun"
"net" "net"
"net/netip" "net/netip"
"time" "time"
@@ -28,7 +27,6 @@ func RegisterOutbound(registry *outbound.Registry) {
var ( var (
_ N.ParallelDialer = (*Outbound)(nil) _ N.ParallelDialer = (*Outbound)(nil)
_ dialer.ParallelNetworkDialer = (*Outbound)(nil) _ dialer.ParallelNetworkDialer = (*Outbound)(nil)
_ adapter.DirectRouteOutbound = (*Outbound)(nil)
) )
type Outbound struct { type Outbound struct {
@@ -52,7 +50,7 @@ func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextL
return nil, err return nil, err
} }
outbound := &Outbound{ outbound := &Outbound{
Adapter: outbound.NewAdapterWithDialerOptions(C.TypeDirect, tag, option.DefaultIPNetworks, options.DialerOptions), Adapter: outbound.NewAdapterWithDialerOptions(C.TypeDirect, tag, []string{N.NetworkTCP, N.NetworkUDP}, options.DialerOptions),
logger: logger, logger: logger,
//nolint:staticcheck //nolint:staticcheck
domainStrategy: C.DomainStrategy(options.DomainStrategy), domainStrategy: C.DomainStrategy(options.DomainStrategy),
@@ -244,10 +242,6 @@ func (h *Outbound) ListenSerialNetworkPacket(ctx context.Context, destination M.
return conn, newDestination, nil return conn, newDestination, nil
} }
func (h *Outbound) NewDirectRouteConnection(metadata adapter.InboundContext, routeContext tun.DirectRouteContext) (tun.DirectRouteDestination, error) {
}
/*func (h *Outbound) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { /*func (h *Outbound) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
if h.loopBack.CheckConn(metadata.Source.AddrPort(), M.AddrPortFromNet(conn.LocalAddr())) { if h.loopBack.CheckConn(metadata.Source.AddrPort(), M.AddrPortFromNet(conn.LocalAddr())) {
return E.New("reject loopback connection to ", metadata.Destination) return E.New("reject loopback connection to ", metadata.Destination)

View File

@@ -4,7 +4,6 @@ import (
"context" "context"
"net" "net"
"os" "os"
"time"
"github.com/sagernet/sing-box/adapter" "github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/adapter/outbound" "github.com/sagernet/sing-box/adapter/outbound"
@@ -52,7 +51,7 @@ func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextL
if err != nil { if err != nil {
return nil, err return nil, err
} }
networkList := options.Network.Build(option.DefaultIPNetworks) networkList := options.Network.Build()
var password string var password string
if options.AuthString != "" { if options.AuthString != "" {
password = options.AuthString password = options.AuthString
@@ -77,18 +76,17 @@ func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextL
receiveBps = uint64(options.DownMbps) * hysteria.MbpsToBps receiveBps = uint64(options.DownMbps) * hysteria.MbpsToBps
} }
client, err := hysteria.NewClient(hysteria.ClientOptions{ client, err := hysteria.NewClient(hysteria.ClientOptions{
Context: ctx, Context: ctx,
Dialer: outboundDialer, Dialer: outboundDialer,
Logger: logger, Logger: logger,
ServerAddress: options.ServerOptions.Build(), ServerAddress: options.ServerOptions.Build(),
ServerPorts: options.ServerPorts, SendBPS: sendBps,
HopInterval: time.Duration(options.HopInterval), ReceiveBPS: receiveBps,
SendBPS: sendBps, XPlusPassword: options.Obfs,
ReceiveBPS: receiveBps, Password: password,
XPlusPassword: options.Obfs, TLSConfig: tlsConfig,
Password: password, UDPDisabled: !common.Contains(networkList, N.NetworkUDP),
TLSConfig: tlsConfig,
UDPDisabled: !common.Contains(networkList, N.NetworkUDP),
ConnReceiveWindow: options.ReceiveWindowConn, ConnReceiveWindow: options.ReceiveWindowConn,
StreamReceiveWindow: options.ReceiveWindow, StreamReceiveWindow: options.ReceiveWindow,
DisableMTUDiscovery: options.DisableMTUDiscovery, DisableMTUDiscovery: options.DisableMTUDiscovery,

View File

@@ -64,7 +64,7 @@ func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextL
if err != nil { if err != nil {
return nil, err return nil, err
} }
networkList := options.Network.Build(option.DefaultIPNetworks) networkList := options.Network.Build()
client, err := hysteria2.NewClient(hysteria2.ClientOptions{ client, err := hysteria2.NewClient(hysteria2.ClientOptions{
Context: ctx, Context: ctx,
Dialer: outboundDialer, Dialer: outboundDialer,

View File

@@ -57,7 +57,7 @@ func NewInbound(ctx context.Context, router adapter.Router, logger log.ContextLo
Listen: options.ListenOptions, Listen: options.ListenOptions,
}), }),
networkIsDefault: options.Network == "", networkIsDefault: options.Network == "",
network: options.Network.Build(option.DefaultIPNetworks), network: options.Network.Build(),
authenticator: auth.NewAuthenticator(options.Users), authenticator: auth.NewAuthenticator(options.Users),
} }
if common.Contains(inbound.network, N.NetworkUDP) { if common.Contains(inbound.network, N.NetworkUDP) {

View File

@@ -53,7 +53,7 @@ func NewTProxy(ctx context.Context, router adapter.Router, logger log.ContextLog
tproxy.listener = listener.New(listener.Options{ tproxy.listener = listener.New(listener.Options{
Context: ctx, Context: ctx,
Logger: logger, Logger: logger,
Network: options.Network.Build(option.DefaultIPNetworks), Network: options.Network.Build(),
Listen: options.ListenOptions, Listen: options.ListenOptions,
ConnectionHandler: tproxy, ConnectionHandler: tproxy,
OOBPacketHandler: tproxy, OOBPacketHandler: tproxy,

View File

@@ -84,7 +84,7 @@ func newInbound(ctx context.Context, router adapter.Router, logger log.ContextLo
inbound.listener = listener.New(listener.Options{ inbound.listener = listener.New(listener.Options{
Context: ctx, Context: ctx,
Logger: logger, Logger: logger,
Network: options.Network.Build(option.DefaultIPNetworks), Network: options.Network.Build(),
Listen: options.ListenOptions, Listen: options.ListenOptions,
ConnectionHandler: inbound, ConnectionHandler: inbound,
PacketHandler: inbound, PacketHandler: inbound,

View File

@@ -92,7 +92,7 @@ func newMultiInbound(ctx context.Context, router adapter.Router, logger log.Cont
inbound.listener = listener.New(listener.Options{ inbound.listener = listener.New(listener.Options{
Context: ctx, Context: ctx,
Logger: logger, Logger: logger,
Network: options.Network.Build(option.DefaultIPNetworks), Network: options.Network.Build(),
Listen: options.ListenOptions, Listen: options.ListenOptions,
ConnectionHandler: inbound, ConnectionHandler: inbound,
PacketHandler: inbound, PacketHandler: inbound,

View File

@@ -77,7 +77,7 @@ func newRelayInbound(ctx context.Context, router adapter.Router, logger log.Cont
inbound.listener = listener.New(listener.Options{ inbound.listener = listener.New(listener.Options{
Context: ctx, Context: ctx,
Logger: logger, Logger: logger,
Network: options.Network.Build(option.DefaultIPNetworks), Network: options.Network.Build(),
Listen: options.ListenOptions, Listen: options.ListenOptions,
ConnectionHandler: inbound, ConnectionHandler: inbound,
PacketHandler: inbound, PacketHandler: inbound,

View File

@@ -49,7 +49,7 @@ func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextL
return nil, err return nil, err
} }
outbound := &Outbound{ outbound := &Outbound{
Adapter: outbound.NewAdapterWithDialerOptions(C.TypeShadowsocks, tag, options.Network.Build(option.DefaultIPNetworks), options.DialerOptions), Adapter: outbound.NewAdapterWithDialerOptions(C.TypeShadowsocks, tag, options.Network.Build(), options.DialerOptions),
logger: logger, logger: logger,
dialer: outboundDialer, dialer: outboundDialer,
method: method, method: method,

View File

@@ -51,7 +51,7 @@ func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextL
return nil, err return nil, err
} }
outbound := &Outbound{ outbound := &Outbound{
Adapter: outbound.NewAdapterWithDialerOptions(C.TypeSOCKS, tag, options.Network.Build(option.DefaultIPNetworks), options.DialerOptions), Adapter: outbound.NewAdapterWithDialerOptions(C.TypeSOCKS, tag, options.Network.Build(), options.DialerOptions),
dnsRouter: service.FromContext[adapter.DNSRouter](ctx), dnsRouter: service.FromContext[adapter.DNSRouter](ctx),
logger: logger, logger: logger,
client: socks.NewClient(outboundDialer, options.ServerOptions.Build(), version, options.Username, options.Password), client: socks.NewClient(outboundDialer, options.ServerOptions.Build(), version, options.Username, options.Password),

View File

@@ -1,320 +0,0 @@
package tailscale
import (
"context"
"net"
"net/http"
"net/netip"
"net/url"
"os"
"reflect"
"strings"
"sync"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/common/dialer"
"github.com/sagernet/sing-box/common/tls"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/dns"
"github.com/sagernet/sing-box/dns/transport"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/option"
"github.com/sagernet/sing/common"
E "github.com/sagernet/sing/common/exceptions"
"github.com/sagernet/sing/common/logger"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
"github.com/sagernet/sing/service"
nDNS "github.com/sagernet/tailscale/net/dns"
"github.com/sagernet/tailscale/types/dnstype"
"github.com/sagernet/tailscale/wgengine/router"
"github.com/sagernet/tailscale/wgengine/wgcfg"
mDNS "github.com/miekg/dns"
"go4.org/netipx"
"golang.org/x/net/http2"
)
func RegistryTransport(registry *dns.TransportRegistry) {
dns.RegisterTransport[option.TailscaleDNSServerOptions](registry, C.DNSTypeTailscale, NewDNSTransport)
}
type DNSTransport struct {
dns.TransportAdapter
ctx context.Context
logger logger.ContextLogger
endpointTag string
acceptDefaultResolvers bool
dnsRouter adapter.DNSRouter
endpointManager adapter.EndpointManager
cfg *wgcfg.Config
dnsCfg *nDNS.Config
endpoint *Endpoint
routePrefixes []netip.Prefix
routes map[string][]adapter.DNSTransport
hosts map[string][]netip.Addr
defaultResolvers []adapter.DNSTransport
}
func NewDNSTransport(ctx context.Context, logger log.ContextLogger, tag string, options option.TailscaleDNSServerOptions) (adapter.DNSTransport, error) {
if options.Endpoint == "" {
return nil, E.New("missing tailscale endpoint tag")
}
return &DNSTransport{
TransportAdapter: dns.NewTransportAdapter(C.DNSTypeTailscale, tag, nil),
ctx: ctx,
logger: logger,
endpointTag: options.Endpoint,
acceptDefaultResolvers: options.AcceptDefaultResolvers,
dnsRouter: service.FromContext[adapter.DNSRouter](ctx),
endpointManager: service.FromContext[adapter.EndpointManager](ctx),
}, nil
}
func (t *DNSTransport) Start(stage adapter.StartStage) error {
if stage != adapter.StartStateInitialize {
return nil
}
rawOutbound, loaded := t.endpointManager.Get(t.endpointTag)
if !loaded {
return E.New("endpoint not found: ", t.endpointTag)
}
ep, isTailscale := rawOutbound.(*Endpoint)
if !isTailscale {
return E.New("endpoint is not Tailscale: ", t.endpointTag)
}
if ep.onReconfig != nil {
return E.New("only one Tailscale DNS server is allowed for single endpoint")
}
ep.onReconfig = t.onReconfig
t.endpoint = ep
return nil
}
func (t *DNSTransport) Reset() {
}
func (t *DNSTransport) onReconfig(cfg *wgcfg.Config, routerCfg *router.Config, dnsCfg *nDNS.Config) {
if cfg == nil || dnsCfg == nil {
return
}
if (t.cfg != nil && reflect.DeepEqual(t.cfg, cfg)) && (t.dnsCfg != nil && reflect.DeepEqual(t.dnsCfg, dnsCfg)) {
return
}
t.cfg = cfg
t.dnsCfg = dnsCfg
err := t.updateDNSServers(routerCfg, dnsCfg)
if err != nil {
t.logger.Error(E.Cause(err, "update DNS servers"))
}
}
func (t *DNSTransport) updateDNSServers(routeConfig *router.Config, dnsConfig *nDNS.Config) error {
t.routePrefixes = buildRoutePrefixes(routeConfig)
directDialerOnce := sync.OnceValue(func() N.Dialer {
directDialer := common.Must1(dialer.NewDefault(t.ctx, option.DialerOptions{}))
return &DNSDialer{transport: t, fallbackDialer: directDialer}
})
routes := make(map[string][]adapter.DNSTransport)
for domain, resolvers := range dnsConfig.Routes {
var myResolvers []adapter.DNSTransport
for _, resolver := range resolvers {
myResolver, err := t.createResolver(directDialerOnce, resolver)
if err != nil {
return err
}
myResolvers = append(myResolvers, myResolver)
}
routes[domain.WithTrailingDot()] = myResolvers
}
hosts := make(map[string][]netip.Addr)
for domain, addresses := range dnsConfig.Hosts {
hosts[domain.WithTrailingDot()] = addresses
}
var defaultResolvers []adapter.DNSTransport
for _, resolver := range dnsConfig.DefaultResolvers {
myResolver, err := t.createResolver(directDialerOnce, resolver)
if err != nil {
return err
}
defaultResolvers = append(defaultResolvers, myResolver)
}
t.routes = routes
t.hosts = hosts
t.defaultResolvers = defaultResolvers
if len(defaultResolvers) > 0 {
t.logger.Info("updated ", len(routes), " routes, ", len(hosts), " hosts, default resolvers: ",
strings.Join(common.Map(dnsConfig.DefaultResolvers, func(it *dnstype.Resolver) string { return it.Addr }), " "))
} else {
t.logger.Info("updated ", len(routes), " routes, ", len(hosts), " hosts")
}
return nil
}
func (t *DNSTransport) createResolver(directDialer func() N.Dialer, resolver *dnstype.Resolver) (adapter.DNSTransport, error) {
serverURL, parseURLErr := url.Parse(resolver.Addr)
var myDialer N.Dialer
if parseURLErr == nil && serverURL.Scheme == "http" {
myDialer = t.endpoint
} else {
myDialer = directDialer()
}
if len(resolver.BootstrapResolution) > 0 {
bootstrapTransport := transport.NewUDPRaw(t.logger, t.TransportAdapter, myDialer, M.SocksaddrFrom(resolver.BootstrapResolution[0], 53))
myDialer = dialer.NewResolveDialer(t.ctx, myDialer, false, "", adapter.DNSQueryOptions{Transport: bootstrapTransport}, 0)
}
if serverAddr := M.ParseSocksaddr(resolver.Addr); serverAddr.IsValid() {
if serverAddr.Port == 0 {
serverAddr.Port = 53
}
return transport.NewUDPRaw(t.logger, t.TransportAdapter, myDialer, serverAddr), nil
} else if parseURLErr != nil {
return nil, E.Cause(parseURLErr, "parse resolver address")
} else {
switch serverURL.Scheme {
case "https":
serverAddr = M.ParseSocksaddrHostPortStr(serverURL.Hostname(), serverURL.Port())
if serverAddr.Port == 0 {
serverAddr.Port = 443
}
tlsConfig := common.Must1(tls.NewClient(t.ctx, serverAddr.AddrString(), option.OutboundTLSOptions{
ALPN: []string{http2.NextProtoTLS, "http/1.1"},
}))
return transport.NewHTTPSRaw(t.TransportAdapter, t.logger, myDialer, serverURL, http.Header{}, serverAddr, tlsConfig), nil
case "http":
serverAddr = M.ParseSocksaddrHostPortStr(serverURL.Hostname(), serverURL.Port())
if serverAddr.Port == 0 {
serverAddr.Port = 80
}
return transport.NewHTTPSRaw(t.TransportAdapter, t.logger, myDialer, serverURL, http.Header{}, serverAddr, nil), nil
// case "tls":
default:
return nil, E.New("unknown resolver scheme: ", serverURL.Scheme)
}
}
}
func buildRoutePrefixes(routeConfig *router.Config) []netip.Prefix {
var builder netipx.IPSetBuilder
for _, localAddr := range routeConfig.LocalAddrs {
builder.AddPrefix(localAddr)
}
for _, route := range routeConfig.Routes {
builder.AddPrefix(route)
}
for _, route := range routeConfig.LocalRoutes {
builder.AddPrefix(route)
}
for _, route := range routeConfig.SubnetRoutes {
builder.AddPrefix(route)
}
ipSet, err := builder.IPSet()
if err != nil {
return nil
}
return ipSet.Prefixes()
}
func (t *DNSTransport) Close() error {
return nil
}
func (t *DNSTransport) Raw() bool {
return true
}
func (t *DNSTransport) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg, error) {
if len(message.Question) != 1 {
return nil, os.ErrInvalid
}
question := message.Question[0]
addresses, hostsLoaded := t.hosts[question.Name]
if hostsLoaded {
switch question.Qtype {
case mDNS.TypeA:
addresses4 := common.Filter(addresses, func(addr netip.Addr) bool {
return addr.Is4()
})
if len(addresses4) > 0 {
return dns.FixedResponse(message.Id, question, addresses4, C.DefaultDNSTTL), nil
}
case mDNS.TypeAAAA:
addresses6 := common.Filter(addresses, func(addr netip.Addr) bool {
return addr.Is6()
})
if len(addresses6) > 0 {
return dns.FixedResponse(message.Id, question, addresses6, C.DefaultDNSTTL), nil
}
}
}
for domainSuffix, transports := range t.routes {
if strings.HasSuffix(question.Name, domainSuffix) {
if len(transports) == 0 {
return &mDNS.Msg{
MsgHdr: mDNS.MsgHdr{
Id: message.Id,
Rcode: mDNS.RcodeNameError,
Response: true,
},
Question: []mDNS.Question{question},
}, nil
}
var lastErr error
for _, dnsTransport := range transports {
response, err := dnsTransport.Exchange(ctx, message)
if err != nil {
lastErr = err
continue
}
return response, nil
}
return nil, lastErr
}
}
if t.acceptDefaultResolvers {
if len(t.defaultResolvers) > 0 {
var lastErr error
for _, resolver := range t.defaultResolvers {
response, err := resolver.Exchange(ctx, message)
if err != nil {
lastErr = err
continue
}
return response, nil
}
return nil, lastErr
} else {
return nil, E.New("missing default resolvers")
}
}
return nil, dns.RCodeNameError
}
type DNSDialer struct {
transport *DNSTransport
fallbackDialer N.Dialer
}
func (d *DNSDialer) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
if destination.IsFqdn() {
panic("invalid request here")
}
for _, prefix := range d.transport.routePrefixes {
if prefix.Contains(destination.Addr) {
return d.transport.endpoint.DialContext(ctx, network, destination)
}
}
return d.fallbackDialer.DialContext(ctx, network, destination)
}
func (d *DNSDialer) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
if destination.IsFqdn() {
panic("invalid request here")
}
for _, prefix := range d.transport.routePrefixes {
if prefix.Contains(destination.Addr) {
return d.transport.endpoint.ListenPacket(ctx, destination)
}
}
return d.fallbackDialer.ListenPacket(ctx, destination)
}

View File

@@ -1,476 +0,0 @@
package tailscale
import (
"context"
"fmt"
"net"
"net/netip"
"net/url"
"os"
"path/filepath"
"runtime"
"strings"
"sync/atomic"
"syscall"
"time"
"github.com/sagernet/gvisor/pkg/tcpip"
"github.com/sagernet/gvisor/pkg/tcpip/adapters/gonet"
"github.com/sagernet/gvisor/pkg/tcpip/header"
"github.com/sagernet/gvisor/pkg/tcpip/stack"
"github.com/sagernet/gvisor/pkg/tcpip/transport/icmp"
"github.com/sagernet/gvisor/pkg/tcpip/transport/tcp"
"github.com/sagernet/gvisor/pkg/tcpip/transport/udp"
"github.com/sagernet/sing-box/adapter"
"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/experimental/libbox/platform"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/option"
"github.com/sagernet/sing-tun"
"github.com/sagernet/sing/common"
"github.com/sagernet/sing/common/bufio"
"github.com/sagernet/sing/common/control"
E "github.com/sagernet/sing/common/exceptions"
F "github.com/sagernet/sing/common/format"
"github.com/sagernet/sing/common/logger"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
"github.com/sagernet/sing/service"
"github.com/sagernet/sing/service/filemanager"
"github.com/sagernet/tailscale/ipn"
"github.com/sagernet/tailscale/net/netmon"
"github.com/sagernet/tailscale/net/tsaddr"
"github.com/sagernet/tailscale/tsnet"
"github.com/sagernet/tailscale/types/ipproto"
"github.com/sagernet/tailscale/version"
"github.com/sagernet/tailscale/wgengine"
"github.com/sagernet/tailscale/wgengine/filter"
)
func init() {
version.SetVersion("sing-box " + C.Version)
}
func RegisterEndpoint(registry *endpoint.Registry) {
endpoint.Register[option.TailscaleEndpointOptions](registry, C.TypeTailscale, NewEndpoint)
}
type Endpoint struct {
endpoint.Adapter
ctx context.Context
router adapter.Router
logger logger.ContextLogger
dnsRouter adapter.DNSRouter
network adapter.NetworkManager
platformInterface platform.Interface
server *tsnet.Server
stack *stack.Stack
filter *atomic.Pointer[filter.Filter]
onReconfig wgengine.ReconfigListener
exitNode string
exitNodeAllowLANAccess bool
advertiseRoutes []netip.Prefix
advertiseExitNode bool
udpTimeout time.Duration
}
func NewEndpoint(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.TailscaleEndpointOptions) (adapter.Endpoint, error) {
stateDirectory := options.StateDirectory
if stateDirectory == "" {
stateDirectory = "tailscale"
}
hostname := options.Hostname
if hostname == "" {
osHostname, _ := os.Hostname()
osHostname = strings.TrimSpace(osHostname)
hostname = osHostname
}
if hostname == "" {
hostname = "sing-box"
}
stateDirectory = filemanager.BasePath(ctx, os.ExpandEnv(stateDirectory))
stateDirectory, _ = filepath.Abs(stateDirectory)
for _, advertiseRoute := range options.AdvertiseRoutes {
if advertiseRoute.Addr().IsUnspecified() && advertiseRoute.Bits() == 0 {
return nil, E.New("`advertise_routes` cannot be default, use `advertise_exit_node` instead.")
}
}
if options.AdvertiseExitNode && options.ExitNode != "" {
return nil, E.New("cannot advertise an exit node and use an exit node at the same time.")
}
var udpTimeout time.Duration
if options.UDPTimeout != 0 {
udpTimeout = time.Duration(options.UDPTimeout)
} else {
udpTimeout = C.UDPTimeout
}
var remoteIsDomain bool
if options.ControlURL != "" {
controlURL, err := url.Parse(options.ControlURL)
if err != nil {
return nil, E.Cause(err, "parse control URL")
}
remoteIsDomain = M.IsDomainName(controlURL.Hostname())
} else {
// controlplane.tailscale.com
remoteIsDomain = true
}
outboundDialer, err := dialer.NewWithOptions(dialer.Options{
Context: ctx,
Options: options.DialerOptions,
RemoteIsDomain: remoteIsDomain,
ResolverOnDetour: true,
NewDialer: true,
})
if err != nil {
return nil, err
}
dnsRouter := service.FromContext[adapter.DNSRouter](ctx)
server := &tsnet.Server{
Dir: stateDirectory,
Hostname: hostname,
Logf: func(format string, args ...any) {
logger.Trace(fmt.Sprintf(format, args...))
},
UserLogf: func(format string, args ...any) {
logger.Debug(fmt.Sprintf(format, args...))
},
Ephemeral: options.Ephemeral,
AuthKey: options.AuthKey,
ControlURL: options.ControlURL,
Dialer: &endpointDialer{Dialer: outboundDialer, logger: logger},
LookupHook: func(ctx context.Context, host string) ([]netip.Addr, error) {
return dnsRouter.Lookup(ctx, host, outboundDialer.(dialer.ResolveDialer).QueryOptions())
},
}
return &Endpoint{
Adapter: endpoint.NewAdapter(C.TypeTailscale, tag, []string{N.NetworkTCP, N.NetworkUDP}, nil),
ctx: ctx,
router: router,
logger: logger,
dnsRouter: dnsRouter,
network: service.FromContext[adapter.NetworkManager](ctx),
platformInterface: service.FromContext[platform.Interface](ctx),
server: server,
exitNode: options.ExitNode,
exitNodeAllowLANAccess: options.ExitNodeAllowLANAccess,
advertiseRoutes: options.AdvertiseRoutes,
advertiseExitNode: options.AdvertiseExitNode,
udpTimeout: udpTimeout,
}, nil
}
func (t *Endpoint) Start(stage adapter.StartStage) error {
if stage != adapter.StartStateStart {
return nil
}
if t.platformInterface != nil {
err := t.network.UpdateInterfaces()
if err != nil {
return err
}
netmon.RegisterInterfaceGetter(func() ([]netmon.Interface, error) {
return common.Map(t.network.InterfaceFinder().Interfaces(), func(it control.Interface) netmon.Interface {
return netmon.Interface{
Interface: &net.Interface{
Index: it.Index,
MTU: it.MTU,
Name: it.Name,
HardwareAddr: it.HardwareAddr,
Flags: it.Flags,
},
AltAddrs: common.Map(it.Addresses, func(it netip.Prefix) net.Addr {
return &net.IPNet{
IP: it.Addr().AsSlice(),
Mask: net.CIDRMask(it.Bits(), it.Addr().BitLen()),
}
}),
}
}), nil
})
if runtime.GOOS == "android" {
setAndroidProtectFunc(t.platformInterface)
}
}
err := t.server.Start()
if err != nil {
return err
}
if t.onReconfig != nil {
t.server.ExportLocalBackend().ExportEngine().(wgengine.ExportedUserspaceEngine).SetOnReconfigListener(t.onReconfig)
}
ipStack := t.server.ExportNetstack().ExportIPStack()
ipStack.SetTransportProtocolHandler(tcp.ProtocolNumber, tun.NewTCPForwarder(t.ctx, ipStack, t).HandlePacket)
ipStack.SetTransportProtocolHandler(udp.ProtocolNumber, tun.NewUDPForwarder(t.ctx, ipStack, t, t.udpTimeout).HandlePacket)
icmpForwarder := tun.NewICMPForwarder(t.ctx, ipStack, t, t.udpTimeout)
ipStack.SetTransportProtocolHandler(icmp.ProtocolNumber4, icmpForwarder.HandlePacket)
ipStack.SetTransportProtocolHandler(icmp.ProtocolNumber6, icmpForwarder.HandlePacket)
t.stack = ipStack
localBackend := t.server.ExportLocalBackend()
perfs := &ipn.MaskedPrefs{
ExitNodeIPSet: true,
AdvertiseRoutesSet: true,
}
if len(t.advertiseRoutes) > 0 {
perfs.AdvertiseRoutes = t.advertiseRoutes
}
if t.advertiseExitNode {
perfs.AdvertiseRoutes = append(perfs.AdvertiseRoutes, tsaddr.ExitRoutes()...)
}
_, err = localBackend.EditPrefs(perfs)
if err != nil {
return E.Cause(err, "update prefs")
}
t.filter = localBackend.ExportFilter()
go t.watchState()
return nil
}
func (t *Endpoint) watchState() {
localBackend := t.server.ExportLocalBackend()
localBackend.WatchNotifications(t.ctx, ipn.NotifyInitialState, nil, func(roNotify *ipn.Notify) (keepGoing bool) {
if roNotify.State != nil && *roNotify.State != ipn.NeedsLogin && *roNotify.State != ipn.NoState {
return false
}
authURL := localBackend.StatusWithoutPeers().AuthURL
if authURL != "" {
t.logger.Info("Waiting for authentication: ", authURL)
if t.platformInterface != nil {
err := t.platformInterface.SendNotification(&platform.Notification{
Identifier: "tailscale-authentication",
TypeName: "Tailscale Authentication Notifications",
TypeID: 10,
Title: "Tailscale Authentication",
Body: F.ToString("Tailscale outbound[", t.Tag(), "] is waiting for authentication."),
OpenURL: authURL,
})
if err != nil {
t.logger.Error("send authentication notification: ", err)
}
}
return false
}
return true
})
if t.exitNode != "" {
localBackend.WatchNotifications(t.ctx, ipn.NotifyInitialState, nil, func(roNotify *ipn.Notify) (keepGoing bool) {
if roNotify.State == nil || *roNotify.State != ipn.Running {
return true
}
status, err := common.Must1(t.server.LocalClient()).Status(t.ctx)
if err != nil {
t.logger.Error("set exit node: ", err)
return
}
perfs := &ipn.MaskedPrefs{
Prefs: ipn.Prefs{
ExitNodeAllowLANAccess: t.exitNodeAllowLANAccess,
},
ExitNodeIPSet: true,
ExitNodeAllowLANAccessSet: true,
}
err = perfs.SetExitNodeIP(t.exitNode, status)
if err != nil {
t.logger.Error("set exit node: ", err)
return true
}
_, err = localBackend.EditPrefs(perfs)
if err != nil {
t.logger.Error("set exit node: ", err)
return true
}
return false
})
}
}
func (t *Endpoint) Close() error {
netmon.RegisterInterfaceGetter(nil)
if runtime.GOOS == "android" {
setAndroidProtectFunc(nil)
}
return common.Close(common.PtrOrNil(t.server))
}
func (t *Endpoint) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
switch network {
case N.NetworkTCP:
t.logger.InfoContext(ctx, "outbound connection to ", destination)
case N.NetworkUDP:
t.logger.InfoContext(ctx, "outbound packet connection to ", destination)
}
if destination.IsFqdn() {
destinationAddresses, err := t.dnsRouter.Lookup(ctx, destination.Fqdn, adapter.DNSQueryOptions{})
if err != nil {
return nil, err
}
return N.DialSerial(ctx, t, network, destination, destinationAddresses)
}
addr := tcpip.FullAddress{
NIC: 1,
Port: destination.Port,
Addr: addressFromAddr(destination.Addr),
}
var networkProtocol tcpip.NetworkProtocolNumber
if destination.IsIPv4() {
networkProtocol = header.IPv4ProtocolNumber
} else {
networkProtocol = header.IPv6ProtocolNumber
}
switch N.NetworkName(network) {
case N.NetworkTCP:
tcpConn, err := gonet.DialContextTCP(ctx, t.stack, addr, networkProtocol)
if err != nil {
return nil, err
}
return tcpConn, nil
case N.NetworkUDP:
udpConn, err := gonet.DialUDP(t.stack, nil, &addr, networkProtocol)
if err != nil {
return nil, err
}
return udpConn, nil
default:
return nil, E.Extend(N.ErrUnknownNetwork, network)
}
}
func (t *Endpoint) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
t.logger.InfoContext(ctx, "outbound packet connection to ", destination)
if destination.IsFqdn() {
destinationAddresses, err := t.dnsRouter.Lookup(ctx, destination.Fqdn, adapter.DNSQueryOptions{})
if err != nil {
return nil, err
}
packetConn, _, err := N.ListenSerial(ctx, t, destination, destinationAddresses)
if err != nil {
return nil, err
}
return packetConn, err
}
addr4, addr6 := t.server.TailscaleIPs()
bind := tcpip.FullAddress{
NIC: 1,
}
var networkProtocol tcpip.NetworkProtocolNumber
if destination.IsIPv4() {
if !addr4.IsValid() {
return nil, E.New("missing Tailscale IPv4 address")
}
networkProtocol = header.IPv4ProtocolNumber
bind.Addr = addressFromAddr(addr4)
} else {
if !addr6.IsValid() {
return nil, E.New("missing Tailscale IPv6 address")
}
networkProtocol = header.IPv6ProtocolNumber
bind.Addr = addressFromAddr(addr6)
}
udpConn, err := gonet.DialUDP(t.stack, &bind, nil, networkProtocol)
if err != nil {
return nil, err
}
return udpConn, nil
}
func (t *Endpoint) PrepareConnection(network string, source M.Socksaddr, destination M.Socksaddr, routeContext tun.DirectRouteContext) (tun.DirectRouteDestination, error) {
tsFilter := t.filter.Load()
if tsFilter != nil {
var ipProto ipproto.Proto
switch N.NetworkName(network) {
case N.NetworkTCP:
ipProto = ipproto.TCP
case N.NetworkUDP:
ipProto = ipproto.UDP
}
response := tsFilter.Check(source.Addr, destination.Addr, destination.Port, ipProto)
switch response {
case filter.Drop:
return nil, syscall.ECONNREFUSED
case filter.DropSilently:
return nil, tun.ErrDrop
}
}
return t.router.PreMatch(adapter.InboundContext{
Inbound: t.Tag(),
InboundType: t.Type(),
Network: network,
Source: source,
Destination: destination,
}, routeContext)
}
func (t *Endpoint) NewConnectionEx(ctx context.Context, conn net.Conn, source M.Socksaddr, destination M.Socksaddr, onClose N.CloseHandlerFunc) {
var metadata adapter.InboundContext
metadata.Inbound = t.Tag()
metadata.InboundType = t.Type()
metadata.Source = source
addr4, addr6 := t.server.TailscaleIPs()
switch destination.Addr {
case addr4:
destination.Addr = netip.AddrFrom4([4]uint8{127, 0, 0, 1})
case addr6:
destination.Addr = netip.IPv6Loopback()
}
metadata.Destination = destination
t.logger.InfoContext(ctx, "inbound connection from ", source)
t.logger.InfoContext(ctx, "inbound connection to ", metadata.Destination)
t.router.RouteConnectionEx(ctx, conn, metadata, onClose)
}
func (t *Endpoint) NewPacketConnectionEx(ctx context.Context, conn N.PacketConn, source M.Socksaddr, destination M.Socksaddr, onClose N.CloseHandlerFunc) {
var metadata adapter.InboundContext
metadata.Inbound = t.Tag()
metadata.InboundType = t.Type()
metadata.Source = source
metadata.Destination = destination
addr4, addr6 := t.server.TailscaleIPs()
switch destination.Addr {
case addr4:
metadata.OriginDestination = destination
destination.Addr = netip.AddrFrom4([4]uint8{127, 0, 0, 1})
conn = bufio.NewNATPacketConn(bufio.NewNetPacketConn(conn), metadata.OriginDestination, metadata.Destination)
case addr6:
metadata.OriginDestination = destination
destination.Addr = netip.IPv6Loopback()
conn = bufio.NewNATPacketConn(bufio.NewNetPacketConn(conn), metadata.OriginDestination, metadata.Destination)
}
t.logger.InfoContext(ctx, "inbound packet connection from ", source)
t.logger.InfoContext(ctx, "inbound packet connection to ", destination)
t.router.RoutePacketConnectionEx(ctx, conn, metadata, onClose)
}
func addressFromAddr(destination netip.Addr) tcpip.Address {
if destination.Is6() {
return tcpip.AddrFrom16(destination.As16())
} else {
return tcpip.AddrFrom4(destination.As4())
}
}
type endpointDialer struct {
N.Dialer
logger logger.ContextLogger
}
func (d *endpointDialer) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
switch N.NetworkName(network) {
case N.NetworkTCP:
d.logger.InfoContext(ctx, "output connection to ", destination)
case N.NetworkUDP:
d.logger.InfoContext(ctx, "output packet connection to ", destination)
}
return d.Dialer.DialContext(ctx, network, destination)
}
func (d *endpointDialer) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
d.logger.InfoContext(ctx, "output packet connection")
return d.Dialer.ListenPacket(ctx, destination)
}

View File

@@ -1,16 +0,0 @@
package tailscale
import (
"github.com/sagernet/sing-box/experimental/libbox/platform"
"github.com/sagernet/tailscale/net/netns"
)
func setAndroidProtectFunc(platformInterface platform.Interface) {
if platformInterface != nil {
netns.SetAndroidProtectFunc(func(fd int) error {
return platformInterface.AutoDetectInterfaceControl(fd)
})
} else {
netns.SetAndroidProtectFunc(nil)
}
}

View File

@@ -1,8 +0,0 @@
//go:build !android
package tailscale
import "github.com/sagernet/sing-box/experimental/libbox/platform"
func setAndroidProtectFunc(platformInterface platform.Interface) {
}

View File

@@ -43,7 +43,7 @@ func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextL
return nil, err return nil, err
} }
outbound := &Outbound{ outbound := &Outbound{
Adapter: outbound.NewAdapterWithDialerOptions(C.TypeTrojan, tag, options.Network.Build(option.DefaultIPNetworks), options.DialerOptions), Adapter: outbound.NewAdapterWithDialerOptions(C.TypeTrojan, tag, options.Network.Build(), options.DialerOptions),
logger: logger, logger: logger,
dialer: outboundDialer, dialer: outboundDialer,
serverAddr: options.ServerOptions.Build(), serverAddr: options.ServerOptions.Build(),

View File

@@ -80,7 +80,7 @@ func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextL
return nil, err return nil, err
} }
return &Outbound{ return &Outbound{
Adapter: outbound.NewAdapterWithDialerOptions(C.TypeTUIC, tag, options.Network.Build(option.DefaultIPNetworks), options.DialerOptions), Adapter: outbound.NewAdapterWithDialerOptions(C.TypeTUIC, tag, options.Network.Build(), options.DialerOptions),
logger: logger, logger: logger,
client: client, client: client,
udpStream: options.UDPOverStream, udpStream: options.UDPOverStream,

View File

@@ -8,7 +8,6 @@ import (
"runtime" "runtime"
"strconv" "strconv"
"strings" "strings"
"syscall"
"time" "time"
"github.com/sagernet/sing-box/adapter" "github.com/sagernet/sing-box/adapter"
@@ -313,11 +312,9 @@ func (t *Inbound) Start(stage adapter.StartStage) error {
if len(ipSets) == 0 { if len(ipSets) == 0 {
t.logger.Warn("route_address_set: no destination IP CIDR rules found in rule-set: ", routeRuleSet.Name()) t.logger.Warn("route_address_set: no destination IP CIDR rules found in rule-set: ", routeRuleSet.Name())
} }
t.routeRuleSetCallback = append(t.routeRuleSetCallback, routeRuleSet.RegisterCallback(t.updateRouteAddressSet))
routeRuleSet.DecRef() routeRuleSet.DecRef()
t.routeAddressSet = append(t.routeAddressSet, ipSets...) t.routeAddressSet = append(t.routeAddressSet, ipSets...)
if t.autoRedirect != nil {
t.routeRuleSetCallback = append(t.routeRuleSetCallback, routeRuleSet.RegisterCallback(t.updateRouteAddressSet))
}
} }
t.routeExcludeAddressSet = common.FlatMap(t.routeExcludeRuleSet, adapter.RuleSet.ExtractIPSet) t.routeExcludeAddressSet = common.FlatMap(t.routeExcludeRuleSet, adapter.RuleSet.ExtractIPSet)
for _, routeExcludeRuleSet := range t.routeExcludeRuleSet { for _, routeExcludeRuleSet := range t.routeExcludeRuleSet {
@@ -325,11 +322,9 @@ func (t *Inbound) Start(stage adapter.StartStage) error {
if len(ipSets) == 0 { if len(ipSets) == 0 {
t.logger.Warn("route_address_set: no destination IP CIDR rules found in rule-set: ", routeExcludeRuleSet.Name()) t.logger.Warn("route_address_set: no destination IP CIDR rules found in rule-set: ", routeExcludeRuleSet.Name())
} }
t.routeExcludeRuleSetCallback = append(t.routeExcludeRuleSetCallback, routeExcludeRuleSet.RegisterCallback(t.updateRouteAddressSet))
routeExcludeRuleSet.DecRef() routeExcludeRuleSet.DecRef()
t.routeExcludeAddressSet = append(t.routeExcludeAddressSet, ipSets...) t.routeExcludeAddressSet = append(t.routeExcludeAddressSet, ipSets...)
if t.autoRedirect != nil {
t.routeExcludeRuleSetCallback = append(t.routeExcludeRuleSetCallback, routeExcludeRuleSet.RegisterCallback(t.updateRouteAddressSet))
}
} }
} }
var ( var (
@@ -439,21 +434,15 @@ func (t *Inbound) Close() error {
) )
} }
func (t *Inbound) PrepareConnection(network string, source M.Socksaddr, destination M.Socksaddr, routeContext tun.DirectRouteContext) (tun.DirectRouteDestination, error) { func (t *Inbound) PrepareConnection(network string, source M.Socksaddr, destination M.Socksaddr) error {
routeDestination, err := t.router.PreMatch(adapter.InboundContext{ return t.router.PreMatch(adapter.InboundContext{
Inbound: t.tag, Inbound: t.tag,
InboundType: C.TypeTun, InboundType: C.TypeTun,
Network: network, Network: network,
Source: source, Source: source,
Destination: destination, Destination: destination,
InboundOptions: t.inboundOptions, InboundOptions: t.inboundOptions,
}, routeContext) })
if err != nil {
if !E.IsMulti(err, tun.ErrDrop, syscall.ECONNREFUSED) {
t.logger.Warn(err)
}
}
return routeDestination, err
} }
func (t *Inbound) NewConnectionEx(ctx context.Context, conn net.Conn, source M.Socksaddr, destination M.Socksaddr, onClose N.CloseHandlerFunc) { func (t *Inbound) NewConnectionEx(ctx context.Context, conn net.Conn, source M.Socksaddr, destination M.Socksaddr, onClose N.CloseHandlerFunc) {

View File

@@ -46,7 +46,7 @@ func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextL
return nil, err return nil, err
} }
outbound := &Outbound{ outbound := &Outbound{
Adapter: outbound.NewAdapterWithDialerOptions(C.TypeVLESS, tag, options.Network.Build(option.DefaultIPNetworks), options.DialerOptions), Adapter: outbound.NewAdapterWithDialerOptions(C.TypeVLESS, tag, options.Network.Build(), options.DialerOptions),
logger: logger, logger: logger,
dialer: outboundDialer, dialer: outboundDialer,
serverAddr: options.ServerOptions.Build(), serverAddr: options.ServerOptions.Build(),

View File

@@ -46,7 +46,7 @@ func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextL
return nil, err return nil, err
} }
outbound := &Outbound{ outbound := &Outbound{
Adapter: outbound.NewAdapterWithDialerOptions(C.TypeVMess, tag, options.Network.Build(option.DefaultIPNetworks), options.DialerOptions), Adapter: outbound.NewAdapterWithDialerOptions(C.TypeVMess, tag, options.Network.Build(), options.DialerOptions),
logger: logger, logger: logger,
dialer: outboundDialer, dialer: outboundDialer,
serverAddr: options.ServerOptions.Build(), serverAddr: options.ServerOptions.Build(),

View File

@@ -13,7 +13,6 @@ import (
"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-box/transport/wireguard" "github.com/sagernet/sing-box/transport/wireguard"
"github.com/sagernet/sing-tun"
"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" E "github.com/sagernet/sing/common/exceptions"
@@ -44,7 +43,7 @@ type Endpoint struct {
func NewEndpoint(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.WireGuardEndpointOptions) (adapter.Endpoint, error) { func NewEndpoint(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.WireGuardEndpointOptions) (adapter.Endpoint, error) {
ep := &Endpoint{ ep := &Endpoint{
Adapter: endpoint.NewAdapterWithDialerOptions(C.TypeWireGuard, tag, []string{N.NetworkTCP, N.NetworkUDP, N.NetworkICMPv4, N.NetworkICMPv6}, options.DialerOptions), Adapter: endpoint.NewAdapterWithDialerOptions(C.TypeWireGuard, tag, []string{N.NetworkTCP, N.NetworkUDP}, options.DialerOptions),
ctx: ctx, ctx: ctx,
router: router, router: router,
dnsRouter: service.FromContext[adapter.DNSRouter](ctx), dnsRouter: service.FromContext[adapter.DNSRouter](ctx),
@@ -133,14 +132,14 @@ func (w *Endpoint) InterfaceUpdated() {
return return
} }
func (w *Endpoint) PrepareConnection(network string, source M.Socksaddr, destination M.Socksaddr, context tun.DirectRouteContext) (tun.DirectRouteDestination, error) { func (w *Endpoint) PrepareConnection(network string, source M.Socksaddr, destination M.Socksaddr) error {
return w.router.PreMatch(adapter.InboundContext{ return w.router.PreMatch(adapter.InboundContext{
Inbound: w.Tag(), Inbound: w.Tag(),
InboundType: w.Type(), InboundType: w.Type(),
Network: network, Network: network,
Source: source, Source: source,
Destination: destination, Destination: destination,
}, context) })
} }
func (w *Endpoint) NewConnectionEx(ctx context.Context, conn net.Conn, source M.Socksaddr, destination M.Socksaddr, onClose N.CloseHandlerFunc) { func (w *Endpoint) NewConnectionEx(ctx context.Context, conn net.Conn, source M.Socksaddr, destination M.Socksaddr, onClose N.CloseHandlerFunc) {
@@ -221,12 +220,3 @@ func (w *Endpoint) ListenPacket(ctx context.Context, destination M.Socksaddr) (n
} }
return w.endpoint.ListenPacket(ctx, destination) return w.endpoint.ListenPacket(ctx, destination)
} }
func (w *Endpoint) NewDirectRouteConnection(metadata adapter.InboundContext, routeContext tun.DirectRouteContext) (tun.DirectRouteDestination, error) {
destination, err := w.endpoint.NewDirectRouteConnection(metadata, routeContext)
if err != nil {
return nil, err
}
w.logger.Info("linked ", metadata.Network, " connection to ", metadata.Destination.AddrString())
return destination, nil
}

View File

@@ -45,7 +45,7 @@ func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextL
deprecated.Report(ctx, deprecated.OptionWireGuardGSO) deprecated.Report(ctx, deprecated.OptionWireGuardGSO)
} }
outbound := &Outbound{ outbound := &Outbound{
Adapter: outbound.NewAdapterWithDialerOptions(C.TypeWireGuard, tag, option.DefaultNetworks, options.DialerOptions), Adapter: outbound.NewAdapterWithDialerOptions(C.TypeWireGuard, tag, []string{N.NetworkTCP, N.NetworkUDP}, options.DialerOptions),
ctx: ctx, ctx: ctx,
dnsRouter: service.FromContext[adapter.DNSRouter](ctx), dnsRouter: service.FromContext[adapter.DNSRouter](ctx),
logger: logger, logger: logger,

View File

@@ -18,7 +18,6 @@ import (
"github.com/sagernet/sing-box/option" "github.com/sagernet/sing-box/option"
"github.com/sagernet/sing-box/route/rule" "github.com/sagernet/sing-box/route/rule"
"github.com/sagernet/sing-mux" "github.com/sagernet/sing-mux"
"github.com/sagernet/sing-tun"
"github.com/sagernet/sing-vmess" "github.com/sagernet/sing-vmess"
"github.com/sagernet/sing/common" "github.com/sagernet/sing/common"
"github.com/sagernet/sing/common/buf" "github.com/sagernet/sing/common/buf"
@@ -272,36 +271,19 @@ func (r *Router) routePacketConnection(ctx context.Context, conn N.PacketConn, m
return nil return nil
} }
func (r *Router) PreMatch(metadata adapter.InboundContext, routeContext tun.DirectRouteContext) (tun.DirectRouteDestination, error) { func (r *Router) PreMatch(metadata adapter.InboundContext) error {
selectedRule, _, _, _, err := r.matchRule(r.ctx, &metadata, true, nil, nil) selectedRule, _, _, _, err := r.matchRule(r.ctx, &metadata, true, nil, nil)
if err != nil { if err != nil {
return nil, err return err
} }
if selectedRule == nil { if selectedRule == nil {
defaultOutbound := r.outbound.Default() return nil
if !common.Contains(defaultOutbound.Network(), metadata.Network) {
return nil, E.New(metadata.Network, " is not supported by default outbound: ", defaultOutbound.Tag())
}
return defaultOutbound.(adapter.DirectRouteOutbound).NewDirectRouteConnection(metadata, routeContext)
} }
switch action := selectedRule.Action().(type) { rejectAction, isReject := selectedRule.Action().(*rule.RuleActionReject)
case *rule.RuleActionReject: if !isReject {
return nil, action.Error(context.Background()) return nil
case *rule.RuleActionRoute:
if routeContext == nil {
return nil, nil
}
outbound, loaded := r.outbound.Outbound(action.Outbound)
if !loaded {
return nil, E.New("outbound not found: ", action.Outbound)
}
if !common.Contains(outbound.Network(), metadata.Network) {
return nil, E.New(metadata.Network, " is not supported by outbound: ", action.Outbound)
}
return outbound.(adapter.DirectRouteOutbound).NewDirectRouteConnection(metadata, routeContext)
default:
return nil, nil
} }
return rejectAction.Error(context.Background())
} }
func (r *Router) matchRule( func (r *Router) matchRule(

View File

@@ -62,7 +62,6 @@ func NewClient(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, opt
dialOptions = append(dialOptions, grpc.WithContextDialer(func(ctx context.Context, server string) (net.Conn, error) { dialOptions = append(dialOptions, grpc.WithContextDialer(func(ctx context.Context, server string) (net.Conn, error) {
return dialer.DialContext(ctx, N.NetworkTCP, M.ParseSocksaddr(server)) return dialer.DialContext(ctx, N.NetworkTCP, M.ParseSocksaddr(server))
})) }))
//nolint:staticcheck
dialOptions = append(dialOptions, grpc.WithReturnConnectionError()) dialOptions = append(dialOptions, grpc.WithReturnConnectionError())
return &Client{ return &Client{
ctx: ctx, ctx: ctx,
@@ -85,6 +84,7 @@ func (c *Client) connect() (*grpc.ClientConn, error) {
return conn, nil return conn, nil
} }
//nolint:staticcheck //nolint:staticcheck
//goland:noinspection GoDeprecation
conn, err := grpc.DialContext(c.ctx, c.serverAddr, c.dialOptions...) conn, err := grpc.DialContext(c.ctx, c.serverAddr, c.dialOptions...)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@@ -18,7 +18,6 @@ type GRPCConn struct {
} }
func NewGRPCConn(service GunService) *GRPCConn { func NewGRPCConn(service GunService) *GRPCConn {
//nolint:staticcheck
if client, isClient := service.(GunService_TunClient); isClient { if client, isClient := service.(GunService_TunClient); isClient {
service = &clientConnWrapper{client} service = &clientConnWrapper{client}
} }

View File

@@ -34,7 +34,7 @@ func (c *gunServiceClient) TunCustomName(ctx context.Context, name string, opts
if err != nil { if err != nil {
return nil, err return nil, err
} }
x := &grpc.GenericClientStream[Hunk, Hunk]{ClientStream: stream} x := &gunServiceTunClient{stream}
return x, nil return x, nil
} }

View File

@@ -3,7 +3,6 @@ package v2raygrpc
import ( import (
reflect "reflect" reflect "reflect"
sync "sync" sync "sync"
unsafe "unsafe"
protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl" protoimpl "google.golang.org/protobuf/runtime/protoimpl"
@@ -17,17 +16,20 @@ const (
) )
type Hunk struct { type Hunk struct {
state protoimpl.MessageState `protogen:"open.v1"` state protoimpl.MessageState
Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"`
} }
func (x *Hunk) Reset() { func (x *Hunk) Reset() {
*x = Hunk{} *x = Hunk{}
mi := &file_transport_v2raygrpc_stream_proto_msgTypes[0] if protoimpl.UnsafeEnabled {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) mi := &file_transport_v2raygrpc_stream_proto_msgTypes[0]
ms.StoreMessageInfo(mi) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
} }
func (x *Hunk) String() string { func (x *Hunk) String() string {
@@ -38,7 +40,7 @@ func (*Hunk) ProtoMessage() {}
func (x *Hunk) ProtoReflect() protoreflect.Message { func (x *Hunk) ProtoReflect() protoreflect.Message {
mi := &file_transport_v2raygrpc_stream_proto_msgTypes[0] mi := &file_transport_v2raygrpc_stream_proto_msgTypes[0]
if x != nil { if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -62,7 +64,7 @@ func (x *Hunk) GetData() []byte {
var File_transport_v2raygrpc_stream_proto protoreflect.FileDescriptor var File_transport_v2raygrpc_stream_proto protoreflect.FileDescriptor
var file_transport_v2raygrpc_stream_proto_rawDesc = string([]byte{ var file_transport_v2raygrpc_stream_proto_rawDesc = []byte{
0x0a, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x0a, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x76, 0x32, 0x72, 0x61,
0x79, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x2e, 0x70, 0x72, 0x6f, 0x79, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x12, 0x13, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x76, 0x32, 0x74, 0x6f, 0x12, 0x13, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x76, 0x32,
@@ -77,23 +79,23 @@ var file_transport_v2raygrpc_stream_proto_rawDesc = string([]byte{
0x2f, 0x73, 0x61, 0x67, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2f, 0x73, 0x69, 0x6e, 0x67, 0x2d, 0x62, 0x2f, 0x73, 0x61, 0x67, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2f, 0x73, 0x69, 0x6e, 0x67, 0x2d, 0x62,
0x6f, 0x78, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x76, 0x32, 0x72, 0x6f, 0x78, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x76, 0x32, 0x72,
0x61, 0x79, 0x67, 0x72, 0x70, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x61, 0x79, 0x67, 0x72, 0x70, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}) }
var ( var (
file_transport_v2raygrpc_stream_proto_rawDescOnce sync.Once file_transport_v2raygrpc_stream_proto_rawDescOnce sync.Once
file_transport_v2raygrpc_stream_proto_rawDescData []byte file_transport_v2raygrpc_stream_proto_rawDescData = file_transport_v2raygrpc_stream_proto_rawDesc
) )
func file_transport_v2raygrpc_stream_proto_rawDescGZIP() []byte { func file_transport_v2raygrpc_stream_proto_rawDescGZIP() []byte {
file_transport_v2raygrpc_stream_proto_rawDescOnce.Do(func() { file_transport_v2raygrpc_stream_proto_rawDescOnce.Do(func() {
file_transport_v2raygrpc_stream_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_transport_v2raygrpc_stream_proto_rawDesc), len(file_transport_v2raygrpc_stream_proto_rawDesc))) file_transport_v2raygrpc_stream_proto_rawDescData = protoimpl.X.CompressGZIP(file_transport_v2raygrpc_stream_proto_rawDescData)
}) })
return file_transport_v2raygrpc_stream_proto_rawDescData return file_transport_v2raygrpc_stream_proto_rawDescData
} }
var ( var (
file_transport_v2raygrpc_stream_proto_msgTypes = make([]protoimpl.MessageInfo, 1) file_transport_v2raygrpc_stream_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
file_transport_v2raygrpc_stream_proto_goTypes = []any{ file_transport_v2raygrpc_stream_proto_goTypes = []interface{}{
(*Hunk)(nil), // 0: transport.v2raygrpc.Hunk (*Hunk)(nil), // 0: transport.v2raygrpc.Hunk
} }
) )
@@ -113,11 +115,25 @@ func file_transport_v2raygrpc_stream_proto_init() {
if File_transport_v2raygrpc_stream_proto != nil { if File_transport_v2raygrpc_stream_proto != nil {
return return
} }
if !protoimpl.UnsafeEnabled {
file_transport_v2raygrpc_stream_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Hunk); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{} type x struct{}
out := protoimpl.TypeBuilder{ out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{ File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(), GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_transport_v2raygrpc_stream_proto_rawDesc), len(file_transport_v2raygrpc_stream_proto_rawDesc)), RawDescriptor: file_transport_v2raygrpc_stream_proto_rawDesc,
NumEnums: 0, NumEnums: 0,
NumMessages: 1, NumMessages: 1,
NumExtensions: 0, NumExtensions: 0,
@@ -128,6 +144,7 @@ func file_transport_v2raygrpc_stream_proto_init() {
MessageInfos: file_transport_v2raygrpc_stream_proto_msgTypes, MessageInfos: file_transport_v2raygrpc_stream_proto_msgTypes,
}.Build() }.Build()
File_transport_v2raygrpc_stream_proto = out.File File_transport_v2raygrpc_stream_proto = out.File
file_transport_v2raygrpc_stream_proto_rawDesc = nil
file_transport_v2raygrpc_stream_proto_goTypes = nil file_transport_v2raygrpc_stream_proto_goTypes = nil
file_transport_v2raygrpc_stream_proto_depIdxs = nil file_transport_v2raygrpc_stream_proto_depIdxs = nil
} }

View File

@@ -10,8 +10,8 @@ import (
// This is a compile-time assertion to ensure that this generated file // This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against. // is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.64.0 or later. // Requires gRPC-Go v1.32.0 or later.
const _ = grpc.SupportPackageIsVersion9 const _ = grpc.SupportPackageIsVersion7
const ( const (
GunService_Tun_FullMethodName = "/transport.v2raygrpc.GunService/Tun" GunService_Tun_FullMethodName = "/transport.v2raygrpc.GunService/Tun"
@@ -21,7 +21,7 @@ const (
// //
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type GunServiceClient interface { type GunServiceClient interface {
Tun(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[Hunk, Hunk], error) Tun(ctx context.Context, opts ...grpc.CallOption) (GunService_TunClient, error)
} }
type gunServiceClient struct { type gunServiceClient struct {
@@ -32,39 +32,52 @@ func NewGunServiceClient(cc grpc.ClientConnInterface) GunServiceClient {
return &gunServiceClient{cc} return &gunServiceClient{cc}
} }
func (c *gunServiceClient) Tun(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[Hunk, Hunk], error) { func (c *gunServiceClient) Tun(ctx context.Context, opts ...grpc.CallOption) (GunService_TunClient, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) stream, err := c.cc.NewStream(ctx, &GunService_ServiceDesc.Streams[0], GunService_Tun_FullMethodName, opts...)
stream, err := c.cc.NewStream(ctx, &GunService_ServiceDesc.Streams[0], GunService_Tun_FullMethodName, cOpts...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
x := &grpc.GenericClientStream[Hunk, Hunk]{ClientStream: stream} x := &gunServiceTunClient{stream}
return x, nil return x, nil
} }
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. type GunService_TunClient interface {
type GunService_TunClient = grpc.BidiStreamingClient[Hunk, Hunk] Send(*Hunk) error
Recv() (*Hunk, error)
grpc.ClientStream
}
type gunServiceTunClient struct {
grpc.ClientStream
}
func (x *gunServiceTunClient) Send(m *Hunk) error {
return x.ClientStream.SendMsg(m)
}
func (x *gunServiceTunClient) Recv() (*Hunk, error) {
m := new(Hunk)
if err := x.ClientStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
// GunServiceServer is the server API for GunService service. // GunServiceServer is the server API for GunService service.
// All implementations must embed UnimplementedGunServiceServer // All implementations must embed UnimplementedGunServiceServer
// for forward compatibility. // for forward compatibility
type GunServiceServer interface { type GunServiceServer interface {
Tun(grpc.BidiStreamingServer[Hunk, Hunk]) error Tun(GunService_TunServer) error
mustEmbedUnimplementedGunServiceServer() mustEmbedUnimplementedGunServiceServer()
} }
// UnimplementedGunServiceServer must be embedded to have // UnimplementedGunServiceServer must be embedded to have forward compatible implementations.
// forward compatible implementations.
//
// NOTE: this should be embedded by value instead of pointer to avoid a nil
// pointer dereference when methods are called.
type UnimplementedGunServiceServer struct{} type UnimplementedGunServiceServer struct{}
func (UnimplementedGunServiceServer) Tun(grpc.BidiStreamingServer[Hunk, Hunk]) error { func (UnimplementedGunServiceServer) Tun(GunService_TunServer) error {
return status.Errorf(codes.Unimplemented, "method Tun not implemented") return status.Errorf(codes.Unimplemented, "method Tun not implemented")
} }
func (UnimplementedGunServiceServer) mustEmbedUnimplementedGunServiceServer() {} func (UnimplementedGunServiceServer) mustEmbedUnimplementedGunServiceServer() {}
func (UnimplementedGunServiceServer) testEmbeddedByValue() {}
// UnsafeGunServiceServer may be embedded to opt out of forward compatibility for this service. // UnsafeGunServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to GunServiceServer will // Use of this interface is not recommended, as added methods to GunServiceServer will
@@ -74,22 +87,34 @@ type UnsafeGunServiceServer interface {
} }
func RegisterGunServiceServer(s grpc.ServiceRegistrar, srv GunServiceServer) { func RegisterGunServiceServer(s grpc.ServiceRegistrar, srv GunServiceServer) {
// If the following call pancis, it indicates UnimplementedGunServiceServer was
// embedded by pointer and is nil. This will cause panics if an
// unimplemented method is ever invoked, so we test this at initialization
// time to prevent it from happening at runtime later due to I/O.
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
t.testEmbeddedByValue()
}
s.RegisterService(&GunService_ServiceDesc, srv) s.RegisterService(&GunService_ServiceDesc, srv)
} }
func _GunService_Tun_Handler(srv interface{}, stream grpc.ServerStream) error { func _GunService_Tun_Handler(srv interface{}, stream grpc.ServerStream) error {
return srv.(GunServiceServer).Tun(&grpc.GenericServerStream[Hunk, Hunk]{ServerStream: stream}) return srv.(GunServiceServer).Tun(&gunServiceTunServer{stream})
} }
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. type GunService_TunServer interface {
type GunService_TunServer = grpc.BidiStreamingServer[Hunk, Hunk] Send(*Hunk) error
Recv() (*Hunk, error)
grpc.ServerStream
}
type gunServiceTunServer struct {
grpc.ServerStream
}
func (x *gunServiceTunServer) Send(m *Hunk) error {
return x.ServerStream.SendMsg(m)
}
func (x *gunServiceTunServer) Recv() (*Hunk, error) {
m := new(Hunk)
if err := x.ServerStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
// GunService_ServiceDesc is the grpc.ServiceDesc for GunService service. // GunService_ServiceDesc is the grpc.ServiceDesc for GunService service.
// It's only intended for direct use with grpc.RegisterService, // It's only intended for direct use with grpc.RegisterService,

View File

@@ -5,7 +5,6 @@ import (
"net/netip" "net/netip"
"time" "time"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-tun" "github.com/sagernet/sing-tun"
"github.com/sagernet/sing/common/logger" "github.com/sagernet/sing/common/logger"
N "github.com/sagernet/sing/common/network" N "github.com/sagernet/sing/common/network"
@@ -18,8 +17,6 @@ type Device interface {
N.Dialer N.Dialer
Start() error Start() error
SetDevice(device *device.Device) SetDevice(device *device.Device)
Inet4Address() netip.Addr
Inet6Address() netip.Addr
} }
type DeviceOptions struct { type DeviceOptions struct {
@@ -44,8 +41,3 @@ func NewDevice(options DeviceOptions) (Device, error) {
return newSystemStackDevice(options) return newSystemStackDevice(options)
} }
} }
type NatDevice interface {
Device
CreateDestination(metadata adapter.InboundContext, routeContext tun.DirectRouteContext) (tun.DirectRouteDestination, error)
}

View File

@@ -1,85 +0,0 @@
package wireguard
import (
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-tun"
"github.com/sagernet/sing/common/buf"
)
var _ Device = (*natDeviceWrapper)(nil)
type natDeviceWrapper struct {
Device
gVisorOutbound
packetOutbound chan *buf.Buffer
mapping *tun.NatMapping
writer *tun.NatWriter
buffer [][]byte
}
func NewNATDevice(upstream Device, ipRewrite bool) NatDevice {
wrapper := &natDeviceWrapper{
Device: upstream,
gVisorOutbound: newGVisorOutbound(),
packetOutbound: make(chan *buf.Buffer, 256),
mapping: tun.NewNatMapping(ipRewrite),
}
if ipRewrite {
wrapper.writer = tun.NewNatWriter(upstream.Inet4Address(), upstream.Inet6Address())
}
return wrapper
}
func (d *natDeviceWrapper) Write(bufs [][]byte, offset int) (int, error) {
for _, buffer := range bufs {
handled, err := d.mapping.WritePacket(buffer[offset:])
if handled {
if err != nil {
return 0, err
}
} else {
d.buffer = append(d.buffer, buffer)
}
}
if len(d.buffer) > 0 {
_, err := d.Device.Write(d.buffer, offset)
if err != nil {
return 0, err
}
d.buffer = d.buffer[:0]
}
return 0, nil
}
func (d *natDeviceWrapper) CreateDestination(metadata adapter.InboundContext, routeContext tun.DirectRouteContext) (tun.DirectRouteDestination, error) {
session := tun.DirectRouteSession{
Source: metadata.Source.Addr,
Destination: metadata.Destination.Addr,
}
d.mapping.CreateSession(session, routeContext)
return &natDestinationWrapper{d, session}, nil
}
var _ tun.DirectRouteDestination = (*natDestinationWrapper)(nil)
type natDestinationWrapper struct {
device *natDeviceWrapper
session tun.DirectRouteSession
}
func (d *natDestinationWrapper) WritePacket(buffer *buf.Buffer) error {
if d.device.writer != nil {
d.device.writer.RewritePacket(buffer.Bytes())
}
d.device.packetOutbound <- buffer
return nil
}
func (d *natDestinationWrapper) Close() error {
d.device.mapping.DeleteSession(d.session)
return nil
}
func (d *natDestinationWrapper) Timeout() bool {
return false
}

View File

@@ -1,48 +0,0 @@
//go:build with_gvisor
package wireguard
import (
"github.com/sagernet/gvisor/pkg/tcpip/stack"
)
type gVisorOutbound struct {
outbound chan *stack.PacketBuffer
}
func newGVisorOutbound() gVisorOutbound {
return gVisorOutbound{
outbound: make(chan *stack.PacketBuffer, 256),
}
}
func (d *natDeviceWrapper) Read(bufs [][]byte, sizes []int, offset int) (n int, err error) {
select {
case packet := <-d.outbound:
defer packet.DecRef()
var copyN int
/*rangeIterate(packet.Data().AsRange(), func(view *buffer.View) {
copyN += copy(bufs[0][offset+copyN:], view.AsSlice())
})*/
for _, view := range packet.AsSlices() {
copyN += copy(bufs[0][offset+copyN:], view)
}
sizes[0] = copyN
return 1, nil
case packet := <-d.packetOutbound:
defer packet.Release()
sizes[0] = copy(bufs[0][offset:], packet.Bytes())
return 1, nil
default:
}
return d.Device.Read(bufs, sizes, offset)
}
func (d *natDestinationWrapper) WritePacketBuffer(packetBuffer *stack.PacketBuffer) error {
println("read from wg")
if d.device.writer != nil {
d.device.writer.RewritePacketBuffer(packetBuffer)
}
d.device.outbound <- packetBuffer
return nil
}

View File

@@ -1,20 +0,0 @@
//go:build !with_gvisor
package wireguard
type gVisorOutbound struct{}
func newGVisorOutbound() gVisorOutbound {
return gVisorOutbound{}
}
func (d *natDeviceWrapper) Read(bufs [][]byte, sizes []int, offset int) (n int, err error) {
select {
case packet := <-d.packetOutbound:
defer packet.Release()
sizes[0] = copy(bufs[0][offset:], packet.Bytes())
return 1, nil
default:
}
return d.Device.Read(bufs, sizes, offset)
}

View File

@@ -5,7 +5,6 @@ package wireguard
import ( import (
"context" "context"
"net" "net"
"net/netip"
"os" "os"
"github.com/sagernet/gvisor/pkg/buffer" "github.com/sagernet/gvisor/pkg/buffer"
@@ -15,12 +14,9 @@ import (
"github.com/sagernet/gvisor/pkg/tcpip/network/ipv4" "github.com/sagernet/gvisor/pkg/tcpip/network/ipv4"
"github.com/sagernet/gvisor/pkg/tcpip/network/ipv6" "github.com/sagernet/gvisor/pkg/tcpip/network/ipv6"
"github.com/sagernet/gvisor/pkg/tcpip/stack" "github.com/sagernet/gvisor/pkg/tcpip/stack"
"github.com/sagernet/gvisor/pkg/tcpip/transport/icmp"
"github.com/sagernet/gvisor/pkg/tcpip/transport/tcp" "github.com/sagernet/gvisor/pkg/tcpip/transport/tcp"
"github.com/sagernet/gvisor/pkg/tcpip/transport/udp" "github.com/sagernet/gvisor/pkg/tcpip/transport/udp"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-tun" "github.com/sagernet/sing-tun"
"github.com/sagernet/sing/common/buf"
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"
@@ -28,30 +24,25 @@ import (
wgTun "github.com/sagernet/wireguard-go/tun" wgTun "github.com/sagernet/wireguard-go/tun"
) )
var _ NatDevice = (*stackDevice)(nil) var _ Device = (*stackDevice)(nil)
type stackDevice struct { type stackDevice struct {
stack *stack.Stack stack *stack.Stack
mtu uint32 mtu uint32
events chan wgTun.Event events chan wgTun.Event
outbound chan *stack.PacketBuffer outbound chan *stack.PacketBuffer
packetOutbound chan *buf.Buffer done chan struct{}
done chan struct{} dispatcher stack.NetworkDispatcher
dispatcher stack.NetworkDispatcher addr4 tcpip.Address
addr4 tcpip.Address addr6 tcpip.Address
addr6 tcpip.Address
mapping *tun.NatMapping
writer *tun.NatWriter
} }
func newStackDevice(options DeviceOptions) (*stackDevice, error) { func newStackDevice(options DeviceOptions) (*stackDevice, error) {
tunDevice := &stackDevice{ tunDevice := &stackDevice{
mtu: options.MTU, mtu: options.MTU,
events: make(chan wgTun.Event, 1), events: make(chan wgTun.Event, 1),
outbound: make(chan *stack.PacketBuffer, 256), outbound: make(chan *stack.PacketBuffer, 256),
packetOutbound: make(chan *buf.Buffer, 256), done: make(chan struct{}),
done: make(chan struct{}),
mapping: tun.NewNatMapping(true),
} }
ipStack, err := tun.NewGVisorStack((*wireEndpoint)(tunDevice)) ipStack, err := tun.NewGVisorStack((*wireEndpoint)(tunDevice))
if err != nil { if err != nil {
@@ -77,14 +68,10 @@ func newStackDevice(options DeviceOptions) (*stackDevice, error) {
return nil, E.New("parse local address ", protoAddr.AddressWithPrefix, ": ", gErr.String()) return nil, E.New("parse local address ", protoAddr.AddressWithPrefix, ": ", gErr.String())
} }
} }
tunDevice.writer = tun.NewNatWriter(tunDevice.Inet4Address(), tunDevice.Inet6Address())
tunDevice.stack = ipStack tunDevice.stack = ipStack
if options.Handler != nil { if options.Handler != nil {
ipStack.SetTransportProtocolHandler(tcp.ProtocolNumber, tun.NewTCPForwarder(options.Context, ipStack, options.Handler).HandlePacket) ipStack.SetTransportProtocolHandler(tcp.ProtocolNumber, tun.NewTCPForwarder(options.Context, ipStack, options.Handler).HandlePacket)
ipStack.SetTransportProtocolHandler(udp.ProtocolNumber, tun.NewUDPForwarder(options.Context, ipStack, options.Handler, options.UDPTimeout).HandlePacket) ipStack.SetTransportProtocolHandler(udp.ProtocolNumber, tun.NewUDPForwarder(options.Context, ipStack, options.Handler, options.UDPTimeout).HandlePacket)
icmpForwarder := tun.NewICMPForwarder(options.Context, ipStack, options.Handler, options.UDPTimeout)
ipStack.SetTransportProtocolHandler(icmp.ProtocolNumber4, icmpForwarder.HandlePacket)
ipStack.SetTransportProtocolHandler(icmp.ProtocolNumber6, icmpForwarder.HandlePacket)
} }
return tunDevice, nil return tunDevice, nil
} }
@@ -143,14 +130,6 @@ func (w *stackDevice) ListenPacket(ctx context.Context, destination M.Socksaddr)
return udpConn, nil return udpConn, nil
} }
func (w *stackDevice) Inet4Address() netip.Addr {
return netip.AddrFrom4(w.addr4.As4())
}
func (w *stackDevice) Inet6Address() netip.Addr {
return netip.AddrFrom16(w.addr6.As16())
}
func (w *stackDevice) SetDevice(device *device.Device) { func (w *stackDevice) SetDevice(device *device.Device) {
} }
@@ -165,24 +144,20 @@ func (w *stackDevice) File() *os.File {
func (w *stackDevice) Read(bufs [][]byte, sizes []int, offset int) (count int, err error) { func (w *stackDevice) Read(bufs [][]byte, sizes []int, offset int) (count int, err error) {
select { select {
case packet, ok := <-w.outbound: case packetBuffer, ok := <-w.outbound:
if !ok { if !ok {
return 0, os.ErrClosed return 0, os.ErrClosed
} }
defer packet.DecRef() defer packetBuffer.DecRef()
var copyN int p := bufs[0]
/*rangeIterate(packet.Data().AsRange(), func(view *buffer.View) { p = p[offset:]
copyN += copy(bufs[0][offset+copyN:], view.AsSlice()) n := 0
})*/ for _, slice := range packetBuffer.AsSlices() {
for _, view := range packet.AsSlices() { n += copy(p[n:], slice)
copyN += copy(bufs[0][offset+copyN:], view)
} }
sizes[0] = copyN sizes[0] = n
return 1, nil count = 1
case packet := <-w.packetOutbound: return
defer packet.Release()
sizes[0] = copy(bufs[0][offset:], packet.Bytes())
return 1, nil
case <-w.done: case <-w.done:
return 0, os.ErrClosed return 0, os.ErrClosed
} }
@@ -194,14 +169,6 @@ func (w *stackDevice) Write(bufs [][]byte, offset int) (count int, err error) {
if len(b) == 0 { if len(b) == 0 {
continue continue
} }
handled, err := w.mapping.WritePacket(b)
if handled {
if err != nil {
return count, err
}
count++
continue
}
var networkProtocol tcpip.NetworkProtocolNumber var networkProtocol tcpip.NetworkProtocolNumber
switch header.IPVersion(b) { switch header.IPVersion(b) {
case header.IPv4Version: case header.IPv4Version:
@@ -315,157 +282,3 @@ func (ep *wireEndpoint) Close() {
func (ep *wireEndpoint) SetOnCloseAction(f func()) { func (ep *wireEndpoint) SetOnCloseAction(f func()) {
} }
func (w *stackDevice) CreateDestination(metadata adapter.InboundContext, routeContext tun.DirectRouteContext) (tun.DirectRouteDestination, error) {
/* var wq waiter.Queue
ep, err := raw.NewEndpoint(w.stack, ipv4.ProtocolNumber, icmp.ProtocolNumber4, &wq)
if err != nil {
return nil, E.Cause(gonet.TranslateNetstackError(err), "create endpoint")
}
err = ep.Connect(tcpip.FullAddress{
NIC: tun.DefaultNIC,
Port: metadata.Destination.Port,
Addr: tun.AddressFromAddr(metadata.Destination.Addr),
})
if err != nil {
ep.Close()
return nil, E.Cause(gonet.TranslateNetstackError(err), "ICMP connect ", metadata.Destination)
}
fmt.Println("linked ", metadata.Network, " connection to ", metadata.Destination.AddrString())
destination := &endpointNatDestination{
ep: ep,
wq: &wq,
context: routeContext,
}
go destination.loopRead()
return destination, nil*/
session := tun.DirectRouteSession{
Source: metadata.Source.Addr,
Destination: metadata.Destination.Addr,
}
w.mapping.CreateSession(session, routeContext)
return &stackNatDestination{
device: w,
session: session,
}, nil
}
type stackNatDestination struct {
device *stackDevice
session tun.DirectRouteSession
}
func (d *stackNatDestination) WritePacket(buffer *buf.Buffer) error {
if d.device.writer != nil {
d.device.writer.RewritePacket(buffer.Bytes())
}
d.device.packetOutbound <- buffer
return nil
}
func (d *stackNatDestination) WritePacketBuffer(buffer *stack.PacketBuffer) error {
if d.device.writer != nil {
d.device.writer.RewritePacketBuffer(buffer)
}
d.device.outbound <- buffer
return nil
}
func (d *stackNatDestination) Close() error {
d.device.mapping.DeleteSession(d.session)
return nil
}
func (d *stackNatDestination) Timeout() bool {
return false
}
/*type endpointNatDestination struct {
ep tcpip.Endpoint
wq *waiter.Queue
networkProto tcpip.NetworkProtocolNumber
context tun.DirectRouteContext
done chan struct{}
}
func (d *endpointNatDestination) loopRead() {
for {
println("start read")
buffer, err := commonRead(d.ep, d.wq, d.done)
if err != nil {
log.Error(err)
return
}
println("done read")
ipHdr := header.IPv4(buffer.Bytes())
if ipHdr.TransportProtocol() != header.ICMPv4ProtocolNumber {
buffer.Release()
continue
}
icmpHdr := header.ICMPv4(ipHdr.Payload())
if icmpHdr.Type() != header.ICMPv4EchoReply {
buffer.Release()
continue
}
fmt.Println("read echo reply")
_ = d.context.WritePacket(ipHdr)
buffer.Release()
}
}
func commonRead(ep tcpip.Endpoint, wq *waiter.Queue, done chan struct{}) (*buf.Buffer, error) {
buffer := buf.NewPacket()
result, err := ep.Read(buffer, tcpip.ReadOptions{})
if err != nil {
if _, ok := err.(*tcpip.ErrWouldBlock); ok {
waitEntry, notifyCh := waiter.NewChannelEntry(waiter.ReadableEvents)
wq.EventRegister(&waitEntry)
defer wq.EventUnregister(&waitEntry)
for {
result, err = ep.Read(buffer, tcpip.ReadOptions{})
if _, ok := err.(*tcpip.ErrWouldBlock); !ok {
break
}
select {
case <-notifyCh:
case <-done:
buffer.Release()
return nil, context.DeadlineExceeded
}
}
}
return nil, gonet.TranslateNetstackError(err)
}
buffer.Truncate(result.Count)
return buffer, nil
}
func (d *endpointNatDestination) WritePacket(buffer *buf.Buffer) error {
_, err := d.ep.Write(buffer, tcpip.WriteOptions{})
if err != nil {
return gonet.TranslateNetstackError(err)
}
return nil
}
func (d *endpointNatDestination) WritePacketBuffer(buffer *stack.PacketBuffer) error {
data := buffer.ToView().AsSlice()
println("write echo request buffer :" + fmt.Sprint(data))
_, err := d.ep.Write(bytes.NewReader(data), tcpip.WriteOptions{})
if err != nil {
log.Error(err)
return gonet.TranslateNetstackError(err)
}
return nil
}
func (d *endpointNatDestination) Close() error {
d.ep.Abort()
close(d.done)
return nil
}
func (d *endpointNatDestination) Timeout() bool {
return false
}
*/

View File

@@ -28,36 +28,16 @@ type systemDevice struct {
batchDevice tun.LinuxTUN batchDevice tun.LinuxTUN
events chan wgTun.Event events chan wgTun.Event
closeOnce sync.Once closeOnce sync.Once
addr4 netip.Addr
addr6 netip.Addr
} }
func newSystemDevice(options DeviceOptions) (*systemDevice, error) { func newSystemDevice(options DeviceOptions) (*systemDevice, error) {
if options.Name == "" { if options.Name == "" {
options.Name = tun.CalculateInterfaceName("wg") options.Name = tun.CalculateInterfaceName("wg")
} }
var inet4Address netip.Addr
var inet6Address netip.Addr
if len(options.Address) > 0 {
if prefix := common.Find(options.Address, func(it netip.Prefix) bool {
return it.Addr().Is4()
}); prefix.IsValid() {
inet4Address = prefix.Addr()
}
}
if len(options.Address) > 0 {
if prefix := common.Find(options.Address, func(it netip.Prefix) bool {
return it.Addr().Is6()
}); prefix.IsValid() {
inet6Address = prefix.Addr()
}
}
return &systemDevice{ return &systemDevice{
options: options, options: options,
dialer: options.CreateDialer(options.Name), dialer: options.CreateDialer(options.Name),
events: make(chan wgTun.Event, 1), events: make(chan wgTun.Event, 1),
addr4: inet4Address,
addr6: inet6Address,
}, nil }, nil
} }
@@ -69,14 +49,6 @@ func (w *systemDevice) ListenPacket(ctx context.Context, destination M.Socksaddr
return w.dialer.ListenPacket(ctx, destination) return w.dialer.ListenPacket(ctx, destination)
} }
func (w *systemDevice) Inet4Address() netip.Addr {
return w.addr4
}
func (w *systemDevice) Inet6Address() netip.Addr {
return w.addr6
}
func (w *systemDevice) SetDevice(device *device.Device) { func (w *systemDevice) SetDevice(device *device.Device) {
} }

View File

@@ -10,8 +10,6 @@ import (
"os" "os"
"strings" "strings"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-tun"
"github.com/sagernet/sing/common" "github.com/sagernet/sing/common"
E "github.com/sagernet/sing/common/exceptions" E "github.com/sagernet/sing/common/exceptions"
F "github.com/sagernet/sing/common/format" F "github.com/sagernet/sing/common/format"
@@ -31,7 +29,6 @@ type Endpoint struct {
ipcConf string ipcConf string
allowedAddress []netip.Prefix allowedAddress []netip.Prefix
tunDevice Device tunDevice Device
natDevice NatDevice
device *device.Device device *device.Device
pauseManager pause.Manager pauseManager pause.Manager
pauseCallback *list.Element[pause.Callback] pauseCallback *list.Element[pause.Callback]
@@ -114,17 +111,12 @@ func NewEndpoint(options EndpointOptions) (*Endpoint, error) {
if err != nil { if err != nil {
return nil, E.Cause(err, "create WireGuard device") return nil, E.Cause(err, "create WireGuard device")
} }
natDevice, isNatDevice := tunDevice.(NatDevice)
if !isNatDevice {
natDevice = NewNATDevice(tunDevice, true)
}
return &Endpoint{ return &Endpoint{
options: options, options: options,
peers: peers, peers: peers,
ipcConf: ipcConf, ipcConf: ipcConf,
allowedAddress: allowedAddresses, allowedAddress: allowedAddresses,
tunDevice: tunDevice, tunDevice: tunDevice,
natDevice: natDevice,
}, nil }, nil
} }
@@ -184,13 +176,7 @@ func (e *Endpoint) Start(resolve bool) error {
e.options.Logger.Error(fmt.Sprintf(strings.ToLower(format), args...)) e.options.Logger.Error(fmt.Sprintf(strings.ToLower(format), args...))
}, },
} }
var deviceInput Device wgDevice := device.NewDevice(e.options.Context, e.tunDevice, bind, logger, e.options.Workers)
if e.natDevice != nil {
deviceInput = e.natDevice
} else {
deviceInput = e.tunDevice
}
wgDevice := device.NewDevice(e.options.Context, deviceInput, bind, logger, e.options.Workers)
e.tunDevice.SetDevice(wgDevice) e.tunDevice.SetDevice(wgDevice)
ipcConf := e.ipcConf ipcConf := e.ipcConf
for _, peer := range e.peers { for _, peer := range e.peers {
@@ -208,20 +194,6 @@ func (e *Endpoint) Start(resolve bool) error {
return nil return nil
} }
func (e *Endpoint) Close() error {
if e.device != nil {
e.device.Close()
}
if e.pauseCallback != nil {
e.pauseManager.UnregisterCallback(e.pauseCallback)
}
return nil
}
func (e *Endpoint) BindUpdate() error {
return e.device.BindUpdate()
}
func (e *Endpoint) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) { func (e *Endpoint) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
if !destination.Addr.IsValid() { if !destination.Addr.IsValid() {
return nil, E.Cause(os.ErrInvalid, "invalid non-IP destination") return nil, E.Cause(os.ErrInvalid, "invalid non-IP destination")
@@ -236,11 +208,18 @@ func (e *Endpoint) ListenPacket(ctx context.Context, destination M.Socksaddr) (n
return e.tunDevice.ListenPacket(ctx, destination) return e.tunDevice.ListenPacket(ctx, destination)
} }
func (e *Endpoint) NewDirectRouteConnection(metadata adapter.InboundContext, routeContext tun.DirectRouteContext) (tun.DirectRouteDestination, error) { func (e *Endpoint) BindUpdate() error {
if e.natDevice == nil { return e.device.BindUpdate()
return nil, os.ErrInvalid }
func (e *Endpoint) Close() error {
if e.device != nil {
e.device.Close()
} }
return e.natDevice.CreateDestination(metadata, routeContext) if e.pauseCallback != nil {
e.pauseManager.UnregisterCallback(e.pauseCallback)
}
return nil
} }
func (e *Endpoint) onPauseUpdated(event int) { func (e *Endpoint) onPauseUpdated(event int) {