diff --git a/examples/amnezia/client.json b/examples/amnezia/client.json index 1dd0c98a..c99bb515 100644 --- a/examples/amnezia/client.json +++ b/examples/amnezia/client.json @@ -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": " 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 diff --git a/go.sum b/go.sum index 5f9db4ba..dd61d5b2 100644 --- a/go.sum +++ b/go.sum @@ -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= @@ -201,6 +199,8 @@ github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854 h1:6uUiZcDRnZSAegryaUG 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= diff --git a/option/wireguard.go b/option/wireguard.go index f0b49181..f9e71a40 100644 --- a/option/wireguard.go +++ b/option/wireguard.go @@ -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"` } diff --git a/protocol/wireguard/endpoint.go b/protocol/wireguard/endpoint.go index f39927a8..7afd1c95 100644 --- a/protocol/wireguard/endpoint.go +++ b/protocol/wireguard/endpoint.go @@ -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{ diff --git a/protocol/wireguard/endpoint_warp.go b/protocol/wireguard/endpoint_warp.go index 24e129cc..80b53010 100644 --- a/protocol/wireguard/endpoint_warp.go +++ b/protocol/wireguard/endpoint_warp.go @@ -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) { diff --git a/protocol/wireguard/outbound.go b/protocol/wireguard/outbound.go index 28531c39..fc45655e 100644 --- a/protocol/wireguard/outbound.go +++ b/protocol/wireguard/outbound.go @@ -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{ diff --git a/transport/wireguard/endpoint.go b/transport/wireguard/endpoint.go index 903132e7..bde22eab 100644 --- a/transport/wireguard/endpoint.go +++ b/transport/wireguard/endpoint.go @@ -181,19 +181,71 @@ 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() } + logger.Errorf(ipcConf) err = wgDevice.IpcSet(ipcConf) if err != nil { return E.Cause(err, "setup wireguard: \n", ipcConf) diff --git a/transport/wireguard/endpoint_options.go b/transport/wireguard/endpoint_options.go index 46640c7b..a0a0a8c7 100644 --- a/transport/wireguard/endpoint_options.go +++ b/transport/wireguard/endpoint_options.go @@ -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 }