Răsfoiți Sursa

Feat: sniffer exclude domain & ip

JimhHan 5 ani în urmă
părinte
comite
06fc82bad1

+ 18 - 2
app/dispatcher/default.go

@@ -178,8 +178,8 @@ func (d *DefaultDispatcher) getLink(ctx context.Context) (*transport.Link, *tran
 
 func shouldOverride(ctx context.Context, result SniffResult, request session.SniffingRequest, destination net.Destination) bool {
 	domain := result.Domain()
-	for _, d := range request.ExcludeForDomain {
-		if domain == d {
+	if request.ExcludedDomainMatcher != nil {
+		if request.ExcludedDomainMatcher.ApplyDomain(domain) {
 			return false
 		}
 	}
@@ -205,6 +205,16 @@ func shouldOverride(ctx context.Context, result SniffResult, request session.Sni
 	return false
 }
 
+func canSniff(ctx context.Context, req session.SniffingRequest, destination net.Destination) bool {
+	if destination.Address.Family().IsIP() && req.ExcludedIPMatcher != nil {
+		if req.ExcludedIPMatcher.MatchIP(destination.Address.IP()) {
+			return false
+		}
+	}
+
+	return true
+}
+
 // Dispatch implements routing.Dispatcher.
 func (d *DefaultDispatcher) Dispatch(ctx context.Context, destination net.Destination) (*transport.Link, error) {
 	if !destination.IsValid() {
@@ -222,6 +232,12 @@ func (d *DefaultDispatcher) Dispatch(ctx context.Context, destination net.Destin
 		ctx = session.ContextWithContent(ctx, content)
 	}
 	sniffingRequest := content.SniffingRequest
+
+	if !canSniff(ctx, sniffingRequest, destination) {
+		newError("skip sniffing for ip ", destination.Address.String()).AtDebug().WriteToLog()
+		sniffingRequest.Enabled = false
+	}
+
 	switch {
 	case !sniffingRequest.Enabled:
 		go d.routedDispatch(ctx, outbound, destination)

+ 32 - 0
app/proxyman/config.go

@@ -1,5 +1,12 @@
 package proxyman
 
+import (
+	"github.com/xtls/xray-core/common/matcher/domain"
+	"github.com/xtls/xray-core/common/matcher/geoip"
+)
+
+//go:generate go run github.com/xtls/xray-core/common/errors/errorgen
+
 func (s *AllocationStrategy) GetConcurrencyValue() uint32 {
 	if s == nil || s.Concurrency == nil {
 		return 3
@@ -37,3 +44,28 @@ func (c *ReceiverConfig) GetEffectiveSniffingSettings() *SniffingConfig {
 
 	return nil
 }
+
+type SniffingMatcher struct {
+	ExDomain *domain.DomainMatcher
+	ExIP     *geoip.MultiGeoIPMatcher
+}
+
+func NewSniffingMatcher(sc *SniffingConfig) (*SniffingMatcher, error) {
+	m := new(SniffingMatcher)
+
+	if sc.DomainsExcluded != nil {
+		exDomain, err := domain.NewDomainMatcher(sc.DomainsExcluded)
+		if err != nil {
+			return nil, newError("failed to parse domain").Base(err)
+		}
+		m.ExDomain = exDomain
+	}
+	if sc.IpsExcluded != nil {
+		exIP, err := geoip.NewMultiGeoIPMatcher(sc.IpsExcluded, true)
+		if err != nil {
+			return nil, newError("failed to parse ip").Base(err)
+		}
+		m.ExIP = exIP
+	}
+	return m, nil
+}

+ 174 - 149
app/proxyman/config.pb.go

@@ -1,13 +1,15 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
 // 	protoc-gen-go v1.25.0
-// 	protoc        (unknown)
+// 	protoc        v3.15.6
 // source: app/proxyman/config.proto
 
 package proxyman
 
 import (
 	proto "github.com/golang/protobuf/proto"
+	domain "github.com/xtls/xray-core/common/matcher/domain"
+	geoip "github.com/xtls/xray-core/common/matcher/geoip"
 	net "github.com/xtls/xray-core/common/net"
 	serial "github.com/xtls/xray-core/common/serial"
 	internet "github.com/xtls/xray-core/transport/internet"
@@ -240,8 +242,9 @@ 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     []*domain.Domain `protobuf:"bytes,3,rep,name=domains_excluded,json=domainsExcluded,proto3" json:"domains_excluded,omitempty"`
+	IpsExcluded         []*geoip.GeoIP   `protobuf:"bytes,5,rep,name=ips_excluded,json=ipsExcluded,proto3" json:"ips_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.
 	MetadataOnly bool `protobuf:"varint,4,opt,name=metadata_only,json=metadataOnly,proto3" json:"metadata_only,omitempty"`
@@ -293,13 +296,20 @@ func (x *SniffingConfig) GetDestinationOverride() []string {
 	return nil
 }
 
-func (x *SniffingConfig) GetDomainsExcluded() []string {
+func (x *SniffingConfig) GetDomainsExcluded() []*domain.Domain {
 	if x != nil {
 		return x.DomainsExcluded
 	}
 	return nil
 }
 
+func (x *SniffingConfig) GetIpsExcluded() []*geoip.GeoIP {
+	if x != nil {
+		return x.IpsExcluded
+	}
+	return nil
+}
+
 func (x *SniffingConfig) GetMetadataOnly() bool {
 	if x != nil {
 		return x.MetadataOnly
@@ -738,133 +748,144 @@ var File_app_proxyman_config_proto protoreflect.FileDescriptor
 var file_app_proxyman_config_proto_rawDesc = []byte{
 	0x0a, 0x19, 0x61, 0x70, 0x70, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2f, 0x63,
 	0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x11, 0x78, 0x72, 0x61,
-	0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x1a, 0x18,
-	0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6e, 0x65, 0x74, 0x2f, 0x61, 0x64, 0x64, 0x72, 0x65,
-	0x73, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x15, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e,
-	0x2f, 0x6e, 0x65, 0x74, 0x2f, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a,
-	0x1f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72,
-	0x6e, 0x65, 0x74, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-	0x1a, 0x21, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2f,
-	0x74, 0x79, 0x70, 0x65, 0x64, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x70, 0x72,
-	0x6f, 0x74, 0x6f, 0x22, 0x0f, 0x0a, 0x0d, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f,
-	0x6e, 0x66, 0x69, 0x67, 0x22, 0xae, 0x03, 0x0a, 0x12, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74,
-	0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x3e, 0x0a, 0x04, 0x74,
-	0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2a, 0x2e, 0x78, 0x72, 0x61, 0x79,
+	0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x1a, 0x22,
+	0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2f, 0x64,
+	0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x2f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x70, 0x72, 0x6f,
+	0x74, 0x6f, 0x1a, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6d, 0x61, 0x74, 0x63, 0x68,
+	0x65, 0x72, 0x2f, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x2f, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x2e, 0x70,
+	0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x18, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6e, 0x65, 0x74,
+	0x2f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x15,
+	0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6e, 0x65, 0x74, 0x2f, 0x70, 0x6f, 0x72, 0x74, 0x2e,
+	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74,
+	0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
+	0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x21, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x73,
+	0x65, 0x72, 0x69, 0x61, 0x6c, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x64, 0x5f, 0x6d, 0x65, 0x73, 0x73,
+	0x61, 0x67, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x0f, 0x0a, 0x0d, 0x49, 0x6e, 0x62,
+	0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0xae, 0x03, 0x0a, 0x12, 0x41,
+	0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67,
+	0x79, 0x12, 0x3e, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32,
+	0x2a, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79,
+	0x6d, 0x61, 0x6e, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74,
+	0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70,
+	0x65, 0x12, 0x65, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79,
+	0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x43, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
+	0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x63,
+	0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x2e, 0x41, 0x6c,
+	0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79,
+	0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x0b, 0x63, 0x6f, 0x6e,
+	0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x59, 0x0a, 0x07, 0x72, 0x65, 0x66, 0x72,
+	0x65, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x78, 0x72, 0x61, 0x79,
 	0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x41, 0x6c,
 	0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79,
-	0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x65, 0x0a, 0x0b, 0x63,
-	0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
-	0x32, 0x43, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78,
-	0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53,
-	0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69,
-	0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72,
-	0x72, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e,
-	0x63, 0x79, 0x12, 0x59, 0x0a, 0x07, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x18, 0x03, 0x20,
-	0x01, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70,
-	0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69,
-	0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x63,
-	0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x65, 0x66,
-	0x72, 0x65, 0x73, 0x68, 0x52, 0x07, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x1a, 0x35, 0x0a,
-	0x1d, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74,
-	0x65, 0x67, 0x79, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x14,
-	0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x76,
-	0x61, 0x6c, 0x75, 0x65, 0x1a, 0x31, 0x0a, 0x19, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69,
-	0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73,
-	0x68, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d,
-	0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x2c, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12,
-	0x0a, 0x0a, 0x06, 0x41, 0x6c, 0x77, 0x61, 0x79, 0x73, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x52,
-	0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x45, 0x78, 0x74, 0x65, 0x72,
-	0x6e, 0x61, 0x6c, 0x10, 0x02, 0x22, 0xad, 0x01, 0x0a, 0x0e, 0x53, 0x6e, 0x69, 0x66, 0x66, 0x69,
-	0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62,
-	0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c,
-	0x65, 0x64, 0x12, 0x31, 0x0a, 0x14, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f,
-	0x6e, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09,
-	0x52, 0x13, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x76, 0x65,
-	0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73,
-	0x5f, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52,
-	0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x45, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64,
-	0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x6f, 0x6e, 0x6c,
-	0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74,
-	0x61, 0x4f, 0x6e, 0x6c, 0x79, 0x22, 0x90, 0x04, 0x0a, 0x0e, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76,
-	0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x39, 0x0a, 0x0a, 0x70, 0x6f, 0x72, 0x74,
-	0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x78,
-	0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x50,
-	0x6f, 0x72, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x09, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x61,
-	0x6e, 0x67, 0x65, 0x12, 0x33, 0x0a, 0x06, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x18, 0x02, 0x20,
-	0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f,
-	0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x49, 0x50, 0x4f, 0x72, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e,
-	0x52, 0x06, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x12, 0x56, 0x0a, 0x13, 0x61, 0x6c, 0x6c, 0x6f,
-	0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18,
-	0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70,
-	0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61,
-	0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x12, 0x61, 0x6c,
+	0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74,
+	0x65, 0x67, 0x79, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x52, 0x07, 0x72, 0x65, 0x66, 0x72,
+	0x65, 0x73, 0x68, 0x1a, 0x35, 0x0a, 0x1d, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f,
+	0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72,
+	0x65, 0x6e, 0x63, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20,
+	0x01, 0x28, 0x0d, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x31, 0x0a, 0x19, 0x41, 0x6c,
 	0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79,
-	0x12, 0x4e, 0x0a, 0x0f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69,
-	0x6e, 0x67, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79,
-	0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72,
-	0x6e, 0x65, 0x74, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
-	0x52, 0x0e, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73,
-	0x12, 0x40, 0x0a, 0x1c, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x5f, 0x6f, 0x72, 0x69, 0x67,
-	0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e,
-	0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1a, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x4f,
-	0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69,
-	0x6f, 0x6e, 0x12, 0x4e, 0x0a, 0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x6f, 0x76, 0x65,
-	0x72, 0x72, 0x69, 0x64, 0x65, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x21, 0x2e, 0x78, 0x72,
-	0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e,
-	0x4b, 0x6e, 0x6f, 0x77, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x42, 0x02,
-	0x18, 0x01, 0x52, 0x0e, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69,
-	0x64, 0x65, 0x12, 0x4e, 0x0a, 0x11, 0x73, 0x6e, 0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x5f, 0x73,
-	0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e,
-	0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61,
-	0x6e, 0x2e, 0x53, 0x6e, 0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
-	0x52, 0x10, 0x73, 0x6e, 0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e,
-	0x67, 0x73, 0x4a, 0x04, 0x08, 0x06, 0x10, 0x07, 0x22, 0xc0, 0x01, 0x0a, 0x14, 0x49, 0x6e, 0x62,
-	0x6f, 0x75, 0x6e, 0x64, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69,
-	0x67, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03,
-	0x74, 0x61, 0x67, 0x12, 0x4d, 0x0a, 0x11, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x5f,
-	0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20,
-	0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x72,
-	0x69, 0x61, 0x6c, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
-	0x52, 0x10, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e,
-	0x67, 0x73, 0x12, 0x47, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x73, 0x65, 0x74, 0x74,
-	0x69, 0x6e, 0x67, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61,
-	0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e,
-	0x54, 0x79, 0x70, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x0d, 0x70, 0x72,
-	0x6f, 0x78, 0x79, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x10, 0x0a, 0x0e, 0x4f,
-	0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0xb0, 0x02,
-	0x0a, 0x0c, 0x53, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2d,
-	0x0a, 0x03, 0x76, 0x69, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x78, 0x72,
-	0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x49, 0x50,
-	0x4f, 0x72, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x03, 0x76, 0x69, 0x61, 0x12, 0x4e, 0x0a,
-	0x0f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73,
-	0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72,
-	0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74,
-	0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0e, 0x73,
-	0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x4b, 0x0a,
-	0x0e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18,
-	0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61,
-	0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e,
-	0x50, 0x72, 0x6f, 0x78, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0d, 0x70, 0x72, 0x6f,
-	0x78, 0x79, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x54, 0x0a, 0x12, 0x6d, 0x75,
-	0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73,
-	0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
-	0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x4d, 0x75, 0x6c, 0x74, 0x69,
-	0x70, 0x6c, 0x65, 0x78, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x11, 0x6d,
-	0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73,
-	0x22, 0x50, 0x0a, 0x12, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, 0x69, 0x6e, 0x67,
-	0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65,
-	0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64,
-	0x12, 0x20, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18,
-	0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e,
-	0x63, 0x79, 0x2a, 0x23, 0x0a, 0x0e, 0x4b, 0x6e, 0x6f, 0x77, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f,
-	0x63, 0x6f, 0x6c, 0x73, 0x12, 0x08, 0x0a, 0x04, 0x48, 0x54, 0x54, 0x50, 0x10, 0x00, 0x12, 0x07,
-	0x0a, 0x03, 0x54, 0x4c, 0x53, 0x10, 0x01, 0x42, 0x55, 0x0a, 0x15, 0x63, 0x6f, 0x6d, 0x2e, 0x78,
+	0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
+	0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x2c, 0x0a,
+	0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0a, 0x0a, 0x06, 0x41, 0x6c, 0x77, 0x61, 0x79, 0x73, 0x10,
+	0x00, 0x12, 0x0a, 0x0a, 0x06, 0x52, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x10, 0x01, 0x12, 0x0c, 0x0a,
+	0x08, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x10, 0x02, 0x22, 0x96, 0x02, 0x0a, 0x0e,
+	0x53, 0x6e, 0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18,
+	0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52,
+	0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x31, 0x0a, 0x14, 0x64, 0x65, 0x73, 0x74,
+	0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65,
+	0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x13, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74,
+	0x69, 0x6f, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x4d, 0x0a, 0x10, 0x64,
+	0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x5f, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64, 0x18,
+	0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d,
+	0x6d, 0x6f, 0x6e, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x64, 0x6f, 0x6d, 0x61,
+	0x69, 0x6e, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69,
+	0x6e, 0x73, 0x45, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64, 0x12, 0x43, 0x0a, 0x0c, 0x69, 0x70,
+	0x73, 0x5f, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b,
+	0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6d,
+	0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x2e, 0x47, 0x65, 0x6f,
+	0x49, 0x50, 0x52, 0x0b, 0x69, 0x70, 0x73, 0x45, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64, 0x12,
+	0x23, 0x0a, 0x0d, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x6f, 0x6e, 0x6c, 0x79,
+	0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
+	0x4f, 0x6e, 0x6c, 0x79, 0x22, 0x90, 0x04, 0x0a, 0x0e, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65,
+	0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x39, 0x0a, 0x0a, 0x70, 0x6f, 0x72, 0x74, 0x5f,
+	0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x78, 0x72,
+	0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x50, 0x6f,
+	0x72, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x09, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x61, 0x6e,
+	0x67, 0x65, 0x12, 0x33, 0x0a, 0x06, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01,
+	0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e,
+	0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x49, 0x50, 0x4f, 0x72, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52,
+	0x06, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x12, 0x56, 0x0a, 0x13, 0x61, 0x6c, 0x6c, 0x6f, 0x63,
+	0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x03,
+	0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e,
+	0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74,
+	0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x12, 0x61, 0x6c, 0x6c,
+	0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12,
+	0x4e, 0x0a, 0x0f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e,
+	0x67, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
+	0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e,
+	0x65, 0x74, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52,
+	0x0e, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12,
+	0x40, 0x0a, 0x1c, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x5f, 0x6f, 0x72, 0x69, 0x67, 0x69,
+	0x6e, 0x61, 0x6c, 0x5f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18,
+	0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1a, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x4f, 0x72,
+	0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f,
+	0x6e, 0x12, 0x4e, 0x0a, 0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x6f, 0x76, 0x65, 0x72,
+	0x72, 0x69, 0x64, 0x65, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x21, 0x2e, 0x78, 0x72, 0x61,
+	0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x4b,
+	0x6e, 0x6f, 0x77, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x42, 0x02, 0x18,
+	0x01, 0x52, 0x0e, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64,
+	0x65, 0x12, 0x4e, 0x0a, 0x11, 0x73, 0x6e, 0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x65,
+	0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x78,
 	0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e,
-	0x50, 0x01, 0x5a, 0x26, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78,
-	0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70,
-	0x70, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0xaa, 0x02, 0x11, 0x58, 0x72, 0x61,
-	0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x62, 0x06,
-	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+	0x2e, 0x53, 0x6e, 0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52,
+	0x10, 0x73, 0x6e, 0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67,
+	0x73, 0x4a, 0x04, 0x08, 0x06, 0x10, 0x07, 0x22, 0xc0, 0x01, 0x0a, 0x14, 0x49, 0x6e, 0x62, 0x6f,
+	0x75, 0x6e, 0x64, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
+	0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74,
+	0x61, 0x67, 0x12, 0x4d, 0x0a, 0x11, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x5f, 0x73,
+	0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e,
+	0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x72, 0x69,
+	0x61, 0x6c, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52,
+	0x10, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67,
+	0x73, 0x12, 0x47, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69,
+	0x6e, 0x67, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79,
+	0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x54,
+	0x79, 0x70, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x0d, 0x70, 0x72, 0x6f,
+	0x78, 0x79, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x10, 0x0a, 0x0e, 0x4f, 0x75,
+	0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0xb0, 0x02, 0x0a,
+	0x0c, 0x53, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2d, 0x0a,
+	0x03, 0x76, 0x69, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x78, 0x72, 0x61,
+	0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x49, 0x50, 0x4f,
+	0x72, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x03, 0x76, 0x69, 0x61, 0x12, 0x4e, 0x0a, 0x0f,
+	0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18,
+	0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61,
+	0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e,
+	0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0e, 0x73, 0x74,
+	0x72, 0x65, 0x61, 0x6d, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x4b, 0x0a, 0x0e,
+	0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x03,
+	0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e,
+	0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x50,
+	0x72, 0x6f, 0x78, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78,
+	0x79, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x54, 0x0a, 0x12, 0x6d, 0x75, 0x6c,
+	0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18,
+	0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70,
+	0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70,
+	0x6c, 0x65, 0x78, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x11, 0x6d, 0x75,
+	0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x22,
+	0x50, 0x0a, 0x12, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, 0x69, 0x6e, 0x67, 0x43,
+	0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64,
+	0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12,
+	0x20, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x02,
+	0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63,
+	0x79, 0x2a, 0x23, 0x0a, 0x0e, 0x4b, 0x6e, 0x6f, 0x77, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63,
+	0x6f, 0x6c, 0x73, 0x12, 0x08, 0x0a, 0x04, 0x48, 0x54, 0x54, 0x50, 0x10, 0x00, 0x12, 0x07, 0x0a,
+	0x03, 0x54, 0x4c, 0x53, 0x10, 0x01, 0x42, 0x55, 0x0a, 0x15, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72,
+	0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x50,
+	0x01, 0x5a, 0x26, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74,
+	0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70, 0x70,
+	0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0xaa, 0x02, 0x11, 0x58, 0x72, 0x61, 0x79,
+	0x2e, 0x41, 0x70, 0x70, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x62, 0x06, 0x70,
+	0x72, 0x6f, 0x74, 0x6f, 0x33,
 }
 
 var (
@@ -894,33 +915,37 @@ var file_app_proxyman_config_proto_goTypes = []interface{}{
 	(*MultiplexingConfig)(nil),                               // 9: xray.app.proxyman.MultiplexingConfig
 	(*AllocationStrategy_AllocationStrategyConcurrency)(nil), // 10: xray.app.proxyman.AllocationStrategy.AllocationStrategyConcurrency
 	(*AllocationStrategy_AllocationStrategyRefresh)(nil),     // 11: xray.app.proxyman.AllocationStrategy.AllocationStrategyRefresh
-	(*net.PortRange)(nil),                                    // 12: xray.common.net.PortRange
-	(*net.IPOrDomain)(nil),                                   // 13: xray.common.net.IPOrDomain
-	(*internet.StreamConfig)(nil),                            // 14: xray.transport.internet.StreamConfig
-	(*serial.TypedMessage)(nil),                              // 15: xray.common.serial.TypedMessage
-	(*internet.ProxyConfig)(nil),                             // 16: xray.transport.internet.ProxyConfig
+	(*domain.Domain)(nil),                                    // 12: xray.common.matcher.domain.Domain
+	(*geoip.GeoIP)(nil),                                      // 13: xray.common.matcher.geoip.GeoIP
+	(*net.PortRange)(nil),                                    // 14: xray.common.net.PortRange
+	(*net.IPOrDomain)(nil),                                   // 15: xray.common.net.IPOrDomain
+	(*internet.StreamConfig)(nil),                            // 16: xray.transport.internet.StreamConfig
+	(*serial.TypedMessage)(nil),                              // 17: xray.common.serial.TypedMessage
+	(*internet.ProxyConfig)(nil),                             // 18: xray.transport.internet.ProxyConfig
 }
 var file_app_proxyman_config_proto_depIdxs = []int32{
 	1,  // 0: xray.app.proxyman.AllocationStrategy.type:type_name -> xray.app.proxyman.AllocationStrategy.Type
 	10, // 1: xray.app.proxyman.AllocationStrategy.concurrency:type_name -> xray.app.proxyman.AllocationStrategy.AllocationStrategyConcurrency
 	11, // 2: xray.app.proxyman.AllocationStrategy.refresh:type_name -> xray.app.proxyman.AllocationStrategy.AllocationStrategyRefresh
-	12, // 3: xray.app.proxyman.ReceiverConfig.port_range:type_name -> xray.common.net.PortRange
-	13, // 4: xray.app.proxyman.ReceiverConfig.listen:type_name -> xray.common.net.IPOrDomain
-	3,  // 5: xray.app.proxyman.ReceiverConfig.allocation_strategy:type_name -> xray.app.proxyman.AllocationStrategy
-	14, // 6: xray.app.proxyman.ReceiverConfig.stream_settings:type_name -> xray.transport.internet.StreamConfig
-	0,  // 7: xray.app.proxyman.ReceiverConfig.domain_override:type_name -> xray.app.proxyman.KnownProtocols
-	4,  // 8: xray.app.proxyman.ReceiverConfig.sniffing_settings:type_name -> xray.app.proxyman.SniffingConfig
-	15, // 9: xray.app.proxyman.InboundHandlerConfig.receiver_settings:type_name -> xray.common.serial.TypedMessage
-	15, // 10: xray.app.proxyman.InboundHandlerConfig.proxy_settings:type_name -> xray.common.serial.TypedMessage
-	13, // 11: xray.app.proxyman.SenderConfig.via:type_name -> xray.common.net.IPOrDomain
-	14, // 12: xray.app.proxyman.SenderConfig.stream_settings:type_name -> xray.transport.internet.StreamConfig
-	16, // 13: xray.app.proxyman.SenderConfig.proxy_settings:type_name -> xray.transport.internet.ProxyConfig
-	9,  // 14: xray.app.proxyman.SenderConfig.multiplex_settings:type_name -> xray.app.proxyman.MultiplexingConfig
-	15, // [15:15] is the sub-list for method output_type
-	15, // [15:15] is the sub-list for method input_type
-	15, // [15:15] is the sub-list for extension type_name
-	15, // [15:15] is the sub-list for extension extendee
-	0,  // [0:15] is the sub-list for field type_name
+	12, // 3: xray.app.proxyman.SniffingConfig.domains_excluded:type_name -> xray.common.matcher.domain.Domain
+	13, // 4: xray.app.proxyman.SniffingConfig.ips_excluded:type_name -> xray.common.matcher.geoip.GeoIP
+	14, // 5: xray.app.proxyman.ReceiverConfig.port_range:type_name -> xray.common.net.PortRange
+	15, // 6: xray.app.proxyman.ReceiverConfig.listen:type_name -> xray.common.net.IPOrDomain
+	3,  // 7: xray.app.proxyman.ReceiverConfig.allocation_strategy:type_name -> xray.app.proxyman.AllocationStrategy
+	16, // 8: xray.app.proxyman.ReceiverConfig.stream_settings:type_name -> xray.transport.internet.StreamConfig
+	0,  // 9: xray.app.proxyman.ReceiverConfig.domain_override:type_name -> xray.app.proxyman.KnownProtocols
+	4,  // 10: xray.app.proxyman.ReceiverConfig.sniffing_settings:type_name -> xray.app.proxyman.SniffingConfig
+	17, // 11: xray.app.proxyman.InboundHandlerConfig.receiver_settings:type_name -> xray.common.serial.TypedMessage
+	17, // 12: xray.app.proxyman.InboundHandlerConfig.proxy_settings:type_name -> xray.common.serial.TypedMessage
+	15, // 13: xray.app.proxyman.SenderConfig.via:type_name -> xray.common.net.IPOrDomain
+	16, // 14: xray.app.proxyman.SenderConfig.stream_settings:type_name -> xray.transport.internet.StreamConfig
+	18, // 15: xray.app.proxyman.SenderConfig.proxy_settings:type_name -> xray.transport.internet.ProxyConfig
+	9,  // 16: xray.app.proxyman.SenderConfig.multiplex_settings:type_name -> xray.app.proxyman.MultiplexingConfig
+	17, // [17:17] is the sub-list for method output_type
+	17, // [17:17] is the sub-list for method input_type
+	17, // [17:17] is the sub-list for extension type_name
+	17, // [17:17] is the sub-list for extension extendee
+	0,  // [0:17] is the sub-list for field type_name
 }
 
 func init() { file_app_proxyman_config_proto_init() }

+ 5 - 1
app/proxyman/config.proto

@@ -6,6 +6,8 @@ option go_package = "github.com/xtls/xray-core/app/proxyman";
 option java_package = "com.xray.app.proxyman";
 option java_multiple_files = true;
 
+import "common/matcher/domain/domain.proto";
+import "common/matcher/geoip/geoip.proto";
 import "common/net/address.proto";
 import "common/net/port.proto";
 import "transport/internet/config.proto";
@@ -56,7 +58,9 @@ 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.matcher.domain.Domain domains_excluded = 3;
+  repeated xray.common.matcher.geoip.GeoIP ips_excluded = 5;
   
   // 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.

+ 9 - 0
app/proxyman/errors.generated.go

@@ -0,0 +1,9 @@
+package proxyman
+
+import "github.com/xtls/xray-core/common/errors"
+
+type errPathObjHolder struct{}
+
+func newError(values ...interface{}) *errors.Error {
+	return errors.New(values...).WithPathObj(errPathObjHolder{})
+}

+ 16 - 2
app/proxyman/inbound/always.go

@@ -91,13 +91,20 @@ func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig *
 		if net.HasNetwork(nl, net.Network_UNIX) {
 			newError("creating unix domain socket worker on ", address).AtDebug().WriteToLog()
 
+			sc := receiverConfig.GetEffectiveSniffingSettings()
+			sm, err := proxyman.NewSniffingMatcher(sc)
+			if err != nil {
+				return nil, err
+			}
+
 			worker := &dsWorker{
 				address:         address,
 				proxy:           p,
 				stream:          mss,
 				tag:             tag,
 				dispatcher:      h.mux,
-				sniffingConfig:  receiverConfig.GetEffectiveSniffingSettings(),
+				sniffingConfig:  sc,
+				sniffingMatcher: sm,
 				uplinkCounter:   uplinkCounter,
 				downlinkCounter: downlinkCounter,
 				ctx:             ctx,
@@ -110,6 +117,12 @@ func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig *
 			if net.HasNetwork(nl, net.Network_TCP) {
 				newError("creating stream worker on ", address, ":", port).AtDebug().WriteToLog()
 
+				sc := receiverConfig.GetEffectiveSniffingSettings()
+				sm, err := proxyman.NewSniffingMatcher(sc)
+				if err != nil {
+					return nil, err
+				}
+
 				worker := &tcpWorker{
 					address:         address,
 					port:            net.Port(port),
@@ -118,7 +131,8 @@ func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig *
 					recvOrigDest:    receiverConfig.ReceiveOriginalDestination,
 					tag:             tag,
 					dispatcher:      h.mux,
-					sniffingConfig:  receiverConfig.GetEffectiveSniffingSettings(),
+					sniffingConfig:  sc,
+					sniffingMatcher: sm,
 					uplinkCounter:   uplinkCounter,
 					downlinkCounter: downlinkCounter,
 					ctx:             ctx,

+ 6 - 2
app/proxyman/inbound/worker.go

@@ -39,6 +39,7 @@ type tcpWorker struct {
 	tag             string
 	dispatcher      routing.Dispatcher
 	sniffingConfig  *proxyman.SniffingConfig
+	sniffingMatcher *proxyman.SniffingMatcher
 	uplinkCounter   stats.Counter
 	downlinkCounter stats.Counter
 
@@ -97,7 +98,8 @@ func (w *tcpWorker) callback(conn internet.Connection) {
 	if w.sniffingConfig != nil {
 		content.SniffingRequest.Enabled = w.sniffingConfig.Enabled
 		content.SniffingRequest.OverrideDestinationForProtocol = w.sniffingConfig.DestinationOverride
-		content.SniffingRequest.ExcludeForDomain = w.sniffingConfig.DomainsExcluded
+		content.SniffingRequest.ExcludedDomainMatcher = w.sniffingMatcher.ExDomain
+		content.SniffingRequest.ExcludedIPMatcher = w.sniffingMatcher.ExIP
 		content.SniffingRequest.MetadataOnly = w.sniffingConfig.MetadataOnly
 	}
 	ctx = session.ContextWithContent(ctx, content)
@@ -428,6 +430,7 @@ type dsWorker struct {
 	tag             string
 	dispatcher      routing.Dispatcher
 	sniffingConfig  *proxyman.SniffingConfig
+	sniffingMatcher *proxyman.SniffingMatcher
 	uplinkCounter   stats.Counter
 	downlinkCounter stats.Counter
 
@@ -459,7 +462,8 @@ func (w *dsWorker) callback(conn internet.Connection) {
 	if w.sniffingConfig != nil {
 		content.SniffingRequest.Enabled = w.sniffingConfig.Enabled
 		content.SniffingRequest.OverrideDestinationForProtocol = w.sniffingConfig.DestinationOverride
-		content.SniffingRequest.ExcludeForDomain = w.sniffingConfig.DomainsExcluded
+		content.SniffingRequest.ExcludedDomainMatcher = w.sniffingMatcher.ExDomain
+		content.SniffingRequest.ExcludedIPMatcher = w.sniffingMatcher.ExIP
 		content.SniffingRequest.MetadataOnly = w.sniffingConfig.MetadataOnly
 	}
 	ctx = session.ContextWithContent(ctx, content)

+ 0 - 55
app/router/condition.go

@@ -6,8 +6,6 @@ import (
 	"go.starlark.net/starlark"
 	"go.starlark.net/syntax"
 
-	dm "github.com/xtls/xray-core/common/matcher/domain"
-	"github.com/xtls/xray-core/common/matcher/str"
 	"github.com/xtls/xray-core/common/net"
 	"github.com/xtls/xray-core/features/routing"
 )
@@ -42,59 +40,6 @@ func (v *ConditionChan) Len() int {
 	return len(*v)
 }
 
-var matcherTypeMap = map[dm.MatchingType]str.Type{
-	dm.MatchingType_Keyword:   str.Substr,
-	dm.MatchingType_Regex:     str.Regex,
-	dm.MatchingType_Subdomain: str.Domain,
-	dm.MatchingType_Full:      str.Full,
-}
-
-func domainToMatcher(domain *dm.Domain) (str.Matcher, error) {
-	matcherType, f := matcherTypeMap[domain.Type]
-	if !f {
-		return nil, newError("unsupported domain type", domain.Type)
-	}
-
-	matcher, err := matcherType.New(domain.Value)
-	if err != nil {
-		return nil, newError("failed to create domain matcher").Base(err)
-	}
-
-	return matcher, nil
-}
-
-type DomainMatcher struct {
-	matchers str.IndexMatcher
-}
-
-func NewDomainMatcher(domains []*dm.Domain) (*DomainMatcher, error) {
-	g := new(str.MatcherGroup)
-	for _, d := range domains {
-		m, err := domainToMatcher(d)
-		if err != nil {
-			return nil, err
-		}
-		g.Add(m)
-	}
-
-	return &DomainMatcher{
-		matchers: g,
-	}, nil
-}
-
-func (m *DomainMatcher) ApplyDomain(domain string) bool {
-	return len(m.matchers.Match(domain)) > 0
-}
-
-// Apply implements Condition.
-func (m *DomainMatcher) Apply(ctx routing.Context) bool {
-	domain := ctx.GetTargetDomain()
-	if len(domain) == 0 {
-		return false
-	}
-	return m.ApplyDomain(strings.ToLower(domain))
-}
-
 type PortMatcher struct {
 	port     net.MemoryPortList
 	onSource bool

+ 2 - 1
app/router/config.go

@@ -1,6 +1,7 @@
 package router
 
 import (
+	dm "github.com/xtls/xray-core/common/matcher/domain"
 	"github.com/xtls/xray-core/common/matcher/geoip"
 	"github.com/xtls/xray-core/common/net"
 	"github.com/xtls/xray-core/features/outbound"
@@ -29,7 +30,7 @@ func (rr *RoutingRule) BuildCondition() (Condition, error) {
 	conds := NewConditionChan()
 
 	if len(rr.Domain) > 0 {
-		matcher, err := NewDomainMatcher(rr.Domain)
+		matcher, err := dm.NewDomainMatcher(rr.Domain)
 		if err != nil {
 			return nil, newError("failed to build domain condition").Base(err)
 		}

+ 1 - 1
common/matcher/domain/conf/domain.go

@@ -7,7 +7,7 @@ import (
 	"github.com/xtls/xray-core/common/matcher/geosite"
 )
 
-func ParaseDomainRule(domain string) ([]*dm.Domain, error) {
+func ParseDomainRule(domain string) ([]*dm.Domain, error) {
 	if strings.HasPrefix(domain, "geosite:") {
 		country := strings.ToUpper(domain[8:])
 		domains, err := geosite.LoadGeositeWithAttr("geosite.dat", country)

+ 60 - 0
common/matcher/domain/matcher.go

@@ -0,0 +1,60 @@
+package domain
+
+import (
+	"github.com/xtls/xray-core/common/matcher/str"
+	"github.com/xtls/xray-core/features/routing"
+	"strings"
+)
+
+var matcherTypeMap = map[MatchingType]str.Type{
+	MatchingType_Keyword:   str.Substr,
+	MatchingType_Regex:     str.Regex,
+	MatchingType_Subdomain: str.Domain,
+	MatchingType_Full:      str.Full,
+}
+
+func domainToMatcher(domain *Domain) (str.Matcher, error) {
+	matcherType, f := matcherTypeMap[domain.Type]
+	if !f {
+		return nil, newError("unsupported domain type", domain.Type)
+	}
+
+	matcher, err := matcherType.New(domain.Value)
+	if err != nil {
+		return nil, newError("failed to create domain matcher").Base(err)
+	}
+
+	return matcher, nil
+}
+
+type DomainMatcher struct {
+	matchers str.IndexMatcher
+}
+
+func NewDomainMatcher(domains []*Domain) (*DomainMatcher, error) {
+	g := new(str.MatcherGroup)
+	for _, d := range domains {
+		m, err := domainToMatcher(d)
+		if err != nil {
+			return nil, err
+		}
+		g.Add(m)
+	}
+
+	return &DomainMatcher{
+		matchers: g,
+	}, nil
+}
+
+func (m *DomainMatcher) ApplyDomain(domain string) bool {
+	return len(m.matchers.Match(domain)) > 0
+}
+
+// Apply implements Condition.
+func (m *DomainMatcher) Apply(ctx routing.Context) bool {
+	domain := ctx.GetTargetDomain()
+	if len(domain) == 0 {
+		return false
+	}
+	return m.ApplyDomain(strings.ToLower(domain))
+}

+ 119 - 1
common/matcher/geoip/conf.go

@@ -1,7 +1,11 @@
 package geoip
 
 import (
+	"github.com/xtls/xray-core/common/net"
+	"github.com/xtls/xray-core/infra/conf/common"
 	"runtime"
+	"strconv"
+	"strings"
 
 	"github.com/golang/protobuf/proto"
 	"github.com/xtls/xray-core/common/platform/filesystem"
@@ -13,7 +17,7 @@ var (
 )
 
 func LoadGeoIP(code string) ([]*CIDR, error) {
-	return LoadIPFile("geoip.dat", code)
+	return LoadIPFile("dat", code)
 }
 
 func LoadIPFile(file, code string) ([]*CIDR, error) {
@@ -88,3 +92,117 @@ func find(data, code []byte) []byte {
 		data = data[bodyL:]
 	}
 }
+
+func ParaseIPList(ips common.StringList) ([]*GeoIP, error) {
+	var geoipList []*GeoIP
+	var customCidrs []*CIDR
+
+	for _, ip := range ips {
+		if strings.HasPrefix(ip, "geoip:") {
+			country := ip[6:]
+			geoipc, err := LoadGeoIP(strings.ToUpper(country))
+			if err != nil {
+				return nil, newError("failed to load GeoIP: ", country).Base(err)
+			}
+
+			geoipList = append(geoipList, &GeoIP{
+				CountryCode: strings.ToUpper(country),
+				Cidr:        geoipc,
+			})
+			continue
+		}
+		var isExtDatFile = 0
+		{
+			const prefix = "ext:"
+			if strings.HasPrefix(ip, prefix) {
+				isExtDatFile = len(prefix)
+			}
+			const prefixQualified = "ext-ip:"
+			if strings.HasPrefix(ip, prefixQualified) {
+				isExtDatFile = len(prefixQualified)
+			}
+		}
+		if isExtDatFile != 0 {
+			kv := strings.Split(ip[isExtDatFile:], ":")
+			if len(kv) != 2 {
+				return nil, newError("invalid external resource: ", ip)
+			}
+
+			filename := kv[0]
+			country := kv[1]
+			geoipc, err := LoadIPFile(filename, strings.ToUpper(country))
+			if err != nil {
+				return nil, newError("failed to load IPs: ", country, " from ", filename).Base(err)
+			}
+
+			geoipList = append(geoipList, &GeoIP{
+				CountryCode: strings.ToUpper(filename + "_" + country),
+				Cidr:        geoipc,
+			})
+
+			continue
+		}
+
+		ipRule, err := ParseIP(ip)
+		if err != nil {
+			return nil, newError("invalid IP: ", ip).Base(err)
+		}
+		customCidrs = append(customCidrs, ipRule)
+	}
+
+	if len(customCidrs) > 0 {
+		geoipList = append(geoipList, &GeoIP{
+			Cidr: customCidrs,
+		})
+	}
+
+	return geoipList, nil
+}
+
+func ParseIP(s string) (*CIDR, error) {
+	var addr, mask string
+	i := strings.Index(s, "/")
+	if i < 0 {
+		addr = s
+	} else {
+		addr = s[:i]
+		mask = s[i+1:]
+	}
+	ip := net.ParseAddress(addr)
+	switch ip.Family() {
+	case net.AddressFamilyIPv4:
+		bits := uint32(32)
+		if len(mask) > 0 {
+			bits64, err := strconv.ParseUint(mask, 10, 32)
+			if err != nil {
+				return nil, newError("invalid network mask for router: ", mask).Base(err)
+			}
+			bits = uint32(bits64)
+		}
+		if bits > 32 {
+			return nil, newError("invalid network mask for router: ", bits)
+		}
+		return &CIDR{
+			Ip:     ip.IP(),
+			Prefix: bits,
+		}, nil
+	case net.AddressFamilyIPv6:
+		bits := uint32(128)
+		if len(mask) > 0 {
+			bits64, err := strconv.ParseUint(mask, 10, 32)
+			if err != nil {
+				return nil, newError("invalid network mask for router: ", mask).Base(err)
+			}
+			bits = uint32(bits64)
+		}
+		if bits > 128 {
+			return nil, newError("invalid network mask for router: ", bits)
+		}
+		return &CIDR{
+			Ip:     ip.IP(),
+			Prefix: bits,
+		}, nil
+	default:
+		return nil, newError("unsupported address for router: ", s)
+	}
+}

+ 10 - 0
common/matcher/geoip/matcher.go

@@ -45,3 +45,13 @@ func (m *MultiGeoIPMatcher) Apply(ctx routing.Context) bool {
 	}
 	return false
 }
+
+// MatchIP match given ip.
+func (m *MultiGeoIPMatcher) MatchIP(ip net.IP) bool {
+	for _, matcher := range m.matchers {
+		if matcher.Match(ip) {
+			return true
+		}
+	}
+	return false
+}

+ 4 - 1
common/session/session.go

@@ -3,6 +3,8 @@ package session // import "github.com/xtls/xray-core/common/session"
 
 import (
 	"context"
+	"github.com/xtls/xray-core/common/matcher/domain"
+	"github.com/xtls/xray-core/common/matcher/geoip"
 	"math/rand"
 
 	"github.com/xtls/xray-core/common/errors"
@@ -60,7 +62,8 @@ type Outbound struct {
 
 // SniffingRequest controls the behavior of content sniffing.
 type SniffingRequest struct {
-	ExcludeForDomain               []string
+	ExcludedDomainMatcher          *domain.DomainMatcher
+	ExcludedIPMatcher              *geoip.MultiGeoIPMatcher
 	OverrideDestinationForProtocol []string
 	Enabled                        bool
 	MetadataOnly                   bool

+ 3 - 1
infra/conf/common.go → infra/conf/common/common.go

@@ -1,4 +1,4 @@
-package conf
+package common
 
 import (
 	"encoding/json"
@@ -9,6 +9,8 @@ import (
 	"github.com/xtls/xray-core/common/protocol"
 )
 
+//go:generate go run github.com/xtls/xray-core/common/errors/errorgen
+
 type StringList []string
 
 func NewStringList(raw []string) *StringList {

+ 2 - 2
infra/conf/common_test.go → infra/conf/common/common_test.go

@@ -1,4 +1,4 @@
-package conf_test
+package common_test
 
 import (
 	"encoding/json"
@@ -11,7 +11,7 @@ import (
 	"github.com/xtls/xray-core/common"
 	"github.com/xtls/xray-core/common/net"
 	"github.com/xtls/xray-core/common/protocol"
-	. "github.com/xtls/xray-core/infra/conf"
+	. "github.com/xtls/xray-core/infra/conf/common"
 )
 
 func TestStringListUnmarshalError(t *testing.T) {

+ 9 - 0
infra/conf/common/errors.generated.go

@@ -0,0 +1,9 @@
+package common
+
+import "github.com/xtls/xray-core/common/errors"
+
+type errPathObjHolder struct{}
+
+func newError(values ...interface{}) *errors.Error {
+	return errors.New(values...).WithPathObj(errPathObjHolder{})
+}

+ 18 - 16
infra/conf/dns.go

@@ -2,6 +2,8 @@ package conf
 
 import (
 	"encoding/json"
+	"github.com/xtls/xray-core/common/matcher/geoip"
+	"github.com/xtls/xray-core/infra/conf/common"
 	"sort"
 	"strings"
 
@@ -13,24 +15,24 @@ import (
 )
 
 type NameServerConfig struct {
-	Address   *Address
+	Address   *common.Address
 	Port      uint16
 	Domains   []string
-	ExpectIPs StringList
+	ExpectIPs common.StringList
 }
 
 func (c *NameServerConfig) UnmarshalJSON(data []byte) error {
-	var address Address
+	var address common.Address
 	if err := json.Unmarshal(data, &address); err == nil {
 		c.Address = &address
 		return nil
 	}
 
 	var advanced struct {
-		Address   *Address   `json:"address"`
-		Port      uint16     `json:"port"`
-		Domains   []string   `json:"domains"`
-		ExpectIPs StringList `json:"expectIps"`
+		Address   *common.Address   `json:"address"`
+		Port      uint16            `json:"port"`
+		Domains   []string          `json:"domains"`
+		ExpectIPs common.StringList `json:"expectIps"`
 	}
 	if err := json.Unmarshal(data, &advanced); err == nil {
 		c.Address = advanced.Address
@@ -52,7 +54,7 @@ func (c *NameServerConfig) Build() (*dns.NameServer, error) {
 	var originalRules []*dns.NameServer_OriginalRule
 
 	for _, rule := range c.Domains {
-		parsedDomain, err := conf.ParaseDomainRule(rule)
+		parsedDomain, err := conf.ParseDomainRule(rule)
 		if err != nil {
 			return nil, newError("invalid domain rule: ", rule).Base(err)
 		}
@@ -69,7 +71,7 @@ func (c *NameServerConfig) Build() (*dns.NameServer, error) {
 		})
 	}
 
-	geoipList, err := toCidrList(c.ExpectIPs)
+	geoipList, err := geoip.ParaseIPList(c.ExpectIPs)
 	if err != nil {
 		return nil, newError("invalid IP rule: ", c.ExpectIPs).Base(err)
 	}
@@ -88,15 +90,15 @@ func (c *NameServerConfig) Build() (*dns.NameServer, error) {
 
 // DNSConfig is a JSON serializable object for dns.Config.
 type DNSConfig struct {
-	Servers       []*NameServerConfig `json:"servers"`
-	Hosts         map[string]*Address `json:"hosts"`
-	ClientIP      *Address            `json:"clientIp"`
-	Tag           string              `json:"tag"`
-	QueryStrategy string              `json:"queryStrategy"`
-	DisableCache  bool                `json:"disableCache"`
+	Servers       []*NameServerConfig        `json:"servers"`
+	Hosts         map[string]*common.Address `json:"hosts"`
+	ClientIP      *common.Address            `json:"clientIp"`
+	Tag           string                     `json:"tag"`
+	QueryStrategy string                     `json:"queryStrategy"`
+	DisableCache  bool                       `json:"disableCache"`
 }
 
-func getHostMapping(addr *Address) *dns.Config_HostMapping {
+func getHostMapping(addr *common.Address) *dns.Config_HostMapping {
 	if addr.Family().IsIP() {
 		return &dns.Config_HostMapping{
 			Ip: [][]byte{[]byte(addr.IP())},

+ 4 - 3
infra/conf/dns_proxy.go

@@ -3,13 +3,14 @@ package conf
 import (
 	"github.com/golang/protobuf/proto"
 	"github.com/xtls/xray-core/common/net"
+	"github.com/xtls/xray-core/infra/conf/common"
 	"github.com/xtls/xray-core/proxy/dns"
 )
 
 type DNSOutboundConfig struct {
-	Network Network  `json:"network"`
-	Address *Address `json:"address"`
-	Port    uint16   `json:"port"`
+	Network common.Network  `json:"network"`
+	Address *common.Address `json:"address"`
+	Port    uint16          `json:"port"`
 }
 
 func (c *DNSOutboundConfig) Build() (proto.Message, error) {

+ 7 - 6
infra/conf/dokodemo.go

@@ -2,16 +2,17 @@ package conf
 
 import (
 	"github.com/golang/protobuf/proto"
+	"github.com/xtls/xray-core/infra/conf/common"
 	"github.com/xtls/xray-core/proxy/dokodemo"
 )
 
 type DokodemoConfig struct {
-	Host         *Address     `json:"address"`
-	PortValue    uint16       `json:"port"`
-	NetworkList  *NetworkList `json:"network"`
-	TimeoutValue uint32       `json:"timeout"`
-	Redirect     bool         `json:"followRedirect"`
-	UserLevel    uint32       `json:"userLevel"`
+	Host         *common.Address     `json:"address"`
+	PortValue    uint16              `json:"port"`
+	NetworkList  *common.NetworkList `json:"network"`
+	TimeoutValue uint32              `json:"timeout"`
+	Redirect     bool                `json:"followRedirect"`
+	UserLevel    uint32              `json:"userLevel"`
 }
 
 func (v *DokodemoConfig) Build() (proto.Message, error) {

+ 2 - 1
infra/conf/http.go

@@ -2,6 +2,7 @@ package conf
 
 import (
 	"encoding/json"
+	"github.com/xtls/xray-core/infra/conf/common"
 
 	"github.com/golang/protobuf/proto"
 	"github.com/xtls/xray-core/common/protocol"
@@ -46,7 +47,7 @@ func (c *HTTPServerConfig) Build() (proto.Message, error) {
 }
 
 type HTTPRemoteConfig struct {
-	Address *Address          `json:"address"`
+	Address *common.Address   `json:"address"`
 	Port    uint16            `json:"port"`
 	Users   []json.RawMessage `json:"users"`
 }

+ 18 - 106
infra/conf/router.go

@@ -2,6 +2,7 @@ package conf
 
 import (
 	"encoding/json"
+	"github.com/xtls/xray-core/infra/conf/common"
 	"strconv"
 	"strings"
 
@@ -10,7 +11,6 @@ import (
 	"github.com/xtls/xray-core/common/matcher/geoip"
 	"github.com/xtls/xray-core/common/matcher/geosite"
 	"github.com/xtls/xray-core/common/net"
-	"github.com/xtls/xray-core/common/platform/filesystem"
 )
 
 type RouterRulesConfig struct {
@@ -19,8 +19,8 @@ type RouterRulesConfig struct {
 }
 
 type BalancingRule struct {
-	Tag       string     `json:"tag"`
-	Selectors StringList `json:"selector"`
+	Tag       string            `json:"tag"`
+	Selectors common.StringList `json:"selector"`
 }
 
 func (r *BalancingRule) Build() (*router.BalancingRule, error) {
@@ -148,108 +148,20 @@ func ParseIP(s string) (*geoip.CIDR, error) {
 	}
 }
 
-var (
-	FileCache = make(map[string][]byte)
-	IPCache   = make(map[string]*geoip.GeoIP)
-)
-
-func loadFile(file string) ([]byte, error) {
-	if FileCache[file] == nil {
-		bs, err := filesystem.ReadAsset(file)
-		if err != nil {
-			return nil, newError("failed to open file: ", file).Base(err)
-		}
-		if len(bs) == 0 {
-			return nil, newError("empty file: ", file)
-		}
-		// Do not cache file, may save RAM when there
-		// are many files, but consume CPU each time.
-		return bs, nil
-		FileCache[file] = bs
-	}
-	return FileCache[file], nil
-}
-
-func toCidrList(ips StringList) ([]*geoip.GeoIP, error) {
-	var geoipList []*geoip.GeoIP
-	var customCidrs []*geoip.CIDR
-
-	for _, ip := range ips {
-		if strings.HasPrefix(ip, "geoip:") {
-			country := ip[6:]
-			geoipc, err := geoip.LoadGeoIP(strings.ToUpper(country))
-			if err != nil {
-				return nil, newError("failed to load GeoIP: ", country).Base(err)
-			}
-
-			geoipList = append(geoipList, &geoip.GeoIP{
-				CountryCode: strings.ToUpper(country),
-				Cidr:        geoipc,
-			})
-			continue
-		}
-		var isExtDatFile = 0
-		{
-			const prefix = "ext:"
-			if strings.HasPrefix(ip, prefix) {
-				isExtDatFile = len(prefix)
-			}
-			const prefixQualified = "ext-ip:"
-			if strings.HasPrefix(ip, prefixQualified) {
-				isExtDatFile = len(prefixQualified)
-			}
-		}
-		if isExtDatFile != 0 {
-			kv := strings.Split(ip[isExtDatFile:], ":")
-			if len(kv) != 2 {
-				return nil, newError("invalid external resource: ", ip)
-			}
-
-			filename := kv[0]
-			country := kv[1]
-			geoipc, err := geoip.LoadIPFile(filename, strings.ToUpper(country))
-			if err != nil {
-				return nil, newError("failed to load IPs: ", country, " from ", filename).Base(err)
-			}
-
-			geoipList = append(geoipList, &geoip.GeoIP{
-				CountryCode: strings.ToUpper(filename + "_" + country),
-				Cidr:        geoipc,
-			})
-
-			continue
-		}
-
-		ipRule, err := ParseIP(ip)
-		if err != nil {
-			return nil, newError("invalid IP: ", ip).Base(err)
-		}
-		customCidrs = append(customCidrs, ipRule)
-	}
-
-	if len(customCidrs) > 0 {
-		geoipList = append(geoipList, &geoip.GeoIP{
-			Cidr: customCidrs,
-		})
-	}
-
-	return geoipList, nil
-}
-
 func parseFieldRule(msg json.RawMessage) (*router.RoutingRule, error) {
 	type RawFieldRule struct {
 		RouterRule
-		Domain     *StringList  `json:"domain"`
-		Domains    *StringList  `json:"domains"`
-		IP         *StringList  `json:"ip"`
-		Port       *PortList    `json:"port"`
-		Network    *NetworkList `json:"network"`
-		SourceIP   *StringList  `json:"source"`
-		SourcePort *PortList    `json:"sourcePort"`
-		User       *StringList  `json:"user"`
-		InboundTag *StringList  `json:"inboundTag"`
-		Protocols  *StringList  `json:"protocol"`
-		Attributes string       `json:"attrs"`
+		Domain     *common.StringList  `json:"domain"`
+		Domains    *common.StringList  `json:"domains"`
+		IP         *common.StringList  `json:"ip"`
+		Port       *common.PortList    `json:"port"`
+		Network    *common.NetworkList `json:"network"`
+		SourceIP   *common.StringList  `json:"source"`
+		SourcePort *common.PortList    `json:"sourcePort"`
+		User       *common.StringList  `json:"user"`
+		InboundTag *common.StringList  `json:"inboundTag"`
+		Protocols  *common.StringList  `json:"protocol"`
+		Attributes string              `json:"attrs"`
 	}
 	rawFieldRule := new(RawFieldRule)
 	err := json.Unmarshal(msg, rawFieldRule)
@@ -273,7 +185,7 @@ func parseFieldRule(msg json.RawMessage) (*router.RoutingRule, error) {
 
 	if rawFieldRule.Domain != nil {
 		for _, domain := range *rawFieldRule.Domain {
-			rules, err := conf.ParaseDomainRule(domain)
+			rules, err := conf.ParseDomainRule(domain)
 			if err != nil {
 				return nil, newError("failed to parse domain rule: ", domain).Base(err)
 			}
@@ -283,7 +195,7 @@ func parseFieldRule(msg json.RawMessage) (*router.RoutingRule, error) {
 
 	if rawFieldRule.Domains != nil {
 		for _, domain := range *rawFieldRule.Domains {
-			rules, err := conf.ParaseDomainRule(domain)
+			rules, err := conf.ParseDomainRule(domain)
 			if err != nil {
 				return nil, newError("failed to parse domain rule: ", domain).Base(err)
 			}
@@ -292,7 +204,7 @@ func parseFieldRule(msg json.RawMessage) (*router.RoutingRule, error) {
 	}
 
 	if rawFieldRule.IP != nil {
-		geoipList, err := toCidrList(*rawFieldRule.IP)
+		geoipList, err := geoip.ParaseIPList(*rawFieldRule.IP)
 		if err != nil {
 			return nil, err
 		}
@@ -308,7 +220,7 @@ func parseFieldRule(msg json.RawMessage) (*router.RoutingRule, error) {
 	}
 
 	if rawFieldRule.SourceIP != nil {
-		geoipList, err := toCidrList(*rawFieldRule.SourceIP)
+		geoipList, err := geoip.ParaseIPList(*rawFieldRule.SourceIP)
 		if err != nil {
 			return nil, err
 		}

+ 8 - 7
infra/conf/shadowsocks.go

@@ -1,6 +1,7 @@
 package conf
 
 import (
+	"github.com/xtls/xray-core/infra/conf/common"
 	"strings"
 
 	"github.com/golang/protobuf/proto"
@@ -46,7 +47,7 @@ type ShadowsocksServerConfig struct {
 	Level       byte                     `json:"level"`
 	Email       string                   `json:"email"`
 	Users       []*ShadowsocksUserConfig `json:"clients"`
-	NetworkList *NetworkList             `json:"network"`
+	NetworkList *common.NetworkList      `json:"network"`
 }
 
 func (v *ShadowsocksServerConfig) Build() (proto.Message, error) {
@@ -93,12 +94,12 @@ func (v *ShadowsocksServerConfig) Build() (proto.Message, error) {
 }
 
 type ShadowsocksServerTarget struct {
-	Address  *Address `json:"address"`
-	Port     uint16   `json:"port"`
-	Cipher   string   `json:"method"`
-	Password string   `json:"password"`
-	Email    string   `json:"email"`
-	Level    byte     `json:"level"`
+	Address  *common.Address `json:"address"`
+	Port     uint16          `json:"port"`
+	Cipher   string          `json:"method"`
+	Password string          `json:"password"`
+	Email    string          `json:"email"`
+	Level    byte            `json:"level"`
 }
 
 type ShadowsocksClientConfig struct {

+ 3 - 2
infra/conf/socks.go

@@ -2,6 +2,7 @@ package conf
 
 import (
 	"encoding/json"
+	"github.com/xtls/xray-core/infra/conf/common"
 
 	"github.com/golang/protobuf/proto"
 	"github.com/xtls/xray-core/common/protocol"
@@ -30,7 +31,7 @@ type SocksServerConfig struct {
 	AuthMethod string          `json:"auth"`
 	Accounts   []*SocksAccount `json:"accounts"`
 	UDP        bool            `json:"udp"`
-	Host       *Address        `json:"ip"`
+	Host       *common.Address `json:"ip"`
 	Timeout    uint32          `json:"timeout"`
 	UserLevel  uint32          `json:"userLevel"`
 }
@@ -65,7 +66,7 @@ func (v *SocksServerConfig) Build() (proto.Message, error) {
 }
 
 type SocksRemoteConfig struct {
-	Address *Address          `json:"address"`
+	Address *common.Address   `json:"address"`
 	Port    uint16            `json:"port"`
 	Users   []json.RawMessage `json:"users"`
 }

+ 10 - 9
infra/conf/transport_authenticators.go

@@ -1,6 +1,7 @@
 package conf
 
 import (
+	"github.com/xtls/xray-core/infra/conf/common"
 	"sort"
 
 	"github.com/golang/protobuf/proto"
@@ -57,13 +58,13 @@ func (DTLSAuthenticator) Build() (proto.Message, error) {
 }
 
 type AuthenticatorRequest struct {
-	Version string                 `json:"version"`
-	Method  string                 `json:"method"`
-	Path    StringList             `json:"path"`
-	Headers map[string]*StringList `json:"headers"`
+	Version string                        `json:"version"`
+	Method  string                        `json:"method"`
+	Path    common.StringList             `json:"path"`
+	Headers map[string]*common.StringList `json:"headers"`
 }
 
-func sortMapKeys(m map[string]*StringList) []string {
+func sortMapKeys(m map[string]*common.StringList) []string {
 	var keys []string
 	for key := range m {
 		keys = append(keys, key)
@@ -133,10 +134,10 @@ func (v *AuthenticatorRequest) Build() (*http.RequestConfig, error) {
 }
 
 type AuthenticatorResponse struct {
-	Version string                 `json:"version"`
-	Status  string                 `json:"status"`
-	Reason  string                 `json:"reason"`
-	Headers map[string]*StringList `json:"headers"`
+	Version string                        `json:"version"`
+	Status  string                        `json:"status"`
+	Reason  string                        `json:"reason"`
+	Headers map[string]*common.StringList `json:"headers"`
 }
 
 func (v *AuthenticatorResponse) Build() (*http.ResponseConfig, error) {

+ 23 - 22
infra/conf/transport_internet.go

@@ -2,6 +2,7 @@ package conf
 
 import (
 	"encoding/json"
+	"github.com/xtls/xray-core/infra/conf/common"
 	"math"
 	"net/url"
 	"strconv"
@@ -179,8 +180,8 @@ func (c *WebSocketConfig) Build() (proto.Message, error) {
 }
 
 type HTTPConfig struct {
-	Host *StringList `json:"host"`
-	Path string      `json:"path"`
+	Host *common.StringList `json:"host"`
+	Path string             `json:"path"`
 }
 
 // Build implements Buildable.
@@ -311,16 +312,16 @@ func (c *TLSCertConfig) Build() (*tls.Certificate, error) {
 }
 
 type TLSConfig struct {
-	Insecure                 bool             `json:"allowInsecure"`
-	Certs                    []*TLSCertConfig `json:"certificates"`
-	ServerName               string           `json:"serverName"`
-	ALPN                     *StringList      `json:"alpn"`
-	EnableSessionResumption  bool             `json:"enableSessionResumption"`
-	DisableSystemRoot        bool             `json:"disableSystemRoot"`
-	MinVersion               string           `json:"minVersion"`
-	MaxVersion               string           `json:"maxVersion"`
-	CipherSuites             string           `json:"cipherSuites"`
-	PreferServerCipherSuites bool             `json:"preferServerCipherSuites"`
+	Insecure                 bool               `json:"allowInsecure"`
+	Certs                    []*TLSCertConfig   `json:"certificates"`
+	ServerName               string             `json:"serverName"`
+	ALPN                     *common.StringList `json:"alpn"`
+	EnableSessionResumption  bool               `json:"enableSessionResumption"`
+	DisableSystemRoot        bool               `json:"disableSystemRoot"`
+	MinVersion               string             `json:"minVersion"`
+	MaxVersion               string             `json:"maxVersion"`
+	CipherSuites             string             `json:"cipherSuites"`
+	PreferServerCipherSuites bool               `json:"preferServerCipherSuites"`
 }
 
 // Build implements Buildable.
@@ -401,16 +402,16 @@ func (c *XTLSCertConfig) Build() (*xtls.Certificate, error) {
 }
 
 type XTLSConfig struct {
-	Insecure                 bool              `json:"allowInsecure"`
-	Certs                    []*XTLSCertConfig `json:"certificates"`
-	ServerName               string            `json:"serverName"`
-	ALPN                     *StringList       `json:"alpn"`
-	EnableSessionResumption  bool              `json:"enableSessionResumption"`
-	DisableSystemRoot        bool              `json:"disableSystemRoot"`
-	MinVersion               string            `json:"minVersion"`
-	MaxVersion               string            `json:"maxVersion"`
-	CipherSuites             string            `json:"cipherSuites"`
-	PreferServerCipherSuites bool              `json:"preferServerCipherSuites"`
+	Insecure                 bool               `json:"allowInsecure"`
+	Certs                    []*XTLSCertConfig  `json:"certificates"`
+	ServerName               string             `json:"serverName"`
+	ALPN                     *common.StringList `json:"alpn"`
+	EnableSessionResumption  bool               `json:"enableSessionResumption"`
+	DisableSystemRoot        bool               `json:"disableSystemRoot"`
+	MinVersion               string             `json:"minVersion"`
+	MaxVersion               string             `json:"maxVersion"`
+	CipherSuites             string             `json:"cipherSuites"`
+	PreferServerCipherSuites bool               `json:"preferServerCipherSuites"`
 }
 
 // Build implements Buildable.

+ 7 - 6
infra/conf/trojan.go

@@ -2,6 +2,7 @@ package conf
 
 import (
 	"encoding/json"
+	"github.com/xtls/xray-core/infra/conf/common"
 	"runtime"
 	"strconv"
 	"syscall"
@@ -16,12 +17,12 @@ import (
 
 // TrojanServerTarget is configuration of a single trojan server
 type TrojanServerTarget struct {
-	Address  *Address `json:"address"`
-	Port     uint16   `json:"port"`
-	Password string   `json:"password"`
-	Email    string   `json:"email"`
-	Level    byte     `json:"level"`
-	Flow     string   `json:"flow"`
+	Address  *common.Address `json:"address"`
+	Port     uint16          `json:"port"`
+	Password string          `json:"password"`
+	Email    string          `json:"email"`
+	Level    byte            `json:"level"`
+	Flow     string          `json:"flow"`
 }
 
 // TrojanClientConfig is configuration of trojan servers

+ 2 - 1
infra/conf/vless.go

@@ -2,6 +2,7 @@ package conf
 
 import (
 	"encoding/json"
+	"github.com/xtls/xray-core/infra/conf/common"
 	"runtime"
 	"strconv"
 	"syscall"
@@ -137,7 +138,7 @@ func (c *VLessInboundConfig) Build() (proto.Message, error) {
 }
 
 type VLessOutboundVnext struct {
-	Address *Address          `json:"address"`
+	Address *common.Address   `json:"address"`
 	Port    uint16            `json:"port"`
 	Users   []json.RawMessage `json:"users"`
 }

+ 2 - 1
infra/conf/vmess.go

@@ -2,6 +2,7 @@ package conf
 
 import (
 	"encoding/json"
+	"github.com/xtls/xray-core/infra/conf/common"
 	"strings"
 
 	"github.com/golang/protobuf/proto"
@@ -123,7 +124,7 @@ func (c *VMessInboundConfig) Build() (proto.Message, error) {
 }
 
 type VMessOutboundTarget struct {
-	Address *Address          `json:"address"`
+	Address *common.Address   `json:"address"`
 	Port    uint16            `json:"port"`
 	Users   []json.RawMessage `json:"users"`
 }

+ 32 - 13
infra/conf/xray.go

@@ -2,6 +2,10 @@ package conf
 
 import (
 	"encoding/json"
+	"github.com/xtls/xray-core/common/matcher/domain"
+	"github.com/xtls/xray-core/common/matcher/domain/conf"
+	"github.com/xtls/xray-core/common/matcher/geoip"
+	"github.com/xtls/xray-core/infra/conf/common"
 	"github.com/xtls/xray-core/transport/internet"
 	"log"
 	"os"
@@ -59,10 +63,11 @@ func toProtocolList(s []string) ([]proxyman.KnownProtocols, error) {
 }
 
 type SniffingConfig struct {
-	Enabled         bool        `json:"enabled"`
-	DestOverride    *StringList `json:"destOverride"`
-	DomainsExcluded *StringList `json:"domainsExcluded"`
-	MetadataOnly    bool        `json:"metadataOnly"`
+	Enabled         bool               `json:"enabled"`
+	DestOverride    *common.StringList `json:"destOverride"`
+	DomainsExcluded *common.StringList `json:"domainsExcluded"`
+	IPsExcluded     *common.StringList `json:"ipsExcluded"`
+	MetadataOnly    bool               `json:"metadataOnly"`
 }
 
 // Build implements Buildable.
@@ -83,17 +88,31 @@ func (c *SniffingConfig) Build() (*proxyman.SniffingConfig, error) {
 		}
 	}
 
-	var d []string
+	var exDomain []*domain.Domain
 	if c.DomainsExcluded != nil {
-		for _, domain := range *c.DomainsExcluded {
-			d = append(d, strings.ToLower(domain))
+		for _, dmr := range *c.DomainsExcluded {
+			if dm, err := conf.ParseDomainRule(dmr); err == nil {
+				exDomain = append(exDomain, dm...)
+			} else {
+				return nil, newError("failed to parse excluded domain").Base(err)
+			}
+		}
+	}
+
+	var exIP []*geoip.GeoIP
+	if c.IPsExcluded != nil {
+		exip, err := geoip.ParaseIPList(*c.IPsExcluded)
+		if err != nil {
+			return nil, newError("failed to parse excluded ip").Base(err)
 		}
+		exIP = exip
 	}
 
 	return &proxyman.SniffingConfig{
 		Enabled:             c.Enabled,
 		DestinationOverride: p,
-		DomainsExcluded:     d,
+		DomainsExcluded:     exDomain,
+		IpsExcluded:         exIP,
 		MetadataOnly:        c.MetadataOnly,
 	}, nil
 }
@@ -156,13 +175,13 @@ func (c *InboundDetourAllocationConfig) Build() (*proxyman.AllocationStrategy, e
 
 type InboundDetourConfig struct {
 	Protocol       string                         `json:"protocol"`
-	PortRange      *PortRange                     `json:"port"`
-	ListenOn       *Address                       `json:"listen"`
+	PortRange      *common.PortRange              `json:"port"`
+	ListenOn       *common.Address                `json:"listen"`
 	Settings       *json.RawMessage               `json:"settings"`
 	Tag            string                         `json:"tag"`
 	Allocation     *InboundDetourAllocationConfig `json:"allocate"`
 	StreamSetting  *StreamConfig                  `json:"streamSettings"`
-	DomainOverride *StringList                    `json:"domainOverride"`
+	DomainOverride *common.StringList             `json:"domainOverride"`
 	SniffingConfig *SniffingConfig                `json:"sniffing"`
 }
 
@@ -264,7 +283,7 @@ func (c *InboundDetourConfig) Build() (*core.InboundHandlerConfig, error) {
 
 type OutboundDetourConfig struct {
 	Protocol      string           `json:"protocol"`
-	SendThrough   *Address         `json:"sendThrough"`
+	SendThrough   *common.Address  `json:"sendThrough"`
 	Tag           string           `json:"tag"`
 	Settings      *json.RawMessage `json:"settings"`
 	StreamSetting *StreamConfig    `json:"streamSettings"`
@@ -622,7 +641,7 @@ func (c *Config) Build() (*core.Config, error) {
 
 	// Backward compatibility.
 	if len(inbounds) > 0 && inbounds[0].PortRange == nil && c.Port > 0 {
-		inbounds[0].PortRange = &PortRange{
+		inbounds[0].PortRange = &common.PortRange{
 			From: uint32(c.Port),
 			To:   uint32(c.Port),
 		}

+ 47 - 0
infra/conf/xray_test.go

@@ -2,6 +2,7 @@ package conf_test
 
 import (
 	"encoding/json"
+	"github.com/xtls/xray-core/common/matcher/domain"
 	"reflect"
 	"testing"
 
@@ -372,6 +373,52 @@ func TestMuxConfig_Build(t *testing.T) {
 	}
 }
 
+func TestSniffingConfig_Build(t *testing.T) {
+	tests := []struct {
+		name   string
+		fields string
+		want   *proxyman.SniffingConfig
+	}{
+		{"default", `
+{
+	"enabled": true, 
+	"destOverride": ["tls"],
+	"domainsExcluded": ["domain:google.com"],
+	"ipsExcluded": ["8.8.8.8"]
+}`, &proxyman.SniffingConfig{
+			Enabled:             true,
+			DestinationOverride: []string{"tls"},
+			DomainsExcluded: []*domain.Domain{
+				{
+					Type:  domain.MatchingType_Subdomain,
+					Value: "google.com",
+				},
+			},
+			IpsExcluded: []*geoip.GeoIP{
+				{
+					Cidr: []*geoip.CIDR{{Ip: []byte{8, 8, 8, 8}, Prefix: 32}},
+				},
+			},
+		}},
+		{"empty def", `{}`, &proxyman.SniffingConfig{
+			Enabled: false,
+		}},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			m := &SniffingConfig{}
+			common.Must(json.Unmarshal([]byte(tt.fields), m))
+			got, err := m.Build()
+			if err != nil {
+				t.Errorf("%v", err)
+			}
+			if !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("SniffingConfig.Build() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
 func TestConfig_Override(t *testing.T) {
 	tests := []struct {
 		name string