package main import ( "net/netip" "testing" C "github.com/sagernet/sing-box/constant" "github.com/sagernet/sing-box/option" "github.com/sagernet/sing-shadowsocks/shadowaead_2022" "github.com/gofrs/uuid/v5" ) func TestBrutalShadowsocks(t *testing.T) { method := shadowaead_2022.List[0] password := mkBase64(t, 16) startInstance(t, option.Options{ Inbounds: []option.Inbound{ { Type: C.TypeMixed, Tag: "mixed-in", MixedOptions: option.HTTPMixedInboundOptions{ ListenOptions: option.ListenOptions{ Listen: option.NewListenAddress(netip.IPv4Unspecified()), ListenPort: clientPort, }, }, }, { Type: C.TypeShadowsocks, ShadowsocksOptions: option.ShadowsocksInboundOptions{ ListenOptions: option.ListenOptions{ Listen: option.NewListenAddress(netip.IPv4Unspecified()), ListenPort: serverPort, }, Method: method, Password: password, Multiplex: &option.InboundMultiplexOptions{ Enabled: true, Brutal: &option.BrutalOptions{ Enabled: true, UpMbps: 100, DownMbps: 100, }, }, }, }, }, LegacyOutbounds: []option.LegacyOutbound{ { Type: C.TypeDirect, }, { Type: C.TypeShadowsocks, Tag: "ss-out", ShadowsocksOptions: option.ShadowsocksOutboundOptions{ ServerOptions: option.ServerOptions{ Server: "127.0.0.1", ServerPort: serverPort, }, Method: method, Password: password, Multiplex: &option.OutboundMultiplexOptions{ Enabled: true, Protocol: "smux", Padding: true, Brutal: &option.BrutalOptions{ Enabled: true, UpMbps: 100, DownMbps: 100, }, }, }, }, }, Route: &option.RouteOptions{ Rules: []option.Rule{ { Type: C.RuleTypeDefault, DefaultOptions: option.DefaultRule{ RawDefaultRule: option.RawDefaultRule{ Inbound: []string{"mixed-in"}, }, RuleAction: option.RuleAction{ Action: C.RuleActionTypeRoute, RouteOptions: option.RouteActionOptions{ Outbound: "ss-out", }, }, }, }, }, }, }) testSuit(t, clientPort, testPort) } func TestBrutalTrojan(t *testing.T) { _, certPem, keyPem := createSelfSignedCertificate(t, "example.org") password := mkBase64(t, 16) startInstance(t, option.Options{ Inbounds: []option.Inbound{ { Type: C.TypeMixed, Tag: "mixed-in", MixedOptions: option.HTTPMixedInboundOptions{ ListenOptions: option.ListenOptions{ Listen: option.NewListenAddress(netip.IPv4Unspecified()), ListenPort: clientPort, }, }, }, { Type: C.TypeTrojan, TrojanOptions: option.TrojanInboundOptions{ ListenOptions: option.ListenOptions{ Listen: option.NewListenAddress(netip.IPv4Unspecified()), ListenPort: serverPort, }, Users: []option.TrojanUser{{Password: password}}, Multiplex: &option.InboundMultiplexOptions{ Enabled: true, Brutal: &option.BrutalOptions{ Enabled: true, UpMbps: 100, DownMbps: 100, }, }, InboundTLSOptionsContainer: option.InboundTLSOptionsContainer{ TLS: &option.InboundTLSOptions{ Enabled: true, ServerName: "example.org", CertificatePath: certPem, KeyPath: keyPem, }, }, }, }, }, LegacyOutbounds: []option.LegacyOutbound{ { Type: C.TypeDirect, }, { Type: C.TypeTrojan, Tag: "ss-out", TrojanOptions: option.TrojanOutboundOptions{ ServerOptions: option.ServerOptions{ Server: "127.0.0.1", ServerPort: serverPort, }, Password: password, Multiplex: &option.OutboundMultiplexOptions{ Enabled: true, Protocol: "yamux", Padding: true, Brutal: &option.BrutalOptions{ Enabled: true, UpMbps: 100, DownMbps: 100, }, }, OutboundTLSOptionsContainer: option.OutboundTLSOptionsContainer{ TLS: &option.OutboundTLSOptions{ Enabled: true, ServerName: "example.org", CertificatePath: certPem, }, }, }, }, }, Route: &option.RouteOptions{ Rules: []option.Rule{ { Type: C.RuleTypeDefault, DefaultOptions: option.DefaultRule{ RawDefaultRule: option.RawDefaultRule{ Inbound: []string{"mixed-in"}, }, RuleAction: option.RuleAction{ Action: C.RuleActionTypeRoute, RouteOptions: option.RouteActionOptions{ Outbound: "ss-out", }, }, }, }, }, }, }) testSuit(t, clientPort, testPort) } func TestBrutalVMess(t *testing.T) { user, _ := uuid.NewV4() startInstance(t, option.Options{ Inbounds: []option.Inbound{ { Type: C.TypeMixed, Tag: "mixed-in", MixedOptions: option.HTTPMixedInboundOptions{ ListenOptions: option.ListenOptions{ Listen: option.NewListenAddress(netip.IPv4Unspecified()), ListenPort: clientPort, }, }, }, { Type: C.TypeVMess, VMessOptions: option.VMessInboundOptions{ ListenOptions: option.ListenOptions{ Listen: option.NewListenAddress(netip.IPv4Unspecified()), ListenPort: serverPort, }, Users: []option.VMessUser{{UUID: user.String()}}, Multiplex: &option.InboundMultiplexOptions{ Enabled: true, Brutal: &option.BrutalOptions{ Enabled: true, UpMbps: 100, DownMbps: 100, }, }, }, }, }, LegacyOutbounds: []option.LegacyOutbound{ { Type: C.TypeDirect, }, { Type: C.TypeVMess, Tag: "ss-out", VMessOptions: option.VMessOutboundOptions{ ServerOptions: option.ServerOptions{ Server: "127.0.0.1", ServerPort: serverPort, }, UUID: user.String(), Multiplex: &option.OutboundMultiplexOptions{ Enabled: true, Protocol: "h2mux", Padding: true, Brutal: &option.BrutalOptions{ Enabled: true, UpMbps: 100, DownMbps: 100, }, }, }, }, }, Route: &option.RouteOptions{ Rules: []option.Rule{ { Type: C.RuleTypeDefault, DefaultOptions: option.DefaultRule{ RawDefaultRule: option.RawDefaultRule{ Inbound: []string{"mixed-in"}, }, RuleAction: option.RuleAction{ Action: C.RuleActionTypeRoute, RouteOptions: option.RouteActionOptions{ Outbound: "ss-out", }, }, }, }, }, }, }) testSuit(t, clientPort, testPort) } func TestBrutalVLESS(t *testing.T) { user, _ := uuid.NewV4() startInstance(t, option.Options{ Inbounds: []option.Inbound{ { Type: C.TypeMixed, Tag: "mixed-in", MixedOptions: option.HTTPMixedInboundOptions{ ListenOptions: option.ListenOptions{ Listen: option.NewListenAddress(netip.IPv4Unspecified()), ListenPort: clientPort, }, }, }, { Type: C.TypeVLESS, VLESSOptions: option.VLESSInboundOptions{ ListenOptions: option.ListenOptions{ Listen: option.NewListenAddress(netip.IPv4Unspecified()), ListenPort: serverPort, }, Users: []option.VLESSUser{{UUID: user.String()}}, Multiplex: &option.InboundMultiplexOptions{ Enabled: true, Brutal: &option.BrutalOptions{ Enabled: true, UpMbps: 100, DownMbps: 100, }, }, InboundTLSOptionsContainer: option.InboundTLSOptionsContainer{ TLS: &option.InboundTLSOptions{ Enabled: true, ServerName: "google.com", Reality: &option.InboundRealityOptions{ Enabled: true, Handshake: option.InboundRealityHandshakeOptions{ ServerOptions: option.ServerOptions{ Server: "google.com", ServerPort: 443, }, }, ShortID: []string{"0123456789abcdef"}, PrivateKey: "UuMBgl7MXTPx9inmQp2UC7Jcnwc6XYbwDNebonM-FCc", }, }, }, }, }, }, LegacyOutbounds: []option.LegacyOutbound{ { Type: C.TypeDirect, }, { Type: C.TypeVLESS, Tag: "ss-out", VLESSOptions: option.VLESSOutboundOptions{ ServerOptions: option.ServerOptions{ Server: "127.0.0.1", ServerPort: serverPort, }, UUID: user.String(), OutboundTLSOptionsContainer: option.OutboundTLSOptionsContainer{ TLS: &option.OutboundTLSOptions{ Enabled: true, ServerName: "google.com", Reality: &option.OutboundRealityOptions{ Enabled: true, ShortID: "0123456789abcdef", PublicKey: "jNXHt1yRo0vDuchQlIP6Z0ZvjT3KtzVI-T4E7RoLJS0", }, UTLS: &option.OutboundUTLSOptions{ Enabled: true, }, }, }, Multiplex: &option.OutboundMultiplexOptions{ Enabled: true, Protocol: "h2mux", Padding: true, Brutal: &option.BrutalOptions{ Enabled: true, UpMbps: 100, DownMbps: 100, }, }, }, }, }, Route: &option.RouteOptions{ Rules: []option.Rule{ { Type: C.RuleTypeDefault, DefaultOptions: option.DefaultRule{ RawDefaultRule: option.RawDefaultRule{ Inbound: []string{"mixed-in"}, }, RuleAction: option.RuleAction{ Action: C.RuleActionTypeRoute, RouteOptions: option.RouteActionOptions{ Outbound: "ss-out", }, }, }, }, }, }, }) testSuit(t, clientPort, testPort) }