mirror of
https://github.com/shtorm-7/sing-box-extended.git
synced 2026-07-29 18:16:47 +03:00
Compare commits
6 Commits
v1.13.12-e
...
v1.13.12-e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a09cfe2bf8 | ||
|
|
4e0f7e7e62 | ||
|
|
1a54d79022 | ||
|
|
ca0b484d7a | ||
|
|
6c1d568876 | ||
|
|
41040ba1e2 |
@@ -94,6 +94,74 @@ builds:
|
|||||||
- android_arm64
|
- android_arm64
|
||||||
- android_386
|
- android_386
|
||||||
- android_amd64
|
- android_amd64
|
||||||
|
- id: compressed
|
||||||
|
<<: *template
|
||||||
|
targets:
|
||||||
|
- linux_386
|
||||||
|
- linux_amd64_v1
|
||||||
|
- linux_arm64
|
||||||
|
- linux_arm_6
|
||||||
|
- linux_arm_7
|
||||||
|
- linux_riscv64
|
||||||
|
- id: compressed-mips
|
||||||
|
<<: *template
|
||||||
|
tags:
|
||||||
|
- with_gvisor
|
||||||
|
- with_quic
|
||||||
|
- with_dhcp
|
||||||
|
- with_wireguard
|
||||||
|
- with_utls
|
||||||
|
- with_acme
|
||||||
|
- with_clash_api
|
||||||
|
- with_tailscale
|
||||||
|
- with_masque
|
||||||
|
- with_mtproxy
|
||||||
|
targets:
|
||||||
|
- linux_mips
|
||||||
|
- linux_mips_softfloat
|
||||||
|
- linux_mipsle
|
||||||
|
- linux_mipsle_softfloat
|
||||||
|
- id: compressed-android
|
||||||
|
<<: *template
|
||||||
|
env:
|
||||||
|
- CGO_ENABLED=1
|
||||||
|
- GOTOOLCHAIN=local
|
||||||
|
overrides:
|
||||||
|
- goos: android
|
||||||
|
goarch: arm
|
||||||
|
goarm: 7
|
||||||
|
env:
|
||||||
|
- CC=armv7a-linux-androideabi21-clang
|
||||||
|
- CXX=armv7a-linux-androideabi21-clang++
|
||||||
|
- goos: android
|
||||||
|
goarch: arm64
|
||||||
|
env:
|
||||||
|
- CC=aarch64-linux-android21-clang
|
||||||
|
- CXX=aarch64-linux-android21-clang++
|
||||||
|
- goos: android
|
||||||
|
goarch: 386
|
||||||
|
env:
|
||||||
|
- CC=i686-linux-android21-clang
|
||||||
|
- CXX=i686-linux-android21-clang++
|
||||||
|
- goos: android
|
||||||
|
goarch: amd64
|
||||||
|
goamd64: v1
|
||||||
|
env:
|
||||||
|
- CC=x86_64-linux-android21-clang
|
||||||
|
- CXX=x86_64-linux-android21-clang++
|
||||||
|
targets:
|
||||||
|
- android_arm_7
|
||||||
|
- android_arm64
|
||||||
|
- android_386
|
||||||
|
- android_amd64
|
||||||
|
upx:
|
||||||
|
- enabled: true
|
||||||
|
ids:
|
||||||
|
- compressed
|
||||||
|
- compressed-mips
|
||||||
|
- compressed-android
|
||||||
|
compress: best
|
||||||
|
lzma: true
|
||||||
archives:
|
archives:
|
||||||
- &template
|
- &template
|
||||||
id: archive
|
id: archive
|
||||||
@@ -116,6 +184,13 @@ archives:
|
|||||||
builds:
|
builds:
|
||||||
- legacy
|
- legacy
|
||||||
name_template: '{{ .ProjectName }}-{{ .Version }}-{{ .Os }}-{{ .Arch }}-legacy'
|
name_template: '{{ .ProjectName }}-{{ .Version }}-{{ .Os }}-{{ .Arch }}-legacy'
|
||||||
|
- id: archive-compressed
|
||||||
|
<<: *template
|
||||||
|
builds:
|
||||||
|
- compressed
|
||||||
|
- compressed-mips
|
||||||
|
- compressed-android
|
||||||
|
name_template: '{{ .ProjectName }}-{{ .Version }}-{{ .Os }}-{{ .Arch }}{{ with .Arm }}v{{ . }}{{ end }}{{ if and .Mips (not (eq .Mips "hardfloat")) }}-{{ .Mips }}{{ end }}{{ if not (eq .Amd64 "v1") }}{{ .Amd64 }}{{ end }}-compressed'
|
||||||
source:
|
source:
|
||||||
enabled: false
|
enabled: false
|
||||||
name_template: '{{ .ProjectName }}-{{ .Version }}.source'
|
name_template: '{{ .ProjectName }}-{{ .Version }}.source'
|
||||||
@@ -134,5 +209,6 @@ release:
|
|||||||
mode: replace
|
mode: replace
|
||||||
ids:
|
ids:
|
||||||
- archive
|
- archive
|
||||||
|
- archive-compressed
|
||||||
- package
|
- package
|
||||||
skip_upload: true
|
skip_upload: true
|
||||||
|
|||||||
12
Makefile
12
Makefile
@@ -28,21 +28,13 @@ build:
|
|||||||
export GOTOOLCHAIN=local && \
|
export GOTOOLCHAIN=local && \
|
||||||
go build $(MAIN_PARAMS) $(MAIN)
|
go build $(MAIN_PARAMS) $(MAIN)
|
||||||
|
|
||||||
admin_panel_web:
|
build_admin_panel:
|
||||||
cd $(ADMIN_PANEL_WEB) && \
|
cd $(ADMIN_PANEL_WEB) && \
|
||||||
npm install --no-fund --no-audit && \
|
npm install --no-fund --no-audit && \
|
||||||
npm run build
|
npm run build
|
||||||
|
|
||||||
admin_panel_pack:
|
|
||||||
go run ./cmd/internal/admin_panel_pack \
|
go run ./cmd/internal/admin_panel_pack \
|
||||||
-dir $(ADMIN_PANEL_DIST)
|
-dir $(ADMIN_PANEL_DIST)
|
||||||
|
|
||||||
admin_panel_regen: admin_panel_web admin_panel_pack
|
|
||||||
|
|
||||||
build_admin_panel:
|
|
||||||
export GOTOOLCHAIN=local && \
|
|
||||||
go build $(PARAMS) -tags "$(ADMIN_PANEL_TAGS)" $(MAIN)
|
|
||||||
|
|
||||||
race:
|
race:
|
||||||
export GOTOOLCHAIN=local && \
|
export GOTOOLCHAIN=local && \
|
||||||
go build -race $(MAIN_PARAMS) $(MAIN)
|
go build -race $(MAIN_PARAMS) $(MAIN)
|
||||||
@@ -86,7 +78,7 @@ proto_install:
|
|||||||
update_certificates:
|
update_certificates:
|
||||||
go run ./cmd/internal/update_certificates
|
go run ./cmd/internal/update_certificates
|
||||||
|
|
||||||
release:
|
release: build_admin_panel
|
||||||
go run ./cmd/internal/build goreleaser release --skip=validate --clean -p 3 --skip publish
|
go run ./cmd/internal/build goreleaser release --skip=validate --clean -p 3 --skip publish
|
||||||
mkdir dist/release
|
mkdir dist/release
|
||||||
mv dist/*.tar.gz \
|
mv dist/*.tar.gz \
|
||||||
|
|||||||
2
go.mod
2
go.mod
@@ -211,7 +211,7 @@ require (
|
|||||||
lukechampine.com/blake3 v1.4.1
|
lukechampine.com/blake3 v1.4.1
|
||||||
)
|
)
|
||||||
|
|
||||||
replace github.com/sagernet/wireguard-go => github.com/shtorm-7/wireguard-go v0.0.2-beta.1-extended-1.4.1
|
replace github.com/sagernet/wireguard-go => github.com/shtorm-7/wireguard-go v0.0.2-beta.1-extended-1.4.2
|
||||||
|
|
||||||
replace github.com/sagernet/tailscale => github.com/shtorm-7/tailscale v1.92.4-sing-box-1.13-mod.7-extended-1.0.2
|
replace github.com/sagernet/tailscale => github.com/shtorm-7/tailscale v1.92.4-sing-box-1.13-mod.7-extended-1.0.2
|
||||||
|
|
||||||
|
|||||||
4
go.sum
4
go.sum
@@ -385,8 +385,8 @@ github.com/shtorm-7/sing-mux v0.3.4-extended-1.0.0 h1:a5OoXr3e2ACbM6vDIaaGL44IdH
|
|||||||
github.com/shtorm-7/sing-mux v0.3.4-extended-1.0.0/go.mod h1:QvlKMyNBNrQoyX4x+gq028uPbLM2XeRpWtDsWBJbFSk=
|
github.com/shtorm-7/sing-mux v0.3.4-extended-1.0.0/go.mod h1:QvlKMyNBNrQoyX4x+gq028uPbLM2XeRpWtDsWBJbFSk=
|
||||||
github.com/shtorm-7/tailscale v1.92.4-sing-box-1.13-mod.7-extended-1.0.2 h1:hSMjh97OszszOd8HrzpaYUQH9dWRRBluJCbwQyz8ZOk=
|
github.com/shtorm-7/tailscale v1.92.4-sing-box-1.13-mod.7-extended-1.0.2 h1:hSMjh97OszszOd8HrzpaYUQH9dWRRBluJCbwQyz8ZOk=
|
||||||
github.com/shtorm-7/tailscale v1.92.4-sing-box-1.13-mod.7-extended-1.0.2/go.mod h1:TYIIqO5sZpWq873rLIeO2usszSMUpR3h6WdqVVs65ug=
|
github.com/shtorm-7/tailscale v1.92.4-sing-box-1.13-mod.7-extended-1.0.2/go.mod h1:TYIIqO5sZpWq873rLIeO2usszSMUpR3h6WdqVVs65ug=
|
||||||
github.com/shtorm-7/wireguard-go v0.0.2-beta.1-extended-1.4.1 h1:SrDp4NPW6NHjCQSXDYmTYx4pqxvmqFt4DwdRk+odV3w=
|
github.com/shtorm-7/wireguard-go v0.0.2-beta.1-extended-1.4.2 h1:oEvk13VPsypigqNK/rlcqC63gTj0ANJAnzUwlZkOia4=
|
||||||
github.com/shtorm-7/wireguard-go v0.0.2-beta.1-extended-1.4.1/go.mod h1:Me2JlCDYHxnd0mnuX7L5LXAeDHCltI7vSKq3eTE6SVE=
|
github.com/shtorm-7/wireguard-go v0.0.2-beta.1-extended-1.4.2/go.mod h1:Me2JlCDYHxnd0mnuX7L5LXAeDHCltI7vSKq3eTE6SVE=
|
||||||
github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8 h1:TG/diQgUe0pntT/2D9tmUCz4VNwm9MfrtPr0SU2qSX8=
|
github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8 h1:TG/diQgUe0pntT/2D9tmUCz4VNwm9MfrtPr0SU2qSX8=
|
||||||
github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8/go.mod h1:P5HUIBuIWKbyjl083/loAegFkfbFNx5i2qEP4CNbm7E=
|
github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8/go.mod h1:P5HUIBuIWKbyjl083/loAegFkfbFNx5i2qEP4CNbm7E=
|
||||||
github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU=
|
github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU=
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ type WireGuardPeer struct {
|
|||||||
PreSharedKey string `json:"pre_shared_key,omitempty"`
|
PreSharedKey string `json:"pre_shared_key,omitempty"`
|
||||||
AllowedIPs badoption.Listable[netip.Prefix] `json:"allowed_ips,omitempty"`
|
AllowedIPs badoption.Listable[netip.Prefix] `json:"allowed_ips,omitempty"`
|
||||||
PersistentKeepaliveInterval uint16 `json:"persistent_keepalive_interval,omitempty"`
|
PersistentKeepaliveInterval uint16 `json:"persistent_keepalive_interval,omitempty"`
|
||||||
Reserved []uint8 `json:"reserved,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type WireGuardAmnezia struct {
|
type WireGuardAmnezia struct {
|
||||||
|
|||||||
@@ -119,7 +119,6 @@ func NewEndpoint(ctx context.Context, router adapter.Router, logger log.ContextL
|
|||||||
netip.MustParsePrefix("::/0"),
|
netip.MustParsePrefix("::/0"),
|
||||||
},
|
},
|
||||||
PersistentKeepaliveInterval: options.PersistentKeepaliveInterval,
|
PersistentKeepaliveInterval: options.PersistentKeepaliveInterval,
|
||||||
Reserved: options.Reserved,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
MTU: 1280,
|
MTU: 1280,
|
||||||
|
|||||||
@@ -47,7 +47,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.NetworkICMP}, 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),
|
||||||
@@ -130,7 +130,6 @@ func NewEndpoint(ctx context.Context, router adapter.Router, logger log.ContextL
|
|||||||
PreSharedKey: it.PreSharedKey,
|
PreSharedKey: it.PreSharedKey,
|
||||||
AllowedIPs: it.AllowedIPs,
|
AllowedIPs: it.AllowedIPs,
|
||||||
PersistentKeepaliveInterval: it.PersistentKeepaliveInterval,
|
PersistentKeepaliveInterval: it.PersistentKeepaliveInterval,
|
||||||
Reserved: it.Reserved,
|
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
Workers: options.Workers,
|
Workers: options.Workers,
|
||||||
|
|||||||
@@ -123,10 +123,10 @@ func (c *Client) DialContext(ctx context.Context) (net.Conn, error) {
|
|||||||
httpClient, xmuxClient := c.getHTTPClient()
|
httpClient, xmuxClient := c.getHTTPClient()
|
||||||
httpClient2, xmuxClient2 := c.getHTTPClient2()
|
httpClient2, xmuxClient2 := c.getHTTPClient2()
|
||||||
if xmuxClient != nil {
|
if xmuxClient != nil {
|
||||||
xmuxClient.OpenUsage.Add(1)
|
xmuxClient.AddOpenUsage(1)
|
||||||
}
|
}
|
||||||
if xmuxClient2 != nil && xmuxClient2 != xmuxClient {
|
if xmuxClient2 != nil && xmuxClient2 != xmuxClient {
|
||||||
xmuxClient2.OpenUsage.Add(1)
|
xmuxClient2.AddOpenUsage(1)
|
||||||
}
|
}
|
||||||
var closed atomic.Int32
|
var closed atomic.Int32
|
||||||
reader, writer := io.Pipe()
|
reader, writer := io.Pipe()
|
||||||
@@ -137,10 +137,10 @@ func (c *Client) DialContext(ctx context.Context) (net.Conn, error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if xmuxClient != nil {
|
if xmuxClient != nil {
|
||||||
xmuxClient.OpenUsage.Add(-1)
|
xmuxClient.AddOpenUsage(-1)
|
||||||
}
|
}
|
||||||
if xmuxClient2 != nil && xmuxClient2 != xmuxClient {
|
if xmuxClient2 != nil && xmuxClient2 != xmuxClient {
|
||||||
xmuxClient2.OpenUsage.Add(-1)
|
xmuxClient2.AddOpenUsage(-1)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,19 +8,24 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptrace"
|
"net/http/httptrace"
|
||||||
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/sagernet/quic-go/http3"
|
||||||
common "github.com/sagernet/sing-box/common/xray"
|
common "github.com/sagernet/sing-box/common/xray"
|
||||||
"github.com/sagernet/sing-box/common/xray/buf"
|
"github.com/sagernet/sing-box/common/xray/buf"
|
||||||
"github.com/sagernet/sing-box/common/xray/signal/done"
|
"github.com/sagernet/sing-box/common/xray/signal/done"
|
||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
|
"golang.org/x/net/http2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// interface to abstract between use of browser dialer, vs net/http
|
// interface to abstract between use of browser dialer, vs net/http
|
||||||
type DialerClient interface {
|
type DialerClient interface {
|
||||||
IsClosed() bool
|
IsClosed() bool
|
||||||
|
Close()
|
||||||
|
|
||||||
// ctx, url, sessionId, body, uploadOnly
|
// ctx, url, sessionId, body, uploadOnly
|
||||||
OpenStream(context.Context, string, string, io.Reader, bool) (io.ReadCloser, net.Addr, net.Addr, error)
|
OpenStream(context.Context, string, string, io.Reader, bool) (io.ReadCloser, net.Addr, net.Addr, error)
|
||||||
@@ -38,9 +43,54 @@ type DefaultDialerClient struct {
|
|||||||
// pool of net.Conn, created using dialUploadConn
|
// pool of net.Conn, created using dialUploadConn
|
||||||
uploadRawPool *sync.Pool
|
uploadRawPool *sync.Pool
|
||||||
dialUploadConn func(ctxInner context.Context) (net.Conn, error)
|
dialUploadConn func(ctxInner context.Context) (net.Conn, error)
|
||||||
|
|
||||||
|
mtx sync.RWMutex
|
||||||
|
}
|
||||||
|
|
||||||
|
type clientConnPool struct {
|
||||||
|
t *http2.Transport
|
||||||
|
mu sync.Mutex
|
||||||
|
conns map[string][]*http2.ClientConn // key is host:port
|
||||||
|
}
|
||||||
|
|
||||||
|
type efaceWords struct {
|
||||||
|
typ unsafe.Pointer
|
||||||
|
data unsafe.Pointer
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:linkname transportConnPool golang.org/x/net/http2.(*Transport).connPool
|
||||||
|
func transportConnPool(t *http2.Transport) http2.ClientConnPool
|
||||||
|
|
||||||
|
func (c *DefaultDialerClient) Close() {
|
||||||
|
c.mtx.Lock()
|
||||||
|
defer c.mtx.Unlock()
|
||||||
|
if c.closed {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.closed = true
|
||||||
|
switch transport := c.client.Transport.(type) {
|
||||||
|
case *http.Transport:
|
||||||
|
transport.CloseIdleConnections()
|
||||||
|
case *http2.Transport:
|
||||||
|
connPool := transportConnPool(transport)
|
||||||
|
p := (*clientConnPool)((*efaceWords)(unsafe.Pointer(&connPool)).data)
|
||||||
|
p.mu.Lock()
|
||||||
|
defer p.mu.Unlock()
|
||||||
|
for _, vv := range p.conns {
|
||||||
|
for _, cc := range vv {
|
||||||
|
cc.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case *http3.Transport:
|
||||||
|
transport.Close()
|
||||||
|
default:
|
||||||
|
panic(E.New("unknown transport type: ", reflect.TypeOf(transport)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *DefaultDialerClient) IsClosed() bool {
|
func (c *DefaultDialerClient) IsClosed() bool {
|
||||||
|
c.mtx.RLock()
|
||||||
|
defer c.mtx.RUnlock()
|
||||||
return c.closed
|
return c.closed
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,7 +117,7 @@ func (c *DefaultDialerClient) OpenStream(ctx context.Context, url string, sessio
|
|||||||
resp, err := c.client.Do(req)
|
resp, err := c.client.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !uploadOnly { // stream-down is enough
|
if !uploadOnly { // stream-down is enough
|
||||||
c.closed = true
|
c.Close()
|
||||||
}
|
}
|
||||||
gotConn.Close()
|
gotConn.Close()
|
||||||
common.Close(body)
|
common.Close(body)
|
||||||
@@ -133,7 +183,7 @@ func (c *DefaultDialerClient) PostPacket(ctx context.Context, url string, sessio
|
|||||||
if h1UploadConn.UnreadedResponsesCount > 0 {
|
if h1UploadConn.UnreadedResponsesCount > 0 {
|
||||||
resp, err := http.ReadResponse(h1UploadConn.RespBufReader, req)
|
resp, err := http.ReadResponse(h1UploadConn.RespBufReader, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.closed = true
|
c.Close()
|
||||||
return fmt.Errorf("error while reading response: %s", err.Error())
|
return fmt.Errorf("error while reading response: %s", err.Error())
|
||||||
}
|
}
|
||||||
io.Copy(io.Discard, resp.Body)
|
io.Copy(io.Discard, resp.Body)
|
||||||
|
|||||||
@@ -13,15 +13,43 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type XmuxConn interface {
|
type XmuxConn interface {
|
||||||
|
Close()
|
||||||
IsClosed() bool
|
IsClosed() bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type XmuxClient struct {
|
type XmuxClient struct {
|
||||||
XmuxConn XmuxConn
|
XmuxConn XmuxConn
|
||||||
OpenUsage atomic.Int32
|
openUsage int32
|
||||||
leftUsage int32
|
leftUsage int32
|
||||||
LeftRequests atomic.Int32
|
LeftRequests atomic.Int32
|
||||||
UnreusableAt time.Time
|
UnreusableAt time.Time
|
||||||
|
|
||||||
|
closed bool
|
||||||
|
mtx sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *XmuxClient) Close() {
|
||||||
|
c.mtx.Lock()
|
||||||
|
defer c.mtx.Unlock()
|
||||||
|
c.closed = true
|
||||||
|
if c.openUsage <= 0 {
|
||||||
|
c.XmuxConn.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *XmuxClient) AddOpenUsage(delta int32) {
|
||||||
|
c.mtx.Lock()
|
||||||
|
defer c.mtx.Unlock()
|
||||||
|
c.openUsage += delta
|
||||||
|
if c.closed && c.openUsage <= 0 {
|
||||||
|
c.XmuxConn.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *XmuxClient) GetOpenUsage() int32 {
|
||||||
|
c.mtx.Lock()
|
||||||
|
defer c.mtx.Unlock()
|
||||||
|
return c.openUsage
|
||||||
}
|
}
|
||||||
|
|
||||||
type XmuxManager struct {
|
type XmuxManager struct {
|
||||||
@@ -65,6 +93,7 @@ func (m *XmuxManager) newXmuxClient() *XmuxClient {
|
|||||||
func (m *XmuxManager) GetXmuxClient(ctx context.Context) *XmuxClient {
|
func (m *XmuxManager) GetXmuxClient(ctx context.Context) *XmuxClient {
|
||||||
m.mtx.Lock()
|
m.mtx.Lock()
|
||||||
defer m.mtx.Unlock()
|
defer m.mtx.Unlock()
|
||||||
|
var evicted []*XmuxClient
|
||||||
for i := 0; i < len(m.xmuxClients); {
|
for i := 0; i < len(m.xmuxClients); {
|
||||||
xmuxClient := m.xmuxClients[i]
|
xmuxClient := m.xmuxClients[i]
|
||||||
if xmuxClient.XmuxConn.IsClosed() ||
|
if xmuxClient.XmuxConn.IsClosed() ||
|
||||||
@@ -72,10 +101,14 @@ func (m *XmuxManager) GetXmuxClient(ctx context.Context) *XmuxClient {
|
|||||||
xmuxClient.LeftRequests.Load() <= 0 ||
|
xmuxClient.LeftRequests.Load() <= 0 ||
|
||||||
(xmuxClient.UnreusableAt != time.Time{} && time.Now().After(xmuxClient.UnreusableAt)) {
|
(xmuxClient.UnreusableAt != time.Time{} && time.Now().After(xmuxClient.UnreusableAt)) {
|
||||||
m.xmuxClients = append(m.xmuxClients[:i], m.xmuxClients[i+1:]...)
|
m.xmuxClients = append(m.xmuxClients[:i], m.xmuxClients[i+1:]...)
|
||||||
|
evicted = append(evicted, xmuxClient)
|
||||||
} else {
|
} else {
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for _, c := range evicted {
|
||||||
|
c.Close()
|
||||||
|
}
|
||||||
if len(m.xmuxClients) == 0 {
|
if len(m.xmuxClients) == 0 {
|
||||||
return m.newXmuxClient()
|
return m.newXmuxClient()
|
||||||
}
|
}
|
||||||
@@ -85,7 +118,7 @@ func (m *XmuxManager) GetXmuxClient(ctx context.Context) *XmuxClient {
|
|||||||
xmuxClients := make([]*XmuxClient, 0)
|
xmuxClients := make([]*XmuxClient, 0)
|
||||||
if m.concurrency > 0 {
|
if m.concurrency > 0 {
|
||||||
for _, xmuxClient := range m.xmuxClients {
|
for _, xmuxClient := range m.xmuxClients {
|
||||||
if xmuxClient.OpenUsage.Load() < m.concurrency {
|
if xmuxClient.GetOpenUsage() < m.concurrency {
|
||||||
xmuxClients = append(xmuxClients, xmuxClient)
|
xmuxClients = append(xmuxClients, xmuxClient)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,32 +21,28 @@ import (
|
|||||||
var _ conn.Bind = (*ClientBind)(nil)
|
var _ conn.Bind = (*ClientBind)(nil)
|
||||||
|
|
||||||
type ClientBind struct {
|
type ClientBind struct {
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
logger logger.Logger
|
logger logger.Logger
|
||||||
pauseManager pause.Manager
|
pauseManager pause.Manager
|
||||||
bindCtx context.Context
|
bindCtx context.Context
|
||||||
bindDone context.CancelFunc
|
bindDone context.CancelFunc
|
||||||
dialer N.Dialer
|
dialer N.Dialer
|
||||||
reservedForEndpoint map[netip.AddrPort][3]uint8
|
connAccess sync.Mutex
|
||||||
connAccess sync.Mutex
|
conn *wireConn
|
||||||
conn *wireConn
|
done chan struct{}
|
||||||
done chan struct{}
|
isConnect bool
|
||||||
isConnect bool
|
connectAddr netip.AddrPort
|
||||||
connectAddr netip.AddrPort
|
|
||||||
reserved [3]uint8
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewClientBind(ctx context.Context, logger logger.Logger, dialer N.Dialer, isConnect bool, connectAddr netip.AddrPort, reserved [3]uint8) *ClientBind {
|
func NewClientBind(ctx context.Context, logger logger.Logger, dialer N.Dialer, isConnect bool, connectAddr netip.AddrPort) *ClientBind {
|
||||||
return &ClientBind{
|
return &ClientBind{
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
logger: logger,
|
logger: logger,
|
||||||
pauseManager: service.FromContext[pause.Manager](ctx),
|
pauseManager: service.FromContext[pause.Manager](ctx),
|
||||||
dialer: dialer,
|
dialer: dialer,
|
||||||
reservedForEndpoint: make(map[netip.AddrPort][3]uint8),
|
done: make(chan struct{}),
|
||||||
done: make(chan struct{}),
|
isConnect: isConnect,
|
||||||
isConnect: isConnect,
|
connectAddr: connectAddr,
|
||||||
connectAddr: connectAddr,
|
|
||||||
reserved: reserved,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,10 +130,6 @@ func (c *ClientBind) receive(packets [][]byte, sizes []int, eps []conn.Endpoint)
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
sizes[0] = n
|
sizes[0] = n
|
||||||
if n > 3 {
|
|
||||||
b := packets[0]
|
|
||||||
clear(b[1:4])
|
|
||||||
}
|
|
||||||
eps[0] = remoteEndpoint(M.SocksaddrFromNet(addr).Unwrap().AddrPort())
|
eps[0] = remoteEndpoint(M.SocksaddrFromNet(addr).Unwrap().AddrPort())
|
||||||
count = 1
|
count = 1
|
||||||
return
|
return
|
||||||
@@ -174,13 +166,6 @@ func (c *ClientBind) Send(bufs [][]byte, ep conn.Endpoint, offset int) error {
|
|||||||
if offset > 0 {
|
if offset > 0 {
|
||||||
buf = buf[offset:]
|
buf = buf[offset:]
|
||||||
}
|
}
|
||||||
if len(buf) > 3 {
|
|
||||||
reserved, loaded := c.reservedForEndpoint[destination]
|
|
||||||
if !loaded {
|
|
||||||
reserved = c.reserved
|
|
||||||
}
|
|
||||||
copy(buf[1:4], reserved[:])
|
|
||||||
}
|
|
||||||
_, err = udpConn.WriteToUDPAddrPort(buf, destination)
|
_, err = udpConn.WriteToUDPAddrPort(buf, destination)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
udpConn.Close()
|
udpConn.Close()
|
||||||
@@ -202,10 +187,6 @@ func (c *ClientBind) BatchSize() int {
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ClientBind) SetReservedForEndpoint(destination netip.AddrPort, reserved [3]byte) {
|
|
||||||
c.reservedForEndpoint[destination] = reserved
|
|
||||||
}
|
|
||||||
|
|
||||||
type wireConn struct {
|
type wireConn struct {
|
||||||
net.PacketConn
|
net.PacketConn
|
||||||
conn net.Conn
|
conn net.Conn
|
||||||
|
|||||||
@@ -82,12 +82,6 @@ func NewEndpoint(options EndpointOptions) (*Endpoint, error) {
|
|||||||
if len(rawPeer.AllowedIPs) == 0 {
|
if len(rawPeer.AllowedIPs) == 0 {
|
||||||
return nil, E.New("missing allowed ips for peer ", peerIndex)
|
return nil, E.New("missing allowed ips for peer ", peerIndex)
|
||||||
}
|
}
|
||||||
if len(rawPeer.Reserved) > 0 {
|
|
||||||
if len(rawPeer.Reserved) != 3 {
|
|
||||||
return nil, E.New("invalid reserved value for peer ", peerIndex, ", required 3 bytes, got ", len(peer.reserved))
|
|
||||||
}
|
|
||||||
copy(peer.reserved[:], rawPeer.Reserved[:])
|
|
||||||
}
|
|
||||||
peers = append(peers, peer)
|
peers = append(peers, peer)
|
||||||
}
|
}
|
||||||
var allowedPrefixBuilder netipx.IPSetBuilder
|
var allowedPrefixBuilder netipx.IPSetBuilder
|
||||||
@@ -157,26 +151,17 @@ func (e *Endpoint) Start(resolve bool) error {
|
|||||||
var bind conn.Bind
|
var bind conn.Bind
|
||||||
wgListener, isWgListener := common.Cast[dialer.WireGuardListener](e.options.Dialer)
|
wgListener, isWgListener := common.Cast[dialer.WireGuardListener](e.options.Dialer)
|
||||||
if isWgListener {
|
if isWgListener {
|
||||||
bind = conn.NewStdNetBind(wgListener.WireGuardControl())
|
bind = conn.NewDefaultBind(wgListener.WireGuardControl())
|
||||||
} else {
|
} else {
|
||||||
var (
|
var (
|
||||||
isConnect bool
|
isConnect bool
|
||||||
connectAddr netip.AddrPort
|
connectAddr netip.AddrPort
|
||||||
reserved [3]uint8
|
|
||||||
)
|
)
|
||||||
if len(e.peers) == 1 && e.peers[0].endpoint.IsValid() {
|
if len(e.peers) == 1 && e.peers[0].endpoint.IsValid() {
|
||||||
isConnect = true
|
isConnect = true
|
||||||
connectAddr = e.peers[0].endpoint
|
connectAddr = e.peers[0].endpoint
|
||||||
reserved = e.peers[0].reserved
|
|
||||||
}
|
|
||||||
bind = NewClientBind(e.options.Context, e.options.Logger, e.options.Dialer, isConnect, connectAddr, reserved)
|
|
||||||
}
|
|
||||||
if isWgListener || len(e.peers) > 1 {
|
|
||||||
for _, peer := range e.peers {
|
|
||||||
if peer.reserved != [3]uint8{} {
|
|
||||||
bind.SetReservedForEndpoint(peer.endpoint, peer.reserved)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
bind = NewClientBind(e.options.Context, e.options.Logger, e.options.Dialer, isConnect, connectAddr)
|
||||||
}
|
}
|
||||||
err := e.tunDevice.Start()
|
err := e.tunDevice.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -336,7 +321,6 @@ type peerConfig struct {
|
|||||||
preSharedKeyHex string
|
preSharedKeyHex string
|
||||||
allowedIPs []netip.Prefix
|
allowedIPs []netip.Prefix
|
||||||
keepalive uint16
|
keepalive uint16
|
||||||
reserved [3]uint8
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c peerConfig) GenerateIpcLines() string {
|
func (c peerConfig) GenerateIpcLines() string {
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ type PeerOptions struct {
|
|||||||
PreSharedKey string
|
PreSharedKey string
|
||||||
AllowedIPs []netip.Prefix
|
AllowedIPs []netip.Prefix
|
||||||
PersistentKeepaliveInterval uint16
|
PersistentKeepaliveInterval uint16
|
||||||
Reserved []uint8
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type AmneziaOptions struct {
|
type AmneziaOptions struct {
|
||||||
|
|||||||
Reference in New Issue
Block a user