diff --git a/app/dispatcher/default.go b/app/dispatcher/default.go index 1c0ba79c..97322ab2 100644 --- a/app/dispatcher/default.go +++ b/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) diff --git a/app/proxyman/config.go b/app/proxyman/config.go index 73c00c74..302d208f 100644 --- a/app/proxyman/config.go +++ b/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 +} diff --git a/app/proxyman/config.pb.go b/app/proxyman/config.pb.go index 4e42cfd5..d8c82e65 100644 --- a/app/proxyman/config.pb.go +++ b/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() } diff --git a/app/proxyman/config.proto b/app/proxyman/config.proto index 83d5ad5e..69fa4f15 100644 --- a/app/proxyman/config.proto +++ b/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. diff --git a/app/proxyman/errors.generated.go b/app/proxyman/errors.generated.go new file mode 100644 index 00000000..56dc500f --- /dev/null +++ b/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{}) +} diff --git a/app/proxyman/inbound/always.go b/app/proxyman/inbound/always.go index a29e7d32..8918ba51 100644 --- a/app/proxyman/inbound/always.go +++ b/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, diff --git a/app/proxyman/inbound/worker.go b/app/proxyman/inbound/worker.go index 04094a4b..7735c133 100644 --- a/app/proxyman/inbound/worker.go +++ b/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) diff --git a/app/router/condition.go b/app/router/condition.go index c6e344f1..8236e8a7 100644 --- a/app/router/condition.go +++ b/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 diff --git a/app/router/config.go b/app/router/config.go index 6fdfeda8..838e2296 100644 --- a/app/router/config.go +++ b/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) } diff --git a/common/matcher/domain/conf/domain.go b/common/matcher/domain/conf/domain.go index e71a9cc6..10a8cf57 100644 --- a/common/matcher/domain/conf/domain.go +++ b/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) diff --git a/common/matcher/domain/matcher.go b/common/matcher/domain/matcher.go new file mode 100644 index 00000000..47425343 --- /dev/null +++ b/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)) +} diff --git a/common/matcher/geoip/conf.go b/common/matcher/geoip/conf.go index d5be09cc..c2c9b8cb 100644 --- a/common/matcher/geoip/conf.go +++ b/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) + } +} diff --git a/common/matcher/geoip/matcher.go b/common/matcher/geoip/matcher.go index c98ed115..e2f4e188 100644 --- a/common/matcher/geoip/matcher.go +++ b/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 +} diff --git a/common/session/session.go b/common/session/session.go index 24ac4631..7c7062aa 100644 --- a/common/session/session.go +++ b/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 diff --git a/infra/conf/common.go b/infra/conf/common/common.go similarity index 98% rename from infra/conf/common.go rename to infra/conf/common/common.go index 0de30728..a2454389 100644 --- a/infra/conf/common.go +++ b/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 { diff --git a/infra/conf/common_test.go b/infra/conf/common/common_test.go similarity index 98% rename from infra/conf/common_test.go rename to infra/conf/common/common_test.go index 39e4cbea..6bc73c93 100644 --- a/infra/conf/common_test.go +++ b/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) { diff --git a/infra/conf/common/errors.generated.go b/infra/conf/common/errors.generated.go new file mode 100644 index 00000000..28b9a625 --- /dev/null +++ b/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{}) +} diff --git a/infra/conf/dns.go b/infra/conf/dns.go index ce7bc24e..807600ec 100644 --- a/infra/conf/dns.go +++ b/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())}, diff --git a/infra/conf/dns_proxy.go b/infra/conf/dns_proxy.go index 922d32ba..4b1f3b91 100644 --- a/infra/conf/dns_proxy.go +++ b/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) { diff --git a/infra/conf/dokodemo.go b/infra/conf/dokodemo.go index 03a21d71..c5b42e65 100644 --- a/infra/conf/dokodemo.go +++ b/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) { diff --git a/infra/conf/http.go b/infra/conf/http.go index e6969582..7b9acaa7 100644 --- a/infra/conf/http.go +++ b/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"` } diff --git a/infra/conf/router.go b/infra/conf/router.go index 128096ab..1f68e304 100644 --- a/infra/conf/router.go +++ b/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 } diff --git a/infra/conf/shadowsocks.go b/infra/conf/shadowsocks.go index fbb2a79d..42b9f038 100644 --- a/infra/conf/shadowsocks.go +++ b/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 { diff --git a/infra/conf/socks.go b/infra/conf/socks.go index 05dad7bc..ea2a4189 100644 --- a/infra/conf/socks.go +++ b/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"` } diff --git a/infra/conf/transport_authenticators.go b/infra/conf/transport_authenticators.go index c9e42605..f000e8d4 100644 --- a/infra/conf/transport_authenticators.go +++ b/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) { diff --git a/infra/conf/transport_internet.go b/infra/conf/transport_internet.go index 15d5dd32..980a49a8 100644 --- a/infra/conf/transport_internet.go +++ b/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. diff --git a/infra/conf/trojan.go b/infra/conf/trojan.go index 4fe96c07..b59894cb 100644 --- a/infra/conf/trojan.go +++ b/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 diff --git a/infra/conf/vless.go b/infra/conf/vless.go index f5ded7a0..33a5c3b1 100644 --- a/infra/conf/vless.go +++ b/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"` } diff --git a/infra/conf/vmess.go b/infra/conf/vmess.go index 1200be07..62084c09 100644 --- a/infra/conf/vmess.go +++ b/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"` } diff --git a/infra/conf/xray.go b/infra/conf/xray.go index 0b139792..f8712221 100644 --- a/infra/conf/xray.go +++ b/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), } diff --git a/infra/conf/xray_test.go b/infra/conf/xray_test.go index 96df370e..bf7e2c51 100644 --- a/infra/conf/xray_test.go +++ b/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