diff --git a/app/dispatcher/default.go b/app/dispatcher/default.go index 9652043e..4800f70b 100644 --- a/app/dispatcher/default.go +++ b/app/dispatcher/default.go @@ -2,7 +2,6 @@ package dispatcher import ( "context" - "regexp" "strings" "sync" "time" @@ -235,22 +234,8 @@ func (d *DefaultDispatcher) shouldOverride(ctx context.Context, result SniffResu if domain == "" { return false } - for _, d := range request.ExcludeForDomain { - if strings.HasPrefix(d, "regexp:") { - pattern := d[7:] - re, err := regexp.Compile(pattern) - if err != nil { - errors.LogInfo(ctx, "Unable to compile regex") - continue - } - if re.MatchString(domain) { - return false - } - } else { - if strings.ToLower(domain) == d { - return false - } - } + if request.ExcludeForDomain != nil && request.ExcludeForDomain.MatchAny(strings.ToLower(domain)) { + return false } protocolString := result.Protocol() if resComp, ok := result.(SnifferResultComposite); ok { diff --git a/app/proxyman/config.go b/app/proxyman/config.go index 871971aa..b5396cd1 100644 --- a/app/proxyman/config.go +++ b/app/proxyman/config.go @@ -1 +1,27 @@ package proxyman + +import ( + "github.com/xtls/xray-core/common/geodata" + "github.com/xtls/xray-core/common/session" +) + +func BuildSniffingRequest(config *SniffingConfig) (session.SniffingRequest, error) { + if config == nil { + return session.SniffingRequest{}, nil + } + + request := session.SniffingRequest{ + Enabled: config.Enabled, + OverrideDestinationForProtocol: config.DestinationOverride, + MetadataOnly: config.MetadataOnly, + RouteOnly: config.RouteOnly, + } + if len(config.DomainsExcluded) > 0 { + excludeForDomain, err := geodata.DomainReg.BuildDomainMatcher(config.DomainsExcluded) + if err != nil { + return session.SniffingRequest{}, err + } + request.ExcludeForDomain = excludeForDomain + } + return request, nil +} diff --git a/app/proxyman/config.pb.go b/app/proxyman/config.pb.go index 8b745a95..9bde2724 100644 --- a/app/proxyman/config.pb.go +++ b/app/proxyman/config.pb.go @@ -7,6 +7,7 @@ package proxyman import ( + geodata "github.com/xtls/xray-core/common/geodata" net "github.com/xtls/xray-core/common/net" serial "github.com/xtls/xray-core/common/serial" internet "github.com/xtls/xray-core/transport/internet" @@ -66,8 +67,8 @@ type SniffingConfig struct { Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"` // Override target destination if sniff'ed protocol is in the given list. // Supported values are "http", "tls", "fakedns". - DestinationOverride []string `protobuf:"bytes,2,rep,name=destination_override,json=destinationOverride,proto3" json:"destination_override,omitempty"` - DomainsExcluded []string `protobuf:"bytes,3,rep,name=domains_excluded,json=domainsExcluded,proto3" json:"domains_excluded,omitempty"` + DestinationOverride []string `protobuf:"bytes,2,rep,name=destination_override,json=destinationOverride,proto3" json:"destination_override,omitempty"` + DomainsExcluded []*geodata.DomainRule `protobuf:"bytes,3,rep,name=domains_excluded,json=domainsExcluded,proto3" json:"domains_excluded,omitempty"` // Whether should only try to sniff metadata without waiting for client input. // Can be used to support SMTP like protocol where server send the first // message. @@ -121,7 +122,7 @@ func (x *SniffingConfig) GetDestinationOverride() []string { return nil } -func (x *SniffingConfig) GetDomainsExcluded() []string { +func (x *SniffingConfig) GetDomainsExcluded() []*geodata.DomainRule { if x != nil { return x.DomainsExcluded } @@ -477,12 +478,12 @@ var File_app_proxyman_config_proto protoreflect.FileDescriptor const file_app_proxyman_config_proto_rawDesc = "" + "\n" + - "\x19app/proxyman/config.proto\x12\x11xray.app.proxyman\x1a\x18common/net/address.proto\x1a\x15common/net/port.proto\x1a\x1ftransport/internet/config.proto\x1a!common/serial/typed_message.proto\"\x0f\n" + - "\rInboundConfig\"\xcc\x01\n" + + "\x19app/proxyman/config.proto\x12\x11xray.app.proxyman\x1a\x18common/net/address.proto\x1a\x15common/net/port.proto\x1a\x1ftransport/internet/config.proto\x1a!common/serial/typed_message.proto\x1a\x1bcommon/geodata/geodat.proto\"\x0f\n" + + "\rInboundConfig\"\xed\x01\n" + "\x0eSniffingConfig\x12\x18\n" + "\aenabled\x18\x01 \x01(\bR\aenabled\x121\n" + - "\x14destination_override\x18\x02 \x03(\tR\x13destinationOverride\x12)\n" + - "\x10domains_excluded\x18\x03 \x03(\tR\x0fdomainsExcluded\x12#\n" + + "\x14destination_override\x18\x02 \x03(\tR\x13destinationOverride\x12J\n" + + "\x10domains_excluded\x18\x03 \x03(\v2\x1f.xray.common.geodata.DomainRuleR\x0fdomainsExcluded\x12#\n" + "\rmetadata_only\x18\x04 \x01(\bR\fmetadataOnly\x12\x1d\n" + "\n" + "route_only\x18\x05 \x01(\bR\trouteOnly\"\xe5\x02\n" + @@ -532,30 +533,32 @@ var file_app_proxyman_config_proto_goTypes = []any{ (*OutboundConfig)(nil), // 4: xray.app.proxyman.OutboundConfig (*SenderConfig)(nil), // 5: xray.app.proxyman.SenderConfig (*MultiplexingConfig)(nil), // 6: xray.app.proxyman.MultiplexingConfig - (*net.PortList)(nil), // 7: xray.common.net.PortList - (*net.IPOrDomain)(nil), // 8: xray.common.net.IPOrDomain - (*internet.StreamConfig)(nil), // 9: xray.transport.internet.StreamConfig - (*serial.TypedMessage)(nil), // 10: xray.common.serial.TypedMessage - (*internet.ProxyConfig)(nil), // 11: xray.transport.internet.ProxyConfig - (internet.DomainStrategy)(0), // 12: xray.transport.internet.DomainStrategy + (*geodata.DomainRule)(nil), // 7: xray.common.geodata.DomainRule + (*net.PortList)(nil), // 8: xray.common.net.PortList + (*net.IPOrDomain)(nil), // 9: xray.common.net.IPOrDomain + (*internet.StreamConfig)(nil), // 10: xray.transport.internet.StreamConfig + (*serial.TypedMessage)(nil), // 11: xray.common.serial.TypedMessage + (*internet.ProxyConfig)(nil), // 12: xray.transport.internet.ProxyConfig + (internet.DomainStrategy)(0), // 13: xray.transport.internet.DomainStrategy } var file_app_proxyman_config_proto_depIdxs = []int32{ - 7, // 0: xray.app.proxyman.ReceiverConfig.port_list:type_name -> xray.common.net.PortList - 8, // 1: xray.app.proxyman.ReceiverConfig.listen:type_name -> xray.common.net.IPOrDomain - 9, // 2: xray.app.proxyman.ReceiverConfig.stream_settings:type_name -> xray.transport.internet.StreamConfig - 1, // 3: xray.app.proxyman.ReceiverConfig.sniffing_settings:type_name -> xray.app.proxyman.SniffingConfig - 10, // 4: xray.app.proxyman.InboundHandlerConfig.receiver_settings:type_name -> xray.common.serial.TypedMessage - 10, // 5: xray.app.proxyman.InboundHandlerConfig.proxy_settings:type_name -> xray.common.serial.TypedMessage - 8, // 6: xray.app.proxyman.SenderConfig.via:type_name -> xray.common.net.IPOrDomain - 9, // 7: xray.app.proxyman.SenderConfig.stream_settings:type_name -> xray.transport.internet.StreamConfig - 11, // 8: xray.app.proxyman.SenderConfig.proxy_settings:type_name -> xray.transport.internet.ProxyConfig - 6, // 9: xray.app.proxyman.SenderConfig.multiplex_settings:type_name -> xray.app.proxyman.MultiplexingConfig - 12, // 10: xray.app.proxyman.SenderConfig.target_strategy:type_name -> xray.transport.internet.DomainStrategy - 11, // [11:11] is the sub-list for method output_type - 11, // [11:11] is the sub-list for method input_type - 11, // [11:11] is the sub-list for extension type_name - 11, // [11:11] is the sub-list for extension extendee - 0, // [0:11] is the sub-list for field type_name + 7, // 0: xray.app.proxyman.SniffingConfig.domains_excluded:type_name -> xray.common.geodata.DomainRule + 8, // 1: xray.app.proxyman.ReceiverConfig.port_list:type_name -> xray.common.net.PortList + 9, // 2: xray.app.proxyman.ReceiverConfig.listen:type_name -> xray.common.net.IPOrDomain + 10, // 3: xray.app.proxyman.ReceiverConfig.stream_settings:type_name -> xray.transport.internet.StreamConfig + 1, // 4: xray.app.proxyman.ReceiverConfig.sniffing_settings:type_name -> xray.app.proxyman.SniffingConfig + 11, // 5: xray.app.proxyman.InboundHandlerConfig.receiver_settings:type_name -> xray.common.serial.TypedMessage + 11, // 6: xray.app.proxyman.InboundHandlerConfig.proxy_settings:type_name -> xray.common.serial.TypedMessage + 9, // 7: xray.app.proxyman.SenderConfig.via:type_name -> xray.common.net.IPOrDomain + 10, // 8: xray.app.proxyman.SenderConfig.stream_settings:type_name -> xray.transport.internet.StreamConfig + 12, // 9: xray.app.proxyman.SenderConfig.proxy_settings:type_name -> xray.transport.internet.ProxyConfig + 6, // 10: xray.app.proxyman.SenderConfig.multiplex_settings:type_name -> xray.app.proxyman.MultiplexingConfig + 13, // 11: xray.app.proxyman.SenderConfig.target_strategy:type_name -> xray.transport.internet.DomainStrategy + 12, // [12:12] is the sub-list for method output_type + 12, // [12:12] is the sub-list for method input_type + 12, // [12:12] is the sub-list for extension type_name + 12, // [12:12] is the sub-list for extension extendee + 0, // [0:12] is the sub-list for field type_name } func init() { file_app_proxyman_config_proto_init() } diff --git a/app/proxyman/config.proto b/app/proxyman/config.proto index 4f1298b9..36944871 100644 --- a/app/proxyman/config.proto +++ b/app/proxyman/config.proto @@ -10,6 +10,7 @@ import "common/net/address.proto"; import "common/net/port.proto"; import "transport/internet/config.proto"; import "common/serial/typed_message.proto"; +import "common/geodata/geodat.proto"; message InboundConfig {} @@ -20,7 +21,8 @@ message SniffingConfig { // Override target destination if sniff'ed protocol is in the given list. // Supported values are "http", "tls", "fakedns". repeated string destination_override = 2; - repeated string domains_excluded = 3; + + repeated xray.common.geodata.DomainRule domains_excluded = 3; // Whether should only try to sniff metadata without waiting for client input. // Can be used to support SMTP like protocol where server send the first diff --git a/app/proxyman/inbound/always.go b/app/proxyman/inbound/always.go index 697e2c16..02b84198 100644 --- a/app/proxyman/inbound/always.go +++ b/app/proxyman/inbound/always.go @@ -53,18 +53,17 @@ type AlwaysOnInboundHandler struct { } func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig *proxyman.ReceiverConfig, proxyConfig interface{}) (*AlwaysOnInboundHandler, error) { + sniffingRequest, err := proxyman.BuildSniffingRequest(receiverConfig.SniffingSettings) + if err != nil { + return nil, err + } + // Set tag and sniffing config in context before creating proxy // This allows proxies like TUN to access these settings ctx = session.ContextWithInbound(ctx, &session.Inbound{Tag: tag}) if receiverConfig.SniffingSettings != nil { ctx = session.ContextWithContent(ctx, &session.Content{ - SniffingRequest: session.SniffingRequest{ - Enabled: receiverConfig.SniffingSettings.Enabled, - OverrideDestinationForProtocol: receiverConfig.SniffingSettings.DestinationOverride, - ExcludeForDomain: receiverConfig.SniffingSettings.DomainsExcluded, - MetadataOnly: receiverConfig.SniffingSettings.MetadataOnly, - RouteOnly: receiverConfig.SniffingSettings.RouteOnly, - }, + SniffingRequest: sniffingRequest, }) } rawProxy, err := common.CreateObject(ctx, proxyConfig) @@ -117,7 +116,7 @@ func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig * stream: mss, tag: tag, dispatcher: h.mux, - sniffingConfig: receiverConfig.SniffingSettings, + sniffingRequest: sniffingRequest, uplinkCounter: uplinkCounter, downlinkCounter: downlinkCounter, ctx: ctx, @@ -139,7 +138,7 @@ func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig * recvOrigDest: receiverConfig.ReceiveOriginalDestination, tag: tag, dispatcher: h.mux, - sniffingConfig: receiverConfig.SniffingSettings, + sniffingRequest: sniffingRequest, uplinkCounter: uplinkCounter, downlinkCounter: downlinkCounter, ctx: ctx, @@ -154,7 +153,7 @@ func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig * address: address, port: net.Port(port), dispatcher: h.mux, - sniffingConfig: receiverConfig.SniffingSettings, + sniffingRequest: sniffingRequest, uplinkCounter: uplinkCounter, downlinkCounter: downlinkCounter, stream: mss, diff --git a/app/proxyman/inbound/worker.go b/app/proxyman/inbound/worker.go index be671b02..1a7b769a 100644 --- a/app/proxyman/inbound/worker.go +++ b/app/proxyman/inbound/worker.go @@ -6,7 +6,6 @@ import ( "sync/atomic" "time" - "github.com/xtls/xray-core/app/proxyman" "github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common/buf" c "github.com/xtls/xray-core/common/ctx" @@ -43,7 +42,7 @@ type tcpWorker struct { recvOrigDest bool tag string dispatcher routing.Dispatcher - sniffingConfig *proxyman.SniffingConfig + sniffingRequest session.SniffingRequest uplinkCounter stats.Counter downlinkCounter stats.Counter @@ -118,13 +117,7 @@ func (w *tcpWorker) callback(conn stat.Connection) { }) content := new(session.Content) - if w.sniffingConfig != nil { - content.SniffingRequest.Enabled = w.sniffingConfig.Enabled - content.SniffingRequest.OverrideDestinationForProtocol = w.sniffingConfig.DestinationOverride - content.SniffingRequest.ExcludeForDomain = w.sniffingConfig.DomainsExcluded - content.SniffingRequest.MetadataOnly = w.sniffingConfig.MetadataOnly - content.SniffingRequest.RouteOnly = w.sniffingConfig.RouteOnly - } + content.SniffingRequest = w.sniffingRequest ctx = session.ContextWithContent(ctx, content) if err := w.proxy.Process(ctx, net.Network_TCP, conn, w.dispatcher); err != nil { @@ -275,7 +268,7 @@ type udpWorker struct { tag string stream *internet.MemoryStreamConfig dispatcher routing.Dispatcher - sniffingConfig *proxyman.SniffingConfig + sniffingRequest session.SniffingRequest uplinkCounter stats.Counter downlinkCounter stats.Counter @@ -365,13 +358,7 @@ func (w *udpWorker) callback(b *buf.Buffer, source net.Destination, originalDest Tag: w.tag, }) content := new(session.Content) - if w.sniffingConfig != nil { - content.SniffingRequest.Enabled = w.sniffingConfig.Enabled - content.SniffingRequest.OverrideDestinationForProtocol = w.sniffingConfig.DestinationOverride - content.SniffingRequest.ExcludeForDomain = w.sniffingConfig.DomainsExcluded - content.SniffingRequest.MetadataOnly = w.sniffingConfig.MetadataOnly - content.SniffingRequest.RouteOnly = w.sniffingConfig.RouteOnly - } + content.SniffingRequest = w.sniffingRequest ctx = session.ContextWithContent(ctx, content) if err := w.proxy.Process(ctx, net.Network_UDP, conn, w.dispatcher); err != nil { errors.LogInfoInner(ctx, err, "connection ends") @@ -487,7 +474,7 @@ type dsWorker struct { stream *internet.MemoryStreamConfig tag string dispatcher routing.Dispatcher - sniffingConfig *proxyman.SniffingConfig + sniffingRequest session.SniffingRequest uplinkCounter stats.Counter downlinkCounter stats.Counter @@ -517,13 +504,7 @@ func (w *dsWorker) callback(conn stat.Connection) { }) content := new(session.Content) - if w.sniffingConfig != nil { - content.SniffingRequest.Enabled = w.sniffingConfig.Enabled - content.SniffingRequest.OverrideDestinationForProtocol = w.sniffingConfig.DestinationOverride - content.SniffingRequest.ExcludeForDomain = w.sniffingConfig.DomainsExcluded - content.SniffingRequest.MetadataOnly = w.sniffingConfig.MetadataOnly - content.SniffingRequest.RouteOnly = w.sniffingConfig.RouteOnly - } + content.SniffingRequest = w.sniffingRequest ctx = session.ContextWithContent(ctx, content) if err := w.proxy.Process(ctx, net.Network_UNIX, conn, w.dispatcher); err != nil { diff --git a/common/session/session.go b/common/session/session.go index 7e0c0369..cec9f971 100644 --- a/common/session/session.go +++ b/common/session/session.go @@ -7,6 +7,7 @@ import ( c "github.com/xtls/xray-core/common/ctx" "github.com/xtls/xray-core/common/errors" + "github.com/xtls/xray-core/common/geodata" "github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/protocol" "github.com/xtls/xray-core/common/signal" @@ -78,7 +79,7 @@ type Outbound struct { // SniffingRequest controls the behavior of content sniffing. They are from inbound config. Read-only type SniffingRequest struct { - ExcludeForDomain []string + ExcludeForDomain geodata.DomainMatcher OverrideDestinationForProtocol []string Enabled bool MetadataOnly bool diff --git a/infra/conf/fakedns.go b/infra/conf/fakedns.go index 3aa20115..e22c483d 100644 --- a/infra/conf/fakedns.go +++ b/infra/conf/fakedns.go @@ -118,26 +118,17 @@ func (FakeDNSPostProcessingStage) Process(config *Config) error { } } - found := false - // Check if there is a Outbound with necessary sniffer on - var inbounds []InboundDetourConfig - - if len(config.InboundConfigs) > 0 { - inbounds = append(inbounds, config.InboundConfigs...) - } - for _, v := range inbounds { - if v.SniffingConfig != nil && v.SniffingConfig.Enabled && v.SniffingConfig.DestOverride != nil { - for _, dov := range *v.SniffingConfig.DestOverride { - if strings.EqualFold(dov, "fakedns") || strings.EqualFold(dov, "fakedns+others") { - found = true - break + // Check if there is a Inbound with necessary sniffer on + for _, v := range config.InboundConfigs { + if v.SniffingConfig != nil && v.SniffingConfig.Enabled { + for _, d := range v.SniffingConfig.DestOverride { + if strings.EqualFold(d, "fakedns") || strings.EqualFold(d, "fakedns+others") { + return nil } } } } - if !found { - errors.LogWarning(context.Background(), "Defined FakeDNS but haven't enabled FakeDNS destOverride at any inbound.") - } + errors.LogWarning(context.Background(), "Defined FakeDNS but haven't enabled FakeDNS destOverride at any inbound.") } return nil diff --git a/infra/conf/xray.go b/infra/conf/xray.go index fce642f0..a96da678 100644 --- a/infra/conf/xray.go +++ b/infra/conf/xray.go @@ -10,6 +10,7 @@ import ( "github.com/xtls/xray-core/app/proxyman" "github.com/xtls/xray-core/app/stats" "github.com/xtls/xray-core/common/errors" + "github.com/xtls/xray-core/common/geodata" "github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/serial" core "github.com/xtls/xray-core/core" @@ -51,38 +52,34 @@ var ( ) type SniffingConfig struct { - Enabled bool `json:"enabled"` - DestOverride *StringList `json:"destOverride"` - DomainsExcluded *StringList `json:"domainsExcluded"` - MetadataOnly bool `json:"metadataOnly"` - RouteOnly bool `json:"routeOnly"` + Enabled bool `json:"enabled"` + DestOverride StringList `json:"destOverride"` + DomainsExcluded StringList `json:"domainsExcluded"` + MetadataOnly bool `json:"metadataOnly"` + RouteOnly bool `json:"routeOnly"` } // Build implements Buildable. func (c *SniffingConfig) Build() (*proxyman.SniffingConfig, error) { var p []string - if c.DestOverride != nil { - for _, protocol := range *c.DestOverride { - switch strings.ToLower(protocol) { - case "http": - p = append(p, "http") - case "tls", "https", "ssl": - p = append(p, "tls") - case "quic": - p = append(p, "quic") - case "fakedns", "fakedns+others": - p = append(p, "fakedns") - default: - return nil, errors.New("unknown protocol: ", protocol) - } + for _, protocol := range c.DestOverride { + switch strings.ToLower(protocol) { + case "http": + p = append(p, "http") + case "tls", "https", "ssl": + p = append(p, "tls") + case "quic": + p = append(p, "quic") + case "fakedns", "fakedns+others": + p = append(p, "fakedns") + default: + return nil, errors.New("unknown protocol: ", protocol) } } - var d []string - if c.DomainsExcluded != nil { - for _, domain := range *c.DomainsExcluded { - d = append(d, strings.ToLower(domain)) - } + d, err := geodata.ParseDomainRules(c.DomainsExcluded, geodata.Domain_Substr) + if err != nil { + return nil, err } return &proxyman.SniffingConfig{ diff --git a/infra/conf/xray_test.go b/infra/conf/xray_test.go index a3a767f2..645c7cb1 100644 --- a/infra/conf/xray_test.go +++ b/infra/conf/xray_test.go @@ -158,6 +158,49 @@ func TestXrayConfig(t *testing.T) { }) } +func TestSniffingConfig_Build(t *testing.T) { + config := &SniffingConfig{ + Enabled: true, + DestOverride: StringList{"http", "tls"}, + DomainsExcluded: StringList{"full:api.example.com", "domain:blocked.example", "regexp:^test[0-9]+\\.internal$"}, + MetadataOnly: true, + RouteOnly: true, + } + + built, err := config.Build() + if err != nil { + t.Fatalf("SniffingConfig.Build() failed: %v", err) + } + + if !built.Enabled || !built.MetadataOnly || !built.RouteOnly { + t.Fatalf("SniffingConfig.Build() lost sniffing flags: %+v", built) + } + if len(built.DestinationOverride) != 2 { + t.Fatalf("SniffingConfig.Build() lost destination overrides: %+v", built.DestinationOverride) + } + if len(built.DomainsExcluded) != 3 { + t.Fatalf("SniffingConfig.Build() produced %d domain rules", len(built.DomainsExcluded)) + } + + want := []struct { + ruleType geodata.Domain_Type + value string + }{ + {ruleType: geodata.Domain_Full, value: "api.example.com"}, + {ruleType: geodata.Domain_Domain, value: "blocked.example"}, + {ruleType: geodata.Domain_Regex, value: "^test[0-9]+\\.internal$"}, + } + for i, tc := range want { + rule := built.DomainsExcluded[i].GetCustom() + if rule == nil { + t.Fatalf("SniffingConfig.Build() produced a non-custom rule at index %d", i) + } + if rule.Type != tc.ruleType || rule.Value != tc.value { + t.Fatalf("SniffingConfig.Build() produced wrong rule at index %d: got (%v, %q), want (%v, %q)", i, rule.Type, rule.Value, tc.ruleType, tc.value) + } + } +} + func TestMuxConfig_Build(t *testing.T) { tests := []struct { name string diff --git a/proxy/vless/outbound/outbound.go b/proxy/vless/outbound/outbound.go index 75e74fe0..12fa7569 100644 --- a/proxy/vless/outbound/outbound.go +++ b/proxy/vless/outbound/outbound.go @@ -12,6 +12,7 @@ import ( "unsafe" utls "github.com/refraction-networking/utls" + proxymanConfig "github.com/xtls/xray-core/app/proxyman" proxyman "github.com/xtls/xray-core/app/proxyman/outbound" "github.com/xtls/xray-core/app/reverse" "github.com/xtls/xray-core/common" @@ -102,14 +103,12 @@ func New(ctx context.Context, config *Config) (*Handler, error) { User: handler.server.User, // TODO: email }) if sc := a.Reverse.Sniffing; sc != nil && sc.Enabled { + request, err := proxymanConfig.BuildSniffingRequest(sc) + if err != nil { + return nil, errors.New("failed to build reverse sniffing request").Base(err).AtError() + } rvsCtx = session.ContextWithContent(rvsCtx, &session.Content{ - SniffingRequest: session.SniffingRequest{ - Enabled: sc.Enabled, - OverrideDestinationForProtocol: sc.DestinationOverride, - ExcludeForDomain: sc.DomainsExcluded, - MetadataOnly: sc.MetadataOnly, - RouteOnly: sc.RouteOnly, - }, + SniffingRequest: request, }) } handler.reverse = &Reverse{