diff --git a/docs/configuration/endpoint/wireguard.md b/docs/configuration/endpoint/wireguard.md index 65bb6929..f25c2550 100644 --- a/docs/configuration/endpoint/wireguard.md +++ b/docs/configuration/endpoint/wireguard.md @@ -35,6 +35,31 @@ icon: material/new-box } ``` +!!! question "Since sing-box 1.xx.0" + +#### Advanced security (AmneziaWG) + +To activate advanced security mode for WireGuard (powered by AmneziaWG), please add the following fields to the configuration: + +```json5 +{ + ... + "private_key": "....", + "jc": 0, // JunkPacketCount + "jmin": 0, // JunkPacketMinSize + "jmax": 0, // JunkPacketMaxSize + "s1": 0, // InitPacketJunkSize + "s2": 0, // ResponsePacketJunkSize + "h1": 0, // InitPacketMagicHeader + "h2": 0, // ResponsePacketMagicHeader + "h3": 0, // UnderloadPacketMagicHeader + "h4": 0, // TransportPacketMagicHeader +} +``` + +Setting any of these values with a non-zero value will activate the corresponding security feature. +If neither of these values is set, the default WireGuard security will be used. + !!! note "" You can ignore the JSON Array [] tag when the content is only one item diff --git a/go.mod b/go.mod index ef321966..c7976a16 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,8 @@ module github.com/sagernet/sing-box -go 1.23.1 +go 1.23.6 + +toolchain go1.24.0 require ( github.com/anytls/sing-anytls v0.0.5 @@ -123,6 +125,7 @@ require ( github.com/tailscale/peercred v0.0.0-20240214030740-b535050b2aa4 // indirect github.com/tailscale/web-client-prebuilt v0.0.0-20240226180453-5db17b287bf1 // indirect github.com/tcnksm/go-httpstat v0.2.0 // indirect + github.com/tevino/abool/v2 v2.1.0 // indirect github.com/u-root/uio v0.0.0-20240118234441-a3c409a6018e // indirect github.com/vishvananda/netns v0.0.4 // indirect github.com/x448/float16 v0.8.4 // indirect @@ -143,3 +146,6 @@ require ( ) //replace github.com/sagernet/sing => ../sing + +// TODO: if github.com/getlantern/wireguard-go gets merged, remove this line +replace github.com/sagernet/wireguard-go => github.com/getlantern/wireguard-go v0.0.1-beta.5.0.20250303165430-793006c422ec diff --git a/go.sum b/go.sum index 5884b69f..c0af8ac4 100644 --- a/go.sum +++ b/go.sum @@ -44,6 +44,8 @@ github.com/fxamacker/cbor/v2 v2.6.0 h1:sU6J2usfADwWlYDAFhZBQ6TnLFBHxgesMrQfQgk1t github.com/fxamacker/cbor/v2 v2.6.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/gaissmai/bart v0.11.1 h1:5Uv5XwsaFBRo4E5VBcb9TzY8B7zxFf+U7isDxqOrRfc= github.com/gaissmai/bart v0.11.1/go.mod h1:KHeYECXQiBjTzQz/om2tqn3sZF1J7hw9m6z41ftj3fg= +github.com/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.1 h1:KOIHODQj58PmL80G2Eak4WdvUzjSJSm0vG72crDCqb8= @@ -204,8 +206,6 @@ github.com/sagernet/tailscale v1.79.0-mod.1 h1:wIuAH7VqBYJNk0h2+bTyk4F0OlSqHvyLD github.com/sagernet/tailscale v1.79.0-mod.1/go.mod h1:RKY5WjYLj3JJ7VO/8ZCw8eAFa4+kWU6A1Ftdk84uB14= github.com/sagernet/utls v1.6.7 h1:Ep3+aJ8FUGGta+II2IEVNUc3EDhaRCZINWkj/LloIA8= github.com/sagernet/utls v1.6.7/go.mod h1:Uua1TKO/FFuAhLr9rkaVnnrTmmiItzDjv1BUb2+ERwM= -github.com/sagernet/wireguard-go v0.0.1-beta.5 h1:aBEsxJUMEONwOZqKPIkuAcv4zJV5p6XlzEN04CF0FXc= -github.com/sagernet/wireguard-go v0.0.1-beta.5/go.mod h1:jGXij2Gn2wbrWuYNUmmNhf1dwcZtvyAvQoe8Xd8MbUo= 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/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= @@ -236,6 +236,8 @@ github.com/tc-hib/winres v0.2.1 h1:YDE0FiP0VmtRaDn7+aaChp1KiF4owBiJa5l964l5ujA= github.com/tc-hib/winres v0.2.1/go.mod h1:C/JaNhH3KBvhNKVbvdlDWkbMDO9H4fKKDaN7/07SSuk= github.com/tcnksm/go-httpstat v0.2.0 h1:rP7T5e5U2HfmOBmZzGgGZjBQ5/GluWUylujl0tJ04I0= github.com/tcnksm/go-httpstat v0.2.0/go.mod h1:s3JVJFtQxtBEBC9dwcdTTXS9xFnM3SXAZwPG41aurT8= +github.com/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/u-root/uio v0.0.0-20240118234441-a3c409a6018e h1:BA9O3BmlTmpjbvajAwzWx4Wo2TRVdpPXZEeemGQcajw= github.com/u-root/uio v0.0.0-20240118234441-a3c409a6018e/go.mod h1:eLL9Nub3yfAho7qB0MzZizFhTU2QkLeoVsWdHtDW264= github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= diff --git a/option/wireguard.go b/option/wireguard.go index 43d3139c..2bfefd93 100644 --- a/option/wireguard.go +++ b/option/wireguard.go @@ -6,6 +6,29 @@ import ( "github.com/sagernet/sing/common/json/badoption" ) +/* +WireGuardAdvancedSecurityOptions provides advanced security options for WireGuard required to activate AmneziaWG. + +In AmneziaWG, random bytes are appended to every auth packet to alter their size. +Thus, "init and response handshake packets" have added "junk" at the beginning of their data, the size of which +is determined by the values S1 and S2. +By default, the initiating handshake packet has a fixed size (148 bytes). After adding the junk, its size becomes 148 bytes + S1. +AmneziaWG also incorporates another trick for more reliable masking. Before initiating a session, Amnezia sends a +certain number of "junk" packets to thoroughly confuse DPI systems. The number of these packets and their +minimum and maximum byte sizes can also be adjusted in the settings, using parameters Jc, Jmin, and Jmax. +*/ +type WireGuardAdvancedSecurityOptions struct { + JunkPacketCount int `json:"junk_packet_count,omitempty"` // jc + JunkPacketMinSize int `json:"junk_packet_min_size,omitempty"` // jmin + JunkPacketMaxSize int `json:"junk_packet_max_size,omitempty"` // jmax + InitPacketJunkSize int `json:"init_packet_junk_size,omitempty"` // s1 + ResponsePacketJunkSize int `json:"response_packet_junk_size,omitempty"` // s2 + InitPacketMagicHeader uint32 `json:"init_packet_magic_header,omitempty"` // h1 + ResponsePacketMagicHeader uint32 `json:"response_packet_magic_header,omitempty"` // h2 + UnderloadPacketMagicHeader uint32 `json:"underload_packet_magic_header,omitempty"` // h3 + TransportPacketMagicHeader uint32 `json:"transport_packet_magic_header,omitempty"` // h4 +} + type WireGuardEndpointOptions struct { System bool `json:"system,omitempty"` Name string `json:"name,omitempty"` @@ -16,6 +39,7 @@ type WireGuardEndpointOptions struct { Peers []WireGuardPeer `json:"peers,omitempty"` UDPTimeout badoption.Duration `json:"udp_timeout,omitempty"` Workers int `json:"workers,omitempty"` + WireGuardAdvancedSecurityOptions DialerOptions } diff --git a/protocol/wireguard/endpoint.go b/protocol/wireguard/endpoint.go index e167bec1..474c4838 100644 --- a/protocol/wireguard/endpoint.go +++ b/protocol/wireguard/endpoint.go @@ -104,7 +104,8 @@ func NewEndpoint(ctx context.Context, router adapter.Router, logger log.ContextL Reserved: it.Reserved, } }), - Workers: options.Workers, + Workers: options.Workers, + WireGuardAdvancedSecurityOptions: options.WireGuardAdvancedSecurityOptions, }) if err != nil { return nil, err diff --git a/test/go.mod b/test/go.mod index 2baf3b41..6984026c 100644 --- a/test/go.mod +++ b/test/go.mod @@ -1,6 +1,6 @@ module test -go 1.23.1 +go 1.23.6 toolchain go1.24.0 @@ -30,7 +30,7 @@ require ( github.com/akutz/memconn v0.1.0 // indirect github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa // indirect github.com/andybalholm/brotli v1.1.0 // indirect - github.com/anytls/sing-anytls v0.0.2 // indirect + github.com/anytls/sing-anytls v0.0.5 // indirect github.com/bits-and-blooms/bitset v1.13.0 // indirect github.com/caddyserver/certmagic v0.21.7 // indirect github.com/caddyserver/zerossl v0.1.3 // indirect diff --git a/test/go.sum b/test/go.sum index d63f3057..0b57c4c6 100644 --- a/test/go.sum +++ b/test/go.sum @@ -14,6 +14,7 @@ github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1 github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= github.com/anytls/sing-anytls v0.0.2 h1:25azSh0o/LMcIkhS4ZutgRTIGwh8O3wuOhsThVM9K9o= github.com/anytls/sing-anytls v0.0.2/go.mod h1:7rjN6IukwysmdusYsrV51Fgu1uW6vsrdd6ctjnEAln8= +github.com/anytls/sing-anytls v0.0.5/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.21.7 h1:66KJioPFJwttL43KYSWk7ErSmE6LfaJgCQuhm8Sg6fg= diff --git a/transport/wireguard/endpoint.go b/transport/wireguard/endpoint.go index 69ce9170..77225bc3 100644 --- a/transport/wireguard/endpoint.go +++ b/transport/wireguard/endpoint.go @@ -47,6 +47,33 @@ func NewEndpoint(options EndpointOptions) (*Endpoint, error) { if options.ListenPort != 0 { ipcConf += "\nlisten_port=" + F.ToString(options.ListenPort) } + if options.JunkPacketCount > 0 { + ipcConf += "\njc=" + F.ToString(options.JunkPacketCount) + } + if options.JunkPacketMinSize > 0 { + ipcConf += "\njmin=" + F.ToString(options.JunkPacketMinSize) + } + if options.JunkPacketMaxSize > 0 { + ipcConf += "\njmax=" + F.ToString(options.JunkPacketMaxSize) + } + if options.InitPacketJunkSize > 0 { + ipcConf += "\ns1=" + F.ToString(options.InitPacketJunkSize) + } + if options.ResponsePacketJunkSize > 0 { + ipcConf += "\ns2=" + F.ToString(options.ResponsePacketJunkSize) + } + if options.InitPacketMagicHeader > 0 { + ipcConf += "\nh1=" + F.ToString(options.InitPacketMagicHeader) + } + if options.ResponsePacketMagicHeader > 0 { + ipcConf += "\nh2=" + F.ToString(options.ResponsePacketMagicHeader) + } + if options.UnderloadPacketMagicHeader > 0 { + ipcConf += "\nh3=" + F.ToString(options.UnderloadPacketMagicHeader) + } + if options.TransportPacketMagicHeader > 0 { + ipcConf += "\nh4=" + F.ToString(options.TransportPacketMagicHeader) + } var peers []peerConfig for peerIndex, rawPeer := range options.Peers { peer := peerConfig{ @@ -255,5 +282,6 @@ func (c peerConfig) GenerateIpcLines() string { if c.keepalive > 0 { ipcLines += "\npersistent_keepalive_interval=" + F.ToString(c.keepalive) } + return ipcLines } diff --git a/transport/wireguard/endpoint_options.go b/transport/wireguard/endpoint_options.go index bb9a46e6..aaf99dab 100644 --- a/transport/wireguard/endpoint_options.go +++ b/transport/wireguard/endpoint_options.go @@ -2,6 +2,7 @@ package wireguard import ( "context" + "github.com/sagernet/sing-box/option" "net/netip" "time" @@ -27,6 +28,7 @@ type EndpointOptions struct { ResolvePeer func(domain string) (netip.Addr, error) Peers []PeerOptions Workers int + option.WireGuardAdvancedSecurityOptions } type PeerOptions struct {