Add new wireguard options

This commit is contained in:
Sergei Maklagin
2025-12-08 22:32:33 +03:00
parent 984fc295b3
commit d8b470d1ba
11 changed files with 130 additions and 67 deletions

View File

@@ -10,6 +10,7 @@ Sing-box with extended features.
* Mieru * Mieru
* XHTTP * XHTTP
* SDNS (DNSCrypt) * SDNS (DNSCrypt)
* Extended wireguard options
* Unified delay * Unified delay
## Examples ## Examples

View File

@@ -27,7 +27,7 @@
}, },
"profile": { "profile": {
"detour": "direct", "detour": "direct",
// for getting existing WARP device profile // For getting existing WARP device profile, else sing-box will create new profile
"id": "", "id": "",
"private_key": "", "private_key": "",
"auth_token": "" "auth_token": ""
@@ -56,7 +56,7 @@
"experimental": { "experimental": {
"cache_file": { "cache_file": {
"enabled": true, "enabled": true,
"store_warp_config": true "store_warp_config": true // For saving WARP device profiles
} }
} }
} }

View File

@@ -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
}
}

8
go.mod
View File

@@ -23,7 +23,6 @@ require (
github.com/mholt/acmez/v3 v3.1.2 github.com/mholt/acmez/v3 v3.1.2
github.com/miekg/dns v1.1.67 github.com/miekg/dns v1.1.67
github.com/oschwald/maxminddb-golang v1.13.1 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/asc-go v0.0.0-20241217030726-d563060fe4e1
github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a
github.com/sagernet/cors v1.2.1 github.com/sagernet/cors v1.2.1
@@ -54,6 +53,7 @@ require (
golang.org/x/mod v0.27.0 golang.org/x/mod v0.27.0
golang.org/x/net v0.43.0 golang.org/x/net v0.43.0
golang.org/x/sys v0.35.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 golang.zx2c4.com/wireguard/wgctrl v0.0.0-20241231184526-a9ab2273dd10
google.golang.org/grpc v1.73.0 google.golang.org/grpc v1.73.0
google.golang.org/protobuf v1.36.6 google.golang.org/protobuf v1.36.6
@@ -66,7 +66,6 @@ require (
github.com/ameshkov/dnsstamps v1.0.3 // indirect github.com/ameshkov/dnsstamps v1.0.3 // indirect
github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // 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/sync v0.16.0 // indirect
golang.org/x/text v0.28.0 // indirect golang.org/x/text v0.28.0 // indirect
golang.org/x/tools v0.36.0 // indirect golang.org/x/tools v0.36.0 // indirect
@@ -142,7 +141,6 @@ require (
go.uber.org/zap/exp v0.3.0 // indirect go.uber.org/zap/exp v0.3.0 // indirect
go4.org/mem v0.0.0-20240501181205-ae6ca9944745 // indirect go4.org/mem v0.0.0-20240501181205-ae6ca9944745 // indirect
golang.org/x/term v0.34.0 // 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/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
golang.zx2c4.com/wireguard/windows v0.5.3 // indirect golang.zx2c4.com/wireguard/windows v0.5.3 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463 // 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 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 replace github.com/sagernet/sing-dns => github.com/shtorm-7/sing-dns v0.4.6-extended-1.0.0

12
go.sum
View File

@@ -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/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 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg= 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/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 h1:gimQJpsI6sc1yIqP/y8GYgiXn/NjgvpM0RNoWLVVmP0=
github.com/safchain/ethtool v0.3.0/go.mod h1:SA9BwrgyAqNo7M+uaL6IYbxpm5wk3L7Mm6ocLW+CJUs= 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/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 h1:gkmBjIjlJ2zQKpLigOkFur5kBKdV6bNRoFu2WkltRQ4=
github.com/sagernet/smux v1.5.34-mod.2/go.mod h1:0KW0+R+ycvA2INW4gbsd7BNyg+HEfLIAxa5N02/28Zc= 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 h1:6uUiZcDRnZSAegryaUGwPC/Fj13JSHwiTftrXhMmYOc=
github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854/go.mod h1:LtfoSK3+NG57tvnVEHgcuBW9ujgE8enPSgzgwStwCAA= 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 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/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/tailscale v1.80.3-sing-box-1.12-mod.2-extended-1.0.0 h1:Yp4dIRwiwLda9JXyGMHkfYRr2r01NarkzsNd/oi10dk=
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/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 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= 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/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 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= 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 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=

View File

@@ -7,16 +7,18 @@ import (
) )
type WireGuardEndpointOptions struct { type WireGuardEndpointOptions struct {
System bool `json:"system,omitempty"` System bool `json:"system,omitempty"`
Name string `json:"name,omitempty"` Name string `json:"name,omitempty"`
MTU uint32 `json:"mtu,omitempty"` MTU uint32 `json:"mtu,omitempty"`
Address badoption.Listable[netip.Prefix] `json:"address"` Address badoption.Listable[netip.Prefix] `json:"address"`
PrivateKey string `json:"private_key"` PrivateKey string `json:"private_key"`
ListenPort uint16 `json:"listen_port,omitempty"` ListenPort uint16 `json:"listen_port,omitempty"`
Peers []WireGuardPeer `json:"peers,omitempty"` Peers []WireGuardPeer `json:"peers,omitempty"`
UDPTimeout badoption.Duration `json:"udp_timeout,omitempty"` UDPTimeout badoption.Duration `json:"udp_timeout,omitempty"`
Workers int `json:"workers,omitempty"` Workers int `json:"workers,omitempty"`
Amnezia *WireGuardAmnezia `json:"amnezia,omitempty"` PreallocatedBuffersPerPool uint32 `json:"preallocated_buffers_per_pool,omitempty"`
DisablePauses bool `json:"disable_pauses,omitempty"`
Amnezia *WireGuardAmnezia `json:"amnezia,omitempty"`
DialerOptions DialerOptions
} }
@@ -31,13 +33,15 @@ type WireGuardPeer struct {
} }
type WireGuardWARPEndpointOptions struct { type WireGuardWARPEndpointOptions struct {
System bool `json:"system,omitempty"` System bool `json:"system,omitempty"`
Name string `json:"name,omitempty"` Name string `json:"name,omitempty"`
ListenPort uint16 `json:"listen_port,omitempty"` ListenPort uint16 `json:"listen_port,omitempty"`
UDPTimeout badoption.Duration `json:"udp_timeout,omitempty"` UDPTimeout badoption.Duration `json:"udp_timeout,omitempty"`
Workers int `json:"workers,omitempty"` Workers int `json:"workers,omitempty"`
Amnezia *WireGuardAmnezia `json:"amnezia,omitempty"` PreallocatedBuffersPerPool uint32 `json:"preallocated_buffers_per_pool,omitempty"`
Profile WARPProfile `json:"profile,omitempty"` DisablePauses bool `json:"disable_pauses,omitempty"`
Amnezia *WireGuardAmnezia `json:"amnezia,omitempty"`
Profile WARPProfile `json:"profile,omitempty"`
DialerOptions DialerOptions
} }
@@ -58,13 +62,15 @@ type LegacyWireGuardOutboundOptions struct {
PrivateKey string `json:"private_key"` PrivateKey string `json:"private_key"`
Peers []LegacyWireGuardPeer `json:"peers,omitempty"` Peers []LegacyWireGuardPeer `json:"peers,omitempty"`
ServerOptions ServerOptions
PeerPublicKey string `json:"peer_public_key"` PeerPublicKey string `json:"peer_public_key"`
PreSharedKey string `json:"pre_shared_key,omitempty"` PreSharedKey string `json:"pre_shared_key,omitempty"`
Reserved []uint8 `json:"reserved,omitempty"` Reserved []uint8 `json:"reserved,omitempty"`
Workers int `json:"workers,omitempty"` Workers int `json:"workers,omitempty"`
MTU uint32 `json:"mtu,omitempty"` PreallocatedBuffersPerPool uint32 `json:"preallocated_buffers_per_pool,omitempty"`
Network NetworkList `json:"network,omitempty"` DisablePauses bool `json:"disable_pauses,omitempty"`
Amnezia *WireGuardAmnezia `json:"amnezia,omitempty"` MTU uint32 `json:"mtu,omitempty"`
Network NetworkList `json:"network,omitempty"`
Amnezia *WireGuardAmnezia `json:"amnezia,omitempty"`
} }
type LegacyWireGuardPeer struct { type LegacyWireGuardPeer struct {

View File

@@ -124,8 +124,10 @@ func NewEndpoint(ctx context.Context, router adapter.Router, logger log.ContextL
Reserved: it.Reserved, Reserved: it.Reserved,
} }
}), }),
Workers: options.Workers, Workers: options.Workers,
Amnezia: amnezia, PreallocatedBuffersPerPool: options.PreallocatedBuffersPerPool,
DisablePauses: options.DisablePauses,
Amnezia: amnezia,
}) })
if err != nil { if err != nil {
return nil, err return nil, err

View File

@@ -130,13 +130,15 @@ func NewWARPEndpoint(ctx context.Context, router adapter.Router, logger log.Cont
logger, logger,
tag, tag,
option.WireGuardEndpointOptions{ option.WireGuardEndpointOptions{
System: options.System, System: options.System,
Name: options.Name, Name: options.Name,
ListenPort: options.ListenPort, ListenPort: options.ListenPort,
UDPTimeout: options.UDPTimeout, UDPTimeout: options.UDPTimeout,
Workers: options.Workers, Workers: options.Workers,
Amnezia: options.Amnezia, PreallocatedBuffersPerPool: options.PreallocatedBuffersPerPool,
DialerOptions: options.DialerOptions, DisablePauses: options.DisablePauses,
Amnezia: options.Amnezia,
DialerOptions: options.DialerOptions,
Address: badoption.Listable[netip.Prefix]{ Address: badoption.Listable[netip.Prefix]{
netip.MustParsePrefix(config.Interface.Addresses.V4 + "/32"), netip.MustParsePrefix(config.Interface.Addresses.V4 + "/32"),

View File

@@ -125,9 +125,11 @@ func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextL
} }
return endpointAddresses[0], nil return endpointAddresses[0], nil
}, },
Peers: peers, Peers: peers,
Workers: options.Workers, Workers: options.Workers,
Amnezia: amnezia, PreallocatedBuffersPerPool: options.PreallocatedBuffersPerPool,
DisablePauses: options.DisablePauses,
Amnezia: amnezia,
}) })
if err != nil { if err != nil {
return nil, err return nil, err

View File

@@ -177,7 +177,7 @@ func (e *Endpoint) Start(resolve bool) error {
e.options.Logger.Error(fmt.Sprintf(strings.ToLower(format), args...)) e.options.Logger.Error(fmt.Sprintf(strings.ToLower(format), args...))
}, },
} }
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) e.tunDevice.SetDevice(wgDevice)
ipcConf := e.ipcConf ipcConf := e.ipcConf
if e.options.Amnezia != nil { if e.options.Amnezia != nil {

View File

@@ -12,22 +12,24 @@ import (
) )
type EndpointOptions struct { type EndpointOptions struct {
Context context.Context Context context.Context
Logger logger.ContextLogger Logger logger.ContextLogger
System bool System bool
Handler tun.Handler Handler tun.Handler
UDPTimeout time.Duration UDPTimeout time.Duration
Dialer N.Dialer Dialer N.Dialer
CreateDialer func(interfaceName string) N.Dialer CreateDialer func(interfaceName string) N.Dialer
Name string Name string
MTU uint32 MTU uint32
Address []netip.Prefix Address []netip.Prefix
PrivateKey string PrivateKey string
ListenPort uint16 ListenPort uint16
ResolvePeer func(domain string) (netip.Addr, error) ResolvePeer func(domain string) (netip.Addr, error)
Peers []PeerOptions Peers []PeerOptions
Workers int Workers int
Amnezia *AmneziaOptions PreallocatedBuffersPerPool uint32
DisablePauses bool
Amnezia *AmneziaOptions
} }
type PeerOptions struct { type PeerOptions struct {