From d8b470d1bace162bdc128babbe53456e0c473026 Mon Sep 17 00:00:00 2001 From: Sergei Maklagin Date: Mon, 8 Dec 2025 22:32:33 +0300 Subject: [PATCH] Add new wireguard options --- README.md | 1 + examples/warp/client.json | 4 +- examples/wireguard/client.json | 52 ++++++++++++++++++++++++ go.mod | 8 ++-- go.sum | 12 ++---- option/wireguard.go | 54 ++++++++++++++----------- protocol/wireguard/endpoint.go | 6 ++- protocol/wireguard/endpoint_warp.go | 16 ++++---- protocol/wireguard/outbound.go | 8 ++-- transport/wireguard/endpoint.go | 2 +- transport/wireguard/endpoint_options.go | 34 ++++++++-------- 11 files changed, 130 insertions(+), 67 deletions(-) create mode 100644 examples/wireguard/client.json diff --git a/README.md b/README.md index 7b2a82e2..c99ee431 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ Sing-box with extended features. * Mieru * XHTTP * SDNS (DNSCrypt) +* Extended wireguard options * Unified delay ## Examples diff --git a/examples/warp/client.json b/examples/warp/client.json index 71793795..874f8234 100644 --- a/examples/warp/client.json +++ b/examples/warp/client.json @@ -27,7 +27,7 @@ }, "profile": { "detour": "direct", - // for getting existing WARP device profile + // For getting existing WARP device profile, else sing-box will create new profile "id": "", "private_key": "", "auth_token": "" @@ -56,7 +56,7 @@ "experimental": { "cache_file": { "enabled": true, - "store_warp_config": true + "store_warp_config": true // For saving WARP device profiles } } } \ No newline at end of file diff --git a/examples/wireguard/client.json b/examples/wireguard/client.json new file mode 100644 index 00000000..74e1ece7 --- /dev/null +++ b/examples/wireguard/client.json @@ -0,0 +1,52 @@ +{ + "log": { + "level": "error" + }, + "dns": { + "servers": [ + { + "type": "local", + "tag": "default" + } + ] + }, + "endpoints": [ + { + "type": "wireguard", + "tag": "wireguard-out", + "mtu": 1408, + "address": null, + "private_key": "", + "listen_port": 10000, + "peers": [ + { + "address": "example.com", + "port": 10001, + "reserved": "AAAA" + } + ], + "udp_timeout": "5m0s", + // Extended options + "preallocated_buffers_per_pool": 256, // Set limit for preallocated buffers (can be useful for devices with low RAM) + "disable_pauses": true, // Disable pauses when android device in sleep mode + } + ], + "inbounds": [ + { + "type": "mixed", + "tag": "mixed-in", + "listen_port": 7897 + } + ], + "outbounds": [ + { + "type": "direct", + "tag": "direct" + }, + ], + "route": { + "final": "wireguard-out", + "default_domain_resolver": "default", + "auto_detect_interface": true + } +} \ No newline at end of file diff --git a/go.mod b/go.mod index 7c1341c7..796b3df8 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,6 @@ require ( github.com/mholt/acmez/v3 v3.1.2 github.com/miekg/dns v1.1.67 github.com/oschwald/maxminddb-golang v1.13.1 - github.com/quic-go/quic-go v0.54.0 github.com/sagernet/asc-go v0.0.0-20241217030726-d563060fe4e1 github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a github.com/sagernet/cors v1.2.1 @@ -54,6 +53,7 @@ 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 @@ -66,7 +66,6 @@ require ( github.com/ameshkov/dnsstamps v1.0.3 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.0 // indirect - go.uber.org/mock v0.5.0 // indirect golang.org/x/sync v0.16.0 // indirect golang.org/x/text v0.28.0 // indirect golang.org/x/tools v0.36.0 // indirect @@ -142,7 +141,6 @@ require ( 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 @@ -150,7 +148,9 @@ require ( lukechampine.com/blake3 v1.4.1 // indirect ) -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/wireguard-go => github.com/shtorm-7/wireguard-go v0.0.1-beta.7-extended-1.1.0 + +replace github.com/sagernet/tailscale => github.com/shtorm-7/tailscale v1.80.3-sing-box-1.12-mod.2-extended-1.0.0 replace github.com/sagernet/sing-dns => github.com/shtorm-7/sing-dns v0.4.6-extended-1.0.0 diff --git a/go.sum b/go.sum index 2b4280d7..eeff4bfb 100644 --- a/go.sum +++ b/go.sum @@ -151,8 +151,6 @@ github.com/prometheus-community/pro-bing v0.4.0 h1:YMbv+i08gQz97OZZBwLyvmmQEEzyf github.com/prometheus-community/pro-bing v0.4.0/go.mod h1:b7wRYZtCcPmt4Sz319BykUU241rWLe1VFXyiyWK/dH4= github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI= github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg= -github.com/quic-go/quic-go v0.54.0 h1:6s1YB9QotYI6Ospeiguknbp2Znb/jZYjZLRXn9kMQBg= -github.com/quic-go/quic-go v0.54.0/go.mod h1:e68ZEaCdyviluZmy44P6Iey98v/Wfz6HCjQEm+l8zTY= 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= @@ -193,14 +191,14 @@ github.com/sagernet/sing-vmess v0.2.7 h1:2ee+9kO0xW5P4mfe6TYVWf9VtY8k1JhNysBqsiY 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.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/shtorm-7/tailscale v1.80.3-sing-box-1.12-mod.2-extended-1.0.0 h1:Yp4dIRwiwLda9JXyGMHkfYRr2r01NarkzsNd/oi10dk= +github.com/shtorm-7/tailscale v1.80.3-sing-box-1.12-mod.2-extended-1.0.0/go.mod h1:+znUAXWwgcgza5mb5do8j9RC95rpY9lbSc/TyEyCGa4= +github.com/shtorm-7/wireguard-go v0.0.1-beta.7-extended-1.1.0 h1:bTmx3NiEeH7mdgsifyNUxIEAA0wokRMSm8iS/hln6n0= +github.com/shtorm-7/wireguard-go v0.0.1-beta.7-extended-1.1.0/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= @@ -271,8 +269,6 @@ 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= -go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM= 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/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= diff --git a/option/wireguard.go b/option/wireguard.go index f9e71a40..46132841 100644 --- a/option/wireguard.go +++ b/option/wireguard.go @@ -7,16 +7,18 @@ import ( ) type WireGuardEndpointOptions struct { - System bool `json:"system,omitempty"` - Name string `json:"name,omitempty"` - MTU uint32 `json:"mtu,omitempty"` - Address badoption.Listable[netip.Prefix] `json:"address"` - PrivateKey string `json:"private_key"` - ListenPort uint16 `json:"listen_port,omitempty"` - Peers []WireGuardPeer `json:"peers,omitempty"` - UDPTimeout badoption.Duration `json:"udp_timeout,omitempty"` - Workers int `json:"workers,omitempty"` - Amnezia *WireGuardAmnezia `json:"amnezia,omitempty"` + System bool `json:"system,omitempty"` + Name string `json:"name,omitempty"` + MTU uint32 `json:"mtu,omitempty"` + Address badoption.Listable[netip.Prefix] `json:"address"` + PrivateKey string `json:"private_key"` + ListenPort uint16 `json:"listen_port,omitempty"` + Peers []WireGuardPeer `json:"peers,omitempty"` + UDPTimeout badoption.Duration `json:"udp_timeout,omitempty"` + Workers int `json:"workers,omitempty"` + PreallocatedBuffersPerPool uint32 `json:"preallocated_buffers_per_pool,omitempty"` + DisablePauses bool `json:"disable_pauses,omitempty"` + Amnezia *WireGuardAmnezia `json:"amnezia,omitempty"` DialerOptions } @@ -31,13 +33,15 @@ 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 WARPProfile `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"` + PreallocatedBuffersPerPool uint32 `json:"preallocated_buffers_per_pool,omitempty"` + DisablePauses bool `json:"disable_pauses,omitempty"` + Amnezia *WireGuardAmnezia `json:"amnezia,omitempty"` + Profile WARPProfile `json:"profile,omitempty"` DialerOptions } @@ -58,13 +62,15 @@ type LegacyWireGuardOutboundOptions struct { PrivateKey string `json:"private_key"` Peers []LegacyWireGuardPeer `json:"peers,omitempty"` ServerOptions - PeerPublicKey string `json:"peer_public_key"` - PreSharedKey string `json:"pre_shared_key,omitempty"` - Reserved []uint8 `json:"reserved,omitempty"` - Workers int `json:"workers,omitempty"` - MTU uint32 `json:"mtu,omitempty"` - Network NetworkList `json:"network,omitempty"` - Amnezia *WireGuardAmnezia `json:"amnezia,omitempty"` + PeerPublicKey string `json:"peer_public_key"` + PreSharedKey string `json:"pre_shared_key,omitempty"` + Reserved []uint8 `json:"reserved,omitempty"` + Workers int `json:"workers,omitempty"` + PreallocatedBuffersPerPool uint32 `json:"preallocated_buffers_per_pool,omitempty"` + DisablePauses bool `json:"disable_pauses,omitempty"` + MTU uint32 `json:"mtu,omitempty"` + Network NetworkList `json:"network,omitempty"` + Amnezia *WireGuardAmnezia `json:"amnezia,omitempty"` } type LegacyWireGuardPeer struct { diff --git a/protocol/wireguard/endpoint.go b/protocol/wireguard/endpoint.go index 7afd1c95..9ec84597 100644 --- a/protocol/wireguard/endpoint.go +++ b/protocol/wireguard/endpoint.go @@ -124,8 +124,10 @@ func NewEndpoint(ctx context.Context, router adapter.Router, logger log.ContextL Reserved: it.Reserved, } }), - Workers: options.Workers, - Amnezia: amnezia, + Workers: options.Workers, + PreallocatedBuffersPerPool: options.PreallocatedBuffersPerPool, + DisablePauses: options.DisablePauses, + Amnezia: amnezia, }) if err != nil { return nil, err diff --git a/protocol/wireguard/endpoint_warp.go b/protocol/wireguard/endpoint_warp.go index 80b53010..690ffb66 100644 --- a/protocol/wireguard/endpoint_warp.go +++ b/protocol/wireguard/endpoint_warp.go @@ -130,13 +130,15 @@ func NewWARPEndpoint(ctx context.Context, router adapter.Router, logger log.Cont logger, tag, option.WireGuardEndpointOptions{ - System: options.System, - Name: options.Name, - ListenPort: options.ListenPort, - UDPTimeout: options.UDPTimeout, - Workers: options.Workers, - Amnezia: options.Amnezia, - DialerOptions: options.DialerOptions, + System: options.System, + Name: options.Name, + ListenPort: options.ListenPort, + UDPTimeout: options.UDPTimeout, + Workers: options.Workers, + PreallocatedBuffersPerPool: options.PreallocatedBuffersPerPool, + DisablePauses: options.DisablePauses, + Amnezia: options.Amnezia, + DialerOptions: options.DialerOptions, Address: badoption.Listable[netip.Prefix]{ netip.MustParsePrefix(config.Interface.Addresses.V4 + "/32"), diff --git a/protocol/wireguard/outbound.go b/protocol/wireguard/outbound.go index fc45655e..d6d75ea8 100644 --- a/protocol/wireguard/outbound.go +++ b/protocol/wireguard/outbound.go @@ -125,9 +125,11 @@ func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextL } return endpointAddresses[0], nil }, - Peers: peers, - Workers: options.Workers, - Amnezia: amnezia, + Peers: peers, + Workers: options.Workers, + PreallocatedBuffersPerPool: options.PreallocatedBuffersPerPool, + DisablePauses: options.DisablePauses, + Amnezia: amnezia, }) if err != nil { return nil, err diff --git a/transport/wireguard/endpoint.go b/transport/wireguard/endpoint.go index df970127..3d320517 100644 --- a/transport/wireguard/endpoint.go +++ b/transport/wireguard/endpoint.go @@ -177,7 +177,7 @@ func (e *Endpoint) Start(resolve bool) error { e.options.Logger.Error(fmt.Sprintf(strings.ToLower(format), args...)) }, } - wgDevice := device.NewDevice(e.options.Context, e.tunDevice, bind, logger, e.options.Workers) + wgDevice := device.NewDevice(e.options.Context, e.tunDevice, bind, logger, e.options.Workers, e.options.PreallocatedBuffersPerPool, e.options.DisablePauses) e.tunDevice.SetDevice(wgDevice) ipcConf := e.ipcConf if e.options.Amnezia != nil { diff --git a/transport/wireguard/endpoint_options.go b/transport/wireguard/endpoint_options.go index a0a0a8c7..a339b328 100644 --- a/transport/wireguard/endpoint_options.go +++ b/transport/wireguard/endpoint_options.go @@ -12,22 +12,24 @@ import ( ) type EndpointOptions struct { - Context context.Context - Logger logger.ContextLogger - System bool - Handler tun.Handler - UDPTimeout time.Duration - Dialer N.Dialer - CreateDialer func(interfaceName string) N.Dialer - Name string - MTU uint32 - Address []netip.Prefix - PrivateKey string - ListenPort uint16 - ResolvePeer func(domain string) (netip.Addr, error) - Peers []PeerOptions - Workers int - Amnezia *AmneziaOptions + Context context.Context + Logger logger.ContextLogger + System bool + Handler tun.Handler + UDPTimeout time.Duration + Dialer N.Dialer + CreateDialer func(interfaceName string) N.Dialer + Name string + MTU uint32 + Address []netip.Prefix + PrivateKey string + ListenPort uint16 + ResolvePeer func(domain string) (netip.Addr, error) + Peers []PeerOptions + Workers int + PreallocatedBuffersPerPool uint32 + DisablePauses bool + Amnezia *AmneziaOptions } type PeerOptions struct {