mirror of
https://github.com/shtorm-7/sing-box-extended.git
synced 2026-06-10 21:38:16 +03:00
Compare commits
37 Commits
v1.12.8-ex
...
v1.12.12-e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6e4b7ed744 | ||
|
|
855d400654 | ||
|
|
4c5e2c6645 | ||
|
|
725eccdea8 | ||
|
|
2ff042abd2 | ||
|
|
ffb282e47e | ||
|
|
54ed58499d | ||
|
|
b1bdc18c85 | ||
|
|
a38030cc0b | ||
|
|
4626aa2cb0 | ||
|
|
5a40b673a4 | ||
|
|
541f63fee4 | ||
|
|
5de6f4a14f | ||
|
|
5658830077 | ||
|
|
0e50edc009 | ||
|
|
444f454810 | ||
|
|
d0e1fd6c7e | ||
|
|
17b4d1e010 | ||
|
|
06791470c9 | ||
|
|
ef14c8ca0e | ||
|
|
36dc883c7c | ||
|
|
6557bd7029 | ||
|
|
41b30c91d9 | ||
|
|
0f767d5ce1 | ||
|
|
328a6de797 | ||
|
|
886be6414d | ||
|
|
9362d3cab3 | ||
|
|
ced2e39dbf | ||
|
|
2159d8877b | ||
|
|
cb7dba3eff | ||
|
|
d9d7f7880d | ||
|
|
a031aaf2c0 | ||
|
|
4bca951773 | ||
|
|
140735dbde | ||
|
|
714a68bba1 | ||
|
|
91f9134379 | ||
|
|
5a4de7b242 |
@@ -1,25 +1,27 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
VERSION="1.23.12"
|
||||
VERSION="1.25.3"
|
||||
|
||||
mkdir -p $HOME/go
|
||||
cd $HOME/go
|
||||
wget "https://dl.google.com/go/go${VERSION}.linux-amd64.tar.gz"
|
||||
tar -xzf "go${VERSION}.linux-amd64.tar.gz"
|
||||
mv go go_legacy
|
||||
cd go_legacy
|
||||
mv go go_win7
|
||||
cd go_win7
|
||||
|
||||
# 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/
|
||||
# this patch file only works on golang1.25.x
|
||||
# that means after golang1.26 release it must be changed
|
||||
# see: https://github.com/MetaCubeX/go/commits/release-branch.go1.25/
|
||||
# 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
|
||||
alias curl='curl -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}"'
|
||||
|
||||
curl https://github.com/MetaCubeX/go/commit/8cb5472d94c34b88733a81091bd328e70ee565a4.diff | patch --verbose -p 1
|
||||
curl https://github.com/MetaCubeX/go/commit/6788c4c6f9fafb56729bad6b660f7ee2272d699f.diff | patch --verbose -p 1
|
||||
curl https://github.com/MetaCubeX/go/commit/a5b2168bb836ed9d6601c626f95e56c07923f906.diff | patch --verbose -p 1
|
||||
curl https://github.com/MetaCubeX/go/commit/f56f1e23507e646c85243a71bde7b9629b2f970c.diff | patch --verbose -p 1
|
||||
38
.github/workflows/build.yml
vendored
38
.github/workflows/build.yml
vendored
@@ -46,7 +46,7 @@ jobs:
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ^1.25.1
|
||||
go-version: ^1.25.3
|
||||
- name: Check input version
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
run: |-
|
||||
@@ -88,9 +88,9 @@ jobs:
|
||||
- { os: linux, arch: loong64, debian: loongarch64, rpm: loongarch64, openwrt: "loongarch64_generic" }
|
||||
|
||||
- { os: windows, arch: amd64 }
|
||||
- { os: windows, arch: amd64, legacy_go123: true, legacy_name: "windows-7" }
|
||||
- { os: windows, arch: amd64, legacy_win7: true, legacy_name: "windows-7" }
|
||||
- { os: windows, arch: "386" }
|
||||
- { os: windows, arch: "386", legacy_go123: true, legacy_name: "windows-7" }
|
||||
- { os: windows, arch: "386", legacy_win7: true, legacy_name: "windows-7" }
|
||||
- { os: windows, arch: arm64 }
|
||||
|
||||
- { os: darwin, arch: amd64 }
|
||||
@@ -110,29 +110,29 @@ jobs:
|
||||
if: ${{ ! (matrix.legacy_go123 || matrix.legacy_go124) }}
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ^1.25.1
|
||||
go-version: ^1.25.3
|
||||
- name: Setup Go 1.24
|
||||
if: matrix.legacy_go124
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ~1.24.6
|
||||
- name: Cache Go 1.23
|
||||
if: matrix.legacy_go123
|
||||
id: cache-legacy-go
|
||||
- name: Cache Go for Windows 7
|
||||
if: matrix.legacy_win7
|
||||
id: cache-go-for-windows7
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/go/go_legacy
|
||||
key: go_legacy_12312
|
||||
- name: Setup Go 1.23
|
||||
if: matrix.legacy_go123 && steps.cache-legacy-go.outputs.cache-hit != 'true'
|
||||
~/go/go_win7
|
||||
key: go_win7_1253
|
||||
- name: Setup Go for Windows 7
|
||||
if: matrix.legacy_win7 && steps.cache-go-for-windows7.outputs.cache-hit != 'true'
|
||||
run: |-
|
||||
.github/setup_legacy_go.sh
|
||||
- name: Setup Go 1.23
|
||||
if: matrix.legacy_go123
|
||||
.github/setup_go_for_windows7.sh
|
||||
- name: Setup Go for Windows 7
|
||||
if: matrix.legacy_win7
|
||||
run: |-
|
||||
echo "PATH=$HOME/go/go_legacy/bin:$PATH" >> $GITHUB_ENV
|
||||
echo "GOROOT=$HOME/go/go_legacy" >> $GITHUB_ENV
|
||||
echo "PATH=$HOME/go/go_win7/bin:$PATH" >> $GITHUB_ENV
|
||||
echo "GOROOT=$HOME/go/go_win7" >> $GITHUB_ENV
|
||||
- name: Setup Android NDK
|
||||
if: matrix.os == 'android'
|
||||
uses: nttld/setup-ndk@v1
|
||||
@@ -300,7 +300,7 @@ jobs:
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ^1.25.1
|
||||
go-version: ^1.25.3
|
||||
- name: Setup Android NDK
|
||||
id: setup-ndk
|
||||
uses: nttld/setup-ndk@v1
|
||||
@@ -380,7 +380,7 @@ jobs:
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ^1.25.1
|
||||
go-version: ^1.25.3
|
||||
- name: Setup Android NDK
|
||||
id: setup-ndk
|
||||
uses: nttld/setup-ndk@v1
|
||||
@@ -479,7 +479,7 @@ jobs:
|
||||
if: matrix.if
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ^1.25.1
|
||||
go-version: ^1.25.3
|
||||
- name: Set tag
|
||||
if: matrix.if
|
||||
run: |-
|
||||
|
||||
2
.github/workflows/lint.yml
vendored
2
.github/workflows/lint.yml
vendored
@@ -32,7 +32,7 @@ jobs:
|
||||
- name: golangci-lint
|
||||
uses: golangci/golangci-lint-action@v8
|
||||
with:
|
||||
version: latest
|
||||
version: v2.4.0
|
||||
args: --timeout=30m
|
||||
install-mode: binary
|
||||
verify: false
|
||||
|
||||
4
.github/workflows/linux.yml
vendored
4
.github/workflows/linux.yml
vendored
@@ -30,7 +30,7 @@ jobs:
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ^1.25.1
|
||||
go-version: ^1.25.3
|
||||
- name: Check input version
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
run: |-
|
||||
@@ -71,7 +71,7 @@ jobs:
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ^1.25.1
|
||||
go-version: ^1.25.3
|
||||
- name: Setup Android NDK
|
||||
if: matrix.os == 'android'
|
||||
uses: nttld/setup-ndk@v1
|
||||
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -15,4 +15,6 @@
|
||||
.DS_Store
|
||||
/config.d/
|
||||
/venv/
|
||||
|
||||
CLAUDE.md
|
||||
AGENTS.md
|
||||
/.claude/
|
||||
|
||||
4
Makefile
4
Makefile
@@ -38,7 +38,7 @@ fmt:
|
||||
@gci write --custom-order -s standard -s "prefix(github.com/sagernet/)" -s "default" .
|
||||
|
||||
fmt_install:
|
||||
go install -v mvdan.cc/gofumpt@latest
|
||||
go install -v mvdan.cc/gofumpt@v0.8.0
|
||||
go install -v github.com/daixiang0/gci@latest
|
||||
|
||||
lint:
|
||||
@@ -49,7 +49,7 @@ lint:
|
||||
GOOS=freebsd golangci-lint run ./...
|
||||
|
||||
lint_install:
|
||||
go install -v github.com/golangci/golangci-lint/v2/cmd/golangci-lint@latest
|
||||
go install -v github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.4.0
|
||||
|
||||
proto:
|
||||
@go run ./cmd/internal/protogen
|
||||
|
||||
@@ -4,7 +4,7 @@ Sing-box with extended features.
|
||||
|
||||
## Features
|
||||
|
||||
* Amnezia
|
||||
* Amnezia 1.5
|
||||
* WARP
|
||||
* Tunneling
|
||||
* Mieru
|
||||
|
||||
Submodule clients/android updated: cd8ac376f6...a4e3c00f0f
Submodule clients/apple updated: 96bee16bf0...84d8cf1757
@@ -134,6 +134,7 @@ func publishTestflight(ctx context.Context) error {
|
||||
asc.PlatformTVOS,
|
||||
}
|
||||
}
|
||||
waitingForProcess := false
|
||||
for _, platform := range platforms {
|
||||
log.Info(string(platform), " list builds")
|
||||
for {
|
||||
@@ -145,12 +146,13 @@ func publishTestflight(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
build := builds.Data[0]
|
||||
if common.Contains(buildIDs, build.ID) || time.Since(build.Attributes.UploadedDate.Time) > 30*time.Minute {
|
||||
if !waitingForProcess && (common.Contains(buildIDs, build.ID) || time.Since(build.Attributes.UploadedDate.Time) > 30*time.Minute) {
|
||||
log.Info(string(platform), " ", tag, " waiting for process")
|
||||
time.Sleep(15 * time.Second)
|
||||
continue
|
||||
}
|
||||
if *build.Attributes.ProcessingState != "VALID" {
|
||||
waitingForProcess = true
|
||||
log.Info(string(platform), " ", tag, " waiting for process: ", *build.Attributes.ProcessingState)
|
||||
time.Sleep(15 * time.Second)
|
||||
continue
|
||||
|
||||
@@ -52,14 +52,6 @@ func (d *DetourDialer) init() {
|
||||
d.initErr = E.New("outbound detour not found: ", d.detour)
|
||||
return
|
||||
}
|
||||
if !d.legacyDNSDialer {
|
||||
if directDialer, isDirect := dialer.(DirectDialer); isDirect {
|
||||
if directDialer.IsEmpty() {
|
||||
d.initErr = E.New("detour to an empty direct outbound makes no sense")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
d.dialer = dialer
|
||||
}
|
||||
|
||||
|
||||
@@ -53,26 +53,48 @@ func ClientHandshake(ctx context.Context, conn net.Conn, config Config) (Conn, e
|
||||
return tlsConn, nil
|
||||
}
|
||||
|
||||
type Dialer struct {
|
||||
type Dialer interface {
|
||||
N.Dialer
|
||||
DialTLSContext(ctx context.Context, destination M.Socksaddr) (Conn, error)
|
||||
}
|
||||
|
||||
type defaultDialer struct {
|
||||
dialer N.Dialer
|
||||
config Config
|
||||
}
|
||||
|
||||
func NewDialer(dialer N.Dialer, config Config) N.Dialer {
|
||||
return &Dialer{dialer, config}
|
||||
func NewDialer(dialer N.Dialer, config Config) Dialer {
|
||||
return &defaultDialer{dialer, config}
|
||||
}
|
||||
|
||||
func (d *Dialer) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
||||
if network != N.NetworkTCP {
|
||||
func (d *defaultDialer) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
||||
if N.NetworkName(network) != N.NetworkTCP {
|
||||
return nil, os.ErrInvalid
|
||||
}
|
||||
conn, err := d.dialer.DialContext(ctx, network, destination)
|
||||
return d.DialTLSContext(ctx, destination)
|
||||
}
|
||||
|
||||
func (d *defaultDialer) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
|
||||
return nil, os.ErrInvalid
|
||||
}
|
||||
|
||||
func (d *defaultDialer) DialTLSContext(ctx context.Context, destination M.Socksaddr) (Conn, error) {
|
||||
return d.dialContext(ctx, destination)
|
||||
}
|
||||
|
||||
func (d *defaultDialer) dialContext(ctx context.Context, destination M.Socksaddr) (Conn, error) {
|
||||
conn, err := d.dialer.DialContext(ctx, N.NetworkTCP, destination)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ClientHandshake(ctx, conn, d.config)
|
||||
tlsConn, err := aTLS.ClientHandshake(ctx, conn, d.config)
|
||||
if err != nil {
|
||||
conn.Close()
|
||||
return nil, err
|
||||
}
|
||||
return tlsConn, nil
|
||||
}
|
||||
|
||||
func (d *Dialer) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
|
||||
return nil, os.ErrInvalid
|
||||
func (d *defaultDialer) Upstream() any {
|
||||
return d.dialer
|
||||
}
|
||||
|
||||
@@ -33,17 +33,22 @@ func (c *Range) UnmarshalJSON(content []byte) error {
|
||||
if err == nil {
|
||||
parts := strings.Split(stringValue, "-")
|
||||
if len(parts) != 2 {
|
||||
return E.New("invalid length of range parts")
|
||||
from, err := strconv.ParseInt(parts[0], 10, 32)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rangeValue.From, rangeValue.To = int32(from), int32(from)
|
||||
} else {
|
||||
from, err := strconv.ParseInt(parts[0], 10, 32)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
to, err := strconv.ParseInt(parts[1], 10, 32)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rangeValue.From, rangeValue.To = int32(from), int32(to)
|
||||
}
|
||||
from, err := strconv.ParseInt(parts[0], 10, 32)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
to, err := strconv.ParseInt(parts[1], 10, 32)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rangeValue.From, rangeValue.To = int32(from), int32(to)
|
||||
} else {
|
||||
err := json.Unmarshal(content, &rangeValue)
|
||||
if err != nil {
|
||||
|
||||
@@ -95,6 +95,20 @@ func (c *Client) Start() {
|
||||
}
|
||||
}
|
||||
|
||||
func extractNegativeTTL(response *dns.Msg) (uint32, bool) {
|
||||
for _, record := range response.Ns {
|
||||
if soa, isSOA := record.(*dns.SOA); isSOA {
|
||||
soaTTL := soa.Header().Ttl
|
||||
soaMinimum := soa.Minttl
|
||||
if soaTTL < soaMinimum {
|
||||
return soaTTL, true
|
||||
}
|
||||
return soaMinimum, true
|
||||
}
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
|
||||
func (c *Client) Exchange(ctx context.Context, transport adapter.DNSTransport, message *dns.Msg, options adapter.DNSQueryOptions, responseChecker func(responseAddrs []netip.Addr) bool) (*dns.Msg, error) {
|
||||
if len(message.Question) == 0 {
|
||||
if c.logger != nil {
|
||||
@@ -214,7 +228,7 @@ func (c *Client) Exchange(ctx context.Context, transport adapter.DNSTransport, m
|
||||
response.Answer = append(response.Answer, validResponse.Answer...)
|
||||
}
|
||||
}*/
|
||||
disableCache = disableCache || response.Rcode != dns.RcodeSuccess || len(response.Answer) == 0
|
||||
disableCache = disableCache || (response.Rcode != dns.RcodeSuccess && response.Rcode != dns.RcodeNameError)
|
||||
if responseChecker != nil {
|
||||
var rejected bool
|
||||
// TODO: add accept_any rule and support to check response instead of addresses
|
||||
@@ -251,10 +265,17 @@ func (c *Client) Exchange(ctx context.Context, transport adapter.DNSTransport, m
|
||||
}
|
||||
}
|
||||
var timeToLive uint32
|
||||
for _, recordList := range [][]dns.RR{response.Answer, response.Ns, response.Extra} {
|
||||
for _, record := range recordList {
|
||||
if timeToLive == 0 || record.Header().Ttl > 0 && record.Header().Ttl < timeToLive {
|
||||
timeToLive = record.Header().Ttl
|
||||
if len(response.Answer) == 0 {
|
||||
if soaTTL, hasSOA := extractNegativeTTL(response); hasSOA {
|
||||
timeToLive = soaTTL
|
||||
}
|
||||
}
|
||||
if timeToLive == 0 {
|
||||
for _, recordList := range [][]dns.RR{response.Answer, response.Ns, response.Extra} {
|
||||
for _, record := range recordList {
|
||||
if timeToLive == 0 || record.Header().Ttl > 0 && record.Header().Ttl < timeToLive {
|
||||
timeToLive = record.Header().Ttl
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -364,14 +385,18 @@ func (c *Client) LookupCache(domain string, strategy C.DomainStrategy) ([]netip.
|
||||
Qtype: dns.TypeA,
|
||||
Qclass: dns.ClassINET,
|
||||
}, nil)
|
||||
if response4 == nil {
|
||||
return nil, false
|
||||
}
|
||||
response6, _ := c.loadResponse(dns.Question{
|
||||
Name: dnsName,
|
||||
Qtype: dns.TypeAAAA,
|
||||
Qclass: dns.ClassINET,
|
||||
}, nil)
|
||||
if response4 != nil || response6 != nil {
|
||||
return sortAddresses(MessageToAddresses(response4), MessageToAddresses(response6), strategy), true
|
||||
if response6 == nil {
|
||||
return nil, false
|
||||
}
|
||||
return sortAddresses(MessageToAddresses(response4), MessageToAddresses(response6), strategy), true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
@@ -15,8 +15,7 @@ func TruncateDNSMessage(request *dns.Msg, response *dns.Msg, headroom int) (*buf
|
||||
}
|
||||
responseLen := response.Len()
|
||||
if responseLen > maxLen {
|
||||
copyResponse := *response
|
||||
response = ©Response
|
||||
response = response.Copy()
|
||||
response.Truncate(maxLen)
|
||||
}
|
||||
buffer := buf.NewSize(headroom*2 + 1 + responseLen)
|
||||
|
||||
@@ -386,12 +386,7 @@ func (r *Router) Lookup(ctx context.Context, domain string, options adapter.DNSQ
|
||||
if rule != nil {
|
||||
switch action := rule.Action().(type) {
|
||||
case *R.RuleActionReject:
|
||||
switch action.Method {
|
||||
case C.RuleActionRejectMethodDefault:
|
||||
return nil, nil
|
||||
case C.RuleActionRejectMethodDrop:
|
||||
return nil, tun.ErrDrop
|
||||
}
|
||||
return nil, &R.RejectedError{Cause: action.Error(ctx)}
|
||||
case *R.RuleActionPredefined:
|
||||
if action.Rcode != mDNS.RcodeSuccess {
|
||||
err = RcodeError(action.Rcode)
|
||||
|
||||
@@ -25,7 +25,6 @@ import (
|
||||
"github.com/sagernet/sing/common/logger"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
aTLS "github.com/sagernet/sing/common/tls"
|
||||
sHTTP "github.com/sagernet/sing/protocol/http"
|
||||
|
||||
mDNS "github.com/miekg/dns"
|
||||
@@ -47,7 +46,7 @@ type HTTPSTransport struct {
|
||||
destination *url.URL
|
||||
headers http.Header
|
||||
transportAccess sync.Mutex
|
||||
transport *http.Transport
|
||||
transport *HTTPSTransportWrapper
|
||||
transportResetAt time.Time
|
||||
}
|
||||
|
||||
@@ -62,11 +61,8 @@ func NewHTTPS(ctx context.Context, logger log.ContextLogger, tag string, options
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if common.Error(tlsConfig.Config()) == nil && !common.Contains(tlsConfig.NextProtos(), http2.NextProtoTLS) {
|
||||
tlsConfig.SetNextProtos(append(tlsConfig.NextProtos(), http2.NextProtoTLS))
|
||||
}
|
||||
if !common.Contains(tlsConfig.NextProtos(), "http/1.1") {
|
||||
tlsConfig.SetNextProtos(append(tlsConfig.NextProtos(), "http/1.1"))
|
||||
if len(tlsConfig.NextProtos()) == 0 {
|
||||
tlsConfig.SetNextProtos([]string{http2.NextProtoTLS, "http/1.1"})
|
||||
}
|
||||
headers := options.Headers.Build()
|
||||
host := headers.Get("Host")
|
||||
@@ -124,37 +120,13 @@ func NewHTTPSRaw(
|
||||
serverAddr M.Socksaddr,
|
||||
tlsConfig tls.Config,
|
||||
) *HTTPSTransport {
|
||||
var transport *http.Transport
|
||||
if tlsConfig != nil {
|
||||
transport = &http.Transport{
|
||||
ForceAttemptHTTP2: true,
|
||||
DialTLSContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||
tcpConn, hErr := dialer.DialContext(ctx, network, serverAddr)
|
||||
if hErr != nil {
|
||||
return nil, hErr
|
||||
}
|
||||
tlsConn, hErr := aTLS.ClientHandshake(ctx, tcpConn, tlsConfig)
|
||||
if hErr != nil {
|
||||
tcpConn.Close()
|
||||
return nil, hErr
|
||||
}
|
||||
return tlsConn, nil
|
||||
},
|
||||
}
|
||||
} else {
|
||||
transport = &http.Transport{
|
||||
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||
return dialer.DialContext(ctx, network, serverAddr)
|
||||
},
|
||||
}
|
||||
}
|
||||
return &HTTPSTransport{
|
||||
TransportAdapter: adapter,
|
||||
logger: logger,
|
||||
dialer: dialer,
|
||||
destination: destination,
|
||||
headers: headers,
|
||||
transport: transport,
|
||||
transport: NewHTTPSTransportWrapper(tls.NewDialer(dialer, tlsConfig), serverAddr),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
80
dns/transport/https_transport.go
Normal file
80
dns/transport/https_transport.go
Normal file
@@ -0,0 +1,80 @@
|
||||
package transport
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net"
|
||||
"net/http"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/sagernet/sing-box/common/tls"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
|
||||
"golang.org/x/net/http2"
|
||||
)
|
||||
|
||||
var errFallback = E.New("fallback to HTTP/1.1")
|
||||
|
||||
type HTTPSTransportWrapper struct {
|
||||
http2Transport *http2.Transport
|
||||
httpTransport *http.Transport
|
||||
fallback *atomic.Bool
|
||||
}
|
||||
|
||||
func NewHTTPSTransportWrapper(dialer tls.Dialer, serverAddr M.Socksaddr) *HTTPSTransportWrapper {
|
||||
var fallback atomic.Bool
|
||||
return &HTTPSTransportWrapper{
|
||||
http2Transport: &http2.Transport{
|
||||
DialTLSContext: func(ctx context.Context, _, _ string, _ *tls.STDConfig) (net.Conn, error) {
|
||||
tlsConn, err := dialer.DialTLSContext(ctx, serverAddr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
state := tlsConn.ConnectionState()
|
||||
if state.NegotiatedProtocol == http2.NextProtoTLS {
|
||||
return tlsConn, nil
|
||||
}
|
||||
tlsConn.Close()
|
||||
fallback.Store(true)
|
||||
return nil, errFallback
|
||||
},
|
||||
},
|
||||
httpTransport: &http.Transport{
|
||||
DialTLSContext: func(ctx context.Context, _, _ string) (net.Conn, error) {
|
||||
return dialer.DialTLSContext(ctx, serverAddr)
|
||||
},
|
||||
},
|
||||
fallback: &fallback,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *HTTPSTransportWrapper) RoundTrip(request *http.Request) (*http.Response, error) {
|
||||
if h.fallback.Load() {
|
||||
return h.httpTransport.RoundTrip(request)
|
||||
} else {
|
||||
response, err := h.http2Transport.RoundTrip(request)
|
||||
if err != nil {
|
||||
if errors.Is(err, errFallback) {
|
||||
return h.httpTransport.RoundTrip(request)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return response, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (h *HTTPSTransportWrapper) CloseIdleConnections() {
|
||||
h.http2Transport.CloseIdleConnections()
|
||||
h.httpTransport.CloseIdleConnections()
|
||||
}
|
||||
|
||||
func (h *HTTPSTransportWrapper) Clone() *HTTPSTransportWrapper {
|
||||
return &HTTPSTransportWrapper{
|
||||
httpTransport: h.httpTransport,
|
||||
http2Transport: &http2.Transport{
|
||||
DialTLSContext: h.http2Transport.DialTLSContext,
|
||||
},
|
||||
fallback: h.fallback,
|
||||
}
|
||||
}
|
||||
@@ -54,18 +54,17 @@ func (t *Transport) Close() error {
|
||||
|
||||
func (t *Transport) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg, error) {
|
||||
question := message.Question[0]
|
||||
domain := dns.FqdnToDomain(question.Name)
|
||||
if question.Qtype == mDNS.TypeA || question.Qtype == mDNS.TypeAAAA {
|
||||
addresses := t.hosts.Lookup(domain)
|
||||
addresses := t.hosts.Lookup(dns.FqdnToDomain(question.Name))
|
||||
if len(addresses) > 0 {
|
||||
return dns.FixedResponse(message.Id, question, addresses, C.DefaultDNSTTL), nil
|
||||
}
|
||||
}
|
||||
systemConfig := getSystemDNSConfig(t.ctx)
|
||||
if systemConfig.singleRequest || !(message.Question[0].Qtype == mDNS.TypeA || message.Question[0].Qtype == mDNS.TypeAAAA) {
|
||||
return t.exchangeSingleRequest(ctx, systemConfig, message, domain)
|
||||
return t.exchangeSingleRequest(ctx, systemConfig, message, question.Name)
|
||||
} else {
|
||||
return t.exchangeParallel(ctx, systemConfig, message, domain)
|
||||
return t.exchangeParallel(ctx, systemConfig, message, question.Name)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -67,7 +67,6 @@ func (f *FallbackTransport) Exchange(ctx context.Context, message *mDNS.Msg) (*m
|
||||
return f.DNSTransport.Exchange(ctx, message)
|
||||
}
|
||||
question := message.Question[0]
|
||||
domain := dns.FqdnToDomain(question.Name)
|
||||
if question.Qtype == mDNS.TypeA || question.Qtype == mDNS.TypeAAAA {
|
||||
var network string
|
||||
if question.Qtype == mDNS.TypeA {
|
||||
@@ -75,7 +74,7 @@ func (f *FallbackTransport) Exchange(ctx context.Context, message *mDNS.Msg) (*m
|
||||
} else {
|
||||
network = "ip6"
|
||||
}
|
||||
addresses, err := f.resolver.LookupNetIP(ctx, network, domain)
|
||||
addresses, err := f.resolver.LookupNetIP(ctx, network, question.Name)
|
||||
if err != nil {
|
||||
var dnsError *net.DNSError
|
||||
if errors.As(err, &dnsError) && dnsError.IsNotFound {
|
||||
@@ -85,7 +84,7 @@ func (f *FallbackTransport) Exchange(ctx context.Context, message *mDNS.Msg) (*m
|
||||
}
|
||||
return dns.FixedResponse(message.Id, question, addresses, C.DefaultDNSTTL), nil
|
||||
} else if question.Qtype == mDNS.TypeNS {
|
||||
records, err := f.resolver.LookupNS(ctx, domain)
|
||||
records, err := f.resolver.LookupNS(ctx, question.Name)
|
||||
if err != nil {
|
||||
var dnsError *net.DNSError
|
||||
if errors.As(err, &dnsError) && dnsError.IsNotFound {
|
||||
@@ -114,7 +113,7 @@ func (f *FallbackTransport) Exchange(ctx context.Context, message *mDNS.Msg) (*m
|
||||
}
|
||||
return response, nil
|
||||
} else if question.Qtype == mDNS.TypeCNAME {
|
||||
cname, err := f.resolver.LookupCNAME(ctx, domain)
|
||||
cname, err := f.resolver.LookupCNAME(ctx, question.Name)
|
||||
if err != nil {
|
||||
var dnsError *net.DNSError
|
||||
if errors.As(err, &dnsError) && dnsError.IsNotFound {
|
||||
@@ -142,7 +141,7 @@ func (f *FallbackTransport) Exchange(ctx context.Context, message *mDNS.Msg) (*m
|
||||
},
|
||||
}, nil
|
||||
} else if question.Qtype == mDNS.TypeTXT {
|
||||
records, err := f.resolver.LookupTXT(ctx, domain)
|
||||
records, err := f.resolver.LookupTXT(ctx, question.Name)
|
||||
if err != nil {
|
||||
var dnsError *net.DNSError
|
||||
if errors.As(err, &dnsError) && dnsError.IsNotFound {
|
||||
@@ -170,7 +169,7 @@ func (f *FallbackTransport) Exchange(ctx context.Context, message *mDNS.Msg) (*m
|
||||
},
|
||||
}, nil
|
||||
} else if question.Qtype == mDNS.TypeMX {
|
||||
records, err := f.resolver.LookupMX(ctx, domain)
|
||||
records, err := f.resolver.LookupMX(ctx, question.Name)
|
||||
if err != nil {
|
||||
var dnsError *net.DNSError
|
||||
if errors.As(err, &dnsError) && dnsError.IsNotFound {
|
||||
|
||||
@@ -2,6 +2,28 @@
|
||||
icon: material/alert-decagram
|
||||
---
|
||||
|
||||
#### 1.12.12
|
||||
|
||||
* Fixes and improvements
|
||||
|
||||
#### 1.12.11
|
||||
|
||||
* Fixes and improvements
|
||||
|
||||
#### 1.12.10
|
||||
|
||||
* Update uTLS to v1.8.1 **1**
|
||||
* Fixes and improvements
|
||||
|
||||
**1**:
|
||||
|
||||
This update fixes an critical issue that could cause simulated Chrome fingerprints to be detected,
|
||||
see https://github.com/refraction-networking/utls/pull/375.
|
||||
|
||||
#### 1.12.9
|
||||
|
||||
* Fixes and improvements
|
||||
|
||||
#### 1.12.8
|
||||
|
||||
* Fixes and improvements
|
||||
@@ -92,7 +114,8 @@ See [Tailscale](/configuration/endpoint/tailscale/).
|
||||
|
||||
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).
|
||||
For Windows 7 users, legacy binaries now continue to compile with Go 1.23 and patches
|
||||
from [MetaCubeX/go](https://github.com/MetaCubeX/go).
|
||||
|
||||
**7**:
|
||||
|
||||
@@ -154,7 +177,8 @@ See [Tun](/configuration/inbound/tun/#loopback_address).
|
||||
|
||||
We have significantly improved the performance of tun inbound on Apple platforms, especially in the gVisor stack.
|
||||
|
||||
The following data was tested using [tun_bench](https://github.com/SagerNet/sing-box/blob/dev-next/cmd/internal/tun_bench/main.go) on M4 MacBook pro.
|
||||
The following data was tested
|
||||
using [tun_bench](https://github.com/SagerNet/sing-box/blob/dev-next/cmd/internal/tun_bench/main.go) on M4 MacBook pro.
|
||||
|
||||
| Version | Stack | MTU | Upload | Download |
|
||||
|-------------|--------|-------|--------|----------|
|
||||
@@ -173,8 +197,8 @@ The following data was tested using [tun_bench](https://github.com/SagerNet/sing
|
||||
|
||||
**18**:
|
||||
|
||||
We continue to experience issues updating our sing-box apps on the App Store and Play Store.
|
||||
Until we rewrite and resubmit the apps, they are considered irrecoverable.
|
||||
We continue to experience issues updating our sing-box apps on the App Store and Play Store.
|
||||
Until we rewrite and resubmit the apps, they are considered irrecoverable.
|
||||
Therefore, after this release, we will not be repeating this notice unless there is new information.
|
||||
|
||||
### 1.11.15
|
||||
@@ -455,7 +479,8 @@ See [AnyTLS Inbound](/configuration/inbound/anytls/) and [AnyTLS Outbound](/conf
|
||||
|
||||
**2**:
|
||||
|
||||
`resolve` route action now accepts `disable_cache` and other options like in DNS route actions, see [Route Action](/configuration/route/rule_action).
|
||||
`resolve` route action now accepts `disable_cache` and other options like in DNS route actions,
|
||||
see [Route Action](/configuration/route/rule_action).
|
||||
|
||||
**3**:
|
||||
|
||||
@@ -486,7 +511,8 @@ See [Tailscale](/configuration/endpoint/tailscale/).
|
||||
|
||||
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).
|
||||
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
|
||||
|
||||
|
||||
@@ -11,16 +11,22 @@ the project maintainer via [GitHub Sponsors](https://github.com/sponsors/nekohas
|
||||
|
||||

|
||||
|
||||
### Special Sponsors
|
||||
## Commercial Sponsors
|
||||
|
||||
**Viral Tech, Inc.**
|
||||
> [Warp](https://go.warp.dev/sing-box), Built for coding with multiple AI agents.
|
||||
|
||||
[](https://go.warp.dev/sing-box)
|
||||
|
||||
## Special Sponsors
|
||||
|
||||
> Viral Tech, Inc.
|
||||
|
||||
Helping us re-list sing-box apps on the Apple Store.
|
||||
|
||||
---
|
||||
|
||||
[](https://www.jetbrains.com)
|
||||
> [JetBrains](https://www.jetbrains.com)
|
||||
|
||||
Free license for the amazing IDEs.
|
||||
|
||||
---
|
||||
[](https://www.jetbrains.com)
|
||||
|
||||
@@ -30,10 +30,23 @@
|
||||
"jc": 120,
|
||||
"jmin": 23,
|
||||
"jmax": 911,
|
||||
"s1": 1,
|
||||
"s2": 2,
|
||||
"s3": 3,
|
||||
"s4": 4,
|
||||
"h1": 1,
|
||||
"h2": 2,
|
||||
"h3": 3,
|
||||
"h4": 4
|
||||
"h4": 4,
|
||||
"i1": "<b 0xc70000000108...",
|
||||
"i2": "<b 0xc70000000108...",
|
||||
"i3": "<b 0xc70000000108...",
|
||||
"i4": "<b 0xc70000000108...",
|
||||
"i5": "<b 0xc70000000108...",
|
||||
"j1": "<b 0xc70000000108...",
|
||||
"j2": "<b 0xc70000000108...",
|
||||
"j3": "<b 0xc70000000108...",
|
||||
"itime": 50,
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
@@ -12,9 +12,7 @@ type iOSPauseFields struct {
|
||||
|
||||
func (s *BoxService) Pause() {
|
||||
s.pauseManager.DevicePause()
|
||||
if !C.IsIos {
|
||||
s.instance.Router().ResetNetwork()
|
||||
} else {
|
||||
if C.IsIos {
|
||||
if s.endPauseTimer == nil {
|
||||
s.endPauseTimer = time.AfterFunc(time.Minute, s.pauseManager.DeviceWake)
|
||||
} else {
|
||||
@@ -26,7 +24,6 @@ func (s *BoxService) Pause() {
|
||||
func (s *BoxService) Wake() {
|
||||
if !C.IsIos {
|
||||
s.pauseManager.DeviceWake()
|
||||
s.instance.Router().ResetNetwork()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
25
go.mod
25
go.mod
@@ -1,11 +1,11 @@
|
||||
module github.com/sagernet/sing-box
|
||||
|
||||
go 1.24.1
|
||||
go 1.24.4
|
||||
|
||||
toolchain go1.24.3
|
||||
toolchain go1.24.6
|
||||
|
||||
require (
|
||||
github.com/anytls/sing-anytls v0.0.8
|
||||
github.com/anytls/sing-anytls v0.0.11
|
||||
github.com/caddyserver/certmagic v0.23.0
|
||||
github.com/coder/websocket v1.8.13
|
||||
github.com/cretz/bine v0.2.0
|
||||
@@ -18,8 +18,8 @@ require (
|
||||
github.com/libdns/alidns v1.0.5-libdns.v1.beta1
|
||||
github.com/libdns/cloudflare v0.2.2-0.20250708034226-c574dccb31a6
|
||||
github.com/logrusorgru/aurora v2.0.3+incompatible
|
||||
github.com/metacubex/tfo-go v0.0.0-20250516165257-e29c16ae41d4
|
||||
github.com/metacubex/utls v1.8.0
|
||||
github.com/metacubex/tfo-go v0.0.0-20250921095601-b102db4216c0
|
||||
github.com/metacubex/utls v1.8.3
|
||||
github.com/mholt/acmez/v3 v3.1.2
|
||||
github.com/miekg/dns v1.1.67
|
||||
github.com/oschwald/maxminddb-golang v1.13.1
|
||||
@@ -30,17 +30,17 @@ require (
|
||||
github.com/sagernet/fswatch v0.1.1
|
||||
github.com/sagernet/gomobile v0.1.8
|
||||
github.com/sagernet/gvisor v0.0.0-20250325023245-7a9c0f5725fb
|
||||
github.com/sagernet/quic-go v0.52.0-beta.1
|
||||
github.com/sagernet/sing v0.7.10
|
||||
github.com/sagernet/quic-go v0.52.0-sing-box-mod.3
|
||||
github.com/sagernet/sing v0.7.13
|
||||
github.com/sagernet/sing-mux v0.3.3
|
||||
github.com/sagernet/sing-quic v0.5.2-0.20250909083218-00a55617c0fb
|
||||
github.com/sagernet/sing-shadowsocks v0.2.8
|
||||
github.com/sagernet/sing-shadowsocks2 v0.2.1
|
||||
github.com/sagernet/sing-shadowtls v0.2.1-0.20250503051639-fcd445d33c11
|
||||
github.com/sagernet/sing-tun v0.7.2
|
||||
github.com/sagernet/sing-tun v0.7.3
|
||||
github.com/sagernet/sing-vmess v0.2.7
|
||||
github.com/sagernet/smux v1.5.34-mod.2
|
||||
github.com/sagernet/tailscale v1.80.3-sing-box-1.12-mod.1
|
||||
github.com/sagernet/tailscale v1.80.3-sing-box-1.12-mod.2
|
||||
github.com/sagernet/wireguard-go v0.0.1-beta.7
|
||||
github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854
|
||||
github.com/spf13/cobra v1.9.1
|
||||
@@ -54,7 +54,6 @@ require (
|
||||
golang.org/x/mod v0.27.0
|
||||
golang.org/x/net v0.43.0
|
||||
golang.org/x/sys v0.35.0
|
||||
golang.org/x/time v0.11.0
|
||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20241231184526-a9ab2273dd10
|
||||
google.golang.org/grpc v1.73.0
|
||||
google.golang.org/protobuf v1.36.6
|
||||
@@ -134,14 +133,16 @@ require (
|
||||
github.com/tailscale/netlink v1.1.1-0.20240822203006-4d49adab4de7 // indirect
|
||||
github.com/tailscale/peercred v0.0.0-20250107143737-35a0c7bd7edc // indirect
|
||||
github.com/tailscale/web-client-prebuilt v0.0.0-20250124233751-d4cd19a26976 // indirect
|
||||
github.com/tevino/abool/v2 v2.1.0 // indirect
|
||||
github.com/tevino/abool v1.2.0 // indirect
|
||||
github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
github.com/zeebo/blake3 v0.2.4 // indirect
|
||||
go.uber.org/atomic v1.11.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap/exp v0.3.0 // indirect
|
||||
go4.org/mem v0.0.0-20240501181205-ae6ca9944745 // indirect
|
||||
golang.org/x/term v0.34.0 // indirect
|
||||
golang.org/x/time v0.11.0 // 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-20250324211829-b45e905df463 // indirect
|
||||
@@ -149,7 +150,7 @@ require (
|
||||
lukechampine.com/blake3 v1.4.1 // indirect
|
||||
)
|
||||
|
||||
replace github.com/sagernet/wireguard-go => github.com/getlantern/wireguard-go v0.0.1-beta.5.0.20250303165430-793006c422ec
|
||||
replace github.com/sagernet/wireguard-go => github.com/shtorm-7/wireguard-go v0.0.1-beta.7-extended-1.0.1
|
||||
|
||||
replace github.com/sagernet/sing-dns => github.com/shtorm-7/sing-dns v0.4.6-extended-1.0.0
|
||||
|
||||
|
||||
40
go.sum
40
go.sum
@@ -12,8 +12,8 @@ github.com/ameshkov/dnsstamps v1.0.3 h1:Srzik+J9mivH1alRACTbys2xOxs0lRH9qnTA7Y1O
|
||||
github.com/ameshkov/dnsstamps v1.0.3/go.mod h1:Ii3eUu73dx4Vw5O4wjzmT5+lkCwovjzaEZZ4gKyIH5A=
|
||||
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
|
||||
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
|
||||
github.com/anytls/sing-anytls v0.0.8 h1:1u/fnH1HoeeMV5mX7/eUOjLBvPdkd1UJRmXiRi6Vymc=
|
||||
github.com/anytls/sing-anytls v0.0.8/go.mod h1:7rjN6IukwysmdusYsrV51Fgu1uW6vsrdd6ctjnEAln8=
|
||||
github.com/anytls/sing-anytls v0.0.11 h1:w8e9Uj1oP3m4zxkyZDewPk0EcQbvVxb7Nn+rapEx4fc=
|
||||
github.com/anytls/sing-anytls v0.0.11/go.mod h1:7rjN6IukwysmdusYsrV51Fgu1uW6vsrdd6ctjnEAln8=
|
||||
github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJRUA0wFAVE=
|
||||
github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
|
||||
github.com/caddyserver/certmagic v0.23.0 h1:CfpZ/50jMfG4+1J/u2LV6piJq4HOfO6ppOnOf7DkFEU=
|
||||
@@ -49,8 +49,6 @@ github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv
|
||||
github.com/fxamacker/cbor/v2 v2.7.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/getlantern/wireguard-go v0.0.1-beta.5.0.20250303165430-793006c422ec h1:jXekDkSozctYj5JQlV1mCsIW+qHpIkgSFhOIpgRSB1I=
|
||||
github.com/getlantern/wireguard-go v0.0.1-beta.5.0.20250303165430-793006c422ec/go.mod h1:akc2Wh+rX9bFFNnHJGsQ8VIV3eJI1LXJYgx2Y+8lcW8=
|
||||
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.2 h1:CMwsvRVTbXVytCk1Wd72Zy1LAsAh9GxMmSNWLHCG618=
|
||||
@@ -130,10 +128,10 @@ github.com/mdlayher/sdnotify v1.0.0 h1:Ma9XeLVN/l0qpyx1tNeMSeTjCPH6NtuD6/N9XdTlQ
|
||||
github.com/mdlayher/sdnotify v1.0.0/go.mod h1:HQUmpM4XgYkhDLtd+Uad8ZFK1T9D5+pNxnXQjCeJlGE=
|
||||
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-20250516165257-e29c16ae41d4 h1:j1VRTiC9JLR4nUbSikx9OGdu/3AgFDqgcLj4GoqyQkc=
|
||||
github.com/metacubex/tfo-go v0.0.0-20250516165257-e29c16ae41d4/go.mod h1:l9oLnLoEXyGZ5RVLsh7QCC5XsouTUyKk4F2nLm2DHLw=
|
||||
github.com/metacubex/utls v1.8.0 h1:mSYi6FMnmc5riARl5UZDmWVy710z+P5b7xuGW0lV9ac=
|
||||
github.com/metacubex/utls v1.8.0/go.mod h1:FdjYzVfCtgtna19hX0ER1Xsa5uJInwdQ4IcaaI98lEQ=
|
||||
github.com/metacubex/tfo-go v0.0.0-20250921095601-b102db4216c0 h1:Ui+/2s5Qz0lSnDUBmEL12M5Oi/PzvFxGTNohm8ZcsmE=
|
||||
github.com/metacubex/tfo-go v0.0.0-20250921095601-b102db4216c0/go.mod h1:l9oLnLoEXyGZ5RVLsh7QCC5XsouTUyKk4F2nLm2DHLw=
|
||||
github.com/metacubex/utls v1.8.3 h1:0m/yCxm3SK6kWve2lKiFb1pue1wHitJ8sQQD4Ikqde4=
|
||||
github.com/metacubex/utls v1.8.3/go.mod h1:kncGGVhFaoGn5M3pFe3SXhZCzsbCJayNOH4UEqTKTko=
|
||||
github.com/mholt/acmez/v3 v3.1.2 h1:auob8J/0FhmdClQicvJvuDavgd5ezwLBfKuYmynhYzc=
|
||||
github.com/mholt/acmez/v3 v3.1.2/go.mod h1:L1wOU06KKvq7tswuMDwKdcHeKpFFgkppZy/y0DFxagQ=
|
||||
github.com/miekg/dns v1.1.67 h1:kg0EHj0G4bfT5/oOys6HhZw4vmMlnoZ+gDu8tJ/AlI0=
|
||||
@@ -174,11 +172,11 @@ github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a h1:ObwtHN2VpqE0ZN
|
||||
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/go.mod h1:OQXAjvjNGGFxaTgVCSTRIhYB5/llyVDeapVoENYBDS8=
|
||||
github.com/sagernet/quic-go v0.52.0-beta.1 h1:hWkojLg64zjV+MJOvJU/kOeWndm3tiEfBLx5foisszs=
|
||||
github.com/sagernet/quic-go v0.52.0-beta.1/go.mod h1:OV+V5kEBb8kJS7k29MzDu6oj9GyMc7HA07sE1tedxz4=
|
||||
github.com/sagernet/quic-go v0.52.0-sing-box-mod.3 h1:ySqffGm82rPqI1TUPqmtHIYd12pfEGScygnOxjTL56w=
|
||||
github.com/sagernet/quic-go v0.52.0-sing-box-mod.3/go.mod h1:OV+V5kEBb8kJS7k29MzDu6oj9GyMc7HA07sE1tedxz4=
|
||||
github.com/sagernet/sing v0.6.9/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
|
||||
github.com/sagernet/sing v0.7.10 h1:2yPhZFx+EkyHPH8hXNezgyRSHyGY12CboId7CtwLROw=
|
||||
github.com/sagernet/sing v0.7.10/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
|
||||
github.com/sagernet/sing v0.7.13 h1:XNYgd8e3cxMULs/LLJspdn/deHrnPWyrrglNHeCUAYM=
|
||||
github.com/sagernet/sing v0.7.13/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
|
||||
github.com/sagernet/sing-mux v0.3.3 h1:YFgt9plMWzH994BMZLmyKL37PdIVaIilwP0Jg+EcLfw=
|
||||
github.com/sagernet/sing-mux v0.3.3/go.mod h1:pht8iFY4c9Xltj7rhVd208npkNaeCxzyXCgulDPLUDA=
|
||||
github.com/sagernet/sing-quic v0.5.2-0.20250909083218-00a55617c0fb h1:5Wx3XeTiKrrrcrAky7Hc1bO3CGxrvho2Vu5b/adlEIM=
|
||||
@@ -189,18 +187,20 @@ github.com/sagernet/sing-shadowsocks2 v0.2.1 h1:dWV9OXCeFPuYGHb6IRqlSptVnSzOelnq
|
||||
github.com/sagernet/sing-shadowsocks2 v0.2.1/go.mod h1:RnXS0lExcDAovvDeniJ4IKa2IuChrdipolPYWBv9hWQ=
|
||||
github.com/sagernet/sing-shadowtls v0.2.1-0.20250503051639-fcd445d33c11 h1:tK+75l64tm9WvEFrYRE1t0YxoFdWQqw/h7Uhzj0vJ+w=
|
||||
github.com/sagernet/sing-shadowtls v0.2.1-0.20250503051639-fcd445d33c11/go.mod h1:sWqKnGlMipCHaGsw1sTTlimyUpgzP4WP3pjhCsYt9oA=
|
||||
github.com/sagernet/sing-tun v0.7.2 h1:uJkAZM0KBqIYzrq077QGqdvj/+4i/pMOx6Pnx0jYqAs=
|
||||
github.com/sagernet/sing-tun v0.7.2/go.mod h1:pUEjh9YHQ2gJT6Lk0TYDklh3WJy7lz+848vleGM3JPM=
|
||||
github.com/sagernet/sing-tun v0.7.3 h1:MFnAir+l24ElEyxdfwtY8mqvUUL9nPnL9TDYLkOmVes=
|
||||
github.com/sagernet/sing-tun v0.7.3/go.mod h1:pUEjh9YHQ2gJT6Lk0TYDklh3WJy7lz+848vleGM3JPM=
|
||||
github.com/sagernet/sing-vmess v0.2.7 h1:2ee+9kO0xW5P4mfe6TYVWf9VtY8k1JhNysBqsiYj0sk=
|
||||
github.com/sagernet/sing-vmess v0.2.7/go.mod h1:5aYoOtYksAyS0NXDm0qKeTYW1yoE1bJVcv+XLcVoyJs=
|
||||
github.com/sagernet/smux v1.5.34-mod.2 h1:gkmBjIjlJ2zQKpLigOkFur5kBKdV6bNRoFu2WkltRQ4=
|
||||
github.com/sagernet/smux v1.5.34-mod.2/go.mod h1:0KW0+R+ycvA2INW4gbsd7BNyg+HEfLIAxa5N02/28Zc=
|
||||
github.com/sagernet/tailscale v1.80.3-sing-box-1.12-mod.1 h1:gMC0q+0VvZBotZMZ9G0R8ZMEIT/Q6KnXbw0/OgMjmdk=
|
||||
github.com/sagernet/tailscale v1.80.3-sing-box-1.12-mod.1/go.mod h1:EBxXsWu4OH2ELbQLq32WoBeIubG8KgDrg4/Oaxjs6lI=
|
||||
github.com/sagernet/tailscale v1.80.3-sing-box-1.12-mod.2 h1:MO7s4ni2bSfAOhcan2rdQSWCztkMXmqyg6jYPZp8bEE=
|
||||
github.com/sagernet/tailscale v1.80.3-sing-box-1.12-mod.2/go.mod h1:EBxXsWu4OH2ELbQLq32WoBeIubG8KgDrg4/Oaxjs6lI=
|
||||
github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854 h1:6uUiZcDRnZSAegryaUGwPC/Fj13JSHwiTftrXhMmYOc=
|
||||
github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854/go.mod h1:LtfoSK3+NG57tvnVEHgcuBW9ujgE8enPSgzgwStwCAA=
|
||||
github.com/shtorm-7/dnscrypt/v2 v2.4.0-extended-1.0.0 h1:e5s7RKBd2rIPR0StbvZ2vTVtJ5jDTsTk5wtIIapZTRg=
|
||||
github.com/shtorm-7/dnscrypt/v2 v2.4.0-extended-1.0.0/go.mod h1:WpEFV2uhebXb8Jhes/5/fSdpmhGV8TL22RDaeWwV6hI=
|
||||
github.com/shtorm-7/wireguard-go v0.0.1-beta.7-extended-1.0.1 h1:IjsKFhL4HlvRo6IpU5kjLnL7TkP5vvCTJyOD6QzKADo=
|
||||
github.com/shtorm-7/wireguard-go v0.0.1-beta.7-extended-1.0.1/go.mod h1:DHxMTUaBGHP3tf8nJ/N8AkcoJDD0PHECLhTfLsw+ylQ=
|
||||
github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
|
||||
github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
|
||||
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
|
||||
@@ -234,8 +234,8 @@ github.com/tailscale/web-client-prebuilt v0.0.0-20250124233751-d4cd19a26976 h1:U
|
||||
github.com/tailscale/web-client-prebuilt v0.0.0-20250124233751-d4cd19a26976/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/tevino/abool/v2 v2.1.0 h1:7w+Vf9f/5gmKT4m4qkayb33/92M+Um45F2BkHOR+L/c=
|
||||
github.com/tevino/abool/v2 v2.1.0/go.mod h1:+Lmlqk6bHDWHqN1cbxqhwEAwMPXgc8I1SDEamtseuXY=
|
||||
github.com/tevino/abool v1.2.0 h1:heAkClL8H6w+mK5md9dzsuohKeXHUpY7Vw0ZCKW+huA=
|
||||
github.com/tevino/abool v1.2.0/go.mod h1:qc66Pna1RiIsPa7O4Egxxs9OqkuxDX55zznh9K07Tzg=
|
||||
github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
|
||||
github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
||||
@@ -267,6 +267,8 @@ go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5J
|
||||
go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w=
|
||||
go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs=
|
||||
go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
|
||||
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
|
||||
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||
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/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU=
|
||||
@@ -340,6 +342,8 @@ gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gvisor.dev/gvisor v0.0.0-20231202080848-1f7806d17489 h1:ze1vwAdliUAr68RQ5NtufWaXaOg8WUO2OACzEV+TNdE=
|
||||
gvisor.dev/gvisor v0.0.0-20231202080848-1f7806d17489/go.mod h1:10sU+Uh5KKNv1+2x2A0Gvzt8FjD3ASIhorV3YsauXhk=
|
||||
howett.net/plist v1.0.1 h1:37GdZ8tP09Q35o9ych3ehygcsL+HqKSwzctveSlarvM=
|
||||
howett.net/plist v1.0.1/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g=
|
||||
lukechampine.com/blake3 v1.4.1 h1:I3Smz7gso8w4/TunLKec6K2fn+kyKtDxr/xcQEN84Wg=
|
||||
|
||||
@@ -31,17 +31,17 @@ type WireGuardPeer struct {
|
||||
}
|
||||
|
||||
type WireGuardWARPEndpointOptions struct {
|
||||
System bool `json:"system,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
ListenPort uint16 `json:"listen_port,omitempty"`
|
||||
UDPTimeout badoption.Duration `json:"udp_timeout,omitempty"`
|
||||
Workers int `json:"workers,omitempty"`
|
||||
Amnezia *WireGuardAmnezia `json:"amnezia,omitempty"`
|
||||
Profile *WireGuardCloudflareProfile `json:"profile,omitempty"`
|
||||
System bool `json:"system,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
ListenPort uint16 `json:"listen_port,omitempty"`
|
||||
UDPTimeout badoption.Duration `json:"udp_timeout,omitempty"`
|
||||
Workers int `json:"workers,omitempty"`
|
||||
Amnezia *WireGuardAmnezia `json:"amnezia,omitempty"`
|
||||
Profile WARPProfile `json:"profile,omitempty"`
|
||||
DialerOptions
|
||||
}
|
||||
|
||||
type WireGuardCloudflareProfile struct {
|
||||
type WARPProfile struct {
|
||||
ID string `json:"id,omitempty"`
|
||||
PrivateKey string `json:"private_key,omitempty"`
|
||||
AuthToken string `json:"auth_token,omitempty"`
|
||||
@@ -76,13 +76,24 @@ type LegacyWireGuardPeer struct {
|
||||
}
|
||||
|
||||
type WireGuardAmnezia struct {
|
||||
JC int `json:"jc,omitempty"`
|
||||
JMin int `json:"jmin,omitempty"`
|
||||
JMax int `json:"jmax,omitempty"`
|
||||
S1 int `json:"s1,omitempty"`
|
||||
S2 int `json:"s2,omitempty"`
|
||||
H1 uint32 `json:"h1,omitempty"`
|
||||
H2 uint32 `json:"h2,omitempty"`
|
||||
H3 uint32 `json:"h3,omitempty"`
|
||||
H4 uint32 `json:"h4,omitempty"`
|
||||
JC int `json:"jc,omitempty"`
|
||||
JMin int `json:"jmin,omitempty"`
|
||||
JMax int `json:"jmax,omitempty"`
|
||||
S1 int `json:"s1,omitempty"`
|
||||
S2 int `json:"s2,omitempty"`
|
||||
S3 int `json:"s3,omitempty"`
|
||||
S4 int `json:"s4,omitempty"`
|
||||
H1 uint32 `json:"h1,omitempty"`
|
||||
H2 uint32 `json:"h2,omitempty"`
|
||||
H3 uint32 `json:"h3,omitempty"`
|
||||
H4 uint32 `json:"h4,omitempty"`
|
||||
I1 string `json:"i1,omitempty"`
|
||||
I2 string `json:"i2,omitempty"`
|
||||
I3 string `json:"i3,omitempty"`
|
||||
I4 string `json:"i4,omitempty"`
|
||||
I5 string `json:"i5,omitempty"`
|
||||
J1 string `json:"j1,omitempty"`
|
||||
J2 string `json:"j2,omitempty"`
|
||||
J3 string `json:"j3,omitempty"`
|
||||
ITime int64 `json:"itime,omitempty"`
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"github.com/sagernet/sing-box/log"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
"github.com/sagernet/sing/common"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
"github.com/sagernet/sing/common/uot"
|
||||
@@ -43,6 +44,13 @@ func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextL
|
||||
if options.TLS == nil || !options.TLS.Enabled {
|
||||
return nil, C.ErrTLSRequired
|
||||
}
|
||||
// TCP Fast Open is incompatible with anytls because TFO creates a lazy connection
|
||||
// that only establishes on first write. The lazy connection returns an empty address
|
||||
// before establishment, but anytls SOCKS wrapper tries to access the remote address
|
||||
// during handshake, causing a null pointer dereference crash.
|
||||
if options.DialerOptions.TCPFastOpen {
|
||||
return nil, E.New("tcp_fast_open is not supported with anytls outbound")
|
||||
}
|
||||
|
||||
tlsConfig, err := tls.NewClient(ctx, options.Server, common.PtrValueOrDefault(options.TLS))
|
||||
if err != nil {
|
||||
|
||||
@@ -68,15 +68,26 @@ func NewEndpoint(ctx context.Context, router adapter.Router, logger log.ContextL
|
||||
var amnezia *wireguard.AmneziaOptions
|
||||
if options.Amnezia != nil {
|
||||
amnezia = &wireguard.AmneziaOptions{
|
||||
JC: options.Amnezia.JC,
|
||||
JMin: options.Amnezia.JMin,
|
||||
JMax: options.Amnezia.JMax,
|
||||
S1: options.Amnezia.S1,
|
||||
S2: options.Amnezia.S2,
|
||||
H1: options.Amnezia.H1,
|
||||
H2: options.Amnezia.H2,
|
||||
H3: options.Amnezia.H3,
|
||||
H4: options.Amnezia.H4,
|
||||
JC: options.Amnezia.JC,
|
||||
JMin: options.Amnezia.JMin,
|
||||
JMax: options.Amnezia.JMax,
|
||||
S1: options.Amnezia.S1,
|
||||
S2: options.Amnezia.S2,
|
||||
S3: options.Amnezia.S3,
|
||||
S4: options.Amnezia.S4,
|
||||
H1: options.Amnezia.H1,
|
||||
H2: options.Amnezia.H2,
|
||||
H3: options.Amnezia.H3,
|
||||
H4: options.Amnezia.H4,
|
||||
I1: options.Amnezia.I1,
|
||||
I2: options.Amnezia.I2,
|
||||
I3: options.Amnezia.I3,
|
||||
I4: options.Amnezia.I4,
|
||||
I5: options.Amnezia.I5,
|
||||
J1: options.Amnezia.J1,
|
||||
J2: options.Amnezia.J2,
|
||||
J3: options.Amnezia.J3,
|
||||
ITime: options.Amnezia.ITime,
|
||||
}
|
||||
}
|
||||
wgEndpoint, err := wireguard.NewEndpoint(wireguard.EndpointOptions{
|
||||
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
"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/json/badoption"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
@@ -41,10 +42,8 @@ func NewWARPEndpoint(ctx context.Context, router adapter.Router, logger log.Cont
|
||||
if options.Detour != "" {
|
||||
dependencies = append(dependencies, options.Detour)
|
||||
}
|
||||
if options.Profile != nil {
|
||||
if options.Profile.Detour != "" {
|
||||
dependencies = append(dependencies, options.Profile.Detour)
|
||||
}
|
||||
if options.Profile.Detour != "" {
|
||||
dependencies = append(dependencies, options.Profile.Detour)
|
||||
}
|
||||
warpEndpoint := &WARPEndpoint{
|
||||
Adapter: endpoint.NewAdapter(C.TypeWARP, tag, []string{N.NetworkTCP, N.NetworkUDP}, dependencies),
|
||||
@@ -80,17 +79,15 @@ func NewWARPEndpoint(ctx context.Context, router adapter.Router, logger log.Cont
|
||||
}
|
||||
}
|
||||
opts := make([]cloudflare.CloudflareApiOption, 0, 1)
|
||||
if options.Profile != nil {
|
||||
if options.Profile.Detour != "" {
|
||||
detour, ok := service.FromContext[adapter.OutboundManager](ctx).Outbound(options.Profile.Detour)
|
||||
if !ok {
|
||||
logger.ErrorContext(ctx, E.New("outbound detour not found: ", options.Profile.Detour))
|
||||
return
|
||||
}
|
||||
opts = append(opts, cloudflare.WithDialContext(func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||
return detour.DialContext(ctx, network, M.ParseSocksaddr(addr))
|
||||
}))
|
||||
if options.Profile.Detour != "" {
|
||||
detour, ok := service.FromContext[adapter.OutboundManager](ctx).Outbound(options.Profile.Detour)
|
||||
if !ok {
|
||||
logger.ErrorContext(ctx, E.New("outbound detour not found: ", options.Profile.Detour))
|
||||
return
|
||||
}
|
||||
opts = append(opts, cloudflare.WithDialContext(func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||
return detour.DialContext(ctx, network, M.ParseSocksaddr(addr))
|
||||
}))
|
||||
}
|
||||
api := cloudflare.NewCloudflareApi(opts...)
|
||||
var profile *cloudflare.CloudflareProfile
|
||||
@@ -185,10 +182,7 @@ func (w *WARPEndpoint) Start(stage adapter.StartStage) error {
|
||||
}
|
||||
|
||||
func (w *WARPEndpoint) Close() error {
|
||||
if ok := w.isEndpointInitialized(); !ok {
|
||||
return E.New("endpoint not initialized")
|
||||
}
|
||||
return w.endpoint.Close()
|
||||
return common.Close(w.endpoint)
|
||||
}
|
||||
|
||||
func (w *WARPEndpoint) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
||||
|
||||
@@ -82,15 +82,26 @@ func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextL
|
||||
var amnezia *wireguard.AmneziaOptions
|
||||
if options.Amnezia != nil {
|
||||
amnezia = &wireguard.AmneziaOptions{
|
||||
JC: options.Amnezia.JC,
|
||||
JMin: options.Amnezia.JMin,
|
||||
JMax: options.Amnezia.JMax,
|
||||
S1: options.Amnezia.S1,
|
||||
S2: options.Amnezia.S2,
|
||||
H1: options.Amnezia.H1,
|
||||
H2: options.Amnezia.H2,
|
||||
H3: options.Amnezia.H3,
|
||||
H4: options.Amnezia.H4,
|
||||
JC: options.Amnezia.JC,
|
||||
JMin: options.Amnezia.JMin,
|
||||
JMax: options.Amnezia.JMax,
|
||||
S1: options.Amnezia.S1,
|
||||
S2: options.Amnezia.S2,
|
||||
S3: options.Amnezia.S3,
|
||||
S4: options.Amnezia.S4,
|
||||
H1: options.Amnezia.H1,
|
||||
H2: options.Amnezia.H2,
|
||||
H3: options.Amnezia.H3,
|
||||
H4: options.Amnezia.H4,
|
||||
I1: options.Amnezia.I1,
|
||||
I2: options.Amnezia.I2,
|
||||
I3: options.Amnezia.I3,
|
||||
I4: options.Amnezia.I4,
|
||||
I5: options.Amnezia.I5,
|
||||
J1: options.Amnezia.J1,
|
||||
J2: options.Amnezia.J2,
|
||||
J3: options.Amnezia.J3,
|
||||
ITime: options.Amnezia.ITime,
|
||||
}
|
||||
}
|
||||
wgEndpoint, err := wireguard.NewEndpoint(wireguard.EndpointOptions{
|
||||
|
||||
@@ -291,7 +291,7 @@ func wrapWsError(err error) error {
|
||||
}
|
||||
var closedErr wsutil.ClosedError
|
||||
if errors.As(err, &closedErr) {
|
||||
if closedErr.Code == ws.StatusNormalClosure {
|
||||
if closedErr.Code == ws.StatusNormalClosure || closedErr.Code == ws.StatusNoStatusRcvd {
|
||||
err = io.EOF
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,7 +138,7 @@ func (c *Client) DialContext(ctx context.Context) (net.Conn, error) {
|
||||
mode := c.options.Mode
|
||||
sessionIdUuid := uuid.New()
|
||||
requestURL := c.getRequestURL(sessionIdUuid.String())
|
||||
requestURL2 := c.getRequestURL(sessionIdUuid.String())
|
||||
requestURL2 := c.getRequestURL2(sessionIdUuid.String())
|
||||
httpClient, xmuxClient := c.getHTTPClient()
|
||||
httpClient2, xmuxClient2 := c.getHTTPClient2()
|
||||
if xmuxClient != nil {
|
||||
|
||||
@@ -181,15 +181,66 @@ func (e *Endpoint) Start(resolve bool) error {
|
||||
e.tunDevice.SetDevice(wgDevice)
|
||||
ipcConf := e.ipcConf
|
||||
if e.options.Amnezia != nil {
|
||||
ipcConf += "\njc=" + strconv.Itoa(e.options.Amnezia.JC) + "\n"
|
||||
ipcConf += "jmin=" + strconv.Itoa(e.options.Amnezia.JMin) + "\n"
|
||||
ipcConf += "jmax=" + strconv.Itoa(e.options.Amnezia.JMax) + "\n"
|
||||
ipcConf += "s1=" + strconv.Itoa(e.options.Amnezia.S1) + "\n"
|
||||
ipcConf += "s2=" + strconv.Itoa(e.options.Amnezia.S2) + "\n"
|
||||
ipcConf += "h1=" + strconv.FormatUint(uint64(e.options.Amnezia.H1), 10) + "\n"
|
||||
ipcConf += "h2=" + strconv.FormatUint(uint64(e.options.Amnezia.H2), 10) + "\n"
|
||||
ipcConf += "h3=" + strconv.FormatUint(uint64(e.options.Amnezia.H3), 10) + "\n"
|
||||
ipcConf += "h4=" + strconv.FormatUint(uint64(e.options.Amnezia.H4), 10)
|
||||
if e.options.Amnezia.JC > 0 {
|
||||
ipcConf += "\njc=" + strconv.Itoa(e.options.Amnezia.JC)
|
||||
}
|
||||
if e.options.Amnezia.JMin > 0 {
|
||||
ipcConf += "\njmin=" + strconv.Itoa(e.options.Amnezia.JMin)
|
||||
}
|
||||
if e.options.Amnezia.JMax > 0 {
|
||||
ipcConf += "\njmax=" + strconv.Itoa(e.options.Amnezia.JMax)
|
||||
}
|
||||
if e.options.Amnezia.S1 > 0 {
|
||||
ipcConf += "\ns1=" + strconv.Itoa(e.options.Amnezia.S1)
|
||||
}
|
||||
if e.options.Amnezia.S2 > 0 {
|
||||
ipcConf += "\ns2=" + strconv.Itoa(e.options.Amnezia.S2)
|
||||
}
|
||||
if e.options.Amnezia.S3 > 0 {
|
||||
ipcConf += "\ns3=" + strconv.Itoa(e.options.Amnezia.S3)
|
||||
}
|
||||
if e.options.Amnezia.S4 > 0 {
|
||||
ipcConf += "\ns4=" + strconv.Itoa(e.options.Amnezia.S4)
|
||||
}
|
||||
if e.options.Amnezia.H1 > 0 {
|
||||
ipcConf += "\nh1=" + strconv.FormatUint(uint64(e.options.Amnezia.H1), 10)
|
||||
}
|
||||
if e.options.Amnezia.H2 > 0 {
|
||||
ipcConf += "\nh2=" + strconv.FormatUint(uint64(e.options.Amnezia.H2), 10)
|
||||
}
|
||||
if e.options.Amnezia.H3 > 0 {
|
||||
ipcConf += "\nh3=" + strconv.FormatUint(uint64(e.options.Amnezia.H3), 10)
|
||||
}
|
||||
if e.options.Amnezia.H4 > 0 {
|
||||
ipcConf += "\nh4=" + strconv.FormatUint(uint64(e.options.Amnezia.H4), 10)
|
||||
}
|
||||
if e.options.Amnezia.I1 != "" {
|
||||
ipcConf += "\ni1=" + e.options.Amnezia.I1
|
||||
}
|
||||
if e.options.Amnezia.I2 != "" {
|
||||
ipcConf += "\ni2=" + e.options.Amnezia.I2
|
||||
}
|
||||
if e.options.Amnezia.I3 != "" {
|
||||
ipcConf += "\ni3=" + e.options.Amnezia.I3
|
||||
}
|
||||
if e.options.Amnezia.I4 != "" {
|
||||
ipcConf += "\ni4=" + e.options.Amnezia.I4
|
||||
}
|
||||
if e.options.Amnezia.I5 != "" {
|
||||
ipcConf += "\ni5=" + e.options.Amnezia.I5
|
||||
}
|
||||
if e.options.Amnezia.J1 != "" {
|
||||
ipcConf += "\nj1=" + e.options.Amnezia.J1
|
||||
}
|
||||
if e.options.Amnezia.J2 != "" {
|
||||
ipcConf += "\nj2=" + e.options.Amnezia.J2
|
||||
}
|
||||
if e.options.Amnezia.J3 != "" {
|
||||
ipcConf += "\nj3=" + e.options.Amnezia.J3
|
||||
}
|
||||
if e.options.Amnezia.ITime > 0 {
|
||||
ipcConf += "\nitime=" + strconv.FormatInt(e.options.Amnezia.ITime, 10)
|
||||
}
|
||||
}
|
||||
for _, peer := range e.peers {
|
||||
ipcConf += peer.GenerateIpcLines()
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"net/netip"
|
||||
"time"
|
||||
|
||||
"github.com/sagernet/sing-tun"
|
||||
tun "github.com/sagernet/sing-tun"
|
||||
"github.com/sagernet/sing/common/logger"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
@@ -40,13 +40,24 @@ type PeerOptions struct {
|
||||
}
|
||||
|
||||
type AmneziaOptions struct {
|
||||
JC int
|
||||
JMin int
|
||||
JMax int
|
||||
S1 int
|
||||
S2 int
|
||||
H1 uint32
|
||||
H2 uint32
|
||||
H3 uint32
|
||||
H4 uint32
|
||||
JC int
|
||||
JMin int
|
||||
JMax int
|
||||
S1 int
|
||||
S2 int
|
||||
S3 int
|
||||
S4 int
|
||||
H1 uint32
|
||||
H2 uint32
|
||||
H3 uint32
|
||||
H4 uint32
|
||||
I1 string
|
||||
I2 string
|
||||
I3 string
|
||||
I4 string
|
||||
I5 string
|
||||
J1 string
|
||||
J2 string
|
||||
J3 string
|
||||
ITime int64
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user