mirror of
https://github.com/XTLS/Xray-core.git
synced 2026-05-08 14:13:22 +00:00
Sniffing: domainsExcluded supports "geosite:" (#5927)
https://github.com/XTLS/Xray-core/pull/5927#issuecomment-4238238050 https://github.com/XTLS/Xray-core/pull/5927#issuecomment-4238119874
This commit is contained in:
@@ -2,7 +2,6 @@ package dispatcher
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"regexp"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@@ -235,22 +234,8 @@ func (d *DefaultDispatcher) shouldOverride(ctx context.Context, result SniffResu
|
|||||||
if domain == "" {
|
if domain == "" {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
for _, d := range request.ExcludeForDomain {
|
if request.ExcludeForDomain != nil && request.ExcludeForDomain.MatchAny(strings.ToLower(domain)) {
|
||||||
if strings.HasPrefix(d, "regexp:") {
|
return false
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
protocolString := result.Protocol()
|
protocolString := result.Protocol()
|
||||||
if resComp, ok := result.(SnifferResultComposite); ok {
|
if resComp, ok := result.(SnifferResultComposite); ok {
|
||||||
|
|||||||
@@ -1 +1,27 @@
|
|||||||
package proxyman
|
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
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
package proxyman
|
package proxyman
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
geodata "github.com/xtls/xray-core/common/geodata"
|
||||||
net "github.com/xtls/xray-core/common/net"
|
net "github.com/xtls/xray-core/common/net"
|
||||||
serial "github.com/xtls/xray-core/common/serial"
|
serial "github.com/xtls/xray-core/common/serial"
|
||||||
internet "github.com/xtls/xray-core/transport/internet"
|
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"`
|
Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"`
|
||||||
// Override target destination if sniff'ed protocol is in the given list.
|
// Override target destination if sniff'ed protocol is in the given list.
|
||||||
// Supported values are "http", "tls", "fakedns".
|
// Supported values are "http", "tls", "fakedns".
|
||||||
DestinationOverride []string `protobuf:"bytes,2,rep,name=destination_override,json=destinationOverride,proto3" json:"destination_override,omitempty"`
|
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"`
|
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.
|
// 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
|
// Can be used to support SMTP like protocol where server send the first
|
||||||
// message.
|
// message.
|
||||||
@@ -121,7 +122,7 @@ func (x *SniffingConfig) GetDestinationOverride() []string {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *SniffingConfig) GetDomainsExcluded() []string {
|
func (x *SniffingConfig) GetDomainsExcluded() []*geodata.DomainRule {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.DomainsExcluded
|
return x.DomainsExcluded
|
||||||
}
|
}
|
||||||
@@ -477,12 +478,12 @@ var File_app_proxyman_config_proto protoreflect.FileDescriptor
|
|||||||
|
|
||||||
const file_app_proxyman_config_proto_rawDesc = "" +
|
const file_app_proxyman_config_proto_rawDesc = "" +
|
||||||
"\n" +
|
"\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" +
|
"\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\"\xcc\x01\n" +
|
"\rInboundConfig\"\xed\x01\n" +
|
||||||
"\x0eSniffingConfig\x12\x18\n" +
|
"\x0eSniffingConfig\x12\x18\n" +
|
||||||
"\aenabled\x18\x01 \x01(\bR\aenabled\x121\n" +
|
"\aenabled\x18\x01 \x01(\bR\aenabled\x121\n" +
|
||||||
"\x14destination_override\x18\x02 \x03(\tR\x13destinationOverride\x12)\n" +
|
"\x14destination_override\x18\x02 \x03(\tR\x13destinationOverride\x12J\n" +
|
||||||
"\x10domains_excluded\x18\x03 \x03(\tR\x0fdomainsExcluded\x12#\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" +
|
"\rmetadata_only\x18\x04 \x01(\bR\fmetadataOnly\x12\x1d\n" +
|
||||||
"\n" +
|
"\n" +
|
||||||
"route_only\x18\x05 \x01(\bR\trouteOnly\"\xe5\x02\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
|
(*OutboundConfig)(nil), // 4: xray.app.proxyman.OutboundConfig
|
||||||
(*SenderConfig)(nil), // 5: xray.app.proxyman.SenderConfig
|
(*SenderConfig)(nil), // 5: xray.app.proxyman.SenderConfig
|
||||||
(*MultiplexingConfig)(nil), // 6: xray.app.proxyman.MultiplexingConfig
|
(*MultiplexingConfig)(nil), // 6: xray.app.proxyman.MultiplexingConfig
|
||||||
(*net.PortList)(nil), // 7: xray.common.net.PortList
|
(*geodata.DomainRule)(nil), // 7: xray.common.geodata.DomainRule
|
||||||
(*net.IPOrDomain)(nil), // 8: xray.common.net.IPOrDomain
|
(*net.PortList)(nil), // 8: xray.common.net.PortList
|
||||||
(*internet.StreamConfig)(nil), // 9: xray.transport.internet.StreamConfig
|
(*net.IPOrDomain)(nil), // 9: xray.common.net.IPOrDomain
|
||||||
(*serial.TypedMessage)(nil), // 10: xray.common.serial.TypedMessage
|
(*internet.StreamConfig)(nil), // 10: xray.transport.internet.StreamConfig
|
||||||
(*internet.ProxyConfig)(nil), // 11: xray.transport.internet.ProxyConfig
|
(*serial.TypedMessage)(nil), // 11: xray.common.serial.TypedMessage
|
||||||
(internet.DomainStrategy)(0), // 12: xray.transport.internet.DomainStrategy
|
(*internet.ProxyConfig)(nil), // 12: xray.transport.internet.ProxyConfig
|
||||||
|
(internet.DomainStrategy)(0), // 13: xray.transport.internet.DomainStrategy
|
||||||
}
|
}
|
||||||
var file_app_proxyman_config_proto_depIdxs = []int32{
|
var file_app_proxyman_config_proto_depIdxs = []int32{
|
||||||
7, // 0: xray.app.proxyman.ReceiverConfig.port_list:type_name -> xray.common.net.PortList
|
7, // 0: xray.app.proxyman.SniffingConfig.domains_excluded:type_name -> xray.common.geodata.DomainRule
|
||||||
8, // 1: xray.app.proxyman.ReceiverConfig.listen:type_name -> xray.common.net.IPOrDomain
|
8, // 1: xray.app.proxyman.ReceiverConfig.port_list:type_name -> xray.common.net.PortList
|
||||||
9, // 2: xray.app.proxyman.ReceiverConfig.stream_settings:type_name -> xray.transport.internet.StreamConfig
|
9, // 2: xray.app.proxyman.ReceiverConfig.listen:type_name -> xray.common.net.IPOrDomain
|
||||||
1, // 3: xray.app.proxyman.ReceiverConfig.sniffing_settings:type_name -> xray.app.proxyman.SniffingConfig
|
10, // 3: xray.app.proxyman.ReceiverConfig.stream_settings:type_name -> xray.transport.internet.StreamConfig
|
||||||
10, // 4: xray.app.proxyman.InboundHandlerConfig.receiver_settings:type_name -> xray.common.serial.TypedMessage
|
1, // 4: xray.app.proxyman.ReceiverConfig.sniffing_settings:type_name -> xray.app.proxyman.SniffingConfig
|
||||||
10, // 5: xray.app.proxyman.InboundHandlerConfig.proxy_settings:type_name -> xray.common.serial.TypedMessage
|
11, // 5: xray.app.proxyman.InboundHandlerConfig.receiver_settings:type_name -> xray.common.serial.TypedMessage
|
||||||
8, // 6: xray.app.proxyman.SenderConfig.via:type_name -> xray.common.net.IPOrDomain
|
11, // 6: xray.app.proxyman.InboundHandlerConfig.proxy_settings:type_name -> xray.common.serial.TypedMessage
|
||||||
9, // 7: xray.app.proxyman.SenderConfig.stream_settings:type_name -> xray.transport.internet.StreamConfig
|
9, // 7: xray.app.proxyman.SenderConfig.via:type_name -> xray.common.net.IPOrDomain
|
||||||
11, // 8: xray.app.proxyman.SenderConfig.proxy_settings:type_name -> xray.transport.internet.ProxyConfig
|
10, // 8: xray.app.proxyman.SenderConfig.stream_settings:type_name -> xray.transport.internet.StreamConfig
|
||||||
6, // 9: xray.app.proxyman.SenderConfig.multiplex_settings:type_name -> xray.app.proxyman.MultiplexingConfig
|
12, // 9: xray.app.proxyman.SenderConfig.proxy_settings:type_name -> xray.transport.internet.ProxyConfig
|
||||||
12, // 10: xray.app.proxyman.SenderConfig.target_strategy:type_name -> xray.transport.internet.DomainStrategy
|
6, // 10: xray.app.proxyman.SenderConfig.multiplex_settings:type_name -> xray.app.proxyman.MultiplexingConfig
|
||||||
11, // [11:11] is the sub-list for method output_type
|
13, // 11: xray.app.proxyman.SenderConfig.target_strategy:type_name -> xray.transport.internet.DomainStrategy
|
||||||
11, // [11:11] is the sub-list for method input_type
|
12, // [12:12] is the sub-list for method output_type
|
||||||
11, // [11:11] is the sub-list for extension type_name
|
12, // [12:12] is the sub-list for method input_type
|
||||||
11, // [11:11] is the sub-list for extension extendee
|
12, // [12:12] is the sub-list for extension type_name
|
||||||
0, // [0:11] is the sub-list for field 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() }
|
func init() { file_app_proxyman_config_proto_init() }
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import "common/net/address.proto";
|
|||||||
import "common/net/port.proto";
|
import "common/net/port.proto";
|
||||||
import "transport/internet/config.proto";
|
import "transport/internet/config.proto";
|
||||||
import "common/serial/typed_message.proto";
|
import "common/serial/typed_message.proto";
|
||||||
|
import "common/geodata/geodat.proto";
|
||||||
|
|
||||||
message InboundConfig {}
|
message InboundConfig {}
|
||||||
|
|
||||||
@@ -20,7 +21,8 @@ message SniffingConfig {
|
|||||||
// Override target destination if sniff'ed protocol is in the given list.
|
// Override target destination if sniff'ed protocol is in the given list.
|
||||||
// Supported values are "http", "tls", "fakedns".
|
// Supported values are "http", "tls", "fakedns".
|
||||||
repeated string destination_override = 2;
|
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.
|
// 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
|
// Can be used to support SMTP like protocol where server send the first
|
||||||
|
|||||||
@@ -53,18 +53,17 @@ type AlwaysOnInboundHandler struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig *proxyman.ReceiverConfig, proxyConfig interface{}) (*AlwaysOnInboundHandler, error) {
|
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
|
// Set tag and sniffing config in context before creating proxy
|
||||||
// This allows proxies like TUN to access these settings
|
// This allows proxies like TUN to access these settings
|
||||||
ctx = session.ContextWithInbound(ctx, &session.Inbound{Tag: tag})
|
ctx = session.ContextWithInbound(ctx, &session.Inbound{Tag: tag})
|
||||||
if receiverConfig.SniffingSettings != nil {
|
if receiverConfig.SniffingSettings != nil {
|
||||||
ctx = session.ContextWithContent(ctx, &session.Content{
|
ctx = session.ContextWithContent(ctx, &session.Content{
|
||||||
SniffingRequest: session.SniffingRequest{
|
SniffingRequest: sniffingRequest,
|
||||||
Enabled: receiverConfig.SniffingSettings.Enabled,
|
|
||||||
OverrideDestinationForProtocol: receiverConfig.SniffingSettings.DestinationOverride,
|
|
||||||
ExcludeForDomain: receiverConfig.SniffingSettings.DomainsExcluded,
|
|
||||||
MetadataOnly: receiverConfig.SniffingSettings.MetadataOnly,
|
|
||||||
RouteOnly: receiverConfig.SniffingSettings.RouteOnly,
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
rawProxy, err := common.CreateObject(ctx, proxyConfig)
|
rawProxy, err := common.CreateObject(ctx, proxyConfig)
|
||||||
@@ -117,7 +116,7 @@ func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig *
|
|||||||
stream: mss,
|
stream: mss,
|
||||||
tag: tag,
|
tag: tag,
|
||||||
dispatcher: h.mux,
|
dispatcher: h.mux,
|
||||||
sniffingConfig: receiverConfig.SniffingSettings,
|
sniffingRequest: sniffingRequest,
|
||||||
uplinkCounter: uplinkCounter,
|
uplinkCounter: uplinkCounter,
|
||||||
downlinkCounter: downlinkCounter,
|
downlinkCounter: downlinkCounter,
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
@@ -139,7 +138,7 @@ func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig *
|
|||||||
recvOrigDest: receiverConfig.ReceiveOriginalDestination,
|
recvOrigDest: receiverConfig.ReceiveOriginalDestination,
|
||||||
tag: tag,
|
tag: tag,
|
||||||
dispatcher: h.mux,
|
dispatcher: h.mux,
|
||||||
sniffingConfig: receiverConfig.SniffingSettings,
|
sniffingRequest: sniffingRequest,
|
||||||
uplinkCounter: uplinkCounter,
|
uplinkCounter: uplinkCounter,
|
||||||
downlinkCounter: downlinkCounter,
|
downlinkCounter: downlinkCounter,
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
@@ -154,7 +153,7 @@ func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig *
|
|||||||
address: address,
|
address: address,
|
||||||
port: net.Port(port),
|
port: net.Port(port),
|
||||||
dispatcher: h.mux,
|
dispatcher: h.mux,
|
||||||
sniffingConfig: receiverConfig.SniffingSettings,
|
sniffingRequest: sniffingRequest,
|
||||||
uplinkCounter: uplinkCounter,
|
uplinkCounter: uplinkCounter,
|
||||||
downlinkCounter: downlinkCounter,
|
downlinkCounter: downlinkCounter,
|
||||||
stream: mss,
|
stream: mss,
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import (
|
|||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/app/proxyman"
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/buf"
|
"github.com/xtls/xray-core/common/buf"
|
||||||
c "github.com/xtls/xray-core/common/ctx"
|
c "github.com/xtls/xray-core/common/ctx"
|
||||||
@@ -43,7 +42,7 @@ type tcpWorker struct {
|
|||||||
recvOrigDest bool
|
recvOrigDest bool
|
||||||
tag string
|
tag string
|
||||||
dispatcher routing.Dispatcher
|
dispatcher routing.Dispatcher
|
||||||
sniffingConfig *proxyman.SniffingConfig
|
sniffingRequest session.SniffingRequest
|
||||||
uplinkCounter stats.Counter
|
uplinkCounter stats.Counter
|
||||||
downlinkCounter stats.Counter
|
downlinkCounter stats.Counter
|
||||||
|
|
||||||
@@ -118,13 +117,7 @@ func (w *tcpWorker) callback(conn stat.Connection) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
content := new(session.Content)
|
content := new(session.Content)
|
||||||
if w.sniffingConfig != nil {
|
content.SniffingRequest = w.sniffingRequest
|
||||||
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
|
|
||||||
}
|
|
||||||
ctx = session.ContextWithContent(ctx, content)
|
ctx = session.ContextWithContent(ctx, content)
|
||||||
|
|
||||||
if err := w.proxy.Process(ctx, net.Network_TCP, conn, w.dispatcher); err != nil {
|
if err := w.proxy.Process(ctx, net.Network_TCP, conn, w.dispatcher); err != nil {
|
||||||
@@ -275,7 +268,7 @@ type udpWorker struct {
|
|||||||
tag string
|
tag string
|
||||||
stream *internet.MemoryStreamConfig
|
stream *internet.MemoryStreamConfig
|
||||||
dispatcher routing.Dispatcher
|
dispatcher routing.Dispatcher
|
||||||
sniffingConfig *proxyman.SniffingConfig
|
sniffingRequest session.SniffingRequest
|
||||||
uplinkCounter stats.Counter
|
uplinkCounter stats.Counter
|
||||||
downlinkCounter stats.Counter
|
downlinkCounter stats.Counter
|
||||||
|
|
||||||
@@ -365,13 +358,7 @@ func (w *udpWorker) callback(b *buf.Buffer, source net.Destination, originalDest
|
|||||||
Tag: w.tag,
|
Tag: w.tag,
|
||||||
})
|
})
|
||||||
content := new(session.Content)
|
content := new(session.Content)
|
||||||
if w.sniffingConfig != nil {
|
content.SniffingRequest = w.sniffingRequest
|
||||||
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
|
|
||||||
}
|
|
||||||
ctx = session.ContextWithContent(ctx, content)
|
ctx = session.ContextWithContent(ctx, content)
|
||||||
if err := w.proxy.Process(ctx, net.Network_UDP, conn, w.dispatcher); err != nil {
|
if err := w.proxy.Process(ctx, net.Network_UDP, conn, w.dispatcher); err != nil {
|
||||||
errors.LogInfoInner(ctx, err, "connection ends")
|
errors.LogInfoInner(ctx, err, "connection ends")
|
||||||
@@ -487,7 +474,7 @@ type dsWorker struct {
|
|||||||
stream *internet.MemoryStreamConfig
|
stream *internet.MemoryStreamConfig
|
||||||
tag string
|
tag string
|
||||||
dispatcher routing.Dispatcher
|
dispatcher routing.Dispatcher
|
||||||
sniffingConfig *proxyman.SniffingConfig
|
sniffingRequest session.SniffingRequest
|
||||||
uplinkCounter stats.Counter
|
uplinkCounter stats.Counter
|
||||||
downlinkCounter stats.Counter
|
downlinkCounter stats.Counter
|
||||||
|
|
||||||
@@ -517,13 +504,7 @@ func (w *dsWorker) callback(conn stat.Connection) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
content := new(session.Content)
|
content := new(session.Content)
|
||||||
if w.sniffingConfig != nil {
|
content.SniffingRequest = w.sniffingRequest
|
||||||
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
|
|
||||||
}
|
|
||||||
ctx = session.ContextWithContent(ctx, content)
|
ctx = session.ContextWithContent(ctx, content)
|
||||||
|
|
||||||
if err := w.proxy.Process(ctx, net.Network_UNIX, conn, w.dispatcher); err != nil {
|
if err := w.proxy.Process(ctx, net.Network_UNIX, conn, w.dispatcher); err != nil {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
|
|
||||||
c "github.com/xtls/xray-core/common/ctx"
|
c "github.com/xtls/xray-core/common/ctx"
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"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/net"
|
||||||
"github.com/xtls/xray-core/common/protocol"
|
"github.com/xtls/xray-core/common/protocol"
|
||||||
"github.com/xtls/xray-core/common/signal"
|
"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
|
// SniffingRequest controls the behavior of content sniffing. They are from inbound config. Read-only
|
||||||
type SniffingRequest struct {
|
type SniffingRequest struct {
|
||||||
ExcludeForDomain []string
|
ExcludeForDomain geodata.DomainMatcher
|
||||||
OverrideDestinationForProtocol []string
|
OverrideDestinationForProtocol []string
|
||||||
Enabled bool
|
Enabled bool
|
||||||
MetadataOnly bool
|
MetadataOnly bool
|
||||||
|
|||||||
@@ -118,26 +118,17 @@ func (FakeDNSPostProcessingStage) Process(config *Config) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
found := false
|
// Check if there is a Inbound with necessary sniffer on
|
||||||
// Check if there is a Outbound with necessary sniffer on
|
for _, v := range config.InboundConfigs {
|
||||||
var inbounds []InboundDetourConfig
|
if v.SniffingConfig != nil && v.SniffingConfig.Enabled {
|
||||||
|
for _, d := range v.SniffingConfig.DestOverride {
|
||||||
if len(config.InboundConfigs) > 0 {
|
if strings.EqualFold(d, "fakedns") || strings.EqualFold(d, "fakedns+others") {
|
||||||
inbounds = append(inbounds, config.InboundConfigs...)
|
return nil
|
||||||
}
|
|
||||||
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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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
|
return nil
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
"github.com/xtls/xray-core/app/proxyman"
|
"github.com/xtls/xray-core/app/proxyman"
|
||||||
"github.com/xtls/xray-core/app/stats"
|
"github.com/xtls/xray-core/app/stats"
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"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/net"
|
||||||
"github.com/xtls/xray-core/common/serial"
|
"github.com/xtls/xray-core/common/serial"
|
||||||
core "github.com/xtls/xray-core/core"
|
core "github.com/xtls/xray-core/core"
|
||||||
@@ -51,38 +52,34 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type SniffingConfig struct {
|
type SniffingConfig struct {
|
||||||
Enabled bool `json:"enabled"`
|
Enabled bool `json:"enabled"`
|
||||||
DestOverride *StringList `json:"destOverride"`
|
DestOverride StringList `json:"destOverride"`
|
||||||
DomainsExcluded *StringList `json:"domainsExcluded"`
|
DomainsExcluded StringList `json:"domainsExcluded"`
|
||||||
MetadataOnly bool `json:"metadataOnly"`
|
MetadataOnly bool `json:"metadataOnly"`
|
||||||
RouteOnly bool `json:"routeOnly"`
|
RouteOnly bool `json:"routeOnly"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build implements Buildable.
|
// Build implements Buildable.
|
||||||
func (c *SniffingConfig) Build() (*proxyman.SniffingConfig, error) {
|
func (c *SniffingConfig) Build() (*proxyman.SniffingConfig, error) {
|
||||||
var p []string
|
var p []string
|
||||||
if c.DestOverride != nil {
|
for _, protocol := range c.DestOverride {
|
||||||
for _, protocol := range *c.DestOverride {
|
switch strings.ToLower(protocol) {
|
||||||
switch strings.ToLower(protocol) {
|
case "http":
|
||||||
case "http":
|
p = append(p, "http")
|
||||||
p = append(p, "http")
|
case "tls", "https", "ssl":
|
||||||
case "tls", "https", "ssl":
|
p = append(p, "tls")
|
||||||
p = append(p, "tls")
|
case "quic":
|
||||||
case "quic":
|
p = append(p, "quic")
|
||||||
p = append(p, "quic")
|
case "fakedns", "fakedns+others":
|
||||||
case "fakedns", "fakedns+others":
|
p = append(p, "fakedns")
|
||||||
p = append(p, "fakedns")
|
default:
|
||||||
default:
|
return nil, errors.New("unknown protocol: ", protocol)
|
||||||
return nil, errors.New("unknown protocol: ", protocol)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var d []string
|
d, err := geodata.ParseDomainRules(c.DomainsExcluded, geodata.Domain_Substr)
|
||||||
if c.DomainsExcluded != nil {
|
if err != nil {
|
||||||
for _, domain := range *c.DomainsExcluded {
|
return nil, err
|
||||||
d = append(d, strings.ToLower(domain))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return &proxyman.SniffingConfig{
|
return &proxyman.SniffingConfig{
|
||||||
|
|||||||
@@ -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) {
|
func TestMuxConfig_Build(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
utls "github.com/refraction-networking/utls"
|
utls "github.com/refraction-networking/utls"
|
||||||
|
proxymanConfig "github.com/xtls/xray-core/app/proxyman"
|
||||||
proxyman "github.com/xtls/xray-core/app/proxyman/outbound"
|
proxyman "github.com/xtls/xray-core/app/proxyman/outbound"
|
||||||
"github.com/xtls/xray-core/app/reverse"
|
"github.com/xtls/xray-core/app/reverse"
|
||||||
"github.com/xtls/xray-core/common"
|
"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
|
User: handler.server.User, // TODO: email
|
||||||
})
|
})
|
||||||
if sc := a.Reverse.Sniffing; sc != nil && sc.Enabled {
|
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{
|
rvsCtx = session.ContextWithContent(rvsCtx, &session.Content{
|
||||||
SniffingRequest: session.SniffingRequest{
|
SniffingRequest: request,
|
||||||
Enabled: sc.Enabled,
|
|
||||||
OverrideDestinationForProtocol: sc.DestinationOverride,
|
|
||||||
ExcludeForDomain: sc.DomainsExcluded,
|
|
||||||
MetadataOnly: sc.MetadataOnly,
|
|
||||||
RouteOnly: sc.RouteOnly,
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
handler.reverse = &Reverse{
|
handler.reverse = &Reverse{
|
||||||
|
|||||||
Reference in New Issue
Block a user