Compare commits

..

28 Commits

Author SHA1 Message Date
Arthur Morgan
1dca3cb3dd v1.4.3 2021-09-08 01:38:12 +08:00
Arthur Morgan
28d17ac17f go1.17 2021-09-08 01:33:14 +08:00
Arthur Morgan
e6019a89c9 adjust for go1.17 2021-09-08 01:30:20 +08:00
Arthur Morgan
3213e5dd81 update dependencies 2021-09-08 01:13:32 +08:00
Arthur Morgan
c950edede2 Merge pull request #618 from XTLS/fix/service-name
gRPC: Use `PathEscape` encoded service name
2021-09-08 00:53:55 +08:00
Arthur Morgan
64892fb2c3 Merge pull request #609 from XTLS/fix/dialer
Move `DomainStrategy` & `DialerProxy` to `DialSystem`
2021-09-08 00:53:37 +08:00
Arthur Morgan
0403e6ddc3 Merge pull request #669 from AkinoKaede/fix-cannot-disable-readv
Fix cannot disable ReadV
2021-09-08 00:53:00 +08:00
Arthur Morgan
d9d239750b Merge pull request #633 from XTLS/feature/h2-health-check
Add health check for h2 & gRPC
2021-09-08 00:52:10 +08:00
Arthur Morgan
73e10f0f6f Merge pull request #599 from XTLS/fix/buffer
Check buffer before releasing and reusing
2021-09-08 00:51:33 +08:00
Arthur Morgan
7a9e72b133 Merge pull request #589 from bhoppi/main
Fix: new cert issuing is incorrectly delayed
2021-09-08 00:50:32 +08:00
Arthur Morgan
66b58e6076 Merge pull request #553 from XTLS/tls/reject-unknown-sni
Add: reject unknown SNI
2021-09-08 00:48:51 +08:00
秋のかえで
17cdeac57f Fix: cannot disable ReadV 2021-08-07 18:26:28 +08:00
hmol233
e4bf620795 minor tweak 2021-07-10 16:41:23 +08:00
hmol233
31c7141fef gRPC: add keepalive option PermitWithoutStream 2021-07-05 21:25:21 +08:00
hmol233
57b9006d26 gRPC: add keepalive option for server 2021-07-05 21:25:03 +08:00
hmol233
d9d04a230f Add h2 & gRPC health check 2021-07-03 16:01:59 +08:00
hmol233
3dc9fba20d gRPC: Use PathEscape encoded service name 2021-06-27 16:46:26 +08:00
RPRX
d45298a10d Add AnXray 2021-06-20 15:13:37 +00:00
RPRX
6e8581f5dc Re-Add Qv2ray 2021-06-20 15:12:36 +00:00
hmol233
86a8fb5d84 Move DomainStrategy & DialerProxy to DialSystem
Fix https://github.com/XTLS/Xray-core/issues/608
2021-06-18 19:28:02 +08:00
hmol233
3531b95d82 ? 2021-06-14 20:43:48 +08:00
hmol233
b977899926 Check buffer before releasing
to avoid `extending out of bound` issue in some cases
2021-06-14 20:40:17 +08:00
Bhoppi Chaw
2220411644 fix new cert issuing is incorrectly delayed 2021-06-05 23:32:05 +08:00
hmol233
3b8618b379 Fix linkname 2021-05-10 07:11:27 +08:00
hmol233
e8a8465220 Fix reject unknown sni with single cert 2021-05-10 00:28:40 +08:00
hmol233
1f92b948c0 Fix errNoCertificates 2021-05-10 00:11:45 +08:00
hmol233
53b99efe78 Add: reject unknown SNI
Co-Authored-By: 玖柒Max <60207794+jiuqi9997@users.noreply.github.com>
2021-05-09 23:47:21 +08:00
RPRX
1e3d739a5b Remove Qv2ray 2021-04-27 10:35:01 +00:00
124 changed files with 3298 additions and 4944 deletions

View File

@@ -121,7 +121,7 @@ jobs:
- name: Set up Go - name: Set up Go
uses: actions/setup-go@v2 uses: actions/setup-go@v2
with: with:
go-version: ^1.16 go-version: ^1.17
- name: Get project dependencies - name: Get project dependencies
run: go mod download run: go mod download

View File

@@ -44,6 +44,7 @@
- [Netch (NetFilter & TUN/TAP)](https://github.com/NetchX/Netch) - [Netch (NetFilter & TUN/TAP)](https://github.com/NetchX/Netch)
- Android - Android
- [v2rayNG](https://github.com/2dust/v2rayNG) - [v2rayNG](https://github.com/2dust/v2rayNG)
- [AnXray](https://github.com/XTLS/AnXray)
- [Kitsunebi](https://github.com/rurirei/Kitsunebi/tree/release_xtls) - [Kitsunebi](https://github.com/rurirei/Kitsunebi/tree/release_xtls)
- iOS / Mac - iOS / Mac
- [Shadowrocket](https://apps.apple.com/app/shadowrocket/id932747118) - [Shadowrocket](https://apps.apple.com/app/shadowrocket/id932747118)

View File

@@ -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 { func shouldOverride(ctx context.Context, result SniffResult, request session.SniffingRequest, destination net.Destination) bool {
domain := result.Domain() domain := result.Domain()
if request.ExcludedDomainMatcher != nil { for _, d := range request.ExcludeForDomain {
if request.ExcludedDomainMatcher.ApplyDomain(domain) { if strings.ToLower(domain) == d {
return false return false
} }
} }
@@ -205,16 +205,6 @@ func shouldOverride(ctx context.Context, result SniffResult, request session.Sni
return false 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. // Dispatch implements routing.Dispatcher.
func (d *DefaultDispatcher) Dispatch(ctx context.Context, destination net.Destination) (*transport.Link, error) { func (d *DefaultDispatcher) Dispatch(ctx context.Context, destination net.Destination) (*transport.Link, error) {
if !destination.IsValid() { if !destination.IsValid() {
@@ -232,12 +222,6 @@ func (d *DefaultDispatcher) Dispatch(ctx context.Context, destination net.Destin
ctx = session.ContextWithContent(ctx, content) ctx = session.ContextWithContent(ctx, content)
} }
sniffingRequest := content.SniffingRequest sniffingRequest := content.SniffingRequest
if !canSniff(ctx, sniffingRequest, destination) {
newError("skip sniffing for ip ", destination.Address.String()).AtDebug().WriteToLog()
sniffingRequest.Enabled = false
}
switch { switch {
case !sniffingRequest.Enabled: case !sniffingRequest.Enabled:
go d.routedDispatch(ctx, outbound, destination) go d.routedDispatch(ctx, outbound, destination)
@@ -325,10 +309,15 @@ func sniffer(ctx context.Context, cReader *cachedReader, metadataOnly bool) (Sni
func (d *DefaultDispatcher) routedDispatch(ctx context.Context, link *transport.Link, destination net.Destination) { func (d *DefaultDispatcher) routedDispatch(ctx context.Context, link *transport.Link, destination net.Destination) {
var handler outbound.Handler var handler outbound.Handler
skipRoutePick := false
if content := session.ContentFromContext(ctx); content != nil {
skipRoutePick = content.SkipRoutePick
}
routingLink := routing_session.AsRoutingContext(ctx) routingLink := routing_session.AsRoutingContext(ctx)
inTag := routingLink.GetInboundTag() inTag := routingLink.GetInboundTag()
isPickRoute := false isPickRoute := false
if d.router != nil { if d.router != nil && !skipRoutePick {
if route, err := d.router.PickRoute(routingLink); err == nil { if route, err := d.router.PickRoute(routingLink); err == nil {
outTag := route.GetOutboundTag() outTag := route.GetOutboundTag()
isPickRoute = true isPickRoute = true

View File

@@ -1,64 +0,0 @@
package dns
import (
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/common/uuid"
)
var typeMap = 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,
}
// References:
// https://www.iana.org/assignments/special-use-domain-names/special-use-domain-names.xhtml
// https://unix.stackexchange.com/questions/92441/whats-the-difference-between-local-home-and-lan
var localTLDsAndDotlessDomains = []*dm.Domain{
{Type: dm.MatchingType_Regex, Value: "^[^.]+$"}, // This will only match domains without any dot
{Type: dm.MatchingType_Subdomain, Value: "local"},
{Type: dm.MatchingType_Subdomain, Value: "localdomain"},
{Type: dm.MatchingType_Subdomain, Value: "localhost"},
{Type: dm.MatchingType_Subdomain, Value: "lan"},
{Type: dm.MatchingType_Subdomain, Value: "home.arpa"},
{Type: dm.MatchingType_Subdomain, Value: "example"},
{Type: dm.MatchingType_Subdomain, Value: "invalid"},
{Type: dm.MatchingType_Subdomain, Value: "test"},
}
var localTLDsAndDotlessDomainsRule = &NameServer_OriginalRule{
Rule: "geosite:private",
Size: uint32(len(localTLDsAndDotlessDomains)),
}
func toStrMatcher(t dm.MatchingType, domain string) (str.Matcher, error) {
strMType, f := typeMap[t]
if !f {
return nil, newError("unknown mapping type", t).AtWarning()
}
matcher, err := strMType.New(domain)
if err != nil {
return nil, newError("failed to create str matcher").Base(err)
}
return matcher, nil
}
func toNetIP(addrs []net.Address) ([]net.IP, error) {
ips := make([]net.IP, 0, len(addrs))
for _, addr := range addrs {
if addr.Family().IsIP() {
ips = append(ips, addr.IP())
} else {
return nil, newError("Failed to convert address", addr, "to Net IP.").AtWarning()
}
}
return ips, nil
}
func generateRandomTag() string {
id := uuid.New()
return "xray.system." + id.String()
}

View File

@@ -1,14 +1,14 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.26.0 // protoc-gen-go v1.25.0
// protoc v3.15.8 // protoc v3.14.0
// source: app/dns/config.proto // source: app/dns/config.proto
package dns package dns
import ( import (
domain "github.com/xtls/xray-core/common/matcher/domain" proto "github.com/golang/protobuf/proto"
geoip "github.com/xtls/xray-core/common/matcher/geoip" router "github.com/xtls/xray-core/app/router"
net "github.com/xtls/xray-core/common/net" net "github.com/xtls/xray-core/common/net"
protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl" protoimpl "google.golang.org/protobuf/runtime/protoimpl"
@@ -23,115 +23,71 @@ const (
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
) )
type QueryStrategy int32 // This is a compile-time assertion that a sufficiently up-to-date version
// of the legacy proto package is being used.
const _ = proto.ProtoPackageIsVersion4
type DomainMatchingType int32
const ( const (
QueryStrategy_USE_IP QueryStrategy = 0 DomainMatchingType_Full DomainMatchingType = 0
QueryStrategy_USE_IP4 QueryStrategy = 1 DomainMatchingType_Subdomain DomainMatchingType = 1
QueryStrategy_USE_IP6 QueryStrategy = 2 DomainMatchingType_Keyword DomainMatchingType = 2
DomainMatchingType_Regex DomainMatchingType = 3
) )
// Enum value maps for QueryStrategy. // Enum value maps for DomainMatchingType.
var ( var (
QueryStrategy_name = map[int32]string{ DomainMatchingType_name = map[int32]string{
0: "USE_IP", 0: "Full",
1: "USE_IP4", 1: "Subdomain",
2: "USE_IP6", 2: "Keyword",
3: "Regex",
} }
QueryStrategy_value = map[string]int32{ DomainMatchingType_value = map[string]int32{
"USE_IP": 0, "Full": 0,
"USE_IP4": 1, "Subdomain": 1,
"USE_IP6": 2, "Keyword": 2,
"Regex": 3,
} }
) )
func (x QueryStrategy) Enum() *QueryStrategy { func (x DomainMatchingType) Enum() *DomainMatchingType {
p := new(QueryStrategy) p := new(DomainMatchingType)
*p = x *p = x
return p return p
} }
func (x QueryStrategy) String() string { func (x DomainMatchingType) String() string {
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
} }
func (QueryStrategy) Descriptor() protoreflect.EnumDescriptor { func (DomainMatchingType) Descriptor() protoreflect.EnumDescriptor {
return file_app_dns_config_proto_enumTypes[0].Descriptor() return file_app_dns_config_proto_enumTypes[0].Descriptor()
} }
func (QueryStrategy) Type() protoreflect.EnumType { func (DomainMatchingType) Type() protoreflect.EnumType {
return &file_app_dns_config_proto_enumTypes[0] return &file_app_dns_config_proto_enumTypes[0]
} }
func (x QueryStrategy) Number() protoreflect.EnumNumber { func (x DomainMatchingType) Number() protoreflect.EnumNumber {
return protoreflect.EnumNumber(x) return protoreflect.EnumNumber(x)
} }
// Deprecated: Use QueryStrategy.Descriptor instead. // Deprecated: Use DomainMatchingType.Descriptor instead.
func (QueryStrategy) EnumDescriptor() ([]byte, []int) { func (DomainMatchingType) EnumDescriptor() ([]byte, []int) {
return file_app_dns_config_proto_rawDescGZIP(), []int{0} return file_app_dns_config_proto_rawDescGZIP(), []int{0}
} }
type CacheStrategy int32
const (
CacheStrategy_Cache_ALL CacheStrategy = 0
CacheStrategy_Cache_NOERROR CacheStrategy = 1
CacheStrategy_Cache_DISABLE CacheStrategy = 2
)
// Enum value maps for CacheStrategy.
var (
CacheStrategy_name = map[int32]string{
0: "Cache_ALL",
1: "Cache_NOERROR",
2: "Cache_DISABLE",
}
CacheStrategy_value = map[string]int32{
"Cache_ALL": 0,
"Cache_NOERROR": 1,
"Cache_DISABLE": 2,
}
)
func (x CacheStrategy) Enum() *CacheStrategy {
p := new(CacheStrategy)
*p = x
return p
}
func (x CacheStrategy) String() string {
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
func (CacheStrategy) Descriptor() protoreflect.EnumDescriptor {
return file_app_dns_config_proto_enumTypes[1].Descriptor()
}
func (CacheStrategy) Type() protoreflect.EnumType {
return &file_app_dns_config_proto_enumTypes[1]
}
func (x CacheStrategy) Number() protoreflect.EnumNumber {
return protoreflect.EnumNumber(x)
}
// Deprecated: Use CacheStrategy.Descriptor instead.
func (CacheStrategy) EnumDescriptor() ([]byte, []int) {
return file_app_dns_config_proto_rawDescGZIP(), []int{1}
}
type NameServer struct { type NameServer struct {
state protoimpl.MessageState state protoimpl.MessageState
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
Address *net.Endpoint `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` Address *net.Endpoint `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
ClientIp []byte `protobuf:"bytes,5,opt,name=client_ip,json=clientIp,proto3" json:"client_ip,omitempty"` PrioritizedDomain []*NameServer_PriorityDomain `protobuf:"bytes,2,rep,name=prioritized_domain,json=prioritizedDomain,proto3" json:"prioritized_domain,omitempty"`
SkipFallback bool `protobuf:"varint,6,opt,name=skipFallback,proto3" json:"skipFallback,omitempty"` Geoip []*router.GeoIP `protobuf:"bytes,3,rep,name=geoip,proto3" json:"geoip,omitempty"`
PrioritizedDomain []*domain.Domain `protobuf:"bytes,2,rep,name=prioritized_domain,json=prioritizedDomain,proto3" json:"prioritized_domain,omitempty"` OriginalRules []*NameServer_OriginalRule `protobuf:"bytes,4,rep,name=original_rules,json=originalRules,proto3" json:"original_rules,omitempty"`
Geoip []*geoip.GeoIP `protobuf:"bytes,3,rep,name=geoip,proto3" json:"geoip,omitempty"`
OriginalRules []*NameServer_OriginalRule `protobuf:"bytes,4,rep,name=original_rules,json=originalRules,proto3" json:"original_rules,omitempty"`
} }
func (x *NameServer) Reset() { func (x *NameServer) Reset() {
@@ -173,28 +129,14 @@ func (x *NameServer) GetAddress() *net.Endpoint {
return nil return nil
} }
func (x *NameServer) GetClientIp() []byte { func (x *NameServer) GetPrioritizedDomain() []*NameServer_PriorityDomain {
if x != nil {
return x.ClientIp
}
return nil
}
func (x *NameServer) GetSkipFallback() bool {
if x != nil {
return x.SkipFallback
}
return false
}
func (x *NameServer) GetPrioritizedDomain() []*domain.Domain {
if x != nil { if x != nil {
return x.PrioritizedDomain return x.PrioritizedDomain
} }
return nil return nil
} }
func (x *NameServer) GetGeoip() []*geoip.GeoIP { func (x *NameServer) GetGeoip() []*router.GeoIP {
if x != nil { if x != nil {
return x.Geoip return x.Geoip
} }
@@ -232,10 +174,6 @@ type Config struct {
StaticHosts []*Config_HostMapping `protobuf:"bytes,4,rep,name=static_hosts,json=staticHosts,proto3" json:"static_hosts,omitempty"` StaticHosts []*Config_HostMapping `protobuf:"bytes,4,rep,name=static_hosts,json=staticHosts,proto3" json:"static_hosts,omitempty"`
// Tag is the inbound tag of DNS client. // Tag is the inbound tag of DNS client.
Tag string `protobuf:"bytes,6,opt,name=tag,proto3" json:"tag,omitempty"` Tag string `protobuf:"bytes,6,opt,name=tag,proto3" json:"tag,omitempty"`
// DisableCache disables DNS cache
CacheStrategy CacheStrategy `protobuf:"varint,8,opt,name=cache_strategy,json=cacheStrategy,proto3,enum=xray.app.dns.CacheStrategy" json:"cache_strategy,omitempty"`
QueryStrategy QueryStrategy `protobuf:"varint,9,opt,name=query_strategy,json=queryStrategy,proto3,enum=xray.app.dns.QueryStrategy" json:"query_strategy,omitempty"`
DisableFallback bool `protobuf:"varint,10,opt,name=disableFallback,proto3" json:"disableFallback,omitempty"`
} }
func (x *Config) Reset() { func (x *Config) Reset() {
@@ -314,25 +252,59 @@ func (x *Config) GetTag() string {
return "" return ""
} }
func (x *Config) GetCacheStrategy() CacheStrategy { type NameServer_PriorityDomain struct {
if x != nil { state protoimpl.MessageState
return x.CacheStrategy sizeCache protoimpl.SizeCache
} unknownFields protoimpl.UnknownFields
return CacheStrategy_Cache_ALL
Type DomainMatchingType `protobuf:"varint,1,opt,name=type,proto3,enum=xray.app.dns.DomainMatchingType" json:"type,omitempty"`
Domain string `protobuf:"bytes,2,opt,name=domain,proto3" json:"domain,omitempty"`
} }
func (x *Config) GetQueryStrategy() QueryStrategy { func (x *NameServer_PriorityDomain) Reset() {
if x != nil { *x = NameServer_PriorityDomain{}
return x.QueryStrategy if protoimpl.UnsafeEnabled {
mi := &file_app_dns_config_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
} }
return QueryStrategy_USE_IP
} }
func (x *Config) GetDisableFallback() bool { func (x *NameServer_PriorityDomain) String() string {
if x != nil { return protoimpl.X.MessageStringOf(x)
return x.DisableFallback }
func (*NameServer_PriorityDomain) ProtoMessage() {}
func (x *NameServer_PriorityDomain) ProtoReflect() protoreflect.Message {
mi := &file_app_dns_config_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
} }
return false return mi.MessageOf(x)
}
// Deprecated: Use NameServer_PriorityDomain.ProtoReflect.Descriptor instead.
func (*NameServer_PriorityDomain) Descriptor() ([]byte, []int) {
return file_app_dns_config_proto_rawDescGZIP(), []int{0, 0}
}
func (x *NameServer_PriorityDomain) GetType() DomainMatchingType {
if x != nil {
return x.Type
}
return DomainMatchingType_Full
}
func (x *NameServer_PriorityDomain) GetDomain() string {
if x != nil {
return x.Domain
}
return ""
} }
type NameServer_OriginalRule struct { type NameServer_OriginalRule struct {
@@ -347,7 +319,7 @@ type NameServer_OriginalRule struct {
func (x *NameServer_OriginalRule) Reset() { func (x *NameServer_OriginalRule) Reset() {
*x = NameServer_OriginalRule{} *x = NameServer_OriginalRule{}
if protoimpl.UnsafeEnabled { if protoimpl.UnsafeEnabled {
mi := &file_app_dns_config_proto_msgTypes[2] mi := &file_app_dns_config_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -360,7 +332,7 @@ func (x *NameServer_OriginalRule) String() string {
func (*NameServer_OriginalRule) ProtoMessage() {} func (*NameServer_OriginalRule) ProtoMessage() {}
func (x *NameServer_OriginalRule) ProtoReflect() protoreflect.Message { func (x *NameServer_OriginalRule) ProtoReflect() protoreflect.Message {
mi := &file_app_dns_config_proto_msgTypes[2] mi := &file_app_dns_config_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil { if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -373,7 +345,7 @@ func (x *NameServer_OriginalRule) ProtoReflect() protoreflect.Message {
// Deprecated: Use NameServer_OriginalRule.ProtoReflect.Descriptor instead. // Deprecated: Use NameServer_OriginalRule.ProtoReflect.Descriptor instead.
func (*NameServer_OriginalRule) Descriptor() ([]byte, []int) { func (*NameServer_OriginalRule) Descriptor() ([]byte, []int) {
return file_app_dns_config_proto_rawDescGZIP(), []int{0, 0} return file_app_dns_config_proto_rawDescGZIP(), []int{0, 1}
} }
func (x *NameServer_OriginalRule) GetRule() string { func (x *NameServer_OriginalRule) GetRule() string {
@@ -395,18 +367,19 @@ type Config_HostMapping struct {
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
Type domain.MatchingType `protobuf:"varint,1,opt,name=type,proto3,enum=xray.common.matcher.domain.MatchingType" json:"type,omitempty"` Type DomainMatchingType `protobuf:"varint,1,opt,name=type,proto3,enum=xray.app.dns.DomainMatchingType" json:"type,omitempty"`
Domain string `protobuf:"bytes,2,opt,name=domain,proto3" json:"domain,omitempty"` Domain string `protobuf:"bytes,2,opt,name=domain,proto3" json:"domain,omitempty"`
Ip [][]byte `protobuf:"bytes,3,rep,name=ip,proto3" json:"ip,omitempty"` Ip [][]byte `protobuf:"bytes,3,rep,name=ip,proto3" json:"ip,omitempty"`
// ProxiedDomain indicates the mapped domain has the same IP address on this // ProxiedDomain indicates the mapped domain has the same IP address on this
// domain. Xray will use this domain for IP queries. // domain. Xray will use this domain for IP queries. This field is only
// effective if ip is empty.
ProxiedDomain string `protobuf:"bytes,4,opt,name=proxied_domain,json=proxiedDomain,proto3" json:"proxied_domain,omitempty"` ProxiedDomain string `protobuf:"bytes,4,opt,name=proxied_domain,json=proxiedDomain,proto3" json:"proxied_domain,omitempty"`
} }
func (x *Config_HostMapping) Reset() { func (x *Config_HostMapping) Reset() {
*x = Config_HostMapping{} *x = Config_HostMapping{}
if protoimpl.UnsafeEnabled { if protoimpl.UnsafeEnabled {
mi := &file_app_dns_config_proto_msgTypes[4] mi := &file_app_dns_config_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -419,7 +392,7 @@ func (x *Config_HostMapping) String() string {
func (*Config_HostMapping) ProtoMessage() {} func (*Config_HostMapping) ProtoMessage() {}
func (x *Config_HostMapping) ProtoReflect() protoreflect.Message { func (x *Config_HostMapping) ProtoReflect() protoreflect.Message {
mi := &file_app_dns_config_proto_msgTypes[4] mi := &file_app_dns_config_proto_msgTypes[5]
if protoimpl.UnsafeEnabled && x != nil { if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -435,11 +408,11 @@ func (*Config_HostMapping) Descriptor() ([]byte, []int) {
return file_app_dns_config_proto_rawDescGZIP(), []int{1, 1} return file_app_dns_config_proto_rawDescGZIP(), []int{1, 1}
} }
func (x *Config_HostMapping) GetType() domain.MatchingType { func (x *Config_HostMapping) GetType() DomainMatchingType {
if x != nil { if x != nil {
return x.Type return x.Type
} }
return domain.MatchingType_Full return DomainMatchingType_Full
} }
func (x *Config_HostMapping) GetDomain() string { func (x *Config_HostMapping) GetDomain() string {
@@ -471,96 +444,79 @@ var file_app_dns_config_proto_rawDesc = []byte{
0x2e, 0x64, 0x6e, 0x73, 0x1a, 0x18, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6e, 0x65, 0x74, 0x2e, 0x64, 0x6e, 0x73, 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, 0x1c, 0x2f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c,
0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6e, 0x65, 0x74, 0x2f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6e, 0x65, 0x74, 0x2f, 0x64, 0x65, 0x73, 0x74, 0x69,
0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x22, 0x63, 0x6f, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x17, 0x61, 0x70,
0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2f, 0x64, 0x6f, 0x6d, 0x70, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e,
0x61, 0x69, 0x6e, 0x2f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xad, 0x03, 0x0a, 0x0a, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65,
0x1a, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x72, 0x76, 0x65, 0x72, 0x12, 0x33, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18,
0x2f, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x2f, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d,
0x74, 0x6f, 0x22, 0x93, 0x03, 0x0a, 0x0a, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74,
0x72, 0x12, 0x33, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x56, 0x0a, 0x12, 0x70, 0x72, 0x69,
0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18,
0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x07, 0x61, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70,
0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e,
0x5f, 0x69, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x11,
0x74, 0x49, 0x70, 0x12, 0x22, 0x0a, 0x0c, 0x73, 0x6b, 0x69, 0x70, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x7a, 0x65, 0x64, 0x44, 0x6f, 0x6d, 0x61, 0x69,
0x61, 0x63, 0x6b, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x73, 0x6b, 0x69, 0x70, 0x46, 0x6e, 0x12, 0x2c, 0x0a, 0x05, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b,
0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x12, 0x51, 0x0a, 0x12, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x32, 0x16, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74,
0x69, 0x74, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x52, 0x05, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x12,
0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x4c, 0x0a, 0x0e, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x72, 0x75, 0x6c, 0x65,
0x6e, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61,
0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x11, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65,
0x69, 0x7a, 0x65, 0x64, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x36, 0x0a, 0x05, 0x67, 0x65, 0x72, 0x2e, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x0d,
0x6f, 0x69, 0x70, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x1a, 0x5e, 0x0a,
0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x0e, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12,
0x67, 0x65, 0x6f, 0x69, 0x70, 0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x52, 0x05, 0x67, 0x65, 0x6f, 0x34, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e,
0x69, 0x70, 0x12, 0x4c, 0x0a, 0x0e, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x72, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x44, 0x6f, 0x6d,
0x75, 0x6c, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x54, 0x79, 0x70, 0x65, 0x52,
0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65,
0x72, 0x76, 0x65, 0x72, 0x2e, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x52, 0x75, 0x6c,
0x65, 0x52, 0x0d, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x73,
0x1a, 0x36, 0x0a, 0x0c, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x52, 0x75, 0x6c, 0x65,
0x12, 0x12, 0x0a, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
0x72, 0x75, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01,
0x28, 0x0d, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x22, 0xdf, 0x05, 0x0a, 0x06, 0x43, 0x6f, 0x6e,
0x66, 0x69, 0x67, 0x12, 0x3f, 0x0a, 0x0b, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65,
0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x45, 0x6e, 0x64, 0x70, 0x6f,
0x69, 0x6e, 0x74, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0b, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72,
0x76, 0x65, 0x72, 0x73, 0x12, 0x39, 0x0a, 0x0b, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x65, 0x72,
0x76, 0x65, 0x72, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x78, 0x72, 0x61, 0x79,
0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72,
0x76, 0x65, 0x72, 0x52, 0x0a, 0x6e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12,
0x39, 0x0a, 0x05, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f,
0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x43, 0x6f,
0x6e, 0x66, 0x69, 0x67, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x42,
0x02, 0x18, 0x01, 0x52, 0x05, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6c,
0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x63,
0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x70, 0x12, 0x43, 0x0a, 0x0c, 0x73, 0x74, 0x61, 0x74, 0x69,
0x63, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e,
0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x43, 0x6f, 0x6e,
0x66, 0x69, 0x67, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52,
0x0b, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x12, 0x10, 0x0a, 0x03,
0x74, 0x61, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x42,
0x0a, 0x0e, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79,
0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x43, 0x61, 0x63, 0x68, 0x65, 0x53, 0x74, 0x72, 0x61, 0x74,
0x65, 0x67, 0x79, 0x52, 0x0d, 0x63, 0x61, 0x63, 0x68, 0x65, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65,
0x67, 0x79, 0x12, 0x42, 0x0a, 0x0e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x73, 0x74, 0x72, 0x61,
0x74, 0x65, 0x67, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x78, 0x72, 0x61,
0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53,
0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x0d, 0x71, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74,
0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x28, 0x0a, 0x0f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c,
0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52,
0x0f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b,
0x1a, 0x55, 0x0a, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10,
0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79,
0x12, 0x31, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 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, 0x05, 0x76, 0x61,
0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x9a, 0x01, 0x0a, 0x0b, 0x48, 0x6f, 0x73, 0x74,
0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x3c, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18,
0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x28, 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, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x54, 0x79, 0x70, 0x65, 0x52,
0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18,
0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x1a, 0x36, 0x0a,
0x02, 0x69, 0x70, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x02, 0x69, 0x70, 0x12, 0x25, 0x0a, 0x0c, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x12, 0x0a,
0x0e, 0x70, 0x72, 0x6f, 0x78, 0x69, 0x65, 0x64, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x75, 0x6c,
0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78, 0x69, 0x65, 0x64, 0x44, 0x6f, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52,
0x6d, 0x61, 0x69, 0x6e, 0x4a, 0x04, 0x08, 0x07, 0x10, 0x08, 0x2a, 0x35, 0x0a, 0x0d, 0x51, 0x75, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x22, 0x9f, 0x04, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
0x65, 0x72, 0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x0a, 0x0a, 0x06, 0x55, 0x12, 0x3f, 0x0a, 0x0b, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x18,
0x53, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d,
0x50, 0x34, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x10, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74,
0x02, 0x2a, 0x44, 0x0a, 0x0d, 0x43, 0x61, 0x63, 0x68, 0x65, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0b, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72,
0x67, 0x79, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x41, 0x4c, 0x4c, 0x10, 0x73, 0x12, 0x39, 0x0a, 0x0b, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
0x00, 0x12, 0x11, 0x0a, 0x0d, 0x43, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x4e, 0x4f, 0x45, 0x52, 0x52, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
0x4f, 0x52, 0x10, 0x01, 0x12, 0x11, 0x0a, 0x0d, 0x43, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x44, 0x49, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72,
0x53, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x02, 0x42, 0x46, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x52, 0x0a, 0x6e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x39, 0x0a, 0x05,
0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x50, 0x01, 0x5a, 0x21, 0x67, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x78, 0x72,
0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69,
0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x64, 0x6e, 0x73, 0x67, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x42, 0x02, 0x18, 0x01,
0xaa, 0x02, 0x0c, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x44, 0x6e, 0x73, 0x62, 0x52, 0x05, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e,
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x74, 0x5f, 0x69, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65,
0x6e, 0x74, 0x49, 0x70, 0x12, 0x43, 0x0a, 0x0c, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x5f, 0x68,
0x6f, 0x73, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61,
0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
0x2e, 0x48, 0x6f, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x0b, 0x73, 0x74,
0x61, 0x74, 0x69, 0x63, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67,
0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x1a, 0x55, 0x0a, 0x0a, 0x48,
0x6f, 0x73, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79,
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x31, 0x0a, 0x05, 0x76,
0x61, 0x6c, 0x75, 0x65, 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, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02,
0x38, 0x01, 0x1a, 0x92, 0x01, 0x0a, 0x0b, 0x48, 0x6f, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69,
0x6e, 0x67, 0x12, 0x34, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e,
0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e,
0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x54, 0x79,
0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61,
0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e,
0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x02, 0x69, 0x70,
0x12, 0x25, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x78, 0x69, 0x65, 0x64, 0x5f, 0x64, 0x6f, 0x6d, 0x61,
0x69, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78, 0x69, 0x65,
0x64, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x2a, 0x45, 0x0a, 0x12, 0x44, 0x6f, 0x6d, 0x61, 0x69,
0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x54, 0x79, 0x70, 0x65, 0x12, 0x08, 0x0a,
0x04, 0x46, 0x75, 0x6c, 0x6c, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x53, 0x75, 0x62, 0x64, 0x6f,
0x6d, 0x61, 0x69, 0x6e, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x4b, 0x65, 0x79, 0x77, 0x6f, 0x72,
0x64, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x52, 0x65, 0x67, 0x65, 0x78, 0x10, 0x03, 0x42, 0x46,
0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64,
0x6e, 0x73, 0x50, 0x01, 0x5a, 0x21, 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, 0x64, 0x6e, 0x73, 0xaa, 0x02, 0x0c, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41,
0x70, 0x70, 0x2e, 0x44, 0x6e, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
} }
var ( var (
@@ -575,40 +531,37 @@ func file_app_dns_config_proto_rawDescGZIP() []byte {
return file_app_dns_config_proto_rawDescData return file_app_dns_config_proto_rawDescData
} }
var file_app_dns_config_proto_enumTypes = make([]protoimpl.EnumInfo, 2) var file_app_dns_config_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
var file_app_dns_config_proto_msgTypes = make([]protoimpl.MessageInfo, 5) var file_app_dns_config_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
var file_app_dns_config_proto_goTypes = []interface{}{ var file_app_dns_config_proto_goTypes = []interface{}{
(QueryStrategy)(0), // 0: xray.app.dns.QueryStrategy (DomainMatchingType)(0), // 0: xray.app.dns.DomainMatchingType
(CacheStrategy)(0), // 1: xray.app.dns.CacheStrategy (*NameServer)(nil), // 1: xray.app.dns.NameServer
(*NameServer)(nil), // 2: xray.app.dns.NameServer (*Config)(nil), // 2: xray.app.dns.Config
(*Config)(nil), // 3: xray.app.dns.Config (*NameServer_PriorityDomain)(nil), // 3: xray.app.dns.NameServer.PriorityDomain
(*NameServer_OriginalRule)(nil), // 4: xray.app.dns.NameServer.OriginalRule (*NameServer_OriginalRule)(nil), // 4: xray.app.dns.NameServer.OriginalRule
nil, // 5: xray.app.dns.Config.HostsEntry nil, // 5: xray.app.dns.Config.HostsEntry
(*Config_HostMapping)(nil), // 6: xray.app.dns.Config.HostMapping (*Config_HostMapping)(nil), // 6: xray.app.dns.Config.HostMapping
(*net.Endpoint)(nil), // 7: xray.common.net.Endpoint (*net.Endpoint)(nil), // 7: xray.common.net.Endpoint
(*domain.Domain)(nil), // 8: xray.common.matcher.domain.Domain (*router.GeoIP)(nil), // 8: xray.app.router.GeoIP
(*geoip.GeoIP)(nil), // 9: xray.common.matcher.geoip.GeoIP (*net.IPOrDomain)(nil), // 9: xray.common.net.IPOrDomain
(*net.IPOrDomain)(nil), // 10: xray.common.net.IPOrDomain
(domain.MatchingType)(0), // 11: xray.common.matcher.domain.MatchingType
} }
var file_app_dns_config_proto_depIdxs = []int32{ var file_app_dns_config_proto_depIdxs = []int32{
7, // 0: xray.app.dns.NameServer.address:type_name -> xray.common.net.Endpoint 7, // 0: xray.app.dns.NameServer.address:type_name -> xray.common.net.Endpoint
8, // 1: xray.app.dns.NameServer.prioritized_domain:type_name -> xray.common.matcher.domain.Domain 3, // 1: xray.app.dns.NameServer.prioritized_domain:type_name -> xray.app.dns.NameServer.PriorityDomain
9, // 2: xray.app.dns.NameServer.geoip:type_name -> xray.common.matcher.geoip.GeoIP 8, // 2: xray.app.dns.NameServer.geoip:type_name -> xray.app.router.GeoIP
4, // 3: xray.app.dns.NameServer.original_rules:type_name -> xray.app.dns.NameServer.OriginalRule 4, // 3: xray.app.dns.NameServer.original_rules:type_name -> xray.app.dns.NameServer.OriginalRule
7, // 4: xray.app.dns.Config.NameServers:type_name -> xray.common.net.Endpoint 7, // 4: xray.app.dns.Config.NameServers:type_name -> xray.common.net.Endpoint
2, // 5: xray.app.dns.Config.name_server:type_name -> xray.app.dns.NameServer 1, // 5: xray.app.dns.Config.name_server:type_name -> xray.app.dns.NameServer
5, // 6: xray.app.dns.Config.Hosts:type_name -> xray.app.dns.Config.HostsEntry 5, // 6: xray.app.dns.Config.Hosts:type_name -> xray.app.dns.Config.HostsEntry
6, // 7: xray.app.dns.Config.static_hosts:type_name -> xray.app.dns.Config.HostMapping 6, // 7: xray.app.dns.Config.static_hosts:type_name -> xray.app.dns.Config.HostMapping
1, // 8: xray.app.dns.Config.cache_strategy:type_name -> xray.app.dns.CacheStrategy 0, // 8: xray.app.dns.NameServer.PriorityDomain.type:type_name -> xray.app.dns.DomainMatchingType
0, // 9: xray.app.dns.Config.query_strategy:type_name -> xray.app.dns.QueryStrategy 9, // 9: xray.app.dns.Config.HostsEntry.value:type_name -> xray.common.net.IPOrDomain
10, // 10: xray.app.dns.Config.HostsEntry.value:type_name -> xray.common.net.IPOrDomain 0, // 10: xray.app.dns.Config.HostMapping.type:type_name -> xray.app.dns.DomainMatchingType
11, // 11: xray.app.dns.Config.HostMapping.type:type_name -> xray.common.matcher.domain.MatchingType 11, // [11:11] is the sub-list for method output_type
12, // [12:12] is the sub-list for method output_type 11, // [11:11] is the sub-list for method input_type
12, // [12:12] is the sub-list for method input_type 11, // [11:11] is the sub-list for extension type_name
12, // [12:12] is the sub-list for extension type_name 11, // [11:11] is the sub-list for extension extendee
12, // [12:12] is the sub-list for extension extendee 0, // [0:11] is the sub-list for field type_name
0, // [0:12] is the sub-list for field type_name
} }
func init() { file_app_dns_config_proto_init() } func init() { file_app_dns_config_proto_init() }
@@ -642,6 +595,18 @@ func file_app_dns_config_proto_init() {
} }
} }
file_app_dns_config_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { file_app_dns_config_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*NameServer_PriorityDomain); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_dns_config_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*NameServer_OriginalRule); i { switch v := v.(*NameServer_OriginalRule); i {
case 0: case 0:
return &v.state return &v.state
@@ -653,7 +618,7 @@ func file_app_dns_config_proto_init() {
return nil return nil
} }
} }
file_app_dns_config_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { file_app_dns_config_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Config_HostMapping); i { switch v := v.(*Config_HostMapping); i {
case 0: case 0:
return &v.state return &v.state
@@ -671,8 +636,8 @@ func file_app_dns_config_proto_init() {
File: protoimpl.DescBuilder{ File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(), GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_app_dns_config_proto_rawDesc, RawDescriptor: file_app_dns_config_proto_rawDesc,
NumEnums: 2, NumEnums: 1,
NumMessages: 5, NumMessages: 6,
NumExtensions: 0, NumExtensions: 0,
NumServices: 0, NumServices: 0,
}, },

View File

@@ -8,34 +8,31 @@ option java_multiple_files = true;
import "common/net/address.proto"; import "common/net/address.proto";
import "common/net/destination.proto"; import "common/net/destination.proto";
import "common/matcher/domain/domain.proto"; import "app/router/config.proto";
import "common/matcher/geoip/geoip.proto";
message NameServer { message NameServer {
xray.common.net.Endpoint address = 1; xray.common.net.Endpoint address = 1;
bytes client_ip = 5;
bool skipFallback = 6; message PriorityDomain {
DomainMatchingType type = 1;
string domain = 2;
}
message OriginalRule { message OriginalRule {
string rule = 1; string rule = 1;
uint32 size = 2; uint32 size = 2;
} }
repeated xray.common.matcher.domain.Domain prioritized_domain = 2; repeated PriorityDomain prioritized_domain = 2;
repeated xray.common.matcher.geoip.GeoIP geoip = 3; repeated xray.app.router.GeoIP geoip = 3;
repeated OriginalRule original_rules = 4; repeated OriginalRule original_rules = 4;
} }
enum QueryStrategy { enum DomainMatchingType {
USE_IP = 0; Full = 0;
USE_IP4 = 1; Subdomain = 1;
USE_IP6 = 2; Keyword = 2;
} Regex = 3;
enum CacheStrategy {
Cache_ALL = 0;
Cache_NOERROR = 1;
Cache_DISABLE = 2;
} }
message Config { message Config {
@@ -56,13 +53,14 @@ message Config {
bytes client_ip = 3; bytes client_ip = 3;
message HostMapping { message HostMapping {
xray.common.matcher.domain.MatchingType type = 1; DomainMatchingType type = 1;
string domain = 2; string domain = 2;
repeated bytes ip = 3; repeated bytes ip = 3;
// ProxiedDomain indicates the mapped domain has the same IP address on this // ProxiedDomain indicates the mapped domain has the same IP address on this
// domain. Xray will use this domain for IP queries. // domain. Xray will use this domain for IP queries. This field is only
// effective if ip is empty.
string proxied_domain = 4; string proxied_domain = 4;
} }
@@ -72,11 +70,4 @@ message Config {
string tag = 6; string tag = 6;
reserved 7; reserved 7;
// DisableCache disables DNS cache
CacheStrategy cache_strategy = 8;
QueryStrategy query_strategy = 9;
bool disableFallback = 10;
} }

View File

@@ -2,312 +2,3 @@
package dns package dns
//go:generate go run github.com/xtls/xray-core/common/errors/errorgen //go:generate go run github.com/xtls/xray-core/common/errors/errorgen
import (
"context"
"fmt"
"strings"
"sync"
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/matcher/geoip"
"github.com/xtls/xray-core/common/matcher/str"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/session"
"github.com/xtls/xray-core/features"
"github.com/xtls/xray-core/features/dns"
)
// DNS is a DNS rely server.
type DNS struct {
sync.Mutex
tag string
cacheStrategy CacheStrategy
disableFallback bool
ipOption *dns.IPOption
hosts *StaticHosts
clients []*Client
ctx context.Context
domainMatcher str.IndexMatcher
matcherInfos []DomainMatcherInfo
}
// DomainMatcherInfo contains information attached to index returned by Server.domainMatcher
type DomainMatcherInfo struct {
clientIdx uint16
domainRuleIdx uint16
}
// New creates a new DNS server with given configuration.
func New(ctx context.Context, config *Config) (*DNS, error) {
var tag string
if len(config.Tag) > 0 {
tag = config.Tag
} else {
tag = generateRandomTag()
}
var clientIP net.IP
switch len(config.ClientIp) {
case 0, net.IPv4len, net.IPv6len:
clientIP = net.IP(config.ClientIp)
default:
return nil, newError("unexpected client IP length ", len(config.ClientIp))
}
var ipOption *dns.IPOption
switch config.QueryStrategy {
case QueryStrategy_USE_IP:
ipOption = &dns.IPOption{
IPv4Enable: true,
IPv6Enable: true,
FakeEnable: false,
}
case QueryStrategy_USE_IP4:
ipOption = &dns.IPOption{
IPv4Enable: true,
IPv6Enable: false,
FakeEnable: false,
}
case QueryStrategy_USE_IP6:
ipOption = &dns.IPOption{
IPv4Enable: false,
IPv6Enable: true,
FakeEnable: false,
}
}
hosts, err := NewStaticHosts(config.StaticHosts, config.Hosts)
if err != nil {
return nil, newError("failed to create hosts").Base(err)
}
clients := []*Client{}
domainRuleCount := 0
for _, ns := range config.NameServer {
domainRuleCount += len(ns.PrioritizedDomain)
}
// MatcherInfos is ensured to cover the maximum index domainMatcher could return, where matcher's index starts from 1
matcherInfos := make([]DomainMatcherInfo, domainRuleCount+1)
domainMatcher := &str.MatcherGroup{}
geoipContainer := geoip.GeoIPMatcherContainer{}
for _, endpoint := range config.NameServers {
features.PrintDeprecatedFeatureWarning("simple DNS server")
client, err := NewSimpleClient(ctx, endpoint, clientIP)
if err != nil {
return nil, newError("failed to create client").Base(err)
}
clients = append(clients, client)
}
for _, ns := range config.NameServer {
clientIdx := len(clients)
updateDomain := func(domainRule str.Matcher, originalRuleIdx int, matcherInfos []DomainMatcherInfo) error {
midx := domainMatcher.Add(domainRule)
matcherInfos[midx] = DomainMatcherInfo{
clientIdx: uint16(clientIdx),
domainRuleIdx: uint16(originalRuleIdx),
}
return nil
}
myClientIP := clientIP
switch len(ns.ClientIp) {
case net.IPv4len, net.IPv6len:
myClientIP = net.IP(ns.ClientIp)
}
client, err := NewClient(ctx, ns, myClientIP, geoipContainer, &matcherInfos, updateDomain)
if err != nil {
return nil, newError("failed to create client").Base(err)
}
clients = append(clients, client)
}
// If there is no DNS client in config, add a `localhost` DNS client
if len(clients) == 0 {
clients = append(clients, NewLocalDNSClient())
}
return &DNS{
tag: tag,
hosts: hosts,
ipOption: ipOption,
clients: clients,
ctx: ctx,
domainMatcher: domainMatcher,
matcherInfos: matcherInfos,
cacheStrategy: config.CacheStrategy,
disableFallback: config.DisableFallback,
}, nil
}
// Type implements common.HasType.
func (*DNS) Type() interface{} {
return dns.ClientType()
}
// Start implements common.Runnable.
func (s *DNS) Start() error {
return nil
}
// Close implements common.Closable.
func (s *DNS) Close() error {
return nil
}
// IsOwnLink implements proxy.dns.ownLinkVerifier
func (s *DNS) IsOwnLink(ctx context.Context) bool {
inbound := session.InboundFromContext(ctx)
return inbound != nil && inbound.Tag == s.tag
}
// LookupIP implements dns.Client.
func (s *DNS) LookupIP(domain string) ([]net.IP, error) {
return s.lookupIPInternal(domain, s.ipOption.Copy())
}
// LookupOptions implements dns.Client.
func (s *DNS) LookupOptions(domain string, opts ...dns.Option) ([]net.IP, error) {
opt := s.ipOption.Copy()
for _, o := range opts {
if o != nil {
o(opt)
}
}
return s.lookupIPInternal(domain, opt)
}
// LookupIPv4 implements dns.IPv4Lookup.
func (s *DNS) LookupIPv4(domain string) ([]net.IP, error) {
return s.lookupIPInternal(domain, &dns.IPOption{
IPv4Enable: true,
})
}
// LookupIPv6 implements dns.IPv6Lookup.
func (s *DNS) LookupIPv6(domain string) ([]net.IP, error) {
return s.lookupIPInternal(domain, &dns.IPOption{
IPv6Enable: true,
})
}
func (s *DNS) lookupIPInternal(domain string, option *dns.IPOption) ([]net.IP, error) {
if domain == "" {
return nil, newError("empty domain name")
}
if isQuery(option) {
return nil, newError("empty option: Impossible.").AtWarning()
}
// Normalize the FQDN form query
if strings.HasSuffix(domain, ".") {
domain = domain[:len(domain)-1]
}
// Static host lookup
switch addrs := s.hosts.Lookup(domain, option); {
case addrs == nil: // Domain not recorded in static host
break
case len(addrs) == 0: // Domain recorded, but no valid IP returned (e.g. IPv4 address with only IPv6 enabled)
return nil, dns.ErrEmptyResponse
case len(addrs) == 1 && addrs[0].Family().IsDomain(): // Domain replacement
newError("domain replaced: ", domain, " -> ", addrs[0].Domain()).WriteToLog()
domain = addrs[0].Domain()
default:
// Successfully found ip records in static host.
// Skip hosts mapping result in FakeDNS query.
if isIPQuery(option) {
newError("returning ", len(addrs), " IP(s) for domain ", domain, " -> ", addrs).WriteToLog()
return toNetIP(addrs)
}
}
// Name servers lookup
errs := []error{}
ctx := session.ContextWithInbound(s.ctx, &session.Inbound{Tag: s.tag})
for _, client := range s.sortClients(domain, option) {
ips, err := client.QueryIP(ctx, domain, *option, s.cacheStrategy)
if len(ips) > 0 {
return ips, nil
}
if err != nil {
newError("failed to lookup ip for domain ", domain, " at server ", client.Name()).Base(err).WriteToLog()
errs = append(errs, err)
}
if err != context.Canceled && err != context.DeadlineExceeded && err != errExpectedIPNonMatch {
return nil, err
}
}
return nil, newError("returning nil for domain ", domain).Base(errors.Combine(errs...))
}
func (s *DNS) sortClients(domain string, option *dns.IPOption) []*Client {
clients := make([]*Client, 0, len(s.clients))
clientUsed := make([]bool, len(s.clients))
clientNames := make([]string, 0, len(s.clients))
domainRules := []string{}
defer func() {
if len(domainRules) > 0 {
newError("domain ", domain, " matches following rules: ", domainRules).AtDebug().WriteToLog()
}
if len(clientNames) > 0 {
newError("domain ", domain, " will use DNS in order: ", clientNames).AtDebug().WriteToLog()
}
if len(clients) == 0 {
clients = append(clients, s.clients[0])
clientNames = append(clientNames, s.clients[0].Name())
newError("domain ", domain, " will use the first DNS: ", clientNames).AtDebug().WriteToLog()
}
}()
// Priority domain matching
for _, match := range s.domainMatcher.Match(domain) {
info := s.matcherInfos[match]
client := s.clients[info.clientIdx]
domainRule := client.domains[info.domainRuleIdx]
if !canQueryOnClient(option, client) {
newError("skipping the client " + client.Name()).AtDebug().WriteToLog()
continue
}
domainRules = append(domainRules, fmt.Sprintf("%s(DNS idx:%d)", domainRule, info.clientIdx))
if clientUsed[info.clientIdx] {
continue
}
clientUsed[info.clientIdx] = true
clients = append(clients, client)
clientNames = append(clientNames, client.Name())
}
if !s.disableFallback {
// Default round-robin query
for idx, client := range s.clients {
if clientUsed[idx] || client.skipFallback {
continue
}
if !canQueryOnClient(option, client) {
newError("skipping the client " + client.Name()).AtDebug().WriteToLog()
continue
}
clientUsed[idx] = true
clients = append(clients, client)
clientNames = append(clientNames, client.Name())
}
}
return clients
}
func init() {
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
return New(ctx, config.(*Config))
}))
}

View File

@@ -42,10 +42,10 @@ type DoHNameServer struct {
name string name string
} }
// NewDoHNameServer creates DOH server object for remote resolving // NewDoHNameServer creates DOH client object for remote resolving
func NewDoHNameServer(url *url.URL, dispatcher routing.Dispatcher) (*DoHNameServer, error) { func NewDoHNameServer(url *url.URL, dispatcher routing.Dispatcher, clientIP net.IP) (*DoHNameServer, error) {
newError("DNS: created Remote DOH client for ", url.String()).AtInfo().WriteToLog() newError("DNS: created Remote DOH client for ", url.String()).AtInfo().WriteToLog()
s := baseDOHNameServer(url, "DOH") s := baseDOHNameServer(url, "DOH", clientIP)
s.dispatcher = dispatcher s.dispatcher = dispatcher
tr := &http.Transport{ tr := &http.Transport{
@@ -80,12 +80,6 @@ func NewDoHNameServer(url *url.URL, dispatcher routing.Dispatcher) (*DoHNameServ
if err != nil { if err != nil {
return nil, err return nil, err
} }
log.Record(&log.AccessMessage{
From: "DoH",
To: s.dohURL,
Status: log.AccessAccepted,
Detour: "local",
})
cc := common.ChainedClosable{} cc := common.ChainedClosable{}
if cw, ok := link.Writer.(common.Closable); ok { if cw, ok := link.Writer.(common.Closable); ok {
@@ -110,9 +104,9 @@ func NewDoHNameServer(url *url.URL, dispatcher routing.Dispatcher) (*DoHNameServ
} }
// NewDoHLocalNameServer creates DOH client object for local resolving // NewDoHLocalNameServer creates DOH client object for local resolving
func NewDoHLocalNameServer(url *url.URL) *DoHNameServer { func NewDoHLocalNameServer(url *url.URL, clientIP net.IP) *DoHNameServer {
url.Scheme = "https" url.Scheme = "https"
s := baseDOHNameServer(url, "DOHL") s := baseDOHNameServer(url, "DOHL", clientIP)
tr := &http.Transport{ tr := &http.Transport{
IdleConnTimeout: 90 * time.Second, IdleConnTimeout: 90 * time.Second,
ForceAttemptHTTP2: true, ForceAttemptHTTP2: true,
@@ -142,12 +136,13 @@ func NewDoHLocalNameServer(url *url.URL) *DoHNameServer {
return s return s
} }
func baseDOHNameServer(url *url.URL, prefix string) *DoHNameServer { func baseDOHNameServer(url *url.URL, prefix string, clientIP net.IP) *DoHNameServer {
s := &DoHNameServer{ s := &DoHNameServer{
ips: make(map[string]record), ips: make(map[string]record),
pub: pubsub.NewService(), clientIP: clientIP,
name: prefix + "//" + url.Host, pub: pubsub.NewService(),
dohURL: url.String(), name: prefix + "//" + url.Host,
dohURL: url.String(),
} }
s.cleanup = &task.Periodic{ s.cleanup = &task.Periodic{
Interval: time.Minute, Interval: time.Minute,
@@ -157,7 +152,7 @@ func baseDOHNameServer(url *url.URL, prefix string) *DoHNameServer {
return s return s
} }
// Name implements Server. // Name returns client name
func (s *DoHNameServer) Name() string { func (s *DoHNameServer) Name() string {
return s.name return s.name
} }
@@ -240,7 +235,7 @@ func (s *DoHNameServer) newReqID() uint16 {
return uint16(atomic.AddUint32(&s.reqID, 1)) return uint16(atomic.AddUint32(&s.reqID, 1))
} }
func (s *DoHNameServer) sendQuery(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption) { func (s *DoHNameServer) sendQuery(ctx context.Context, domain string, option dns_feature.IPOption) {
newError(s.name, " querying: ", domain).AtInfo().WriteToLog(session.ExportIDToError(ctx)) newError(s.name, " querying: ", domain).AtInfo().WriteToLog(session.ExportIDToError(ctx))
if s.name+"." == "DOH//"+domain { if s.name+"." == "DOH//"+domain {
@@ -248,7 +243,7 @@ func (s *DoHNameServer) sendQuery(ctx context.Context, domain string, clientIP n
return return
} }
reqs := buildReqMsgs(domain, option, s.newReqID, genEDNS0Options(clientIP)) reqs := buildReqMsgs(domain, option, s.newReqID, genEDNS0Options(s.clientIP))
var deadline time.Time var deadline time.Time
if d, ok := ctx.Deadline(); ok { if d, ok := ctx.Deadline(); ok {
@@ -269,8 +264,8 @@ func (s *DoHNameServer) sendQuery(ctx context.Context, domain string, clientIP n
} }
dnsCtx = session.ContextWithContent(dnsCtx, &session.Content{ dnsCtx = session.ContextWithContent(dnsCtx, &session.Content{
Protocol: "https", Protocol: "https",
SkipDNSResolve: true, //SkipRoutePick: true,
}) })
// forced to use mux for DOH // forced to use mux for DOH
@@ -354,7 +349,7 @@ func (s *DoHNameServer) findIPsForDomain(domain string, option dns_feature.IPOpt
} }
if len(ips) > 0 { if len(ips) > 0 {
return toNetIP(ips) return toNetIP(ips), nil
} }
if lastErr != nil { if lastErr != nil {
@@ -368,21 +363,15 @@ func (s *DoHNameServer) findIPsForDomain(domain string, option dns_feature.IPOpt
return nil, errRecordNotFound return nil, errRecordNotFound
} }
// QueryIP implements Server. // QueryIP is called from dns.Server->queryIPTimeout
func (s *DoHNameServer) QueryIP(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption, cs CacheStrategy) ([]net.IP, error) { // nolint: dupl func (s *DoHNameServer) QueryIP(ctx context.Context, domain string, option dns_feature.IPOption) ([]net.IP, error) { // nolint: dupl
fqdn := Fqdn(domain) fqdn := Fqdn(domain)
if cs == CacheStrategy_Cache_DISABLE { ips, err := s.findIPsForDomain(fqdn, option)
newError("DNS cache is disabled. Querying IP for ", domain, " at ", s.name).AtDebug().WriteToLog() if err != errRecordNotFound {
} else { newError(s.name, " cache HIT ", domain, " -> ", ips).Base(err).AtDebug().WriteToLog()
ips, err := s.findIPsForDomain(fqdn, option) log.Record(&log.DNSLog{s.name, domain, ips, log.DNSCacheHit, 0, err})
if err != errRecordNotFound { return ips, err
if cs == CacheStrategy_Cache_NOERROR && err == nil {
newError(s.name, " cache HIT ", domain, " -> ", ips).Base(err).AtDebug().WriteToLog()
log.Record(&log.DNSLog{s.name, domain, ips, log.DNSCacheHit, 0, err})
return ips, err
}
}
} }
// ipv4 and ipv6 belong to different subscription groups // ipv4 and ipv6 belong to different subscription groups
@@ -411,7 +400,7 @@ func (s *DoHNameServer) QueryIP(ctx context.Context, domain string, clientIP net
} }
close(done) close(done)
}() }()
s.sendQuery(ctx, fqdn, clientIP, option) s.sendQuery(ctx, fqdn, option)
start := time.Now() start := time.Now()
for { for {

View File

@@ -2,8 +2,8 @@ package dns
import ( import (
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/matcher/str"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/strmatcher"
"github.com/xtls/xray-core/features" "github.com/xtls/xray-core/features"
"github.com/xtls/xray-core/features/dns" "github.com/xtls/xray-core/features/dns"
) )
@@ -11,12 +11,31 @@ import (
// StaticHosts represents static domain-ip mapping in DNS server. // StaticHosts represents static domain-ip mapping in DNS server.
type StaticHosts struct { type StaticHosts struct {
ips [][]net.Address ips [][]net.Address
matchers *str.MatcherGroup matchers *strmatcher.MatcherGroup
}
var typeMap = map[DomainMatchingType]strmatcher.Type{
DomainMatchingType_Full: strmatcher.Full,
DomainMatchingType_Subdomain: strmatcher.Domain,
DomainMatchingType_Keyword: strmatcher.Substr,
DomainMatchingType_Regex: strmatcher.Regex,
}
func toStrMatcher(t DomainMatchingType, domain string) (strmatcher.Matcher, error) {
strMType, f := typeMap[t]
if !f {
return nil, newError("unknown mapping type", t).AtWarning()
}
matcher, err := strMType.New(domain)
if err != nil {
return nil, newError("failed to create str matcher").Base(err)
}
return matcher, nil
} }
// NewStaticHosts creates a new StaticHosts instance. // NewStaticHosts creates a new StaticHosts instance.
func NewStaticHosts(hosts []*Config_HostMapping, legacy map[string]*net.IPOrDomain) (*StaticHosts, error) { func NewStaticHosts(hosts []*Config_HostMapping, legacy map[string]*net.IPOrDomain) (*StaticHosts, error) {
g := new(str.MatcherGroup) g := new(strmatcher.MatcherGroup)
sh := &StaticHosts{ sh := &StaticHosts{
ips: make([][]net.Address, len(hosts)+len(legacy)+16), ips: make([][]net.Address, len(hosts)+len(legacy)+16),
matchers: g, matchers: g,
@@ -26,7 +45,7 @@ func NewStaticHosts(hosts []*Config_HostMapping, legacy map[string]*net.IPOrDoma
features.PrintDeprecatedFeatureWarning("simple host mapping") features.PrintDeprecatedFeatureWarning("simple host mapping")
for domain, ip := range legacy { for domain, ip := range legacy {
matcher, err := str.Full.New(domain) matcher, err := strmatcher.Full.New(domain)
common.Must(err) common.Must(err)
id := g.Add(matcher) id := g.Add(matcher)
@@ -47,9 +66,6 @@ func NewStaticHosts(hosts []*Config_HostMapping, legacy map[string]*net.IPOrDoma
id := g.Add(matcher) id := g.Add(matcher)
ips := make([]net.Address, 0, len(mapping.Ip)+1) ips := make([]net.Address, 0, len(mapping.Ip)+1)
switch { switch {
case len(mapping.ProxiedDomain) > 0:
ips = append(ips, net.DomainAddress(mapping.ProxiedDomain))
case len(mapping.Ip) > 0: case len(mapping.Ip) > 0:
for _, ip := range mapping.Ip { for _, ip := range mapping.Ip {
addr := net.IPAddress(ip) addr := net.IPAddress(ip)
@@ -59,56 +75,49 @@ func NewStaticHosts(hosts []*Config_HostMapping, legacy map[string]*net.IPOrDoma
ips = append(ips, addr) ips = append(ips, addr)
} }
case len(mapping.ProxiedDomain) > 0:
ips = append(ips, net.DomainAddress(mapping.ProxiedDomain))
default: default:
return nil, newError("neither IP address nor proxied domain specified for domain: ", mapping.Domain).AtWarning() return nil, newError("neither IP address nor proxied domain specified for domain: ", mapping.Domain).AtWarning()
} }
// Special handling for localhost IPv6. This is a dirty workaround as JSON config supports only single IP mapping.
if len(ips) == 1 && ips[0] == net.LocalHostIP {
ips = append(ips, net.LocalHostIPv6)
}
sh.ips[id] = ips sh.ips[id] = ips
} }
return sh, nil return sh, nil
} }
func filterIP(ips []net.Address, option *dns.IPOption) []net.Address { func filterIP(ips []net.Address, option dns.IPOption) []net.Address {
filtered := make([]net.Address, 0, len(ips)) filtered := make([]net.Address, 0, len(ips))
for _, ip := range ips { for _, ip := range ips {
if (ip.Family().IsIPv4() && option.IPv4Enable) || (ip.Family().IsIPv6() && option.IPv6Enable) { if (ip.Family().IsIPv4() && option.IPv4Enable) || (ip.Family().IsIPv6() && option.IPv6Enable) {
filtered = append(filtered, ip) filtered = append(filtered, ip)
} }
} }
if len(filtered) == 0 {
return nil
}
return filtered return filtered
} }
func (h *StaticHosts) lookupInternal(domain string) []net.Address { // LookupIP returns IP address for the given domain, if exists in this StaticHosts.
var ips []net.Address func (h *StaticHosts) LookupIP(domain string, option dns.IPOption) []net.Address {
for _, id := range h.matchers.Match(domain) { indices := h.matchers.Match(domain)
if len(indices) == 0 {
return nil
}
ips := []net.Address{}
for _, id := range indices {
ips = append(ips, h.ips[id]...) ips = append(ips, h.ips[id]...)
} }
if len(ips) == 1 && ips[0].Family().IsDomain() { if len(ips) == 1 && ips[0].Family().IsDomain() {
return ips return ips
} }
return ips return filterIP(ips, option)
}
func (h *StaticHosts) lookup(domain string, option *dns.IPOption, maxDepth int) []net.Address {
switch addrs := h.lookupInternal(domain); {
case len(addrs) == 0: // Not recorded in static hosts, return nil
return nil
case len(addrs) == 1 && addrs[0].Family().IsDomain(): // Try to unwrap domain
newError("found replaced domain: ", domain, " -> ", addrs[0].Domain(), ". Try to unwrap it").AtDebug().WriteToLog()
if maxDepth > 0 {
unwrapped := h.lookup(addrs[0].Domain(), option, maxDepth-1)
if unwrapped != nil {
return unwrapped
}
}
return addrs
default: // IP record found, return a non-nil IP array
return filterIP(addrs, option)
}
}
// Lookup returns IP addresses or proxied domain for the given domain, if exists in this StaticHosts.
func (h *StaticHosts) Lookup(domain string, option *dns.IPOption) []net.Address {
return h.lookup(domain, option, 5)
} }

View File

@@ -7,7 +7,6 @@ import (
. "github.com/xtls/xray-core/app/dns" . "github.com/xtls/xray-core/app/dns"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/matcher/domain"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/features/dns" "github.com/xtls/xray-core/features/dns"
) )
@@ -15,39 +14,24 @@ import (
func TestStaticHosts(t *testing.T) { func TestStaticHosts(t *testing.T) {
pb := []*Config_HostMapping{ pb := []*Config_HostMapping{
{ {
Type: domain.MatchingType_Full, Type: DomainMatchingType_Full,
Domain: "example.com", Domain: "example.com",
Ip: [][]byte{ Ip: [][]byte{
{1, 1, 1, 1}, {1, 1, 1, 1},
}, },
}, },
{ {
Type: domain.MatchingType_Full, Type: DomainMatchingType_Subdomain,
Domain: "proxy.example.com",
Ip: [][]byte{
{1, 2, 3, 4},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
},
ProxiedDomain: "another-proxy.example.com",
},
{
Type: domain.MatchingType_Full,
Domain: "proxy2.example.com",
ProxiedDomain: "proxy.example.com",
},
{
Type: domain.MatchingType_Subdomain,
Domain: "example.cn", Domain: "example.cn",
Ip: [][]byte{ Ip: [][]byte{
{2, 2, 2, 2}, {2, 2, 2, 2},
}, },
}, },
{ {
Type: domain.MatchingType_Subdomain, Type: DomainMatchingType_Subdomain,
Domain: "baidu.com", Domain: "baidu.com",
Ip: [][]byte{ Ip: [][]byte{
{127, 0, 0, 1}, {127, 0, 0, 1},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
}, },
}, },
} }
@@ -56,7 +40,7 @@ func TestStaticHosts(t *testing.T) {
common.Must(err) common.Must(err)
{ {
ips := hosts.Lookup("example.com", &dns.IPOption{ ips := hosts.LookupIP("example.com", dns.IPOption{
IPv4Enable: true, IPv4Enable: true,
IPv6Enable: true, IPv6Enable: true,
}) })
@@ -69,33 +53,7 @@ func TestStaticHosts(t *testing.T) {
} }
{ {
domain := hosts.Lookup("proxy.example.com", &dns.IPOption{ ips := hosts.LookupIP("www.example.cn", dns.IPOption{
IPv4Enable: true,
IPv6Enable: false,
})
if len(domain) != 1 {
t.Error("expect 1 domain, but got ", len(domain))
}
if diff := cmp.Diff(domain[0].Domain(), "another-proxy.example.com"); diff != "" {
t.Error(diff)
}
}
{
domain := hosts.Lookup("proxy2.example.com", &dns.IPOption{
IPv4Enable: true,
IPv6Enable: false,
})
if len(domain) != 1 {
t.Error("expect 1 domain, but got ", len(domain))
}
if diff := cmp.Diff(domain[0].Domain(), "another-proxy.example.com"); diff != "" {
t.Error(diff)
}
}
{
ips := hosts.Lookup("www.example.cn", &dns.IPOption{
IPv4Enable: true, IPv4Enable: true,
IPv6Enable: true, IPv6Enable: true,
}) })
@@ -108,7 +66,7 @@ func TestStaticHosts(t *testing.T) {
} }
{ {
ips := hosts.Lookup("baidu.com", &dns.IPOption{ ips := hosts.LookupIP("baidu.com", dns.IPOption{
IPv4Enable: false, IPv4Enable: false,
IPv6Enable: true, IPv6Enable: true,
}) })

View File

@@ -2,211 +2,40 @@ package dns
import ( import (
"context" "context"
"net/url"
"strings"
"time"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/matcher/geoip"
"github.com/xtls/xray-core/common/matcher/str"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
core "github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/features/dns" "github.com/xtls/xray-core/features/dns"
"github.com/xtls/xray-core/features/routing" "github.com/xtls/xray-core/features/dns/localdns"
) )
// Server is the interface for Name Server. // Client is the interface for DNS client.
type Server interface { type Client interface {
// Name of the Client. // Name of the Client.
Name() string Name() string
// QueryIP sends IP queries to its configured server. // QueryIP sends IP queries to its configured server.
QueryIP(ctx context.Context, domain string, clientIP net.IP, option dns.IPOption, cs CacheStrategy) ([]net.IP, error) QueryIP(ctx context.Context, domain string, option dns.IPOption) ([]net.IP, error)
} }
// Client is the interface for DNS client. type LocalNameServer struct {
type Client struct { client *localdns.Client
server Server
clientIP net.IP
skipFallback bool
domains []string
expectIPs []*geoip.GeoIPMatcher
} }
var errExpectedIPNonMatch = errors.New("expectIPs not match") func (s *LocalNameServer) QueryIP(_ context.Context, domain string, option dns.IPOption) ([]net.IP, error) {
if option.IPv4Enable || option.IPv6Enable {
return s.client.LookupIP(domain, option)
}
// NewServer creates a name server object according to the network destination url. return nil, newError("neither IPv4 nor IPv6 is enabled")
func NewServer(dest net.Destination, dispatcher routing.Dispatcher) (Server, error) {
if address := dest.Address; address.Family().IsDomain() {
u, err := url.Parse(address.Domain())
if err != nil {
return nil, err
}
switch {
case strings.EqualFold(u.String(), "localhost"):
return NewLocalNameServer(), nil
case strings.EqualFold(u.Scheme, "https"): // DOH Remote mode
return NewDoHNameServer(u, dispatcher)
case strings.EqualFold(u.Scheme, "https+local"): // DOH Local mode
return NewDoHLocalNameServer(u), nil
case strings.EqualFold(u.Scheme, "quic+local"): // DNS-over-QUIC Local mode
return NewQUICNameServer(u)
case strings.EqualFold(u.String(), "fakedns"):
return NewFakeDNSServer(), nil
}
}
if dest.Network == net.Network_Unknown {
dest.Network = net.Network_UDP
}
if dest.Network == net.Network_UDP { // UDP classic DNS mode
return NewClassicNameServer(dest, dispatcher), nil
}
return nil, newError("No available name server could be created from ", dest).AtWarning()
} }
// NewClient creates a DNS client managing a name server with client IP, domain rules and expected IPs. func (s *LocalNameServer) Name() string {
func NewClient(ctx context.Context, ns *NameServer, clientIP net.IP, container geoip.GeoIPMatcherContainer, matcherInfos *[]DomainMatcherInfo, updateDomainRule func(str.Matcher, int, []DomainMatcherInfo) error) (*Client, error) { return "localhost"
client := &Client{}
err := core.RequireFeatures(ctx, func(dispatcher routing.Dispatcher) error {
// Create a new server for each client for now
server, err := NewServer(ns.Address.AsDestination(), dispatcher)
if err != nil {
return newError("failed to create nameserver").Base(err).AtWarning()
}
// Priotize local domains with specific TLDs or without any dot to local DNS
if _, isLocalDNS := server.(*LocalNameServer); isLocalDNS {
ns.PrioritizedDomain = append(ns.PrioritizedDomain, localTLDsAndDotlessDomains...)
ns.OriginalRules = append(ns.OriginalRules, localTLDsAndDotlessDomainsRule)
// The following lines is a solution to avoid core panicsrule index out of range when setting `localhost` DNS client in config.
// Because the `localhost` DNS client will apend len(localTLDsAndDotlessDomains) rules into matcherInfos to match `geosite:private` default rule.
// But `matcherInfos` has no enough length to add rules, which leads to core panics (rule index out of range).
// To avoid this, the length of `matcherInfos` must be equal to the expected, so manually append it with Golang default zero value first for later modification.
for i := 0; i < len(localTLDsAndDotlessDomains); i++ {
*matcherInfos = append(*matcherInfos, DomainMatcherInfo{
clientIdx: uint16(0),
domainRuleIdx: uint16(0),
})
}
}
// Establish domain rules
var rules []string
ruleCurr := 0
ruleIter := 0
for _, domain := range ns.PrioritizedDomain {
domainRule, err := toStrMatcher(domain.Type, domain.Value)
if err != nil {
return newError("failed to create prioritized domain").Base(err).AtWarning()
}
originalRuleIdx := ruleCurr
if ruleCurr < len(ns.OriginalRules) {
rule := ns.OriginalRules[ruleCurr]
if ruleCurr >= len(rules) {
rules = append(rules, rule.Rule)
}
ruleIter++
if ruleIter >= int(rule.Size) {
ruleIter = 0
ruleCurr++
}
} else { // No original rule, generate one according to current domain matcher (majorly for compatibility with tests)
rules = append(rules, domainRule.String())
ruleCurr++
}
err = updateDomainRule(domainRule, originalRuleIdx, *matcherInfos)
if err != nil {
return newError("failed to create prioritized domain").Base(err).AtWarning()
}
}
// Establish expected IPs
var matchers []*geoip.GeoIPMatcher
for _, geoip := range ns.Geoip {
matcher, err := container.Add(geoip)
if err != nil {
return newError("failed to create ip matcher").Base(err).AtWarning()
}
matchers = append(matchers, matcher)
}
if len(clientIP) > 0 {
switch ns.Address.Address.GetAddress().(type) {
case *net.IPOrDomain_Domain:
newError("DNS: client ", ns.Address.Address.GetDomain(), " uses clientIP ", clientIP.String()).AtInfo().WriteToLog()
case *net.IPOrDomain_Ip:
newError("DNS: client ", ns.Address.Address.GetIp(), " uses clientIP ", clientIP.String()).AtInfo().WriteToLog()
}
}
client.server = server
client.clientIP = clientIP
client.domains = rules
client.expectIPs = matchers
return nil
})
return client, err
} }
// NewSimpleClient creates a DNS client with a simple destination. func NewLocalNameServer() *LocalNameServer {
func NewSimpleClient(ctx context.Context, endpoint *net.Endpoint, clientIP net.IP) (*Client, error) { newError("DNS: created localhost client").AtInfo().WriteToLog()
client := &Client{} return &LocalNameServer{
err := core.RequireFeatures(ctx, func(dispatcher routing.Dispatcher) error { client: localdns.New(),
server, err := NewServer(endpoint.AsDestination(), dispatcher)
if err != nil {
return newError("failed to create nameserver").Base(err).AtWarning()
}
client.server = server
client.clientIP = clientIP
return nil
})
if len(clientIP) > 0 {
switch endpoint.Address.GetAddress().(type) {
case *net.IPOrDomain_Domain:
newError("DNS: client ", endpoint.Address.GetDomain(), " uses clientIP ", clientIP.String()).AtInfo().WriteToLog()
case *net.IPOrDomain_Ip:
newError("DNS: client ", endpoint.Address.GetIp(), " uses clientIP ", clientIP.String()).AtInfo().WriteToLog()
}
} }
return client, err
}
// Name returns the server name the client manages.
func (c *Client) Name() string {
return c.server.Name()
}
// QueryIP send DNS query to the name server with the client's IP.
func (c *Client) QueryIP(ctx context.Context, domain string, option dns.IPOption, cs CacheStrategy) ([]net.IP, error) {
ctx, cancel := context.WithTimeout(ctx, 4*time.Second)
ips, err := c.server.QueryIP(ctx, domain, c.clientIP, option, cs)
cancel()
if err != nil {
return ips, err
}
return c.MatchExpectedIPs(domain, ips)
}
// MatchExpectedIPs matches queried domain IPs with expected IPs and returns matched ones.
func (c *Client) MatchExpectedIPs(domain string, ips []net.IP) ([]net.IP, error) {
if len(c.expectIPs) == 0 {
return ips, nil
}
newIps := []net.IP{}
for _, ip := range ips {
for _, matcher := range c.expectIPs {
if matcher.Match(ip) {
newIps = append(newIps, ip)
break
}
}
}
if len(newIps) == 0 {
return nil, errExpectedIPNonMatch
}
newError("domain ", domain, " expectIPs ", newIps, " matched at server ", c.Name()).AtDebug().WriteToLog()
return newIps, nil
} }

View File

@@ -1,60 +0,0 @@
package dns_test
import (
"context"
"net/url"
"testing"
"time"
"github.com/google/go-cmp/cmp"
. "github.com/xtls/xray-core/app/dns"
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/net"
dns_feature "github.com/xtls/xray-core/features/dns"
)
func TestDOHNameServer(t *testing.T) {
url, err := url.Parse("https+local://1.1.1.1/dns-query")
common.Must(err)
s := NewDoHLocalNameServer(url)
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), dns_feature.IPOption{
IPv4Enable: true,
IPv6Enable: true,
}, CacheStrategy_Cache_ALL)
cancel()
common.Must(err)
if len(ips) == 0 {
t.Error("expect some ips, but got 0")
}
}
func TestDOHNameServerWithCache(t *testing.T) {
url, err := url.Parse("https+local://1.1.1.1/dns-query")
common.Must(err)
s := NewDoHLocalNameServer(url)
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), dns_feature.IPOption{
IPv4Enable: true,
IPv6Enable: true,
}, CacheStrategy_Cache_ALL)
cancel()
common.Must(err)
if len(ips) == 0 {
t.Error("expect some ips, but got 0")
}
ctx2, cancel := context.WithTimeout(context.Background(), time.Second*2)
ips2, err := s.QueryIP(ctx2, "google.com", net.IP(nil), dns_feature.IPOption{
IPv4Enable: true,
IPv6Enable: true,
}, CacheStrategy_Cache_ALL)
cancel()
common.Must(err)
if r := cmp.Diff(ips2, ips); r != "" {
t.Fatal(r)
}
}

View File

@@ -16,13 +16,11 @@ func NewFakeDNSServer() *FakeDNSServer {
return &FakeDNSServer{} return &FakeDNSServer{}
} }
const FakeDNSName = "FakeDNS"
func (FakeDNSServer) Name() string { func (FakeDNSServer) Name() string {
return FakeDNSName return "FakeDNS"
} }
func (f *FakeDNSServer) QueryIP(ctx context.Context, domain string, _ net.IP, _ dns.IPOption, _ CacheStrategy) ([]net.IP, error) { func (f *FakeDNSServer) QueryIP(ctx context.Context, domain string, _ dns.IPOption) ([]net.IP, error) {
if f.fakeDNSEngine == nil { if f.fakeDNSEngine == nil {
if err := core.RequireFeatures(ctx, func(fd dns.FakeDNSEngine) { if err := core.RequireFeatures(ctx, func(fd dns.FakeDNSEngine) {
f.fakeDNSEngine = fd f.fakeDNSEngine = fd
@@ -32,9 +30,9 @@ func (f *FakeDNSServer) QueryIP(ctx context.Context, domain string, _ net.IP, _
} }
ips := f.fakeDNSEngine.GetFakeIPForDomain(domain) ips := f.fakeDNSEngine.GetFakeIPForDomain(domain)
netIP, err := toNetIP(ips) netIP := toNetIP(ips)
if err != nil { if netIP == nil {
return nil, newError("Unable to convert IP to net ip").Base(err).AtError() return nil, newError("Unable to convert IP to net ip").AtError()
} }
newError(f.Name(), " got answer: ", domain, " -> ", ips).AtInfo().WriteToLog() newError(f.Name(), " got answer: ", domain, " -> ", ips).AtInfo().WriteToLog()

View File

@@ -1,53 +0,0 @@
package dns
import (
"context"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/features/dns"
"github.com/xtls/xray-core/features/dns/localdns"
)
// LocalNameServer is an wrapper over local DNS feature.
type LocalNameServer struct {
client *localdns.Client
}
// QueryIP implements Server.
func (s *LocalNameServer) QueryIP(_ context.Context, domain string, _ net.IP, option dns.IPOption, _ CacheStrategy) ([]net.IP, error) {
var ips []net.IP
var err error
switch {
case option.IPv4Enable && option.IPv6Enable:
ips, err = s.client.LookupIP(domain)
case option.IPv4Enable:
ips, err = s.client.LookupIPv4(domain)
case option.IPv6Enable:
ips, err = s.client.LookupIPv6(domain)
}
if len(ips) > 0 {
newError("Localhost got answer: ", domain, " -> ", ips).AtInfo().WriteToLog()
}
return ips, err
}
// Name implements Server.
func (s *LocalNameServer) Name() string {
return "localhost"
}
// NewLocalNameServer creates localdns server object for directly lookup in system DNS.
func NewLocalNameServer() *LocalNameServer {
newError("DNS: created localhost client").AtInfo().WriteToLog()
return &LocalNameServer{
client: localdns.New(),
}
}
// NewLocalDNSClient creates localdns client object for directly lookup in system DNS.
func NewLocalDNSClient() *Client {
return &Client{server: NewLocalNameServer()}
}

View File

@@ -1,394 +0,0 @@
package dns
import (
"context"
"net/url"
"sync"
"sync/atomic"
"time"
"github.com/lucas-clemente/quic-go"
"golang.org/x/net/dns/dnsmessage"
"golang.org/x/net/http2"
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/log"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/protocol/dns"
"github.com/xtls/xray-core/common/session"
"github.com/xtls/xray-core/common/signal/pubsub"
"github.com/xtls/xray-core/common/task"
dns_feature "github.com/xtls/xray-core/features/dns"
"github.com/xtls/xray-core/transport/internet/tls"
)
// NextProtoDQ - During connection establishment, DNS/QUIC support is indicated
// by selecting the ALPN token "dq" in the crypto handshake.
const NextProtoDQ = "doq-i00"
// QUICNameServer implemented DNS over QUIC
type QUICNameServer struct {
sync.RWMutex
ips map[string]record
pub *pubsub.Service
cleanup *task.Periodic
reqID uint32
name string
destination net.Destination
session quic.Session
}
// NewQUICNameServer creates DNS-over-QUIC client object for local resolving
func NewQUICNameServer(url *url.URL) (*QUICNameServer, error) {
newError("DNS: created Local DNS-over-QUIC client for ", url.String()).AtInfo().WriteToLog()
var err error
port := net.Port(784)
if url.Port() != "" {
port, err = net.PortFromString(url.Port())
if err != nil {
return nil, err
}
}
dest := net.UDPDestination(net.DomainAddress(url.Hostname()), port)
s := &QUICNameServer{
ips: make(map[string]record),
pub: pubsub.NewService(),
name: url.String(),
destination: dest,
}
s.cleanup = &task.Periodic{
Interval: time.Minute,
Execute: s.Cleanup,
}
return s, nil
}
// Name returns client name
func (s *QUICNameServer) Name() string {
return s.name
}
// Cleanup clears expired items from cache
func (s *QUICNameServer) Cleanup() error {
now := time.Now()
s.Lock()
defer s.Unlock()
if len(s.ips) == 0 {
return newError("nothing to do. stopping...")
}
for domain, record := range s.ips {
if record.A != nil && record.A.Expire.Before(now) {
record.A = nil
}
if record.AAAA != nil && record.AAAA.Expire.Before(now) {
record.AAAA = nil
}
if record.A == nil && record.AAAA == nil {
newError(s.name, " cleanup ", domain).AtDebug().WriteToLog()
delete(s.ips, domain)
} else {
s.ips[domain] = record
}
}
if len(s.ips) == 0 {
s.ips = make(map[string]record)
}
return nil
}
func (s *QUICNameServer) updateIP(req *dnsRequest, ipRec *IPRecord) {
elapsed := time.Since(req.start)
s.Lock()
rec := s.ips[req.domain]
updated := false
switch req.reqType {
case dnsmessage.TypeA:
if isNewer(rec.A, ipRec) {
rec.A = ipRec
updated = true
}
case dnsmessage.TypeAAAA:
addr := make([]net.Address, 0)
for _, ip := range ipRec.IP {
if len(ip.IP()) == net.IPv6len {
addr = append(addr, ip)
}
}
ipRec.IP = addr
if isNewer(rec.AAAA, ipRec) {
rec.AAAA = ipRec
updated = true
}
}
newError(s.name, " got answer: ", req.domain, " ", req.reqType, " -> ", ipRec.IP, " ", elapsed).AtInfo().WriteToLog()
if updated {
s.ips[req.domain] = rec
}
switch req.reqType {
case dnsmessage.TypeA:
s.pub.Publish(req.domain+"4", nil)
case dnsmessage.TypeAAAA:
s.pub.Publish(req.domain+"6", nil)
}
s.Unlock()
common.Must(s.cleanup.Start())
}
func (s *QUICNameServer) newReqID() uint16 {
return uint16(atomic.AddUint32(&s.reqID, 1))
}
func (s *QUICNameServer) sendQuery(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption) {
newError(s.name, " querying: ", domain).AtInfo().WriteToLog(session.ExportIDToError(ctx))
reqs := buildReqMsgs(domain, option, s.newReqID, genEDNS0Options(clientIP))
var deadline time.Time
if d, ok := ctx.Deadline(); ok {
deadline = d
} else {
deadline = time.Now().Add(time.Second * 5)
}
for _, req := range reqs {
go func(r *dnsRequest) {
// generate new context for each req, using same context
// may cause reqs all aborted if any one encounter an error
dnsCtx := context.Background()
// reserve internal dns server requested Inbound
if inbound := session.InboundFromContext(ctx); inbound != nil {
dnsCtx = session.ContextWithInbound(dnsCtx, inbound)
}
dnsCtx = session.ContextWithContent(dnsCtx, &session.Content{
Protocol: "quic",
SkipDNSResolve: true,
})
dnsCtx = log.ContextWithAccessMessage(dnsCtx, &log.AccessMessage{
From: "DoQ",
To: s.name,
Status: log.AccessAccepted,
Reason: "",
})
var cancel context.CancelFunc
dnsCtx, cancel = context.WithDeadline(dnsCtx, deadline)
defer cancel()
b, err := dns.PackMessage(r.msg)
if err != nil {
newError("failed to pack dns query").Base(err).AtError().WriteToLog()
return
}
conn, err := s.openStream(dnsCtx)
if err != nil {
newError("failed to open quic session").Base(err).AtError().WriteToLog()
return
}
_, err = conn.Write(b.Bytes())
if err != nil {
newError("failed to send query").Base(err).AtError().WriteToLog()
return
}
_ = conn.Close()
respBuf := buf.New()
defer respBuf.Release()
n, err := respBuf.ReadFrom(conn)
if err != nil && n == 0 {
newError("failed to read response").Base(err).AtError().WriteToLog()
return
}
rec, err := parseResponse(respBuf.Bytes())
if err != nil {
newError("failed to handle response").Base(err).AtError().WriteToLog()
return
}
s.updateIP(r, rec)
}(req)
}
}
func (s *QUICNameServer) findIPsForDomain(domain string, option dns_feature.IPOption) ([]net.IP, error) {
s.RLock()
record, found := s.ips[domain]
s.RUnlock()
if !found {
return nil, errRecordNotFound
}
var ips []net.Address
var lastErr error
if option.IPv6Enable && record.AAAA != nil && record.AAAA.RCode == dnsmessage.RCodeSuccess {
aaaa, err := record.AAAA.getIPs()
if err != nil {
lastErr = err
}
ips = append(ips, aaaa...)
}
if option.IPv4Enable && record.A != nil && record.A.RCode == dnsmessage.RCodeSuccess {
a, err := record.A.getIPs()
if err != nil {
lastErr = err
}
ips = append(ips, a...)
}
if len(ips) > 0 {
return toNetIP(ips)
}
if lastErr != nil {
return nil, lastErr
}
if (option.IPv4Enable && record.A != nil) || (option.IPv6Enable && record.AAAA != nil) {
return nil, dns_feature.ErrEmptyResponse
}
return nil, errRecordNotFound
}
// QueryIP is called from dns.Server->queryIPTimeout
func (s *QUICNameServer) QueryIP(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption, cs CacheStrategy) ([]net.IP, error) {
fqdn := Fqdn(domain)
if cs == CacheStrategy_Cache_DISABLE {
newError("DNS cache is disabled. Querying IP for ", domain, " at ", s.name).AtDebug().WriteToLog()
} else {
ips, err := s.findIPsForDomain(fqdn, option)
if err != errRecordNotFound {
if cs == CacheStrategy_Cache_NOERROR && err == nil {
newError(s.name, " cache HIT ", domain, " -> ", ips).Base(err).AtDebug().WriteToLog()
log.Record(&log.DNSLog{s.name, domain, ips, log.DNSCacheHit, 0, err})
return ips, err
}
}
}
// ipv4 and ipv6 belong to different subscription groups
var sub4, sub6 *pubsub.Subscriber
if option.IPv4Enable {
sub4 = s.pub.Subscribe(fqdn + "4")
defer sub4.Close()
}
if option.IPv6Enable {
sub6 = s.pub.Subscribe(fqdn + "6")
defer sub6.Close()
}
done := make(chan interface{})
go func() {
if sub4 != nil {
select {
case <-sub4.Wait():
case <-ctx.Done():
}
}
if sub6 != nil {
select {
case <-sub6.Wait():
case <-ctx.Done():
}
}
close(done)
}()
s.sendQuery(ctx, fqdn, clientIP, option)
start := time.Now()
for {
ips, err := s.findIPsForDomain(fqdn, option)
if err != errRecordNotFound {
log.Record(&log.DNSLog{s.name, domain, ips, log.DNSQueried, time.Since(start), err})
return ips, err
}
select {
case <-ctx.Done():
return nil, ctx.Err()
case <-done:
}
}
}
func isActive(s quic.Session) bool {
select {
case <-s.Context().Done():
return false
default:
return true
}
}
func (s *QUICNameServer) getSession() (quic.Session, error) {
var session quic.Session
s.RLock()
session = s.session
if session != nil && isActive(session) {
s.RUnlock()
return session, nil
}
if session != nil {
// we're recreating the session, let's create a new one
_ = session.CloseWithError(0, "")
}
s.RUnlock()
s.Lock()
defer s.Unlock()
var err error
session, err = s.openSession()
if err != nil {
// This does not look too nice, but QUIC (or maybe quic-go)
// doesn't seem stable enough.
// Maybe retransmissions aren't fully implemented in quic-go?
// Anyways, the simple solution is to make a second try when
// it fails to open the QUIC session.
session, err = s.openSession()
if err != nil {
return nil, err
}
}
s.session = session
return session, nil
}
func (s *QUICNameServer) openSession() (quic.Session, error) {
tlsConfig := tls.Config{}
quicConfig := &quic.Config{}
session, err := quic.DialAddrContext(context.Background(), s.destination.NetAddr(), tlsConfig.GetTLSConfig(tls.WithNextProto("http/1.1", http2.NextProtoTLS, NextProtoDQ)), quicConfig)
if err != nil {
return nil, err
}
return session, nil
}
func (s *QUICNameServer) openStream(ctx context.Context) (quic.Stream, error) {
session, err := s.getSession()
if err != nil {
return nil, err
}
// open a new stream
return session.OpenStreamSync(ctx)
}

View File

@@ -1,60 +0,0 @@
package dns_test
import (
"context"
"net/url"
"testing"
"time"
"github.com/google/go-cmp/cmp"
. "github.com/xtls/xray-core/app/dns"
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/net"
dns_feature "github.com/xtls/xray-core/features/dns"
)
func TestQUICNameServer(t *testing.T) {
url, err := url.Parse("quic://dns.adguard.com")
common.Must(err)
s, err := NewQUICNameServer(url)
common.Must(err)
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), dns_feature.IPOption{
IPv4Enable: true,
IPv6Enable: true,
}, CacheStrategy_Cache_ALL)
cancel()
common.Must(err)
if len(ips) == 0 {
t.Error("expect some ips, but got 0")
}
}
func TestQUICNameServerWithCache(t *testing.T) {
url, err := url.Parse("quic://dns.adguard.com")
common.Must(err)
s, err := NewQUICNameServer(url)
common.Must(err)
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), dns_feature.IPOption{
IPv4Enable: true,
IPv6Enable: true,
}, CacheStrategy_Cache_ALL)
cancel()
common.Must(err)
if len(ips) == 0 {
t.Error("expect some ips, but got 0")
}
ctx2, cancel := context.WithTimeout(context.Background(), time.Second*5)
ips2, err := s.QueryIP(ctx2, "google.com", net.IP(nil), dns_feature.IPOption{
IPv4Enable: true,
IPv6Enable: true,
}, CacheStrategy_Cache_ALL)
cancel()
common.Must(err)
if r := cmp.Diff(ips2, ips); r != "" {
t.Fatal(r)
}
}

View File

@@ -7,17 +7,17 @@ import (
. "github.com/xtls/xray-core/app/dns" . "github.com/xtls/xray-core/app/dns"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/net" dns_feature "github.com/xtls/xray-core/features/dns"
"github.com/xtls/xray-core/features/dns"
) )
func TestLocalNameServer(t *testing.T) { func TestLocalNameServer(t *testing.T) {
s := NewLocalNameServer() s := NewLocalNameServer()
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
ips, err := s.QueryIP(ctx, "google.com", net.IP{}, dns.IPOption{ ips, err := s.QueryIP(ctx, "google.com", dns_feature.IPOption{
IPv4Enable: true, IPv4Enable: true,
IPv6Enable: true, IPv6Enable: true,
}, CacheStrategy_Cache_ALL) FakeEnable: false,
})
cancel() cancel()
common.Must(err) common.Must(err)
if len(ips) == 0 { if len(ips) == 0 {

View File

@@ -1,16 +0,0 @@
package dns
import "github.com/xtls/xray-core/features/dns"
func isIPQuery(o *dns.IPOption) bool {
return o.IPv4Enable || o.IPv6Enable
}
func canQueryOnClient(o *dns.IPOption, c *Client) bool {
isIPClient := !(c.Name() == FakeDNSName)
return isIPClient && isIPQuery(o)
}
func isQuery(o *dns.IPOption) bool {
return !(o.IPv4Enable || o.IPv6Enable || o.FakeEnable)
}

437
app/dns/server.go Normal file
View File

@@ -0,0 +1,437 @@
package dns
//go:generate go run github.com/xtls/xray-core/common/errors/errorgen
import (
"context"
"fmt"
"log"
"net/url"
"strings"
"sync"
"time"
"github.com/xtls/xray-core/app/router"
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/session"
"github.com/xtls/xray-core/common/strmatcher"
"github.com/xtls/xray-core/common/uuid"
core "github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/features"
"github.com/xtls/xray-core/features/dns"
"github.com/xtls/xray-core/features/routing"
)
// Server is a DNS rely server.
type Server struct {
sync.Mutex
hosts *StaticHosts
clientIP net.IP
clients []Client // clientIdx -> Client
ctx context.Context
ipIndexMap []*MultiGeoIPMatcher // clientIdx -> *MultiGeoIPMatcher
domainRules [][]string // clientIdx -> domainRuleIdx -> DomainRule
domainMatcher strmatcher.IndexMatcher
matcherInfos []DomainMatcherInfo // matcherIdx -> DomainMatcherInfo
tag string
}
// DomainMatcherInfo contains information attached to index returned by Server.domainMatcher
type DomainMatcherInfo struct {
clientIdx uint16
domainRuleIdx uint16
}
// MultiGeoIPMatcher for match
type MultiGeoIPMatcher struct {
matchers []*router.GeoIPMatcher
}
var errExpectedIPNonMatch = errors.New("expectIPs not match")
// Match check ip match
func (c *MultiGeoIPMatcher) Match(ip net.IP) bool {
for _, matcher := range c.matchers {
if matcher.Match(ip) {
return true
}
}
return false
}
// HasMatcher check has matcher
func (c *MultiGeoIPMatcher) HasMatcher() bool {
return len(c.matchers) > 0
}
func generateRandomTag() string {
id := uuid.New()
return "xray.system." + id.String()
}
// New creates a new DNS server with given configuration.
func New(ctx context.Context, config *Config) (*Server, error) {
server := &Server{
clients: make([]Client, 0, len(config.NameServers)+len(config.NameServer)),
ctx: ctx,
tag: config.Tag,
}
if server.tag == "" {
server.tag = generateRandomTag()
}
if len(config.ClientIp) > 0 {
if len(config.ClientIp) != net.IPv4len && len(config.ClientIp) != net.IPv6len {
return nil, newError("unexpected IP length", len(config.ClientIp))
}
server.clientIP = net.IP(config.ClientIp)
}
hosts, err := NewStaticHosts(config.StaticHosts, config.Hosts)
if err != nil {
return nil, newError("failed to create hosts").Base(err)
}
server.hosts = hosts
addNameServer := func(ns *NameServer) int {
endpoint := ns.Address
address := endpoint.Address.AsAddress()
switch {
case address.Family().IsDomain() && address.Domain() == "localhost":
server.clients = append(server.clients, NewLocalNameServer())
// Priotize local domains with specific TLDs or without any dot to local DNS
// References:
// https://www.iana.org/assignments/special-use-domain-names/special-use-domain-names.xhtml
// https://unix.stackexchange.com/questions/92441/whats-the-difference-between-local-home-and-lan
localTLDsAndDotlessDomains := []*NameServer_PriorityDomain{
{Type: DomainMatchingType_Regex, Domain: "^[^.]+$"}, // This will only match domains without any dot
{Type: DomainMatchingType_Subdomain, Domain: "local"},
{Type: DomainMatchingType_Subdomain, Domain: "localdomain"},
{Type: DomainMatchingType_Subdomain, Domain: "localhost"},
{Type: DomainMatchingType_Subdomain, Domain: "lan"},
{Type: DomainMatchingType_Subdomain, Domain: "home.arpa"},
{Type: DomainMatchingType_Subdomain, Domain: "example"},
{Type: DomainMatchingType_Subdomain, Domain: "invalid"},
{Type: DomainMatchingType_Subdomain, Domain: "test"},
}
ns.PrioritizedDomain = append(ns.PrioritizedDomain, localTLDsAndDotlessDomains...)
case address.Family().IsDomain() && strings.HasPrefix(address.Domain(), "https+local://"):
// URI schemed string treated as domain
// DOH Local mode
u, err := url.Parse(address.Domain())
if err != nil {
log.Fatalln(newError("DNS config error").Base(err))
}
server.clients = append(server.clients, NewDoHLocalNameServer(u, server.clientIP))
case address.Family().IsDomain() && strings.HasPrefix(address.Domain(), "https://"):
// DOH Remote mode
u, err := url.Parse(address.Domain())
if err != nil {
log.Fatalln(newError("DNS config error").Base(err))
}
idx := len(server.clients)
server.clients = append(server.clients, nil)
// need the core dispatcher, register DOHClient at callback
common.Must(core.RequireFeatures(ctx, func(d routing.Dispatcher) {
c, err := NewDoHNameServer(u, d, server.clientIP)
if err != nil {
log.Fatalln(newError("DNS config error").Base(err))
}
server.clients[idx] = c
}))
case address.Family().IsDomain() && address.Domain() == "fakedns":
server.clients = append(server.clients, NewFakeDNSServer())
default:
// UDP classic DNS mode
dest := endpoint.AsDestination()
if dest.Network == net.Network_Unknown {
dest.Network = net.Network_UDP
}
if dest.Network == net.Network_UDP {
idx := len(server.clients)
server.clients = append(server.clients, nil)
common.Must(core.RequireFeatures(ctx, func(d routing.Dispatcher) {
server.clients[idx] = NewClassicNameServer(dest, d, server.clientIP)
}))
}
}
server.ipIndexMap = append(server.ipIndexMap, nil)
return len(server.clients) - 1
}
if len(config.NameServers) > 0 {
features.PrintDeprecatedFeatureWarning("simple DNS server")
for _, destPB := range config.NameServers {
addNameServer(&NameServer{Address: destPB})
}
}
if len(config.NameServer) > 0 {
clientIndices := []int{}
domainRuleCount := 0
for _, ns := range config.NameServer {
idx := addNameServer(ns)
clientIndices = append(clientIndices, idx)
domainRuleCount += len(ns.PrioritizedDomain)
}
domainRules := make([][]string, len(server.clients))
domainMatcher := &strmatcher.MatcherGroup{}
matcherInfos := make([]DomainMatcherInfo, domainRuleCount+1) // matcher index starts from 1
var geoIPMatcherContainer router.GeoIPMatcherContainer
for nidx, ns := range config.NameServer {
idx := clientIndices[nidx]
// Establish domain rule matcher
rules := []string{}
ruleCurr := 0
ruleIter := 0
for _, domain := range ns.PrioritizedDomain {
matcher, err := toStrMatcher(domain.Type, domain.Domain)
if err != nil {
return nil, newError("failed to create prioritized domain").Base(err).AtWarning()
}
midx := domainMatcher.Add(matcher)
if midx >= uint32(len(matcherInfos)) { // This rarely happens according to current matcher's implementation
newError("expanding domain matcher info array to size ", midx, " when adding ", matcher).AtDebug().WriteToLog()
matcherInfos = append(matcherInfos, make([]DomainMatcherInfo, midx-uint32(len(matcherInfos))+1)...)
}
info := &matcherInfos[midx]
info.clientIdx = uint16(idx)
if ruleCurr < len(ns.OriginalRules) {
info.domainRuleIdx = uint16(ruleCurr)
rule := ns.OriginalRules[ruleCurr]
if ruleCurr >= len(rules) {
rules = append(rules, rule.Rule)
}
ruleIter++
if ruleIter >= int(rule.Size) {
ruleIter = 0
ruleCurr++
}
} else { // No original rule, generate one according to current domain matcher (majorly for compatibility with tests)
info.domainRuleIdx = uint16(len(rules))
rules = append(rules, matcher.String())
}
}
domainRules[idx] = rules
// only add to ipIndexMap if GeoIP is configured
if len(ns.Geoip) > 0 {
var matchers []*router.GeoIPMatcher
for _, geoip := range ns.Geoip {
matcher, err := geoIPMatcherContainer.Add(geoip)
if err != nil {
return nil, newError("failed to create ip matcher").Base(err).AtWarning()
}
matchers = append(matchers, matcher)
}
matcher := &MultiGeoIPMatcher{matchers: matchers}
server.ipIndexMap[idx] = matcher
}
}
server.domainRules = domainRules
server.domainMatcher = domainMatcher
server.matcherInfos = matcherInfos
}
if len(server.clients) == 0 {
server.clients = append(server.clients, NewLocalNameServer())
server.ipIndexMap = append(server.ipIndexMap, nil)
}
return server, nil
}
// Type implements common.HasType.
func (*Server) Type() interface{} {
return dns.ClientType()
}
// Start implements common.Runnable.
func (s *Server) Start() error {
return nil
}
// Close implements common.Closable.
func (s *Server) Close() error {
return nil
}
func (s *Server) IsOwnLink(ctx context.Context) bool {
inbound := session.InboundFromContext(ctx)
return inbound != nil && inbound.Tag == s.tag
}
// Match check dns ip match geoip
func (s *Server) Match(idx int, client Client, domain string, ips []net.IP) ([]net.IP, error) {
var matcher *MultiGeoIPMatcher
if idx < len(s.ipIndexMap) {
matcher = s.ipIndexMap[idx]
}
if matcher == nil {
return ips, nil
}
if !matcher.HasMatcher() {
newError("domain ", domain, " server has no valid matcher: ", client.Name(), " idx:", idx).AtDebug().WriteToLog()
return ips, nil
}
newIps := []net.IP{}
for _, ip := range ips {
if matcher.Match(ip) {
newIps = append(newIps, ip)
}
}
if len(newIps) == 0 {
return nil, errExpectedIPNonMatch
}
newError("domain ", domain, " expectIPs ", newIps, " matched at server ", client.Name(), " idx:", idx).AtDebug().WriteToLog()
return newIps, nil
}
func (s *Server) queryIPTimeout(idx int, client Client, domain string, option dns.IPOption) ([]net.IP, error) {
ctx, cancel := context.WithTimeout(s.ctx, time.Second*4)
if len(s.tag) > 0 {
ctx = session.ContextWithInbound(ctx, &session.Inbound{
Tag: s.tag,
})
}
ips, err := client.QueryIP(ctx, domain, option)
cancel()
if err != nil {
return ips, err
}
ips, err = s.Match(idx, client, domain, ips)
return ips, err
}
func (s *Server) lookupStatic(domain string, option dns.IPOption, depth int32) []net.Address {
ips := s.hosts.LookupIP(domain, option)
if ips == nil {
return nil
}
if ips[0].Family().IsDomain() && depth < 5 {
if newIPs := s.lookupStatic(ips[0].Domain(), option, depth+1); newIPs != nil {
return newIPs
}
}
return ips
}
func toNetIP(ips []net.Address) []net.IP {
if len(ips) == 0 {
return nil
}
netips := make([]net.IP, 0, len(ips))
for _, ip := range ips {
netips = append(netips, ip.IP())
}
return netips
}
// LookupIP implements dns.Client.
func (s *Server) LookupIP(domain string, option dns.IPOption) ([]net.IP, error) {
if domain == "" {
return nil, newError("empty domain name")
}
// normalize the FQDN form query
if strings.HasSuffix(domain, ".") {
domain = domain[:len(domain)-1]
}
ips := s.lookupStatic(domain, option, 0)
if ips != nil && ips[0].Family().IsIP() {
newError("returning ", len(ips), " IPs for domain ", domain).WriteToLog()
return toNetIP(ips), nil
}
if ips != nil && ips[0].Family().IsDomain() {
newdomain := ips[0].Domain()
newError("domain replaced: ", domain, " -> ", newdomain).WriteToLog()
domain = newdomain
}
var lastErr error
var matchedClient Client
if s.domainMatcher != nil {
indices := s.domainMatcher.Match(domain)
domainRules := []string{}
matchingDNS := []string{}
for _, idx := range indices {
info := s.matcherInfos[idx]
rule := s.domainRules[info.clientIdx][info.domainRuleIdx]
domainRules = append(domainRules, fmt.Sprintf("%s(DNS idx:%d)", rule, info.clientIdx))
matchingDNS = append(matchingDNS, s.clients[info.clientIdx].Name())
}
if len(domainRules) > 0 {
newError("domain ", domain, " matches following rules: ", domainRules).AtDebug().WriteToLog()
}
if len(matchingDNS) > 0 {
newError("domain ", domain, " uses following DNS first: ", matchingDNS).AtDebug().WriteToLog()
}
for _, idx := range indices {
clientIdx := int(s.matcherInfos[idx].clientIdx)
matchedClient = s.clients[clientIdx]
if !option.FakeEnable && strings.EqualFold(matchedClient.Name(), "FakeDNS") {
newError("skip DNS resolution for domain ", domain, " at server ", matchedClient.Name()).AtDebug().WriteToLog()
continue
}
ips, err := s.queryIPTimeout(clientIdx, matchedClient, domain, option)
if len(ips) > 0 {
return ips, nil
}
if err == dns.ErrEmptyResponse {
return nil, err
}
if err != nil {
newError("failed to lookup ip for domain ", domain, " at server ", matchedClient.Name()).Base(err).WriteToLog()
lastErr = err
}
}
}
for idx, client := range s.clients {
if client == matchedClient {
newError("domain ", domain, " at server ", client.Name(), " idx:", idx, " already lookup failed, just ignore").AtDebug().WriteToLog()
continue
}
if !option.FakeEnable && strings.EqualFold(client.Name(), "FakeDNS") {
newError("skip DNS resolution for domain ", domain, " at server ", client.Name()).AtDebug().WriteToLog()
continue
}
ips, err := s.queryIPTimeout(idx, client, domain, option)
if len(ips) > 0 {
return ips, nil
}
if err != nil {
newError("failed to lookup ip for domain ", domain, " at server ", client.Name()).Base(err).WriteToLog()
lastErr = err
}
if err != context.Canceled && err != context.DeadlineExceeded && err != errExpectedIPNonMatch {
return nil, err
}
}
return nil, newError("returning nil for domain ", domain).Base(lastErr)
}
func init() {
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
return New(ctx, config.(*Config))
}))
}

View File

@@ -12,9 +12,8 @@ import (
"github.com/xtls/xray-core/app/policy" "github.com/xtls/xray-core/app/policy"
"github.com/xtls/xray-core/app/proxyman" "github.com/xtls/xray-core/app/proxyman"
_ "github.com/xtls/xray-core/app/proxyman/outbound" _ "github.com/xtls/xray-core/app/proxyman/outbound"
"github.com/xtls/xray-core/app/router"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"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/common/net"
"github.com/xtls/xray-core/common/serial" "github.com/xtls/xray-core/common/serial"
"github.com/xtls/xray-core/core" "github.com/xtls/xray-core/core"
@@ -155,7 +154,11 @@ func TestUDPServerSubnet(t *testing.T) {
client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client) client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)
ips, err := client.LookupIP("google.com") ips, err := client.LookupIP("google.com", feature_dns.IPOption{
IPv4Enable: true,
IPv6Enable: true,
FakeEnable: false,
})
if err != nil { if err != nil {
t.Fatal("unexpected error: ", err) t.Fatal("unexpected error: ", err)
} }
@@ -210,7 +213,11 @@ func TestUDPServer(t *testing.T) {
client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client) client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)
{ {
ips, err := client.LookupIP("google.com") ips, err := client.LookupIP("google.com", feature_dns.IPOption{
IPv4Enable: true,
IPv6Enable: true,
FakeEnable: false,
})
if err != nil { if err != nil {
t.Fatal("unexpected error: ", err) t.Fatal("unexpected error: ", err)
} }
@@ -221,7 +228,11 @@ func TestUDPServer(t *testing.T) {
} }
{ {
ips, err := client.LookupIP("facebook.com") ips, err := client.LookupIP("facebook.com", feature_dns.IPOption{
IPv4Enable: true,
IPv6Enable: true,
FakeEnable: false,
})
if err != nil { if err != nil {
t.Fatal("unexpected error: ", err) t.Fatal("unexpected error: ", err)
} }
@@ -232,7 +243,11 @@ func TestUDPServer(t *testing.T) {
} }
{ {
_, err := client.LookupIP("notexist.google.com") _, err := client.LookupIP("notexist.google.com", feature_dns.IPOption{
IPv4Enable: true,
IPv6Enable: true,
FakeEnable: false,
})
if err == nil { if err == nil {
t.Fatal("nil error") t.Fatal("nil error")
} }
@@ -242,8 +257,11 @@ func TestUDPServer(t *testing.T) {
} }
{ {
clientv6 := client.(feature_dns.IPv6Lookup) ips, err := client.LookupIP("ipv4only.google.com", feature_dns.IPOption{
ips, err := clientv6.LookupIPv6("ipv4only.google.com") IPv4Enable: false,
IPv6Enable: true,
FakeEnable: false,
})
if err != feature_dns.ErrEmptyResponse { if err != feature_dns.ErrEmptyResponse {
t.Fatal("error: ", err) t.Fatal("error: ", err)
} }
@@ -255,7 +273,11 @@ func TestUDPServer(t *testing.T) {
dnsServer.Shutdown() dnsServer.Shutdown()
{ {
ips, err := client.LookupIP("google.com") ips, err := client.LookupIP("google.com", feature_dns.IPOption{
IPv4Enable: true,
IPv6Enable: true,
FakeEnable: false,
})
if err != nil { if err != nil {
t.Fatal("unexpected error: ", err) t.Fatal("unexpected error: ", err)
} }
@@ -304,10 +326,10 @@ func TestPrioritizedDomain(t *testing.T) {
}, },
Port: uint32(port), Port: uint32(port),
}, },
PrioritizedDomain: []*domain.Domain{ PrioritizedDomain: []*NameServer_PriorityDomain{
{ {
Type: domain.MatchingType_Full, Type: DomainMatchingType_Full,
Value: "google.com", Domain: "google.com",
}, },
}, },
}, },
@@ -332,7 +354,11 @@ func TestPrioritizedDomain(t *testing.T) {
startTime := time.Now() startTime := time.Now()
{ {
ips, err := client.LookupIP("google.com") ips, err := client.LookupIP("google.com", feature_dns.IPOption{
IPv4Enable: true,
IPv6Enable: true,
FakeEnable: false,
})
if err != nil { if err != nil {
t.Fatal("unexpected error: ", err) t.Fatal("unexpected error: ", err)
} }
@@ -391,9 +417,12 @@ func TestUDPServerIPv6(t *testing.T) {
common.Must(err) common.Must(err)
client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client) client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)
client6 := client.(feature_dns.IPv6Lookup)
{ {
ips, err := client6.LookupIPv6("ipv6.google.com") ips, err := client.LookupIP("ipv6.google.com", feature_dns.IPOption{
IPv4Enable: false,
IPv6Enable: true,
FakeEnable: false,
})
if err != nil { if err != nil {
t.Fatal("unexpected error: ", err) t.Fatal("unexpected error: ", err)
} }
@@ -433,7 +462,7 @@ func TestStaticHostDomain(t *testing.T) {
}, },
StaticHosts: []*Config_HostMapping{ StaticHosts: []*Config_HostMapping{
{ {
Type: domain.MatchingType_Full, Type: DomainMatchingType_Full,
Domain: "example.com", Domain: "example.com",
ProxiedDomain: "google.com", ProxiedDomain: "google.com",
}, },
@@ -456,7 +485,11 @@ func TestStaticHostDomain(t *testing.T) {
client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client) client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)
{ {
ips, err := client.LookupIP("example.com") ips, err := client.LookupIP("example.com", feature_dns.IPOption{
IPv4Enable: true,
IPv6Enable: true,
FakeEnable: false,
})
if err != nil { if err != nil {
t.Fatal("unexpected error: ", err) t.Fatal("unexpected error: ", err)
} }
@@ -497,10 +530,10 @@ func TestIPMatch(t *testing.T) {
}, },
Port: uint32(port), Port: uint32(port),
}, },
Geoip: []*geoip.GeoIP{ Geoip: []*router.GeoIP{
{ {
CountryCode: "local", CountryCode: "local",
Cidr: []*geoip.CIDR{ Cidr: []*router.CIDR{
{ {
// inner ip, will not match // inner ip, will not match
Ip: []byte{192, 168, 11, 1}, Ip: []byte{192, 168, 11, 1},
@@ -521,10 +554,10 @@ func TestIPMatch(t *testing.T) {
}, },
Port: uint32(port), Port: uint32(port),
}, },
Geoip: []*geoip.GeoIP{ Geoip: []*router.GeoIP{
{ {
CountryCode: "test", CountryCode: "test",
Cidr: []*geoip.CIDR{ Cidr: []*router.CIDR{
{ {
Ip: []byte{8, 8, 8, 8}, Ip: []byte{8, 8, 8, 8},
Prefix: 32, Prefix: 32,
@@ -533,7 +566,7 @@ func TestIPMatch(t *testing.T) {
}, },
{ {
CountryCode: "test", CountryCode: "test",
Cidr: []*geoip.CIDR{ Cidr: []*router.CIDR{
{ {
Ip: []byte{8, 8, 8, 4}, Ip: []byte{8, 8, 8, 4},
Prefix: 32, Prefix: 32,
@@ -563,7 +596,11 @@ func TestIPMatch(t *testing.T) {
startTime := time.Now() startTime := time.Now()
{ {
ips, err := client.LookupIP("google.com") ips, err := client.LookupIP("google.com", feature_dns.IPOption{
IPv4Enable: true,
IPv6Enable: true,
FakeEnable: false,
})
if err != nil { if err != nil {
t.Fatal("unexpected error: ", err) t.Fatal("unexpected error: ", err)
} }
@@ -617,14 +654,14 @@ func TestLocalDomain(t *testing.T) {
}, },
Port: uint32(port), Port: uint32(port),
}, },
PrioritizedDomain: []*domain.Domain{ PrioritizedDomain: []*NameServer_PriorityDomain{
// Equivalent of dotless:localhost // Equivalent of dotless:localhost
{Type: domain.MatchingType_Regex, Value: "^[^.]*localhost[^.]*$"}, {Type: DomainMatchingType_Regex, Domain: "^[^.]*localhost[^.]*$"},
}, },
Geoip: []*geoip.GeoIP{ Geoip: []*router.GeoIP{
{ // Will match localhost, localhost-a and localhost-b, { // Will match localhost, localhost-a and localhost-b,
CountryCode: "local", CountryCode: "local",
Cidr: []*geoip.CIDR{ Cidr: []*router.CIDR{
{Ip: []byte{127, 0, 0, 2}, Prefix: 32}, {Ip: []byte{127, 0, 0, 2}, Prefix: 32},
{Ip: []byte{127, 0, 0, 3}, Prefix: 32}, {Ip: []byte{127, 0, 0, 3}, Prefix: 32},
{Ip: []byte{127, 0, 0, 4}, Prefix: 32}, {Ip: []byte{127, 0, 0, 4}, Prefix: 32},
@@ -642,22 +679,22 @@ func TestLocalDomain(t *testing.T) {
}, },
Port: uint32(port), Port: uint32(port),
}, },
PrioritizedDomain: []*domain.Domain{ PrioritizedDomain: []*NameServer_PriorityDomain{
// Equivalent of dotless: and domain:local // Equivalent of dotless: and domain:local
{Type: domain.MatchingType_Regex, Value: "^[^.]*$"}, {Type: DomainMatchingType_Regex, Domain: "^[^.]*$"},
{Type: domain.MatchingType_Subdomain, Value: "local"}, {Type: DomainMatchingType_Subdomain, Domain: "local"},
{Type: domain.MatchingType_Subdomain, Value: "localdomain"}, {Type: DomainMatchingType_Subdomain, Domain: "localdomain"},
}, },
}, },
}, },
StaticHosts: []*Config_HostMapping{ StaticHosts: []*Config_HostMapping{
{ {
Type: domain.MatchingType_Full, Type: DomainMatchingType_Full,
Domain: "hostnamestatic", Domain: "hostnamestatic",
Ip: [][]byte{{127, 0, 0, 53}}, Ip: [][]byte{{127, 0, 0, 53}},
}, },
{ {
Type: domain.MatchingType_Full, Type: DomainMatchingType_Full,
Domain: "hostnamealias", Domain: "hostnamealias",
ProxiedDomain: "hostname.localdomain", ProxiedDomain: "hostname.localdomain",
}, },
@@ -682,7 +719,11 @@ func TestLocalDomain(t *testing.T) {
startTime := time.Now() startTime := time.Now()
{ // Will match dotless: { // Will match dotless:
ips, err := client.LookupIP("hostname") ips, err := client.LookupIP("hostname", feature_dns.IPOption{
IPv4Enable: true,
IPv6Enable: true,
FakeEnable: false,
})
if err != nil { if err != nil {
t.Fatal("unexpected error: ", err) t.Fatal("unexpected error: ", err)
} }
@@ -693,7 +734,11 @@ func TestLocalDomain(t *testing.T) {
} }
{ // Will match domain:local { // Will match domain:local
ips, err := client.LookupIP("hostname.local") ips, err := client.LookupIP("hostname.local", feature_dns.IPOption{
IPv4Enable: true,
IPv6Enable: true,
FakeEnable: false,
})
if err != nil { if err != nil {
t.Fatal("unexpected error: ", err) t.Fatal("unexpected error: ", err)
} }
@@ -704,7 +749,11 @@ func TestLocalDomain(t *testing.T) {
} }
{ // Will match static ip { // Will match static ip
ips, err := client.LookupIP("hostnamestatic") ips, err := client.LookupIP("hostnamestatic", feature_dns.IPOption{
IPv4Enable: true,
IPv6Enable: true,
FakeEnable: false,
})
if err != nil { if err != nil {
t.Fatal("unexpected error: ", err) t.Fatal("unexpected error: ", err)
} }
@@ -715,7 +764,11 @@ func TestLocalDomain(t *testing.T) {
} }
{ // Will match domain replacing { // Will match domain replacing
ips, err := client.LookupIP("hostnamealias") ips, err := client.LookupIP("hostnamealias", feature_dns.IPOption{
IPv4Enable: true,
IPv6Enable: true,
FakeEnable: false,
})
if err != nil { if err != nil {
t.Fatal("unexpected error: ", err) t.Fatal("unexpected error: ", err)
} }
@@ -726,7 +779,11 @@ func TestLocalDomain(t *testing.T) {
} }
{ // Will match dotless:localhost, but not expectIPs: 127.0.0.2, 127.0.0.3, then matches at dotless: { // Will match dotless:localhost, but not expectIPs: 127.0.0.2, 127.0.0.3, then matches at dotless:
ips, err := client.LookupIP("localhost") ips, err := client.LookupIP("localhost", feature_dns.IPOption{
IPv4Enable: true,
IPv6Enable: true,
FakeEnable: false,
})
if err != nil { if err != nil {
t.Fatal("unexpected error: ", err) t.Fatal("unexpected error: ", err)
} }
@@ -737,7 +794,11 @@ func TestLocalDomain(t *testing.T) {
} }
{ // Will match dotless:localhost, and expectIPs: 127.0.0.2, 127.0.0.3 { // Will match dotless:localhost, and expectIPs: 127.0.0.2, 127.0.0.3
ips, err := client.LookupIP("localhost-a") ips, err := client.LookupIP("localhost-a", feature_dns.IPOption{
IPv4Enable: true,
IPv6Enable: true,
FakeEnable: false,
})
if err != nil { if err != nil {
t.Fatal("unexpected error: ", err) t.Fatal("unexpected error: ", err)
} }
@@ -748,7 +809,11 @@ func TestLocalDomain(t *testing.T) {
} }
{ // Will match dotless:localhost, and expectIPs: 127.0.0.2, 127.0.0.3 { // Will match dotless:localhost, and expectIPs: 127.0.0.2, 127.0.0.3
ips, err := client.LookupIP("localhost-b") ips, err := client.LookupIP("localhost-b", feature_dns.IPOption{
IPv4Enable: true,
IPv6Enable: true,
FakeEnable: false,
})
if err != nil { if err != nil {
t.Fatal("unexpected error: ", err) t.Fatal("unexpected error: ", err)
} }
@@ -759,7 +824,11 @@ func TestLocalDomain(t *testing.T) {
} }
{ // Will match dotless: { // Will match dotless:
ips, err := client.LookupIP("Mijia Cloud") ips, err := client.LookupIP("Mijia Cloud", feature_dns.IPOption{
IPv4Enable: true,
IPv6Enable: true,
FakeEnable: false,
})
if err != nil { if err != nil {
t.Fatal("unexpected error: ", err) t.Fatal("unexpected error: ", err)
} }
@@ -813,15 +882,15 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
}, },
Port: uint32(port), Port: uint32(port),
}, },
PrioritizedDomain: []*domain.Domain{ PrioritizedDomain: []*NameServer_PriorityDomain{
{ {
Type: domain.MatchingType_Subdomain, Type: DomainMatchingType_Subdomain,
Value: "google.com", Domain: "google.com",
}, },
}, },
Geoip: []*geoip.GeoIP{ Geoip: []*router.GeoIP{
{ // Will only match 8.8.8.8 and 8.8.4.4 { // Will only match 8.8.8.8 and 8.8.4.4
Cidr: []*geoip.CIDR{ Cidr: []*router.CIDR{
{Ip: []byte{8, 8, 8, 8}, Prefix: 32}, {Ip: []byte{8, 8, 8, 8}, Prefix: 32},
{Ip: []byte{8, 8, 4, 4}, Prefix: 32}, {Ip: []byte{8, 8, 4, 4}, Prefix: 32},
}, },
@@ -838,15 +907,15 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
}, },
Port: uint32(port), Port: uint32(port),
}, },
PrioritizedDomain: []*domain.Domain{ PrioritizedDomain: []*NameServer_PriorityDomain{
{ {
Type: domain.MatchingType_Subdomain, Type: DomainMatchingType_Subdomain,
Value: "google.com", Domain: "google.com",
}, },
}, },
Geoip: []*geoip.GeoIP{ Geoip: []*router.GeoIP{
{ // Will match 8.8.8.8 and 8.8.8.7, etc { // Will match 8.8.8.8 and 8.8.8.7, etc
Cidr: []*geoip.CIDR{ Cidr: []*router.CIDR{
{Ip: []byte{8, 8, 8, 7}, Prefix: 24}, {Ip: []byte{8, 8, 8, 7}, Prefix: 24},
}, },
}, },
@@ -862,15 +931,15 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
}, },
Port: uint32(port), Port: uint32(port),
}, },
PrioritizedDomain: []*domain.Domain{ PrioritizedDomain: []*NameServer_PriorityDomain{
{ {
Type: domain.MatchingType_Subdomain, Type: DomainMatchingType_Subdomain,
Value: "api.google.com", Domain: "api.google.com",
}, },
}, },
Geoip: []*geoip.GeoIP{ Geoip: []*router.GeoIP{
{ // Will only match 8.8.7.7 (api.google.com) { // Will only match 8.8.7.7 (api.google.com)
Cidr: []*geoip.CIDR{ Cidr: []*router.CIDR{
{Ip: []byte{8, 8, 7, 7}, Prefix: 32}, {Ip: []byte{8, 8, 7, 7}, Prefix: 32},
}, },
}, },
@@ -886,15 +955,15 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
}, },
Port: uint32(port), Port: uint32(port),
}, },
PrioritizedDomain: []*domain.Domain{ PrioritizedDomain: []*NameServer_PriorityDomain{
{ {
Type: domain.MatchingType_Full, Type: DomainMatchingType_Full,
Value: "v2.api.google.com", Domain: "v2.api.google.com",
}, },
}, },
Geoip: []*geoip.GeoIP{ Geoip: []*router.GeoIP{
{ // Will only match 8.8.7.8 (v2.api.google.com) { // Will only match 8.8.7.8 (v2.api.google.com)
Cidr: []*geoip.CIDR{ Cidr: []*router.CIDR{
{Ip: []byte{8, 8, 7, 8}, Prefix: 32}, {Ip: []byte{8, 8, 7, 8}, Prefix: 32},
}, },
}, },
@@ -921,7 +990,11 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
startTime := time.Now() startTime := time.Now()
{ // Will match server 1,2 and server 1 returns expected ip { // Will match server 1,2 and server 1 returns expected ip
ips, err := client.LookupIP("google.com") ips, err := client.LookupIP("google.com", feature_dns.IPOption{
IPv4Enable: true,
IPv6Enable: true,
FakeEnable: false,
})
if err != nil { if err != nil {
t.Fatal("unexpected error: ", err) t.Fatal("unexpected error: ", err)
} }
@@ -932,8 +1005,11 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
} }
{ // Will match server 1,2 and server 1 returns unexpected ip, then server 2 returns expected one { // Will match server 1,2 and server 1 returns unexpected ip, then server 2 returns expected one
clientv4 := client.(feature_dns.IPv4Lookup) ips, err := client.LookupIP("ipv6.google.com", feature_dns.IPOption{
ips, err := clientv4.LookupIPv4("ipv6.google.com") IPv4Enable: true,
IPv6Enable: false,
FakeEnable: false,
})
if err != nil { if err != nil {
t.Fatal("unexpected error: ", err) t.Fatal("unexpected error: ", err)
} }
@@ -944,7 +1020,11 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
} }
{ // Will match server 3,1,2 and server 3 returns expected one { // Will match server 3,1,2 and server 3 returns expected one
ips, err := client.LookupIP("api.google.com") ips, err := client.LookupIP("api.google.com", feature_dns.IPOption{
IPv4Enable: true,
IPv6Enable: true,
FakeEnable: false,
})
if err != nil { if err != nil {
t.Fatal("unexpected error: ", err) t.Fatal("unexpected error: ", err)
} }
@@ -955,7 +1035,11 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
} }
{ // Will match server 4,3,1,2 and server 4 returns expected one { // Will match server 4,3,1,2 and server 4 returns expected one
ips, err := client.LookupIP("v2.api.google.com") ips, err := client.LookupIP("v2.api.google.com", feature_dns.IPOption{
IPv4Enable: true,
IPv6Enable: true,
FakeEnable: false,
})
if err != nil { if err != nil {
t.Fatal("unexpected error: ", err) t.Fatal("unexpected error: ", err)
} }

View File

@@ -31,10 +31,10 @@ type ClassicNameServer struct {
udpServer *udp.Dispatcher udpServer *udp.Dispatcher
cleanup *task.Periodic cleanup *task.Periodic
reqID uint32 reqID uint32
clientIP net.IP
} }
// NewClassicNameServer creates udp server object for remote resolving. func NewClassicNameServer(address net.Destination, dispatcher routing.Dispatcher, clientIP net.IP) *ClassicNameServer {
func NewClassicNameServer(address net.Destination, dispatcher routing.Dispatcher) *ClassicNameServer {
// default to 53 if unspecific // default to 53 if unspecific
if address.Port == 0 { if address.Port == 0 {
address.Port = net.Port(53) address.Port = net.Port(53)
@@ -44,6 +44,7 @@ func NewClassicNameServer(address net.Destination, dispatcher routing.Dispatcher
address: address, address: address,
ips: make(map[string]record), ips: make(map[string]record),
requests: make(map[uint16]dnsRequest), requests: make(map[uint16]dnsRequest),
clientIP: clientIP,
pub: pubsub.NewService(), pub: pubsub.NewService(),
name: strings.ToUpper(address.String()), name: strings.ToUpper(address.String()),
} }
@@ -56,12 +57,10 @@ func NewClassicNameServer(address net.Destination, dispatcher routing.Dispatcher
return s return s
} }
// Name implements Server.
func (s *ClassicNameServer) Name() string { func (s *ClassicNameServer) Name() string {
return s.name return s.name
} }
// Cleanup clears expired items from cache
func (s *ClassicNameServer) Cleanup() error { func (s *ClassicNameServer) Cleanup() error {
now := time.Now() now := time.Now()
s.Lock() s.Lock()
@@ -103,7 +102,6 @@ func (s *ClassicNameServer) Cleanup() error {
return nil return nil
} }
// HandleResponse handles udp response packet from remote DNS server.
func (s *ClassicNameServer) HandleResponse(ctx context.Context, packet *udp_proto.Packet) { func (s *ClassicNameServer) HandleResponse(ctx context.Context, packet *udp_proto.Packet) {
ipRec, err := parseResponse(packet.Payload.Bytes()) ipRec, err := parseResponse(packet.Payload.Bytes())
if err != nil { if err != nil {
@@ -181,10 +179,10 @@ func (s *ClassicNameServer) addPendingRequest(req *dnsRequest) {
s.requests[id] = *req s.requests[id] = *req
} }
func (s *ClassicNameServer) sendQuery(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption) { func (s *ClassicNameServer) sendQuery(ctx context.Context, domain string, option dns_feature.IPOption) {
newError(s.name, " querying DNS for: ", domain).AtDebug().WriteToLog(session.ExportIDToError(ctx)) newError(s.name, " querying DNS for: ", domain).AtDebug().WriteToLog(session.ExportIDToError(ctx))
reqs := buildReqMsgs(domain, option, s.newReqID, genEDNS0Options(clientIP)) reqs := buildReqMsgs(domain, option, s.newReqID, genEDNS0Options(s.clientIP))
for _, req := range reqs { for _, req := range reqs {
s.addPendingRequest(req) s.addPendingRequest(req)
@@ -193,6 +191,7 @@ func (s *ClassicNameServer) sendQuery(ctx context.Context, domain string, client
if inbound := session.InboundFromContext(ctx); inbound != nil { if inbound := session.InboundFromContext(ctx); inbound != nil {
udpCtx = session.ContextWithInbound(udpCtx, inbound) udpCtx = session.ContextWithInbound(udpCtx, inbound)
} }
udpCtx = session.ContextWithContent(udpCtx, &session.Content{ udpCtx = session.ContextWithContent(udpCtx, &session.Content{
Protocol: "dns", Protocol: "dns",
}) })
@@ -234,7 +233,7 @@ func (s *ClassicNameServer) findIPsForDomain(domain string, option dns_feature.I
} }
if len(ips) > 0 { if len(ips) > 0 {
return toNetIP(ips) return toNetIP(ips), nil
} }
if lastErr != nil { if lastErr != nil {
@@ -245,20 +244,14 @@ func (s *ClassicNameServer) findIPsForDomain(domain string, option dns_feature.I
} }
// QueryIP implements Server. // QueryIP implements Server.
func (s *ClassicNameServer) QueryIP(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption, cs CacheStrategy) ([]net.IP, error) { func (s *ClassicNameServer) QueryIP(ctx context.Context, domain string, option dns_feature.IPOption) ([]net.IP, error) {
fqdn := Fqdn(domain) fqdn := Fqdn(domain)
if cs == CacheStrategy_Cache_DISABLE { ips, err := s.findIPsForDomain(fqdn, option)
newError("DNS cache is disabled. Querying IP for ", domain, " at ", s.name).AtDebug().WriteToLog() if err != errRecordNotFound {
} else { newError(s.name, " cache HIT ", domain, " -> ", ips).Base(err).AtDebug().WriteToLog()
ips, err := s.findIPsForDomain(fqdn, option) log.Record(&log.DNSLog{s.name, domain, ips, log.DNSCacheHit, 0, err})
if err != errRecordNotFound { return ips, err
if cs == CacheStrategy_Cache_NOERROR && err == nil {
newError(s.name, " cache HIT ", domain, " -> ", ips).Base(err).AtDebug().WriteToLog()
log.Record(&log.DNSLog{s.name, domain, ips, log.DNSCacheHit, 0, err})
return ips, err
}
}
} }
// ipv4 and ipv6 belong to different subscription groups // ipv4 and ipv6 belong to different subscription groups
@@ -287,7 +280,7 @@ func (s *ClassicNameServer) QueryIP(ctx context.Context, domain string, clientIP
} }
close(done) close(done)
}() }()
s.sendQuery(ctx, fqdn, clientIP, option) s.sendQuery(ctx, fqdn, option)
start := time.Now() start := time.Now()
for { for {

View File

@@ -1,12 +1,5 @@
package proxyman 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 { func (s *AllocationStrategy) GetConcurrencyValue() uint32 {
if s == nil || s.Concurrency == nil { if s == nil || s.Concurrency == nil {
return 3 return 3
@@ -44,32 +37,3 @@ func (c *ReceiverConfig) GetEffectiveSniffingSettings() *SniffingConfig {
return nil return nil
} }
type SniffingMatcher struct {
ExDomain *domain.DomainMatcher
ExIP *geoip.MultiGeoIPMatcher
}
func NewSniffingMatcher(sc *SniffingConfig) (*SniffingMatcher, error) {
m := new(SniffingMatcher)
if sc == nil {
return m, nil
}
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
}

View File

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

View File

@@ -6,8 +6,6 @@ option go_package = "github.com/xtls/xray-core/app/proxyman";
option java_package = "com.xray.app.proxyman"; option java_package = "com.xray.app.proxyman";
option java_multiple_files = true; 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/address.proto";
import "common/net/port.proto"; import "common/net/port.proto";
import "transport/internet/config.proto"; import "transport/internet/config.proto";
@@ -58,9 +56,7 @@ message SniffingConfig {
// Override target destination if sniff'ed protocol is in the given list. // Override target destination if sniff'ed protocol is in the given list.
// Supported values are "http", "tls", "fakedns". // Supported values are "http", "tls", "fakedns".
repeated string destination_override = 2; repeated string destination_override = 2;
repeated string domains_excluded = 3;
repeated xray.common.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. // 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. // Can be used to support SMTP like protocol where server send the first message.

View File

@@ -1,9 +0,0 @@
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{})
}

View File

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

View File

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

View File

@@ -12,8 +12,6 @@ import (
. "github.com/xtls/xray-core/app/router/command" . "github.com/xtls/xray-core/app/router/command"
"github.com/xtls/xray-core/app/stats" "github.com/xtls/xray-core/app/stats"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"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/common/net"
"github.com/xtls/xray-core/features/routing" "github.com/xtls/xray-core/features/routing"
"github.com/xtls/xray-core/testing/mocks" "github.com/xtls/xray-core/testing/mocks"
@@ -233,11 +231,11 @@ func TestSerivceTestRoute(t *testing.T) {
TargetTag: &router.RoutingRule_Tag{Tag: "out"}, TargetTag: &router.RoutingRule_Tag{Tag: "out"},
}, },
{ {
Domain: []*domain.Domain{{Type: domain.MatchingType_Subdomain, Value: "com"}}, Domain: []*router.Domain{{Type: router.Domain_Domain, Value: "com"}},
TargetTag: &router.RoutingRule_Tag{Tag: "out"}, TargetTag: &router.RoutingRule_Tag{Tag: "out"},
}, },
{ {
SourceGeoip: []*geoip.GeoIP{{CountryCode: "private", Cidr: []*geoip.CIDR{{Ip: []byte{127, 0, 0, 0}, Prefix: 8}}}}, SourceGeoip: []*router.GeoIP{{CountryCode: "private", Cidr: []*router.CIDR{{Ip: []byte{127, 0, 0, 0}, Prefix: 8}}}},
TargetTag: &router.RoutingRule_Tag{Tag: "out"}, TargetTag: &router.RoutingRule_Tag{Tag: "out"},
}, },
{ {

View File

@@ -28,12 +28,6 @@ func (c routingContext) GetTargetPort() net.Port {
return net.Port(c.RoutingContext.GetTargetPort()) return net.Port(c.RoutingContext.GetTargetPort())
} }
// GetSkipDNSResolve is a mock implementation here to match the interface,
// SkipDNSResolve is set from dns module, no use if coming from a protobuf object?
func (c routingContext) GetSkipDNSResolve() bool {
return false
}
// AsRoutingContext converts a protobuf RoutingContext into an implementation of routing.Context. // AsRoutingContext converts a protobuf RoutingContext into an implementation of routing.Context.
func AsRoutingContext(r *RoutingContext) routing.Context { func AsRoutingContext(r *RoutingContext) routing.Context {
return routingContext{r} return routingContext{r}

View File

@@ -7,6 +7,7 @@ import (
"go.starlark.net/syntax" "go.starlark.net/syntax"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/strmatcher"
"github.com/xtls/xray-core/features/routing" "github.com/xtls/xray-core/features/routing"
) )
@@ -40,6 +41,118 @@ func (v *ConditionChan) Len() int {
return len(*v) return len(*v)
} }
var matcherTypeMap = map[Domain_Type]strmatcher.Type{
Domain_Plain: strmatcher.Substr,
Domain_Regex: strmatcher.Regex,
Domain_Domain: strmatcher.Domain,
Domain_Full: strmatcher.Full,
}
func domainToMatcher(domain *Domain) (strmatcher.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 strmatcher.IndexMatcher
}
func NewMphMatcherGroup(domains []*Domain) (*DomainMatcher, error) {
g := strmatcher.NewMphMatcherGroup()
for _, d := range domains {
matcherType, f := matcherTypeMap[d.Type]
if !f {
return nil, newError("unsupported domain type", d.Type)
}
_, err := g.AddPattern(d.Value, matcherType)
if err != nil {
return nil, err
}
}
g.Build()
return &DomainMatcher{
matchers: g,
}, nil
}
func NewDomainMatcher(domains []*Domain) (*DomainMatcher, error) {
g := new(strmatcher.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(strings.ToLower(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(domain)
}
type MultiGeoIPMatcher struct {
matchers []*GeoIPMatcher
onSource bool
}
func NewMultiGeoIPMatcher(geoips []*GeoIP, onSource bool) (*MultiGeoIPMatcher, error) {
var matchers []*GeoIPMatcher
for _, geoip := range geoips {
matcher, err := globalGeoIPContainer.Add(geoip)
if err != nil {
return nil, err
}
matchers = append(matchers, matcher)
}
matcher := &MultiGeoIPMatcher{
matchers: matchers,
onSource: onSource,
}
return matcher, nil
}
// Apply implements Condition.
func (m *MultiGeoIPMatcher) Apply(ctx routing.Context) bool {
var ips []net.IP
if m.onSource {
ips = ctx.GetSourceIPs()
} else {
ips = ctx.GetTargetIPs()
}
for _, ip := range ips {
for _, matcher := range m.matchers {
if matcher.Match(ip) {
return true
}
}
}
return false
}
type PortMatcher struct { type PortMatcher struct {
port net.MemoryPortList port net.MemoryPortList
onSource bool onSource bool

View File

@@ -1,4 +1,4 @@
package geoip package router
import ( import (
"encoding/binary" "encoding/binary"
@@ -7,24 +7,17 @@ import (
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
) )
//go:generate go run github.com/xtls/xray-core/common/errors/errorgen
type ipv6 struct { type ipv6 struct {
a uint64 a uint64
b uint64 b uint64
} }
type GeoIPMatcher struct { type GeoIPMatcher struct {
countryCode string countryCode string
reverseMatch bool ip4 []uint32
ip4 []uint32 prefix4 []uint8
prefix4 []uint8 ip6 []ipv6
ip6 []ipv6 prefix6 []uint8
prefix6 []uint8
}
func (m *GeoIPMatcher) SetReverseMatch(isReverseMatch bool) {
m.reverseMatch = isReverseMatch
} }
func normalize4(ip uint32, prefix uint8) uint32 { func normalize4(ip uint32, prefix uint8) uint32 {
@@ -154,17 +147,8 @@ func (m *GeoIPMatcher) match6(ip ipv6) bool {
func (m *GeoIPMatcher) Match(ip net.IP) bool { func (m *GeoIPMatcher) Match(ip net.IP) bool {
switch len(ip) { switch len(ip) {
case 4: case 4:
if m.reverseMatch {
return !m.match4(binary.BigEndian.Uint32(ip))
}
return m.match4(binary.BigEndian.Uint32(ip)) return m.match4(binary.BigEndian.Uint32(ip))
case 16: case 16:
if m.reverseMatch {
return !m.match6(ipv6{
a: binary.BigEndian.Uint64(ip[0:8]),
b: binary.BigEndian.Uint64(ip[8:16]),
})
}
return m.match6(ipv6{ return m.match6(ipv6{
a: binary.BigEndian.Uint64(ip[0:8]), a: binary.BigEndian.Uint64(ip[0:8]),
b: binary.BigEndian.Uint64(ip[8:16]), b: binary.BigEndian.Uint64(ip[8:16]),
@@ -184,15 +168,14 @@ type GeoIPMatcherContainer struct {
func (c *GeoIPMatcherContainer) Add(geoip *GeoIP) (*GeoIPMatcher, error) { func (c *GeoIPMatcherContainer) Add(geoip *GeoIP) (*GeoIPMatcher, error) {
if len(geoip.CountryCode) > 0 { if len(geoip.CountryCode) > 0 {
for _, m := range c.matchers { for _, m := range c.matchers {
if m.countryCode == geoip.CountryCode && m.reverseMatch == geoip.ReverseMatch { if m.countryCode == geoip.CountryCode {
return m, nil return m, nil
} }
} }
} }
m := &GeoIPMatcher{ m := &GeoIPMatcher{
countryCode: geoip.CountryCode, countryCode: geoip.CountryCode,
reverseMatch: geoip.ReverseMatch,
} }
if err := m.Init(geoip.Cidr); err != nil { if err := m.Init(geoip.Cidr); err != nil {
return nil, err return nil, err
@@ -204,5 +187,5 @@ func (c *GeoIPMatcherContainer) Add(geoip *GeoIP) (*GeoIPMatcher, error) {
} }
var ( var (
GlobalGeoIPContainer GeoIPMatcherContainer globalGeoIPContainer GeoIPMatcherContainer
) )

View File

@@ -1,16 +1,16 @@
package geoip_test package router_test
import ( import (
"os" "os"
"path/filepath" "path/filepath"
"testing" "testing"
"github.com/golang/protobuf/proto"
"github.com/xtls/xray-core/app/router"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
. "github.com/xtls/xray-core/common/matcher/geoip"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/platform" "github.com/xtls/xray-core/common/platform"
"github.com/xtls/xray-core/common/platform/filesystem" "github.com/xtls/xray-core/common/platform/filesystem"
"google.golang.org/protobuf/proto"
) )
func init() { func init() {
@@ -18,47 +18,27 @@ func init() {
common.Must(err) common.Must(err)
if _, err := os.Stat(platform.GetAssetLocation("geoip.dat")); err != nil && os.IsNotExist(err) { if _, err := os.Stat(platform.GetAssetLocation("geoip.dat")); err != nil && os.IsNotExist(err) {
common.Must(filesystem.CopyFile(platform.GetAssetLocation("geoip.dat"), filepath.Join(wd, "..", "..", "..", "resources", "geoip.dat"))) common.Must(filesystem.CopyFile(platform.GetAssetLocation("geoip.dat"), filepath.Join(wd, "..", "..", "resources", "geoip.dat")))
}
if _, err := os.Stat(platform.GetAssetLocation("geoiptestrouter.dat")); err != nil && os.IsNotExist(err) {
common.Must(filesystem.CopyFile(platform.GetAssetLocation("geoiptestrouter.dat"), filepath.Join(wd, "..", "..", "..", "resources", "geoip.dat")))
} }
if _, err := os.Stat(platform.GetAssetLocation("geosite.dat")); err != nil && os.IsNotExist(err) { if _, err := os.Stat(platform.GetAssetLocation("geosite.dat")); err != nil && os.IsNotExist(err) {
common.Must(filesystem.CopyFile(platform.GetAssetLocation("geosite.dat"), filepath.Join(wd, "..", "..", "..", "resources", "geosite.dat"))) common.Must(filesystem.CopyFile(platform.GetAssetLocation("geosite.dat"), filepath.Join(wd, "..", "..", "resources", "geosite.dat")))
}
}
func TestParseIPList(t *testing.T) {
ips := []string{
"geoip:us",
"geoip:cn",
"geoip:!cn",
"ext:geoiptestrouter.dat:!cn",
"ext:geoiptestrouter.dat:ca",
"ext-ip:geoiptestrouter.dat:!cn",
"ext-ip:geoiptestrouter.dat:!ca",
}
_, err := ParseIPList(ips)
if err != nil {
t.Fatalf("Failed to parse geoip list, got %s", err)
} }
} }
func TestGeoIPMatcherContainer(t *testing.T) { func TestGeoIPMatcherContainer(t *testing.T) {
container := &GeoIPMatcherContainer{} container := &router.GeoIPMatcherContainer{}
m1, err := container.Add(&GeoIP{ m1, err := container.Add(&router.GeoIP{
CountryCode: "CN", CountryCode: "CN",
}) })
common.Must(err) common.Must(err)
m2, err := container.Add(&GeoIP{ m2, err := container.Add(&router.GeoIP{
CountryCode: "US", CountryCode: "US",
}) })
common.Must(err) common.Must(err)
m3, err := container.Add(&GeoIP{ m3, err := container.Add(&router.GeoIP{
CountryCode: "CN", CountryCode: "CN",
}) })
common.Must(err) common.Must(err)
@@ -73,7 +53,7 @@ func TestGeoIPMatcherContainer(t *testing.T) {
} }
func TestGeoIPMatcher(t *testing.T) { func TestGeoIPMatcher(t *testing.T) {
cidrList := CIDRList{ cidrList := router.CIDRList{
{Ip: []byte{0, 0, 0, 0}, Prefix: 8}, {Ip: []byte{0, 0, 0, 0}, Prefix: 8},
{Ip: []byte{10, 0, 0, 0}, Prefix: 8}, {Ip: []byte{10, 0, 0, 0}, Prefix: 8},
{Ip: []byte{100, 64, 0, 0}, Prefix: 10}, {Ip: []byte{100, 64, 0, 0}, Prefix: 10},
@@ -90,7 +70,7 @@ func TestGeoIPMatcher(t *testing.T) {
{Ip: []byte{91, 108, 4, 0}, Prefix: 16}, {Ip: []byte{91, 108, 4, 0}, Prefix: 16},
} }
matcher := &GeoIPMatcher{} matcher := &router.GeoIPMatcher{}
common.Must(matcher.Init(cidrList)) common.Must(matcher.Init(cidrList))
testCases := []struct { testCases := []struct {
@@ -143,47 +123,11 @@ func TestGeoIPMatcher(t *testing.T) {
} }
} }
func TestGeoIPReverseMatcher(t *testing.T) {
cidrList := CIDRList{
{Ip: []byte{8, 8, 8, 8}, Prefix: 32},
{Ip: []byte{91, 108, 4, 0}, Prefix: 16},
}
matcher := &GeoIPMatcher{}
matcher.SetReverseMatch(true) // Reverse match
common.Must(matcher.Init(cidrList))
testCases := []struct {
Input string
Output bool
}{
{
Input: "8.8.8.8",
Output: false,
},
{
Input: "2001:cdba::3257:9652",
Output: true,
},
{
Input: "91.108.255.254",
Output: false,
},
}
for _, testCase := range testCases {
ip := net.ParseAddress(testCase.Input).IP()
actual := matcher.Match(ip)
if actual != testCase.Output {
t.Error("expect input", testCase.Input, "to be", testCase.Output, ", but actually", actual)
}
}
}
func TestGeoIPMatcher4CN(t *testing.T) { func TestGeoIPMatcher4CN(t *testing.T) {
ips, err := loadGeoIP("CN") ips, err := loadGeoIP("CN")
common.Must(err) common.Must(err)
matcher := &GeoIPMatcher{} matcher := &router.GeoIPMatcher{}
common.Must(matcher.Init(ips)) common.Must(matcher.Init(ips))
if matcher.Match([]byte{8, 8, 8, 8}) { if matcher.Match([]byte{8, 8, 8, 8}) {
@@ -195,7 +139,7 @@ func TestGeoIPMatcher6US(t *testing.T) {
ips, err := loadGeoIP("US") ips, err := loadGeoIP("US")
common.Must(err) common.Must(err)
matcher := &GeoIPMatcher{} matcher := &router.GeoIPMatcher{}
common.Must(matcher.Init(ips)) common.Must(matcher.Init(ips))
if !matcher.Match(net.ParseAddress("2001:4860:4860::8888").IP()) { if !matcher.Match(net.ParseAddress("2001:4860:4860::8888").IP()) {
@@ -203,12 +147,12 @@ func TestGeoIPMatcher6US(t *testing.T) {
} }
} }
func loadGeoIP(country string) ([]*CIDR, error) { func loadGeoIP(country string) ([]*router.CIDR, error) {
geoipBytes, err := filesystem.ReadAsset("geoip.dat") geoipBytes, err := filesystem.ReadAsset("geoip.dat")
if err != nil { if err != nil {
return nil, err return nil, err
} }
var geoipList GeoIPList var geoipList router.GeoIPList
if err := proto.Unmarshal(geoipBytes, &geoipList); err != nil { if err := proto.Unmarshal(geoipBytes, &geoipList); err != nil {
return nil, err return nil, err
} }
@@ -226,7 +170,7 @@ func BenchmarkGeoIPMatcher4CN(b *testing.B) {
ips, err := loadGeoIP("CN") ips, err := loadGeoIP("CN")
common.Must(err) common.Must(err)
matcher := &GeoIPMatcher{} matcher := &router.GeoIPMatcher{}
common.Must(matcher.Init(ips)) common.Must(matcher.Init(ips))
b.ResetTimer() b.ResetTimer()
@@ -240,7 +184,7 @@ func BenchmarkGeoIPMatcher6US(b *testing.B) {
ips, err := loadGeoIP("US") ips, err := loadGeoIP("US")
common.Must(err) common.Must(err)
matcher := &GeoIPMatcher{} matcher := &router.GeoIPMatcher{}
common.Must(matcher.Init(ips)) common.Must(matcher.Init(ips))
b.ResetTimer() b.ResetTimer()

View File

@@ -11,9 +11,6 @@ import (
. "github.com/xtls/xray-core/app/router" . "github.com/xtls/xray-core/app/router"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/errors" "github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/matcher/domain"
"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/net"
"github.com/xtls/xray-core/common/platform" "github.com/xtls/xray-core/common/platform"
"github.com/xtls/xray-core/common/platform/filesystem" "github.com/xtls/xray-core/common/platform/filesystem"
@@ -29,10 +26,10 @@ func init() {
common.Must(err) common.Must(err)
if _, err := os.Stat(platform.GetAssetLocation("geoip.dat")); err != nil && os.IsNotExist(err) { if _, err := os.Stat(platform.GetAssetLocation("geoip.dat")); err != nil && os.IsNotExist(err) {
common.Must(filesystem.CopyFile(platform.GetAssetLocation("geoip.dat"), filepath.Join(wd, "..", "..", "resources", "geoip.dat"))) common.Must(filesystem.CopyFile(platform.GetAssetLocation("geoip.dat"), filepath.Join(wd, "..", "..", "release", "config", "geoip.dat")))
} }
if _, err := os.Stat(platform.GetAssetLocation("geosite.dat")); err != nil && os.IsNotExist(err) { if _, err := os.Stat(platform.GetAssetLocation("geosite.dat")); err != nil && os.IsNotExist(err) {
common.Must(filesystem.CopyFile(platform.GetAssetLocation("geosite.dat"), filepath.Join(wd, "..", "..", "resources", "geosite.dat"))) common.Must(filesystem.CopyFile(platform.GetAssetLocation("geosite.dat"), filepath.Join(wd, "..", "..", "release", "config", "geosite.dat")))
} }
} }
@@ -64,18 +61,18 @@ func TestRoutingRule(t *testing.T) {
}{ }{
{ {
rule: &RoutingRule{ rule: &RoutingRule{
Domain: []*domain.Domain{ Domain: []*Domain{
{ {
Value: "example.com", Value: "example.com",
Type: domain.MatchingType_Keyword, Type: Domain_Plain,
}, },
{ {
Value: "google.com", Value: "google.com",
Type: domain.MatchingType_Subdomain, Type: Domain_Domain,
}, },
{ {
Value: "^facebook\\.com$", Value: "^facebook\\.com$",
Type: domain.MatchingType_Regex, Type: Domain_Regex,
}, },
}, },
}, },
@@ -112,7 +109,7 @@ func TestRoutingRule(t *testing.T) {
}, },
{ {
rule: &RoutingRule{ rule: &RoutingRule{
Cidr: []*geoip.CIDR{ Cidr: []*CIDR{
{ {
Ip: []byte{8, 8, 8, 8}, Ip: []byte{8, 8, 8, 8},
Prefix: 32, Prefix: 32,
@@ -148,9 +145,9 @@ func TestRoutingRule(t *testing.T) {
}, },
{ {
rule: &RoutingRule{ rule: &RoutingRule{
Geoip: []*geoip.GeoIP{ Geoip: []*GeoIP{
{ {
Cidr: []*geoip.CIDR{ Cidr: []*CIDR{
{ {
Ip: []byte{8, 8, 8, 8}, Ip: []byte{8, 8, 8, 8},
Prefix: 32, Prefix: 32,
@@ -188,7 +185,7 @@ func TestRoutingRule(t *testing.T) {
}, },
{ {
rule: &RoutingRule{ rule: &RoutingRule{
SourceCidr: []*geoip.CIDR{ SourceCidr: []*CIDR{
{ {
Ip: []byte{192, 168, 0, 0}, Ip: []byte{192, 168, 0, 0},
Prefix: 16, Prefix: 16,
@@ -336,19 +333,19 @@ func TestRoutingRule(t *testing.T) {
} }
} }
func loadGeoSite(country string) ([]*domain.Domain, error) { func loadGeoSite(country string) ([]*Domain, error) {
geositeBytes, err := filesystem.ReadAsset("geosite.dat") geositeBytes, err := filesystem.ReadAsset("geosite.dat")
if err != nil { if err != nil {
return nil, err return nil, err
} }
var geositeList geosite.GeoSiteList var geositeList GeoSiteList
if err := proto.Unmarshal(geositeBytes, &geositeList); err != nil { if err := proto.Unmarshal(geositeBytes, &geositeList); err != nil {
return nil, err return nil, err
} }
for _, site := range geositeList.Entry { for _, site := range geositeList.Entry {
if site.CountryCode == country { if site.CountryCode == country {
return geosite.ToDomains(site.Domain), nil return site.Domain, nil
} }
} }
@@ -359,10 +356,10 @@ func TestChinaSites(t *testing.T) {
domains, err := loadGeoSite("CN") domains, err := loadGeoSite("CN")
common.Must(err) common.Must(err)
matcher, err := domain.NewDomainMatcher(domains) matcher, err := NewDomainMatcher(domains)
common.Must(err) common.Must(err)
acMatcher, err := domain.NewMphMatcherGroup(domains) acMatcher, err := NewMphMatcherGroup(domains)
common.Must(err) common.Must(err)
type TestCase struct { type TestCase struct {
@@ -407,7 +404,7 @@ func BenchmarkMphDomainMatcher(b *testing.B) {
domains, err := loadGeoSite("CN") domains, err := loadGeoSite("CN")
common.Must(err) common.Must(err)
matcher, err := domain.NewMphMatcherGroup(domains) matcher, err := NewMphMatcherGroup(domains)
common.Must(err) common.Must(err)
type TestCase struct { type TestCase struct {
@@ -449,7 +446,7 @@ func BenchmarkDomainMatcher(b *testing.B) {
domains, err := loadGeoSite("CN") domains, err := loadGeoSite("CN")
common.Must(err) common.Must(err)
matcher, err := domain.NewDomainMatcher(domains) matcher, err := NewDomainMatcher(domains)
common.Must(err) common.Must(err)
type TestCase struct { type TestCase struct {
@@ -487,32 +484,13 @@ func BenchmarkDomainMatcher(b *testing.B) {
} }
} }
func loadGeoIP(country string) ([]*geoip.CIDR, error) {
geoipBytes, err := filesystem.ReadAsset("dat")
if err != nil {
return nil, err
}
var geoipList geoip.GeoIPList
if err := proto.Unmarshal(geoipBytes, &geoipList); err != nil {
return nil, err
}
for _, geoip := range geoipList.Entry {
if geoip.CountryCode == country {
return geoip.Cidr, nil
}
}
panic("country not found: " + country)
}
func BenchmarkMultiGeoIPMatcher(b *testing.B) { func BenchmarkMultiGeoIPMatcher(b *testing.B) {
var geoips []*geoip.GeoIP var geoips []*GeoIP
{ {
ips, err := loadGeoIP("CN") ips, err := loadGeoIP("CN")
common.Must(err) common.Must(err)
geoips = append(geoips, &geoip.GeoIP{ geoips = append(geoips, &GeoIP{
CountryCode: "CN", CountryCode: "CN",
Cidr: ips, Cidr: ips,
}) })
@@ -521,7 +499,7 @@ func BenchmarkMultiGeoIPMatcher(b *testing.B) {
{ {
ips, err := loadGeoIP("JP") ips, err := loadGeoIP("JP")
common.Must(err) common.Must(err)
geoips = append(geoips, &geoip.GeoIP{ geoips = append(geoips, &GeoIP{
CountryCode: "JP", CountryCode: "JP",
Cidr: ips, Cidr: ips,
}) })
@@ -530,7 +508,7 @@ func BenchmarkMultiGeoIPMatcher(b *testing.B) {
{ {
ips, err := loadGeoIP("CA") ips, err := loadGeoIP("CA")
common.Must(err) common.Must(err)
geoips = append(geoips, &geoip.GeoIP{ geoips = append(geoips, &GeoIP{
CountryCode: "CA", CountryCode: "CA",
Cidr: ips, Cidr: ips,
}) })
@@ -539,13 +517,13 @@ func BenchmarkMultiGeoIPMatcher(b *testing.B) {
{ {
ips, err := loadGeoIP("US") ips, err := loadGeoIP("US")
common.Must(err) common.Must(err)
geoips = append(geoips, &geoip.GeoIP{ geoips = append(geoips, &GeoIP{
CountryCode: "US", CountryCode: "US",
Cidr: ips, Cidr: ips,
}) })
} }
matcher, err := geoip.NewMultiGeoIPMatcher(geoips, false) matcher, err := NewMultiGeoIPMatcher(geoips, false)
common.Must(err) common.Must(err)
ctx := withOutbound(&session.Outbound{Target: net.TCPDestination(net.ParseAddress("8.8.8.8"), 80)}) ctx := withOutbound(&session.Outbound{Target: net.TCPDestination(net.ParseAddress("8.8.8.8"), 80)})

View File

@@ -1,13 +1,50 @@
package router package router
import ( 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/common/net"
"github.com/xtls/xray-core/features/outbound" "github.com/xtls/xray-core/features/outbound"
"github.com/xtls/xray-core/features/routing" "github.com/xtls/xray-core/features/routing"
) )
// CIDRList is an alias of []*CIDR to provide sort.Interface.
type CIDRList []*CIDR
// Len implements sort.Interface.
func (l *CIDRList) Len() int {
return len(*l)
}
// Less implements sort.Interface.
func (l *CIDRList) Less(i int, j int) bool {
ci := (*l)[i]
cj := (*l)[j]
if len(ci.Ip) < len(cj.Ip) {
return true
}
if len(ci.Ip) > len(cj.Ip) {
return false
}
for k := 0; k < len(ci.Ip); k++ {
if ci.Ip[k] < cj.Ip[k] {
return true
}
if ci.Ip[k] > cj.Ip[k] {
return false
}
}
return ci.Prefix < cj.Prefix
}
// Swap implements sort.Interface.
func (l *CIDRList) Swap(i int, j int) {
(*l)[i], (*l)[j] = (*l)[j], (*l)[i]
}
type Rule struct { type Rule struct {
Tag string Tag string
Balancer *Balancer Balancer *Balancer
@@ -32,7 +69,7 @@ func (rr *RoutingRule) BuildCondition() (Condition, error) {
if len(rr.Domain) > 0 { if len(rr.Domain) > 0 {
switch rr.DomainMatcher { switch rr.DomainMatcher {
case "linear": case "linear":
matcher, err := dm.NewDomainMatcher(rr.Domain) matcher, err := NewDomainMatcher(rr.Domain)
if err != nil { if err != nil {
return nil, newError("failed to build domain condition").Base(err) return nil, newError("failed to build domain condition").Base(err)
} }
@@ -40,7 +77,7 @@ func (rr *RoutingRule) BuildCondition() (Condition, error) {
case "mph", "hybrid": case "mph", "hybrid":
fallthrough fallthrough
default: default:
matcher, err := dm.NewMphMatcherGroup(rr.Domain) matcher, err := NewMphMatcherGroup(rr.Domain)
if err != nil { if err != nil {
return nil, newError("failed to build domain condition with MphDomainMatcher").Base(err) return nil, newError("failed to build domain condition with MphDomainMatcher").Base(err)
} }
@@ -75,13 +112,13 @@ func (rr *RoutingRule) BuildCondition() (Condition, error) {
} }
if len(rr.Geoip) > 0 { if len(rr.Geoip) > 0 {
cond, err := geoip.NewMultiGeoIPMatcher(rr.Geoip, false) cond, err := NewMultiGeoIPMatcher(rr.Geoip, false)
if err != nil { if err != nil {
return nil, err return nil, err
} }
conds.Add(cond) conds.Add(cond)
} else if len(rr.Cidr) > 0 { } else if len(rr.Cidr) > 0 {
cond, err := geoip.NewMultiGeoIPMatcher([]*geoip.GeoIP{{Cidr: rr.Cidr}}, false) cond, err := NewMultiGeoIPMatcher([]*GeoIP{{Cidr: rr.Cidr}}, false)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -89,13 +126,13 @@ func (rr *RoutingRule) BuildCondition() (Condition, error) {
} }
if len(rr.SourceGeoip) > 0 { if len(rr.SourceGeoip) > 0 {
cond, err := geoip.NewMultiGeoIPMatcher(rr.SourceGeoip, true) cond, err := NewMultiGeoIPMatcher(rr.SourceGeoip, true)
if err != nil { if err != nil {
return nil, err return nil, err
} }
conds.Add(cond) conds.Add(cond)
} else if len(rr.SourceCidr) > 0 { } else if len(rr.SourceCidr) > 0 {
cond, err := geoip.NewMultiGeoIPMatcher([]*geoip.GeoIP{{Cidr: rr.SourceCidr}}, true) cond, err := NewMultiGeoIPMatcher([]*GeoIP{{Cidr: rr.SourceCidr}}, true)
if err != nil { if err != nil {
return nil, err return nil, err
} }

File diff suppressed because it is too large Load Diff

View File

@@ -8,8 +8,66 @@ option java_multiple_files = true;
import "common/net/port.proto"; import "common/net/port.proto";
import "common/net/network.proto"; import "common/net/network.proto";
import "common/matcher/domain/domain.proto";
import "common/matcher/geoip/geoip.proto"; // Domain for routing decision.
message Domain {
// Type of domain value.
enum Type {
// The value is used as is.
Plain = 0;
// The value is used as a regular expression.
Regex = 1;
// The value is a root domain.
Domain = 2;
// The value is a domain.
Full = 3;
}
// Domain matching type.
Type type = 1;
// Domain value.
string value = 2;
message Attribute {
string key = 1;
oneof typed_value {
bool bool_value = 2;
int64 int_value = 3;
}
}
// Attributes of this domain. May be used for filtering.
repeated Attribute attribute = 3;
}
// IP for routing decision, in CIDR form.
message CIDR {
// IP address, should be either 4 or 16 bytes.
bytes ip = 1;
// Number of leading ones in the network mask.
uint32 prefix = 2;
}
message GeoIP {
string country_code = 1;
repeated CIDR cidr = 2;
}
message GeoIPList {
repeated GeoIP entry = 1;
}
message GeoSite {
string country_code = 1;
repeated Domain domain = 2;
}
message GeoSiteList {
repeated GeoSite entry = 1;
}
message RoutingRule { message RoutingRule {
oneof target_tag { oneof target_tag {
@@ -21,17 +79,17 @@ message RoutingRule {
} }
// List of domains for target domain matching. // List of domains for target domain matching.
repeated xray.common.matcher.domain.Domain domain = 2; repeated Domain domain = 2;
// List of CIDRs for target IP address matching. // List of CIDRs for target IP address matching.
// Deprecated. Use geoip below. // Deprecated. Use geoip below.
repeated xray.common.matcher.geoip.CIDR cidr = 3 [deprecated = true]; repeated CIDR cidr = 3 [deprecated = true];
// List of GeoIPs for target IP address matching. If this entry exists, the // List of GeoIPs for target IP address matching. If this entry exists, the
// cidr above will have no effect. GeoIP fields with the same country code are // cidr above will have no effect. GeoIP fields with the same country code are
// supposed to contain exactly same content. They will be merged during // supposed to contain exactly same content. They will be merged during
// runtime. For customized GeoIPs, please leave country code empty. // runtime. For customized GeoIPs, please leave country code empty.
repeated xray.common.matcher.geoip.GeoIP geoip = 10; repeated GeoIP geoip = 10;
// A range of port [from, to]. If the destination port is in this range, this // A range of port [from, to]. If the destination port is in this range, this
// rule takes effect. Deprecated. Use port_list. // rule takes effect. Deprecated. Use port_list.
@@ -47,11 +105,11 @@ message RoutingRule {
repeated xray.common.net.Network networks = 13; repeated xray.common.net.Network networks = 13;
// List of CIDRs for source IP address matching. // List of CIDRs for source IP address matching.
repeated xray.common.matcher.geoip.CIDR source_cidr = 6 [deprecated = true]; repeated CIDR source_cidr = 6 [deprecated = true];
// List of GeoIPs for source IP address matching. If this entry exists, the // List of GeoIPs for source IP address matching. If this entry exists, the
// source_cidr above will have no effect. // source_cidr above will have no effect.
repeated xray.common.matcher.geoip.GeoIP source_geoip = 11; repeated GeoIP source_geoip = 11;
// List of ports for source port matching. // List of ports for source port matching.
xray.common.net.PortList source_port_list = 16; xray.common.net.PortList source_port_list = 16;

View File

@@ -80,13 +80,7 @@ func (r *Router) PickRoute(ctx routing.Context) (routing.Route, error) {
} }
func (r *Router) pickRouteInternal(ctx routing.Context) (*Rule, routing.Context, error) { func (r *Router) pickRouteInternal(ctx routing.Context) (*Rule, routing.Context, error) {
if r.domainStrategy == Config_IpOnDemand {
// SkipDNSResolve is set from DNS module.
// the DOH remote server maybe a domain name,
// this prevents cycle resolving dead loop
skipDNSResolve := ctx.GetSkipDNSResolve()
if r.domainStrategy == Config_IpOnDemand && !skipDNSResolve {
ctx = routing_dns.ContextWithDNSClient(ctx, r.dns) ctx = routing_dns.ContextWithDNSClient(ctx, r.dns)
} }
@@ -96,7 +90,7 @@ func (r *Router) pickRouteInternal(ctx routing.Context) (*Rule, routing.Context,
} }
} }
if r.domainStrategy != Config_IpIfNonMatch || len(ctx.GetTargetDomain()) == 0 || skipDNSResolve { if r.domainStrategy != Config_IpIfNonMatch || len(ctx.GetTargetDomain()) == 0 {
return nil, ctx, common.ErrNoClue return nil, ctx, common.ErrNoClue
} }

View File

@@ -7,9 +7,9 @@ import (
"github.com/golang/mock/gomock" "github.com/golang/mock/gomock"
. "github.com/xtls/xray-core/app/router" . "github.com/xtls/xray-core/app/router"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/matcher/geoip"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/session" "github.com/xtls/xray-core/common/session"
"github.com/xtls/xray-core/features/dns"
"github.com/xtls/xray-core/features/outbound" "github.com/xtls/xray-core/features/outbound"
routing_session "github.com/xtls/xray-core/features/routing/session" routing_session "github.com/xtls/xray-core/features/routing/session"
"github.com/xtls/xray-core/testing/mocks" "github.com/xtls/xray-core/testing/mocks"
@@ -102,7 +102,7 @@ func TestIPOnDemand(t *testing.T) {
TargetTag: &RoutingRule_Tag{ TargetTag: &RoutingRule_Tag{
Tag: "test", Tag: "test",
}, },
Cidr: []*geoip.CIDR{ Cidr: []*CIDR{
{ {
Ip: []byte{192, 168, 0, 0}, Ip: []byte{192, 168, 0, 0},
Prefix: 16, Prefix: 16,
@@ -116,7 +116,11 @@ func TestIPOnDemand(t *testing.T) {
defer mockCtl.Finish() defer mockCtl.Finish()
mockDNS := mocks.NewDNSClient(mockCtl) mockDNS := mocks.NewDNSClient(mockCtl)
mockDNS.EXPECT().LookupIP(gomock.Eq("example.com")).Return([]net.IP{{192, 168, 0, 1}}, nil).AnyTimes() mockDNS.EXPECT().LookupIP(gomock.Eq("example.com"), dns.IPOption{
IPv4Enable: true,
IPv6Enable: true,
FakeEnable: false,
}).Return([]net.IP{{192, 168, 0, 1}}, nil).AnyTimes()
r := new(Router) r := new(Router)
common.Must(r.Init(config, mockDNS, nil)) common.Must(r.Init(config, mockDNS, nil))
@@ -137,7 +141,7 @@ func TestIPIfNonMatchDomain(t *testing.T) {
TargetTag: &RoutingRule_Tag{ TargetTag: &RoutingRule_Tag{
Tag: "test", Tag: "test",
}, },
Cidr: []*geoip.CIDR{ Cidr: []*CIDR{
{ {
Ip: []byte{192, 168, 0, 0}, Ip: []byte{192, 168, 0, 0},
Prefix: 16, Prefix: 16,
@@ -151,7 +155,11 @@ func TestIPIfNonMatchDomain(t *testing.T) {
defer mockCtl.Finish() defer mockCtl.Finish()
mockDNS := mocks.NewDNSClient(mockCtl) mockDNS := mocks.NewDNSClient(mockCtl)
mockDNS.EXPECT().LookupIP(gomock.Eq("example.com")).Return([]net.IP{{192, 168, 0, 1}}, nil).AnyTimes() mockDNS.EXPECT().LookupIP(gomock.Eq("example.com"), dns.IPOption{
IPv4Enable: true,
IPv6Enable: true,
FakeEnable: false,
}).Return([]net.IP{{192, 168, 0, 1}}, nil).AnyTimes()
r := new(Router) r := new(Router)
common.Must(r.Init(config, mockDNS, nil)) common.Must(r.Init(config, mockDNS, nil))
@@ -172,7 +180,7 @@ func TestIPIfNonMatchIP(t *testing.T) {
TargetTag: &RoutingRule_Tag{ TargetTag: &RoutingRule_Tag{
Tag: "test", Tag: "test",
}, },
Cidr: []*geoip.CIDR{ Cidr: []*CIDR{
{ {
Ip: []byte{127, 0, 0, 0}, Ip: []byte{127, 0, 0, 0},
Prefix: 8, Prefix: 8,

View File

@@ -11,7 +11,7 @@ import (
"github.com/xtls/xray-core/app/stats" "github.com/xtls/xray-core/app/stats"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/matcher/str" "github.com/xtls/xray-core/common/strmatcher"
"github.com/xtls/xray-core/core" "github.com/xtls/xray-core/core"
feature_stats "github.com/xtls/xray-core/features/stats" feature_stats "github.com/xtls/xray-core/features/stats"
) )
@@ -49,7 +49,7 @@ func (s *statsServer) GetStats(ctx context.Context, request *GetStatsRequest) (*
} }
func (s *statsServer) QueryStats(ctx context.Context, request *QueryStatsRequest) (*QueryStatsResponse, error) { func (s *statsServer) QueryStats(ctx context.Context, request *QueryStatsRequest) (*QueryStatsResponse, error) {
matcher, err := str.Substr.New(request.Pattern) matcher, err := strmatcher.Substr.New(request.Pattern)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -24,10 +24,17 @@ type Buffer struct {
UDP *net.Destination UDP *net.Destination
} }
// New creates a Buffer with 0 length and 2K capacity. // New creates a Buffer with 0 length and 8K capacity.
func New() *Buffer { func New() *Buffer {
buf := pool.Get().([]byte)
if cap(buf) >= Size {
buf = buf[:Size]
} else {
buf = make([]byte, Size)
}
return &Buffer{ return &Buffer{
v: pool.Get().([]byte), v: buf,
} }
} }
@@ -50,8 +57,15 @@ func NewExisted(b []byte) *Buffer {
// StackNew creates a new Buffer object on stack. // StackNew creates a new Buffer object on stack.
// This method is for buffers that is released in the same function. // This method is for buffers that is released in the same function.
func StackNew() Buffer { func StackNew() Buffer {
buf := pool.Get().([]byte)
if cap(buf) >= Size {
buf = buf[:Size]
} else {
buf = make([]byte, Size)
}
return Buffer{ return Buffer{
v: pool.Get().([]byte), v: buf,
} }
} }
@@ -64,7 +78,10 @@ func (b *Buffer) Release() {
p := b.v p := b.v
b.v = nil b.v = nil
b.Clear() b.Clear()
pool.Put(p)
if cap(p) == Size {
pool.Put(p)
}
b.UDP = nil b.UDP = nil
} }

View File

@@ -4,7 +4,6 @@ package buf
import ( import (
"io" "io"
"runtime"
"syscall" "syscall"
"github.com/xtls/xray-core/common/platform" "github.com/xtls/xray-core/common/platform"
@@ -134,17 +133,13 @@ func (r *ReadVReader) ReadMultiBuffer() (MultiBuffer, error) {
return mb, nil return mb, nil
} }
var useReadv = true var useReadv bool
func init() { func init() {
const defaultFlagValue = "NOT_DEFINED_AT_ALL" const defaultFlagValue = "NOT_DEFINED_AT_ALL"
value := platform.NewEnvFlag("xray.buf.readv").GetValue(func() string { return defaultFlagValue }) value := platform.NewEnvFlag("xray.buf.readv").GetValue(func() string { return defaultFlagValue })
switch value { switch value {
case defaultFlagValue, "auto": case defaultFlagValue, "auto", "enable":
if (runtime.GOARCH == "386" || runtime.GOARCH == "amd64" || runtime.GOARCH == "s390x") && (runtime.GOOS == "linux" || runtime.GOOS == "darwin" || runtime.GOOS == "windows") {
useReadv = true
}
case "enable":
useReadv = true useReadv = true
} }
} }

View File

@@ -1,3 +0,0 @@
package conf
//go:generate go run github.com/xtls/xray-core/common/errors/errorgen

View File

@@ -1,94 +0,0 @@
package conf
import (
"strings"
dm "github.com/xtls/xray-core/common/matcher/domain"
"github.com/xtls/xray-core/common/matcher/geosite"
)
func ParseDomainRule(domain string) ([]*dm.Domain, error) {
if strings.HasPrefix(domain, "geosite:") {
country := strings.ToUpper(domain[8:])
domains, err := geosite.LoadGeositeWithAttr("geosite.dat", country)
if err != nil {
return nil, newError("failed to load geosite: ", country).Base(err)
}
return domains, nil
}
var isExtDatFile = 0
{
const prefix = "ext:"
if strings.HasPrefix(domain, prefix) {
isExtDatFile = len(prefix)
}
const prefixQualified = "ext-domain:"
if strings.HasPrefix(domain, prefixQualified) {
isExtDatFile = len(prefixQualified)
}
}
if isExtDatFile != 0 {
kv := strings.Split(domain[isExtDatFile:], ":")
if len(kv) != 2 {
return nil, newError("invalid external resource: ", domain)
}
filename := kv[0]
country := kv[1]
domains, err := geosite.LoadGeositeWithAttr(filename, country)
if err != nil {
return nil, newError("failed to load external sites: ", country, " from ", filename).Base(err)
}
return domains, nil
}
domainRule := new(dm.Domain)
switch {
case strings.HasPrefix(domain, "regexp:"):
regexpVal := domain[7:]
if len(regexpVal) == 0 {
return nil, newError("empty regexp type of rule: ", domain)
}
domainRule.Type = dm.MatchingType_Regex
domainRule.Value = regexpVal
case strings.HasPrefix(domain, "domain:"):
domainName := domain[7:]
if len(domainName) == 0 {
return nil, newError("empty domain type of rule: ", domain)
}
domainRule.Type = dm.MatchingType_Subdomain
domainRule.Value = domainName
case strings.HasPrefix(domain, "full:"):
fullVal := domain[5:]
if len(fullVal) == 0 {
return nil, newError("empty full domain type of rule: ", domain)
}
domainRule.Type = dm.MatchingType_Full
domainRule.Value = fullVal
case strings.HasPrefix(domain, "keyword:"):
keywordVal := domain[8:]
if len(keywordVal) == 0 {
return nil, newError("empty keyword type of rule: ", domain)
}
domainRule.Type = dm.MatchingType_Keyword
domainRule.Value = keywordVal
case strings.HasPrefix(domain, "dotless:"):
domainRule.Type = dm.MatchingType_Regex
switch substr := domain[8:]; {
case substr == "":
domainRule.Value = "^[^.]*$"
case !strings.Contains(substr, "."):
domainRule.Value = "^[^.]*" + substr + "[^.]*$"
default:
return nil, newError("substr in dotless rule should not contain a dot: ", substr)
}
default:
domainRule.Type = dm.MatchingType_Keyword
domainRule.Value = domain
}
return []*dm.Domain{domainRule}, nil
}

View File

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

View File

@@ -1,3 +0,0 @@
package domain
//go:generate go run github.com/xtls/xray-core/common/errors/errorgen

View File

@@ -1,229 +0,0 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.25.0
// protoc v3.15.6
// source: common/matcher/domain/domain.proto
package domain
import (
proto "github.com/golang/protobuf/proto"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
// This is a compile-time assertion that a sufficiently up-to-date version
// of the legacy proto package is being used.
const _ = proto.ProtoPackageIsVersion4
type MatchingType int32
const (
MatchingType_Full MatchingType = 0
MatchingType_Subdomain MatchingType = 1
MatchingType_Keyword MatchingType = 2
MatchingType_Regex MatchingType = 3
)
// Enum value maps for MatchingType.
var (
MatchingType_name = map[int32]string{
0: "Full",
1: "Subdomain",
2: "Keyword",
3: "Regex",
}
MatchingType_value = map[string]int32{
"Full": 0,
"Subdomain": 1,
"Keyword": 2,
"Regex": 3,
}
)
func (x MatchingType) Enum() *MatchingType {
p := new(MatchingType)
*p = x
return p
}
func (x MatchingType) String() string {
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
func (MatchingType) Descriptor() protoreflect.EnumDescriptor {
return file_common_matcher_domain_domain_proto_enumTypes[0].Descriptor()
}
func (MatchingType) Type() protoreflect.EnumType {
return &file_common_matcher_domain_domain_proto_enumTypes[0]
}
func (x MatchingType) Number() protoreflect.EnumNumber {
return protoreflect.EnumNumber(x)
}
// Deprecated: Use MatchingType.Descriptor instead.
func (MatchingType) EnumDescriptor() ([]byte, []int) {
return file_common_matcher_domain_domain_proto_rawDescGZIP(), []int{0}
}
type Domain struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// Domain matching type.
Type MatchingType `protobuf:"varint,1,opt,name=type,proto3,enum=xray.common.matcher.domain.MatchingType" json:"type,omitempty"`
// Domain value.
Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
}
func (x *Domain) Reset() {
*x = Domain{}
if protoimpl.UnsafeEnabled {
mi := &file_common_matcher_domain_domain_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Domain) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Domain) ProtoMessage() {}
func (x *Domain) ProtoReflect() protoreflect.Message {
mi := &file_common_matcher_domain_domain_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Domain.ProtoReflect.Descriptor instead.
func (*Domain) Descriptor() ([]byte, []int) {
return file_common_matcher_domain_domain_proto_rawDescGZIP(), []int{0}
}
func (x *Domain) GetType() MatchingType {
if x != nil {
return x.Type
}
return MatchingType_Full
}
func (x *Domain) GetValue() string {
if x != nil {
return x.Value
}
return ""
}
var File_common_matcher_domain_domain_proto protoreflect.FileDescriptor
var file_common_matcher_domain_domain_proto_rawDesc = []byte{
0x0a, 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, 0x12, 0x1a, 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,
0x22, 0x5c, 0x0a, 0x06, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x3c, 0x0a, 0x04, 0x74, 0x79,
0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x28, 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, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x54, 0x79,
0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75,
0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2a, 0x3f,
0x0a, 0x0c, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x54, 0x79, 0x70, 0x65, 0x12, 0x08,
0x0a, 0x04, 0x46, 0x75, 0x6c, 0x6c, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x53, 0x75, 0x62, 0x64,
0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x4b, 0x65, 0x79, 0x77, 0x6f,
0x72, 0x64, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x52, 0x65, 0x67, 0x65, 0x78, 0x10, 0x03, 0x42,
0x70, 0x0a, 0x1e, 0x63, 0x6f, 0x6d, 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, 0x50, 0x01, 0x5a, 0x2f, 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, 0x63,
0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2f, 0x64, 0x6f,
0x6d, 0x61, 0x69, 0x6e, 0xaa, 0x02, 0x1a, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x6d, 0x6d,
0x6f, 0x6e, 0x2e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69,
0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_common_matcher_domain_domain_proto_rawDescOnce sync.Once
file_common_matcher_domain_domain_proto_rawDescData = file_common_matcher_domain_domain_proto_rawDesc
)
func file_common_matcher_domain_domain_proto_rawDescGZIP() []byte {
file_common_matcher_domain_domain_proto_rawDescOnce.Do(func() {
file_common_matcher_domain_domain_proto_rawDescData = protoimpl.X.CompressGZIP(file_common_matcher_domain_domain_proto_rawDescData)
})
return file_common_matcher_domain_domain_proto_rawDescData
}
var file_common_matcher_domain_domain_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
var file_common_matcher_domain_domain_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_common_matcher_domain_domain_proto_goTypes = []interface{}{
(MatchingType)(0), // 0: xray.common.matcher.domain.MatchingType
(*Domain)(nil), // 1: xray.common.matcher.domain.Domain
}
var file_common_matcher_domain_domain_proto_depIdxs = []int32{
0, // 0: xray.common.matcher.domain.Domain.type:type_name -> xray.common.matcher.domain.MatchingType
1, // [1:1] is the sub-list for method output_type
1, // [1:1] is the sub-list for method input_type
1, // [1:1] is the sub-list for extension type_name
1, // [1:1] is the sub-list for extension extendee
0, // [0:1] is the sub-list for field type_name
}
func init() { file_common_matcher_domain_domain_proto_init() }
func file_common_matcher_domain_domain_proto_init() {
if File_common_matcher_domain_domain_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_common_matcher_domain_domain_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Domain); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_common_matcher_domain_domain_proto_rawDesc,
NumEnums: 1,
NumMessages: 1,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_common_matcher_domain_domain_proto_goTypes,
DependencyIndexes: file_common_matcher_domain_domain_proto_depIdxs,
EnumInfos: file_common_matcher_domain_domain_proto_enumTypes,
MessageInfos: file_common_matcher_domain_domain_proto_msgTypes,
}.Build()
File_common_matcher_domain_domain_proto = out.File
file_common_matcher_domain_domain_proto_rawDesc = nil
file_common_matcher_domain_domain_proto_goTypes = nil
file_common_matcher_domain_domain_proto_depIdxs = nil
}

View File

@@ -1,39 +0,0 @@
syntax = "proto3";
package xray.common.matcher.domain;
option csharp_namespace = "Xray.Common.Matcher.Domain";
option go_package = "github.com/xtls/xray-core/common/matcher/domain";
option java_package = "com.xray.common.matcher.domain";
option java_multiple_files = true;
enum MatchingType {
Full = 0;
Subdomain = 1;
Keyword = 2;
Regex = 3;
}
message Domain {
// Domain matching type.
MatchingType type = 1;
// Domain value.
string value = 2;
}
/*
func toDomainMatchingType(t router.Domain_Type) dns.DomainMatchingType {
switch t {
case router.Domain_Domain:
return dns.DomainMatchingType_Subdomain
case router.Domain_Full:
return dns.DomainMatchingType_Full
case router.Domain_Plain:
return dns.DomainMatchingType_Keyword
case router.Domain_Regex:
return dns.DomainMatchingType_Regex
default:
panic("unknown domain type")
}
}
*/

View File

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

View File

@@ -1,79 +0,0 @@
package domain
import (
"strings"
"github.com/xtls/xray-core/common/matcher/str"
"github.com/xtls/xray-core/features/routing"
)
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 NewMphMatcherGroup(domains []*Domain) (*DomainMatcher, error) {
g := str.NewMphMatcherGroup()
for _, d := range domains {
matcherType, f := matcherTypeMap[d.Type]
if !f {
return nil, newError("unsupported domain type", d.Type)
}
_, err := g.AddPattern(d.Value, matcherType)
if err != nil {
return nil, err
}
}
g.Build()
return &DomainMatcher{
matchers: g,
}, nil
}
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(strings.ToLower(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(domain)
}

View File

@@ -1,224 +0,0 @@
package geoip
import (
"runtime"
"strconv"
"strings"
"github.com/golang/protobuf/proto"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/platform/filesystem"
)
var (
FileCache = make(map[string][]byte)
IPCache = make(map[string]*GeoIP)
)
func LoadGeoIP(code string) ([]*CIDR, error) {
return LoadIPFile("geoip.dat", code)
}
func LoadIPFile(file, code string) ([]*CIDR, error) {
index := file + ":" + code
if IPCache[index] == nil {
bs, err := loadFile(file)
if err != nil {
return nil, newError("failed to load file: ", file).Base(err)
}
bs = find(bs, []byte(code))
if bs == nil {
return nil, newError("code not found in ", file, ": ", code)
}
var geoipdat GeoIP
if err := proto.Unmarshal(bs, &geoipdat); err != nil {
return nil, newError("error unmarshal IP in ", file, ": ", code).Base(err)
}
defer runtime.GC() // or debug.FreeOSMemory()
return geoipdat.Cidr, nil // do not cache geoip
// IPCache[index] = &geoipdat
}
return IPCache[index].Cidr, nil
}
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 find(data, code []byte) []byte {
codeL := len(code)
if codeL == 0 {
return nil
}
for {
dataL := len(data)
if dataL < 2 {
return nil
}
x, y := proto.DecodeVarint(data[1:])
if x == 0 && y == 0 {
return nil
}
headL, bodyL := 1+y, int(x)
dataL -= headL
if dataL < bodyL {
return nil
}
data = data[headL:]
if int(data[1]) == codeL {
for i := 0; i < codeL && data[2+i] == code[i]; i++ {
if i+1 == codeL {
return data[:bodyL]
}
}
}
if dataL == bodyL {
return nil
}
data = data[bodyL:]
}
}
func ParseIPList(ips []string) ([]*GeoIP, error) {
var geoipList []*GeoIP
var customCidrs []*CIDR
for _, ip := range ips {
if strings.HasPrefix(ip, "geoip:") {
country := ip[6:]
isReverseMatch := false
if strings.HasPrefix(country, "!") {
country = country[1:]
isReverseMatch = true
}
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,
ReverseMatch: isReverseMatch,
})
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]
if len(filename) == 0 || len(country) == 0 {
return nil, newError("empty filename or empty country in rule")
}
isReverseMatch := false
if strings.HasPrefix(country, "!") {
country = country[1:]
isReverseMatch = true
}
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,
ReverseMatch: isReverseMatch,
})
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)
}
}

View File

@@ -1,40 +0,0 @@
package geoip
// CIDRList is an alias of []*CIDR to provide sort.Interface.
type CIDRList []*CIDR
// Len implements sort.Interface.
func (l *CIDRList) Len() int {
return len(*l)
}
// Less implements sort.Interface.
func (l *CIDRList) Less(i int, j int) bool {
ci := (*l)[i]
cj := (*l)[j]
if len(ci.Ip) < len(cj.Ip) {
return true
}
if len(ci.Ip) > len(cj.Ip) {
return false
}
for k := 0; k < len(ci.Ip); k++ {
if ci.Ip[k] < cj.Ip[k] {
return true
}
if ci.Ip[k] > cj.Ip[k] {
return false
}
}
return ci.Prefix < cj.Prefix
}
// Swap implements sort.Interface.
func (l *CIDRList) Swap(i int, j int) {
(*l)[i], (*l)[j] = (*l)[j], (*l)[i]
}

View File

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

View File

@@ -1,317 +0,0 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.25.0
// protoc v3.15.7
// source: common/matcher/geoip/geoip.proto
package geoip
import (
proto "github.com/golang/protobuf/proto"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
// This is a compile-time assertion that a sufficiently up-to-date version
// of the legacy proto package is being used.
const _ = proto.ProtoPackageIsVersion4
// IP for routing decision, in CIDR form.
type CIDR struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// IP address, should be either 4 or 16 bytes.
Ip []byte `protobuf:"bytes,1,opt,name=ip,proto3" json:"ip,omitempty"`
// Number of leading ones in the network mask.
Prefix uint32 `protobuf:"varint,2,opt,name=prefix,proto3" json:"prefix,omitempty"`
}
func (x *CIDR) Reset() {
*x = CIDR{}
if protoimpl.UnsafeEnabled {
mi := &file_common_matcher_geoip_geoip_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *CIDR) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CIDR) ProtoMessage() {}
func (x *CIDR) ProtoReflect() protoreflect.Message {
mi := &file_common_matcher_geoip_geoip_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use CIDR.ProtoReflect.Descriptor instead.
func (*CIDR) Descriptor() ([]byte, []int) {
return file_common_matcher_geoip_geoip_proto_rawDescGZIP(), []int{0}
}
func (x *CIDR) GetIp() []byte {
if x != nil {
return x.Ip
}
return nil
}
func (x *CIDR) GetPrefix() uint32 {
if x != nil {
return x.Prefix
}
return 0
}
type GeoIP struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
CountryCode string `protobuf:"bytes,1,opt,name=country_code,json=countryCode,proto3" json:"country_code,omitempty"`
Cidr []*CIDR `protobuf:"bytes,2,rep,name=cidr,proto3" json:"cidr,omitempty"`
ReverseMatch bool `protobuf:"varint,3,opt,name=reverse_match,json=reverseMatch,proto3" json:"reverse_match,omitempty"`
}
func (x *GeoIP) Reset() {
*x = GeoIP{}
if protoimpl.UnsafeEnabled {
mi := &file_common_matcher_geoip_geoip_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GeoIP) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GeoIP) ProtoMessage() {}
func (x *GeoIP) ProtoReflect() protoreflect.Message {
mi := &file_common_matcher_geoip_geoip_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GeoIP.ProtoReflect.Descriptor instead.
func (*GeoIP) Descriptor() ([]byte, []int) {
return file_common_matcher_geoip_geoip_proto_rawDescGZIP(), []int{1}
}
func (x *GeoIP) GetCountryCode() string {
if x != nil {
return x.CountryCode
}
return ""
}
func (x *GeoIP) GetCidr() []*CIDR {
if x != nil {
return x.Cidr
}
return nil
}
func (x *GeoIP) GetReverseMatch() bool {
if x != nil {
return x.ReverseMatch
}
return false
}
type GeoIPList struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Entry []*GeoIP `protobuf:"bytes,1,rep,name=entry,proto3" json:"entry,omitempty"`
}
func (x *GeoIPList) Reset() {
*x = GeoIPList{}
if protoimpl.UnsafeEnabled {
mi := &file_common_matcher_geoip_geoip_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GeoIPList) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GeoIPList) ProtoMessage() {}
func (x *GeoIPList) ProtoReflect() protoreflect.Message {
mi := &file_common_matcher_geoip_geoip_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GeoIPList.ProtoReflect.Descriptor instead.
func (*GeoIPList) Descriptor() ([]byte, []int) {
return file_common_matcher_geoip_geoip_proto_rawDescGZIP(), []int{2}
}
func (x *GeoIPList) GetEntry() []*GeoIP {
if x != nil {
return x.Entry
}
return nil
}
var File_common_matcher_geoip_geoip_proto protoreflect.FileDescriptor
var file_common_matcher_geoip_geoip_proto_rawDesc = []byte{
0x0a, 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, 0x12, 0x19, 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, 0x22, 0x2e, 0x0a,
0x04, 0x43, 0x49, 0x44, 0x52, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28,
0x0c, 0x52, 0x02, 0x69, 0x70, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18,
0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x22, 0x84, 0x01,
0x0a, 0x05, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x75, 0x6e, 0x74,
0x72, 0x79, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63,
0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x33, 0x0a, 0x04, 0x63, 0x69,
0x64, 0x72, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 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, 0x43, 0x49, 0x44, 0x52, 0x52, 0x04, 0x63, 0x69, 0x64, 0x72, 0x12,
0x23, 0x0a, 0x0d, 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68,
0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x4d,
0x61, 0x74, 0x63, 0x68, 0x22, 0x43, 0x0a, 0x09, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x4c, 0x69, 0x73,
0x74, 0x12, 0x36, 0x0a, 0x05, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x18, 0x01, 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, 0x05, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x42, 0x6d, 0x0a, 0x1d, 0x63, 0x6f, 0x6d,
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, 0x50, 0x01, 0x5a, 0x2e, 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, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6d,
0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2f, 0x67, 0x65, 0x6f, 0x69, 0x70, 0xaa, 0x02, 0x19, 0x58,
0x72, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4d, 0x61, 0x74, 0x63, 0x68,
0x65, 0x72, 0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_common_matcher_geoip_geoip_proto_rawDescOnce sync.Once
file_common_matcher_geoip_geoip_proto_rawDescData = file_common_matcher_geoip_geoip_proto_rawDesc
)
func file_common_matcher_geoip_geoip_proto_rawDescGZIP() []byte {
file_common_matcher_geoip_geoip_proto_rawDescOnce.Do(func() {
file_common_matcher_geoip_geoip_proto_rawDescData = protoimpl.X.CompressGZIP(file_common_matcher_geoip_geoip_proto_rawDescData)
})
return file_common_matcher_geoip_geoip_proto_rawDescData
}
var file_common_matcher_geoip_geoip_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
var file_common_matcher_geoip_geoip_proto_goTypes = []interface{}{
(*CIDR)(nil), // 0: xray.common.matcher.geoip.CIDR
(*GeoIP)(nil), // 1: xray.common.matcher.geoip.GeoIP
(*GeoIPList)(nil), // 2: xray.common.matcher.geoip.GeoIPList
}
var file_common_matcher_geoip_geoip_proto_depIdxs = []int32{
0, // 0: xray.common.matcher.geoip.GeoIP.cidr:type_name -> xray.common.matcher.geoip.CIDR
1, // 1: xray.common.matcher.geoip.GeoIPList.entry:type_name -> xray.common.matcher.geoip.GeoIP
2, // [2:2] is the sub-list for method output_type
2, // [2:2] is the sub-list for method input_type
2, // [2:2] is the sub-list for extension type_name
2, // [2:2] is the sub-list for extension extendee
0, // [0:2] is the sub-list for field type_name
}
func init() { file_common_matcher_geoip_geoip_proto_init() }
func file_common_matcher_geoip_geoip_proto_init() {
if File_common_matcher_geoip_geoip_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_common_matcher_geoip_geoip_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*CIDR); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_common_matcher_geoip_geoip_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GeoIP); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_common_matcher_geoip_geoip_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GeoIPList); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_common_matcher_geoip_geoip_proto_rawDesc,
NumEnums: 0,
NumMessages: 3,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_common_matcher_geoip_geoip_proto_goTypes,
DependencyIndexes: file_common_matcher_geoip_geoip_proto_depIdxs,
MessageInfos: file_common_matcher_geoip_geoip_proto_msgTypes,
}.Build()
File_common_matcher_geoip_geoip_proto = out.File
file_common_matcher_geoip_geoip_proto_rawDesc = nil
file_common_matcher_geoip_geoip_proto_goTypes = nil
file_common_matcher_geoip_geoip_proto_depIdxs = nil
}

View File

@@ -1,26 +0,0 @@
syntax = "proto3";
package xray.common.matcher.geoip;
option csharp_namespace = "Xray.Common.Matcher.GeoIP";
option go_package = "github.com/xtls/xray-core/common/matcher/geoip";
option java_package = "com.xray.common.matcher.geoip";
option java_multiple_files = true;
// IP for routing decision, in CIDR form.
message CIDR {
// IP address, should be either 4 or 16 bytes.
bytes ip = 1;
// Number of leading ones in the network mask.
uint32 prefix = 2;
}
message GeoIP {
string country_code = 1;
repeated CIDR cidr = 2;
bool reverse_match =3;
}
message GeoIPList {
repeated GeoIP entry = 1;
}

View File

@@ -1,57 +0,0 @@
package geoip
import (
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/features/routing"
)
type MultiGeoIPMatcher struct {
matchers []*GeoIPMatcher
onSource bool
}
func NewMultiGeoIPMatcher(geoips []*GeoIP, onSource bool) (*MultiGeoIPMatcher, error) {
var matchers []*GeoIPMatcher
for _, geoip := range geoips {
matcher, err := GlobalGeoIPContainer.Add(geoip)
if err != nil {
return nil, err
}
matchers = append(matchers, matcher)
}
matcher := &MultiGeoIPMatcher{
matchers: matchers,
onSource: onSource,
}
return matcher, nil
}
// Apply implements Condition.
func (m *MultiGeoIPMatcher) Apply(ctx routing.Context) bool {
var ips []net.IP
if m.onSource {
ips = ctx.GetSourceIPs()
} else {
ips = ctx.GetTargetIPs()
}
for _, ip := range ips {
for _, matcher := range m.matchers {
if matcher.Match(ip) {
return true
}
}
}
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
}

View File

@@ -1,35 +0,0 @@
package geosite
import "strings"
type AttributeList struct {
matcher []AttributeMatcher
}
func (al *AttributeList) Match(domain *Domain) bool {
for _, matcher := range al.matcher {
if !matcher.Match(domain) {
return false
}
}
return true
}
func (al *AttributeList) IsEmpty() bool {
return len(al.matcher) == 0
}
type AttributeMatcher interface {
Match(*Domain) bool
}
type BooleanMatcher string
func (m BooleanMatcher) Match(domain *Domain) bool {
for _, attr := range domain.Attribute {
if strings.EqualFold(attr.GetKey(), string(m)) {
return true
}
}
return false
}

View File

@@ -1,42 +0,0 @@
package geosite
import (
"strings"
dm "github.com/xtls/xray-core/common/matcher/domain"
)
func LoadGeositeWithAttr(file string, siteWithAttr string) ([]*dm.Domain, error) {
parts := strings.Split(siteWithAttr, "@")
if len(parts) == 0 {
return nil, newError("empty site")
}
country := strings.ToUpper(parts[0])
attrs := parseAttrs(parts[1:])
domains, err := loadSite(file, country)
if err != nil {
return nil, err
}
if attrs.IsEmpty() {
return ToDomains(domains), nil
}
filteredDomains := make([]*dm.Domain, 0, len(domains))
for _, domain := range domains {
if attrs.Match(domain) {
filteredDomains = append(filteredDomains, domain.ToDomain())
}
}
return filteredDomains, nil
}
func parseAttrs(attrs []string) *AttributeList {
al := new(AttributeList)
for _, attr := range attrs {
lc := strings.ToLower(attr)
al.matcher = append(al.matcher, BooleanMatcher(lc))
}
return al
}

View File

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

View File

@@ -1,86 +0,0 @@
package geosite
import (
"runtime"
"github.com/golang/protobuf/proto"
"github.com/xtls/xray-core/common/platform/filesystem"
)
var (
SiteCache = make(map[string]*GeoSite)
FileCache = make(map[string][]byte)
)
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 loadSite(file, code string) ([]*Domain, error) {
index := file + ":" + code
if SiteCache[index] == nil {
bs, err := loadFile(file)
if err != nil {
return nil, newError("failed to load file: ", file).Base(err)
}
bs = find(bs, []byte(code))
if bs == nil {
return nil, newError("list not found in ", file, ": ", code)
}
var ges GeoSite
if err := proto.Unmarshal(bs, &ges); err != nil {
return nil, newError("error unmarshal Site in ", file, ": ", code).Base(err)
}
defer runtime.GC() // or debug.FreeOSMemory()
return ges.Domain, nil // do not cache geosite
SiteCache[index] = &ges
}
return SiteCache[index].Domain, nil
}
func find(data, code []byte) []byte {
codeL := len(code)
if codeL == 0 {
return nil
}
for {
dataL := len(data)
if dataL < 2 {
return nil
}
x, y := proto.DecodeVarint(data[1:])
if x == 0 && y == 0 {
return nil
}
headL, bodyL := 1+y, int(x)
dataL -= headL
if dataL < bodyL {
return nil
}
data = data[headL:]
if int(data[1]) == codeL {
for i := 0; i < codeL && data[2+i] == code[i]; i++ {
if i+1 == codeL {
return data[:bodyL]
}
}
}
if dataL == bodyL {
return nil
}
data = data[bodyL:]
}
}

View File

@@ -1,33 +0,0 @@
package geosite
import "github.com/xtls/xray-core/common/matcher/domain"
//go:generate go run github.com/xtls/xray-core/common/errors/errorgen
func ToDomains(dms []*Domain) []*domain.Domain {
dm := make([]*domain.Domain, len(dms))
for idx, entry := range dms {
dm[idx] = entry.ToDomain()
}
return dm
}
func (d *Domain) ToDomain() *domain.Domain {
return &domain.Domain{Type: d.Type.ToMatchingType(), Value: d.Value}
}
func (t Domain_Type) ToMatchingType() domain.MatchingType {
switch t {
case Domain_Plain:
return domain.MatchingType_Keyword
case Domain_Regex:
return domain.MatchingType_Regex
case Domain_Domain:
return domain.MatchingType_Subdomain
case Domain_Full:
return domain.MatchingType_Full
}
panic("impossible")
}

View File

@@ -1,501 +0,0 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.25.0
// protoc v3.15.6
// source: common/matcher/geosite/geosite.proto
package geosite
import (
proto "github.com/golang/protobuf/proto"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
// This is a compile-time assertion that a sufficiently up-to-date version
// of the legacy proto package is being used.
const _ = proto.ProtoPackageIsVersion4
type Domain_Type int32
const (
// The value is used as is.
Domain_Plain Domain_Type = 0
// The value is used as a regular expression.
Domain_Regex Domain_Type = 1
// The value is a root domain.
Domain_Domain Domain_Type = 2
// The value is a domain.
Domain_Full Domain_Type = 3
)
// Enum value maps for Domain_Type.
var (
Domain_Type_name = map[int32]string{
0: "Plain",
1: "Regex",
2: "Domain",
3: "Full",
}
Domain_Type_value = map[string]int32{
"Plain": 0,
"Regex": 1,
"Domain": 2,
"Full": 3,
}
)
func (x Domain_Type) Enum() *Domain_Type {
p := new(Domain_Type)
*p = x
return p
}
func (x Domain_Type) String() string {
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
func (Domain_Type) Descriptor() protoreflect.EnumDescriptor {
return file_common_matcher_geosite_geosite_proto_enumTypes[0].Descriptor()
}
func (Domain_Type) Type() protoreflect.EnumType {
return &file_common_matcher_geosite_geosite_proto_enumTypes[0]
}
func (x Domain_Type) Number() protoreflect.EnumNumber {
return protoreflect.EnumNumber(x)
}
// Deprecated: Use Domain_Type.Descriptor instead.
func (Domain_Type) EnumDescriptor() ([]byte, []int) {
return file_common_matcher_geosite_geosite_proto_rawDescGZIP(), []int{0, 0}
}
type Domain struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// Domain matching type.
Type Domain_Type `protobuf:"varint,1,opt,name=type,proto3,enum=xray.common.matcher.geosite.Domain_Type" json:"type,omitempty"`
// Domain value.
Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
// Attributes of this domain. May be used for filtering.
Attribute []*Domain_Attribute `protobuf:"bytes,3,rep,name=attribute,proto3" json:"attribute,omitempty"`
}
func (x *Domain) Reset() {
*x = Domain{}
if protoimpl.UnsafeEnabled {
mi := &file_common_matcher_geosite_geosite_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Domain) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Domain) ProtoMessage() {}
func (x *Domain) ProtoReflect() protoreflect.Message {
mi := &file_common_matcher_geosite_geosite_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Domain.ProtoReflect.Descriptor instead.
func (*Domain) Descriptor() ([]byte, []int) {
return file_common_matcher_geosite_geosite_proto_rawDescGZIP(), []int{0}
}
func (x *Domain) GetType() Domain_Type {
if x != nil {
return x.Type
}
return Domain_Plain
}
func (x *Domain) GetValue() string {
if x != nil {
return x.Value
}
return ""
}
func (x *Domain) GetAttribute() []*Domain_Attribute {
if x != nil {
return x.Attribute
}
return nil
}
type GeoSite struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
CountryCode string `protobuf:"bytes,1,opt,name=country_code,json=countryCode,proto3" json:"country_code,omitempty"`
Domain []*Domain `protobuf:"bytes,2,rep,name=domain,proto3" json:"domain,omitempty"`
}
func (x *GeoSite) Reset() {
*x = GeoSite{}
if protoimpl.UnsafeEnabled {
mi := &file_common_matcher_geosite_geosite_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GeoSite) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GeoSite) ProtoMessage() {}
func (x *GeoSite) ProtoReflect() protoreflect.Message {
mi := &file_common_matcher_geosite_geosite_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GeoSite.ProtoReflect.Descriptor instead.
func (*GeoSite) Descriptor() ([]byte, []int) {
return file_common_matcher_geosite_geosite_proto_rawDescGZIP(), []int{1}
}
func (x *GeoSite) GetCountryCode() string {
if x != nil {
return x.CountryCode
}
return ""
}
func (x *GeoSite) GetDomain() []*Domain {
if x != nil {
return x.Domain
}
return nil
}
type GeoSiteList struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Entry []*GeoSite `protobuf:"bytes,1,rep,name=entry,proto3" json:"entry,omitempty"`
}
func (x *GeoSiteList) Reset() {
*x = GeoSiteList{}
if protoimpl.UnsafeEnabled {
mi := &file_common_matcher_geosite_geosite_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GeoSiteList) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GeoSiteList) ProtoMessage() {}
func (x *GeoSiteList) ProtoReflect() protoreflect.Message {
mi := &file_common_matcher_geosite_geosite_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GeoSiteList.ProtoReflect.Descriptor instead.
func (*GeoSiteList) Descriptor() ([]byte, []int) {
return file_common_matcher_geosite_geosite_proto_rawDescGZIP(), []int{2}
}
func (x *GeoSiteList) GetEntry() []*GeoSite {
if x != nil {
return x.Entry
}
return nil
}
type Domain_Attribute struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
// Types that are assignable to TypedValue:
// *Domain_Attribute_BoolValue
// *Domain_Attribute_IntValue
TypedValue isDomain_Attribute_TypedValue `protobuf_oneof:"typed_value"`
}
func (x *Domain_Attribute) Reset() {
*x = Domain_Attribute{}
if protoimpl.UnsafeEnabled {
mi := &file_common_matcher_geosite_geosite_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Domain_Attribute) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Domain_Attribute) ProtoMessage() {}
func (x *Domain_Attribute) ProtoReflect() protoreflect.Message {
mi := &file_common_matcher_geosite_geosite_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Domain_Attribute.ProtoReflect.Descriptor instead.
func (*Domain_Attribute) Descriptor() ([]byte, []int) {
return file_common_matcher_geosite_geosite_proto_rawDescGZIP(), []int{0, 0}
}
func (x *Domain_Attribute) GetKey() string {
if x != nil {
return x.Key
}
return ""
}
func (m *Domain_Attribute) GetTypedValue() isDomain_Attribute_TypedValue {
if m != nil {
return m.TypedValue
}
return nil
}
func (x *Domain_Attribute) GetBoolValue() bool {
if x, ok := x.GetTypedValue().(*Domain_Attribute_BoolValue); ok {
return x.BoolValue
}
return false
}
func (x *Domain_Attribute) GetIntValue() int64 {
if x, ok := x.GetTypedValue().(*Domain_Attribute_IntValue); ok {
return x.IntValue
}
return 0
}
type isDomain_Attribute_TypedValue interface {
isDomain_Attribute_TypedValue()
}
type Domain_Attribute_BoolValue struct {
BoolValue bool `protobuf:"varint,2,opt,name=bool_value,json=boolValue,proto3,oneof"`
}
type Domain_Attribute_IntValue struct {
IntValue int64 `protobuf:"varint,3,opt,name=int_value,json=intValue,proto3,oneof"`
}
func (*Domain_Attribute_BoolValue) isDomain_Attribute_TypedValue() {}
func (*Domain_Attribute_IntValue) isDomain_Attribute_TypedValue() {}
var File_common_matcher_geosite_geosite_proto protoreflect.FileDescriptor
var file_common_matcher_geosite_geosite_proto_rawDesc = []byte{
0x0a, 0x24, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72,
0x2f, 0x67, 0x65, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x2f, 0x67, 0x65, 0x6f, 0x73, 0x69, 0x74, 0x65,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1b, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d,
0x6d, 0x6f, 0x6e, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x67, 0x65, 0x6f, 0x73,
0x69, 0x74, 0x65, 0x22, 0xcb, 0x02, 0x0a, 0x06, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x3c,
0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x28, 0x2e, 0x78,
0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68,
0x65, 0x72, 0x2e, 0x67, 0x65, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69,
0x6e, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05,
0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c,
0x75, 0x65, 0x12, 0x4b, 0x0a, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x18,
0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d,
0x6d, 0x6f, 0x6e, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x67, 0x65, 0x6f, 0x73,
0x69, 0x74, 0x65, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69,
0x62, 0x75, 0x74, 0x65, 0x52, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x1a,
0x6c, 0x0a, 0x09, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x10, 0x0a, 0x03,
0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x1f,
0x0a, 0x0a, 0x62, 0x6f, 0x6f, 0x6c, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01,
0x28, 0x08, 0x48, 0x00, 0x52, 0x09, 0x62, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12,
0x1d, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01,
0x28, 0x03, 0x48, 0x00, 0x52, 0x08, 0x69, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x0d,
0x0a, 0x0b, 0x74, 0x79, 0x70, 0x65, 0x64, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x32, 0x0a,
0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x09, 0x0a, 0x05, 0x50, 0x6c, 0x61, 0x69, 0x6e, 0x10, 0x00,
0x12, 0x09, 0x0a, 0x05, 0x52, 0x65, 0x67, 0x65, 0x78, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x44,
0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x46, 0x75, 0x6c, 0x6c, 0x10,
0x03, 0x22, 0x69, 0x0a, 0x07, 0x47, 0x65, 0x6f, 0x53, 0x69, 0x74, 0x65, 0x12, 0x21, 0x0a, 0x0c,
0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01,
0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x12,
0x3b, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32,
0x23, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6d, 0x61,
0x74, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x67, 0x65, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x2e, 0x44, 0x6f,
0x6d, 0x61, 0x69, 0x6e, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x22, 0x49, 0x0a, 0x0b,
0x47, 0x65, 0x6f, 0x53, 0x69, 0x74, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x3a, 0x0a, 0x05, 0x65,
0x6e, 0x74, 0x72, 0x79, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61,
0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72,
0x2e, 0x67, 0x65, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x2e, 0x47, 0x65, 0x6f, 0x53, 0x69, 0x74, 0x65,
0x52, 0x05, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x42, 0x73, 0x0a, 0x1f, 0x63, 0x6f, 0x6d, 0x2e, 0x78,
0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68,
0x65, 0x72, 0x2e, 0x67, 0x65, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x50, 0x01, 0x5a, 0x30, 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, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6d,
0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2f, 0x67, 0x65, 0x6f, 0x73, 0x69, 0x74, 0x65, 0xaa, 0x02,
0x1b, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4d, 0x61, 0x74,
0x63, 0x68, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x6f, 0x53, 0x69, 0x74, 0x65, 0x62, 0x06, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x33,
}
var (
file_common_matcher_geosite_geosite_proto_rawDescOnce sync.Once
file_common_matcher_geosite_geosite_proto_rawDescData = file_common_matcher_geosite_geosite_proto_rawDesc
)
func file_common_matcher_geosite_geosite_proto_rawDescGZIP() []byte {
file_common_matcher_geosite_geosite_proto_rawDescOnce.Do(func() {
file_common_matcher_geosite_geosite_proto_rawDescData = protoimpl.X.CompressGZIP(file_common_matcher_geosite_geosite_proto_rawDescData)
})
return file_common_matcher_geosite_geosite_proto_rawDescData
}
var file_common_matcher_geosite_geosite_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
var file_common_matcher_geosite_geosite_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
var file_common_matcher_geosite_geosite_proto_goTypes = []interface{}{
(Domain_Type)(0), // 0: xray.common.matcher.geosite.Domain.Type
(*Domain)(nil), // 1: xray.common.matcher.geosite.Domain
(*GeoSite)(nil), // 2: xray.common.matcher.geosite.GeoSite
(*GeoSiteList)(nil), // 3: xray.common.matcher.geosite.GeoSiteList
(*Domain_Attribute)(nil), // 4: xray.common.matcher.geosite.Domain.Attribute
}
var file_common_matcher_geosite_geosite_proto_depIdxs = []int32{
0, // 0: xray.common.matcher.geosite.Domain.type:type_name -> xray.common.matcher.geosite.Domain.Type
4, // 1: xray.common.matcher.geosite.Domain.attribute:type_name -> xray.common.matcher.geosite.Domain.Attribute
1, // 2: xray.common.matcher.geosite.GeoSite.domain:type_name -> xray.common.matcher.geosite.Domain
2, // 3: xray.common.matcher.geosite.GeoSiteList.entry:type_name -> xray.common.matcher.geosite.GeoSite
4, // [4:4] is the sub-list for method output_type
4, // [4:4] is the sub-list for method input_type
4, // [4:4] is the sub-list for extension type_name
4, // [4:4] is the sub-list for extension extendee
0, // [0:4] is the sub-list for field type_name
}
func init() { file_common_matcher_geosite_geosite_proto_init() }
func file_common_matcher_geosite_geosite_proto_init() {
if File_common_matcher_geosite_geosite_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_common_matcher_geosite_geosite_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Domain); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_common_matcher_geosite_geosite_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GeoSite); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_common_matcher_geosite_geosite_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GeoSiteList); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_common_matcher_geosite_geosite_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Domain_Attribute); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
file_common_matcher_geosite_geosite_proto_msgTypes[3].OneofWrappers = []interface{}{
(*Domain_Attribute_BoolValue)(nil),
(*Domain_Attribute_IntValue)(nil),
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_common_matcher_geosite_geosite_proto_rawDesc,
NumEnums: 1,
NumMessages: 4,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_common_matcher_geosite_geosite_proto_goTypes,
DependencyIndexes: file_common_matcher_geosite_geosite_proto_depIdxs,
EnumInfos: file_common_matcher_geosite_geosite_proto_enumTypes,
MessageInfos: file_common_matcher_geosite_geosite_proto_msgTypes,
}.Build()
File_common_matcher_geosite_geosite_proto = out.File
file_common_matcher_geosite_geosite_proto_rawDesc = nil
file_common_matcher_geosite_geosite_proto_goTypes = nil
file_common_matcher_geosite_geosite_proto_depIdxs = nil
}

View File

@@ -1,46 +0,0 @@
syntax = "proto3";
package xray.common.matcher.geosite;
option csharp_namespace = "Xray.Common.Matcher.GeoSite";
option go_package = "github.com/xtls/xray-core/common/matcher/geosite";
option java_package = "com.xray.common.matcher.geosite";
option java_multiple_files = true;
message Domain {
enum Type {
// The value is used as is.
Plain = 0;
// The value is used as a regular expression.
Regex = 1;
// The value is a root domain.
Domain = 2;
// The value is a domain.
Full = 3;
}
// Domain matching type.
Type type = 1;
// Domain value.
string value = 2;
message Attribute {
string key = 1;
oneof typed_value {
bool bool_value = 2;
int64 int_value = 3;
}
}
// Attributes of this domain. May be used for filtering.
repeated Attribute attribute = 3;
}
message GeoSite {
string country_code = 1;
repeated Domain domain = 2;
}
message GeoSiteList {
repeated GeoSite entry = 1;
}

View File

@@ -6,8 +6,6 @@ import (
"math/rand" "math/rand"
"github.com/xtls/xray-core/common/errors" "github.com/xtls/xray-core/common/errors"
"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/common/net"
"github.com/xtls/xray-core/common/protocol" "github.com/xtls/xray-core/common/protocol"
"github.com/xtls/xray-core/common/signal" "github.com/xtls/xray-core/common/signal"
@@ -62,8 +60,7 @@ type Outbound struct {
// SniffingRequest controls the behavior of content sniffing. // SniffingRequest controls the behavior of content sniffing.
type SniffingRequest struct { type SniffingRequest struct {
ExcludedDomainMatcher *domain.DomainMatcher ExcludeForDomain []string
ExcludedIPMatcher *geoip.MultiGeoIPMatcher
OverrideDestinationForProtocol []string OverrideDestinationForProtocol []string
Enabled bool Enabled bool
MetadataOnly bool MetadataOnly bool
@@ -78,7 +75,7 @@ type Content struct {
Attributes map[string]string Attributes map[string]string
SkipDNSResolve bool SkipRoutePick bool
} }
// Sockopt is the settings for socket connection. // Sockopt is the settings for socket connection.

View File

@@ -1,4 +1,4 @@
package str package strmatcher
import ( import (
"container/list" "container/list"

View File

@@ -1,23 +1,23 @@
package str_test package strmatcher_test
import ( import (
"strconv" "strconv"
"testing" "testing"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
. "github.com/xtls/xray-core/common/matcher/str" . "github.com/xtls/xray-core/common/strmatcher"
) )
func BenchmarkACAutomaton(b *testing.B) { func BenchmarkACAutomaton(b *testing.B) {
ac := NewACAutomaton() ac := NewACAutomaton()
for i := 1; i <= 1024; i++ { for i := 1; i <= 1024; i++ {
ac.Add(strconv.Itoa(i)+".xray.com", Domain) ac.Add(strconv.Itoa(i)+".v2ray.com", Domain)
} }
ac.Build() ac.Build()
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
_ = ac.Match("0.xray.com") _ = ac.Match("0.v2ray.com")
} }
} }

View File

@@ -1,4 +1,4 @@
package str package strmatcher
import "strings" import "strings"

View File

@@ -1,10 +1,10 @@
package str_test package strmatcher_test
import ( import (
"reflect" "reflect"
"testing" "testing"
. "github.com/xtls/xray-core/common/matcher/str" . "github.com/xtls/xray-core/common/strmatcher"
) )
func TestDomainMatcherGroup(t *testing.T) { func TestDomainMatcherGroup(t *testing.T) {

View File

@@ -1,4 +1,4 @@
package str package strmatcher
type FullMatcherGroup struct { type FullMatcherGroup struct {
matchers map[string][]uint32 matchers map[string][]uint32

View File

@@ -1,10 +1,10 @@
package str_test package strmatcher_test
import ( import (
"reflect" "reflect"
"testing" "testing"
. "github.com/xtls/xray-core/common/matcher/str" . "github.com/xtls/xray-core/common/strmatcher"
) )
func TestFullMatcherGroup(t *testing.T) { func TestFullMatcherGroup(t *testing.T) {

View File

@@ -1,4 +1,4 @@
package str package strmatcher
import ( import (
"regexp" "regexp"

View File

@@ -1,10 +1,10 @@
package str_test package strmatcher_test
import ( import (
"testing" "testing"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
. "github.com/xtls/xray-core/common/matcher/str" . "github.com/xtls/xray-core/common/strmatcher"
) )
func TestMatcher(t *testing.T) { func TestMatcher(t *testing.T) {

View File

@@ -1,4 +1,4 @@
package str package strmatcher
import ( import (
"math/bits" "math/bits"

View File

@@ -1,4 +1,4 @@
package str package strmatcher
import ( import (
"regexp" "regexp"

View File

@@ -1,11 +1,11 @@
package str_test package strmatcher_test
import ( import (
"reflect" "reflect"
"testing" "testing"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
. "github.com/xtls/xray-core/common/matcher/str" . "github.com/xtls/xray-core/common/strmatcher"
) )
func TestMatcherGroup(t *testing.T) { func TestMatcherGroup(t *testing.T) {

View File

@@ -18,7 +18,7 @@ import (
) )
var ( var (
version = "1.4.2" version = "1.4.3"
build = "Custom" build = "Custom"
codename = "Xray, Penetrates Everything." codename = "Xray, Penetrates Everything."
intro = "A unified platform for anti-censorship." intro = "A unified platform for anti-censorship."

View File

@@ -14,12 +14,6 @@ type IPOption struct {
FakeEnable bool FakeEnable bool
} }
func (p *IPOption) Copy() *IPOption {
return &IPOption{p.IPv4Enable, p.IPv6Enable, p.FakeEnable}
}
type Option func(dopt *IPOption) *IPOption
// Client is a Xray feature for querying DNS information. // Client is a Xray feature for querying DNS information.
// //
// xray:api:stable // xray:api:stable
@@ -27,24 +21,7 @@ type Client interface {
features.Feature features.Feature
// LookupIP returns IP address for the given domain. IPs may contain IPv4 and/or IPv6 addresses. // LookupIP returns IP address for the given domain. IPs may contain IPv4 and/or IPv6 addresses.
LookupIP(domain string) ([]net.IP, error) LookupIP(domain string, option IPOption) ([]net.IP, error)
// LookupOptions query IP address for domain with *IPOption.
LookupOptions(domain string, opt ...Option) ([]net.IP, error)
}
// IPv4Lookup is an optional feature for querying IPv4 addresses only.
//
// xray:api:beta
type IPv4Lookup interface {
LookupIPv4(domain string) ([]net.IP, error)
}
// IPv6Lookup is an optional feature for querying IPv6 addresses only.
//
// xray:api:beta
type IPv6Lookup interface {
LookupIPv6(domain string) ([]net.IP, error)
} }
// ClientType returns the type of Client interface. Can be used for implementing common.HasType. // ClientType returns the type of Client interface. Can be used for implementing common.HasType.
@@ -73,35 +50,3 @@ func RCodeFromError(err error) uint16 {
} }
return 0 return 0
} }
var (
LookupIPv4Only = func(d *IPOption) *IPOption {
d.IPv4Enable = true
d.IPv6Enable = false
return d
}
LookupIPv6Only = func(d *IPOption) *IPOption {
d.IPv4Enable = false
d.IPv6Enable = true
return d
}
LookupIP = func(d *IPOption) *IPOption {
d.IPv4Enable = true
d.IPv6Enable = true
return d
}
LookupFake = func(d *IPOption) *IPOption {
d.FakeEnable = true
return d
}
LookupNoFake = func(d *IPOption) *IPOption {
d.FakeEnable = false
return d
}
LookupAll = func(d *IPOption) *IPOption {
LookupIP(d)
LookupFake(d)
return d
}
)

View File

@@ -20,64 +20,41 @@ func (*Client) Start() error { return nil }
func (*Client) Close() error { return nil } func (*Client) Close() error { return nil }
// LookupIP implements Client. // LookupIP implements Client.
func (*Client) LookupIP(host string) ([]net.IP, error) { func (*Client) LookupIP(host string, option dns.IPOption) ([]net.IP, error) {
ips, err := net.LookupIP(host) ips, err := net.LookupIP(host)
if err != nil { if err != nil {
return nil, err return nil, err
} }
parsedIPs := make([]net.IP, 0, len(ips)) parsedIPs := make([]net.IP, 0, len(ips))
ipv4 := make([]net.IP, 0, len(ips))
ipv6 := make([]net.IP, 0, len(ips))
for _, ip := range ips { for _, ip := range ips {
parsed := net.IPAddress(ip) parsed := net.IPAddress(ip)
if parsed != nil { if parsed != nil {
parsedIPs = append(parsedIPs, parsed.IP()) parsedIPs = append(parsedIPs, parsed.IP())
} }
}
if len(parsedIPs) == 0 {
return nil, dns.ErrEmptyResponse
}
return parsedIPs, nil
}
// LookupOptions implements Client.
func (c *Client) LookupOptions(host string, _ ...dns.Option) ([]net.IP, error) {
return c.LookupIP(host)
}
// LookupIPv4 implements IPv4Lookup.
func (c *Client) LookupIPv4(host string) ([]net.IP, error) {
ips, err := c.LookupIP(host)
if err != nil {
return nil, err
}
ipv4 := make([]net.IP, 0, len(ips))
for _, ip := range ips {
if len(ip) == net.IPv4len { if len(ip) == net.IPv4len {
ipv4 = append(ipv4, ip) ipv4 = append(ipv4, ip)
} }
}
if len(ipv4) == 0 {
return nil, dns.ErrEmptyResponse
}
return ipv4, nil
}
// LookupIPv6 implements IPv6Lookup.
func (c *Client) LookupIPv6(host string) ([]net.IP, error) {
ips, err := c.LookupIP(host)
if err != nil {
return nil, err
}
ipv6 := make([]net.IP, 0, len(ips))
for _, ip := range ips {
if len(ip) == net.IPv6len { if len(ip) == net.IPv6len {
ipv6 = append(ipv6, ip) ipv6 = append(ipv6, ip)
} }
} }
if len(ipv6) == 0 { switch {
return nil, dns.ErrEmptyResponse case option.IPv4Enable && option.IPv6Enable:
if len(parsedIPs) > 0 {
return parsedIPs, nil
}
case option.IPv4Enable:
if len(ipv4) > 0 {
return ipv4, nil
}
case option.IPv6Enable:
if len(ipv6) > 0 {
return ipv6, nil
}
} }
return nil, dns.ErrEmptyResponse
return ipv6, nil
} }
// New create a new dns.Client that queries localhost for DNS. // New create a new dns.Client that queries localhost for DNS.

View File

@@ -37,7 +37,4 @@ type Context interface {
// GetAttributes returns extra attributes from the conneciont content. // GetAttributes returns extra attributes from the conneciont content.
GetAttributes() map[string]string GetAttributes() map[string]string
// GetSkipDNSResolve returns a flag switch for weather skip dns resolve during route pick.
GetSkipDNSResolve() bool
} }

View File

@@ -26,12 +26,16 @@ func (ctx *ResolvableContext) GetTargetIPs() []net.IP {
} }
if domain := ctx.GetTargetDomain(); len(domain) != 0 { if domain := ctx.GetTargetDomain(); len(domain) != 0 {
ips, err := ctx.dnsClient.LookupIP(domain) ips, err := ctx.dnsClient.LookupIP(domain, dns.IPOption{
IPv4Enable: true,
IPv6Enable: true,
FakeEnable: false,
})
if err == nil { if err == nil {
ctx.resolvedIPs = ips ctx.resolvedIPs = ips
return ips return ips
} }
newError("failed to resolve ip for ", domain).Base(err).WriteToLog() newError("resolve ip for ", domain).Base(err).WriteToLog()
} }
return nil return nil

View File

@@ -109,14 +109,6 @@ func (ctx *Context) GetAttributes() map[string]string {
return ctx.Content.Attributes return ctx.Content.Attributes
} }
// GetSkipDNSResolve implements routing.Context.
func (ctx *Context) GetSkipDNSResolve() bool {
if ctx.Content == nil {
return false
}
return ctx.Content.SkipDNSResolve
}
// AsRoutingContext creates a context from context.context with session info. // AsRoutingContext creates a context from context.context with session info.
func AsRoutingContext(ctx context.Context) routing.Context { func AsRoutingContext(ctx context.Context) routing.Context {
return &Context{ return &Context{

51
go.mod
View File

@@ -1,27 +1,48 @@
module github.com/xtls/xray-core module github.com/xtls/xray-core
go 1.16 go 1.17
require ( require (
github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32 github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32
github.com/golang/mock v1.5.0 github.com/golang/mock v1.6.0
github.com/golang/protobuf v1.5.2 github.com/golang/protobuf v1.5.2
github.com/google/go-cmp v0.5.5 github.com/google/go-cmp v0.5.6
github.com/gorilla/websocket v1.4.2 github.com/gorilla/websocket v1.4.2
github.com/lucas-clemente/quic-go v0.20.0 github.com/lucas-clemente/quic-go v0.23.0
github.com/miekg/dns v1.1.41 github.com/miekg/dns v1.1.43
github.com/pelletier/go-toml v1.8.1 github.com/pelletier/go-toml v1.9.4
github.com/pires/go-proxyproto v0.5.0 github.com/pires/go-proxyproto v0.6.0
github.com/refraction-networking/utls v0.0.0-20201210053706-2179f286686b github.com/refraction-networking/utls v0.0.0-20210713165636-0b2885c8c0d4
github.com/seiflotfy/cuckoofilter v0.0.0-20201222105146-bc6005554a0c github.com/seiflotfy/cuckoofilter v0.0.0-20201222105146-bc6005554a0c
github.com/stretchr/testify v1.7.0 github.com/stretchr/testify v1.7.0
github.com/xtls/go v0.0.0-20201118062508-3632bf3b7499 github.com/xtls/go v0.0.0-20201118062508-3632bf3b7499
go.starlark.net v0.0.0-20210312235212-74c10e2c17dc go.starlark.net v0.0.0-20210901212718-87f333178d59
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 golang.org/x/crypto v0.0.0-20210817164053-32db794688a5
golang.org/x/net v0.0.0-20210330230544-e57232859fb2 golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44 golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34
google.golang.org/grpc v1.36.1 google.golang.org/grpc v1.40.0
google.golang.org/protobuf v1.26.0 google.golang.org/protobuf v1.27.1
h12.io/socks v1.0.2 h12.io/socks v1.0.3
)
require (
github.com/cheekybits/genny v1.0.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dgryski/go-metro v0.0.0-20200812162917-85c65e2d0165 // indirect
github.com/fsnotify/fsnotify v1.5.1 // indirect
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
github.com/marten-seemann/qtls-go1-16 v0.1.4 // indirect
github.com/marten-seemann/qtls-go1-17 v0.1.0 // indirect
github.com/nxadm/tail v1.4.8 // indirect
github.com/onsi/ginkgo v1.16.4 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
golang.org/x/mod v0.5.0 // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/tools v0.1.5 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83 // indirect
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
) )

131
go.sum
View File

@@ -8,18 +8,23 @@ dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1
dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU=
git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE= github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE=
github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
@@ -29,29 +34,35 @@ github.com/dgryski/go-metro v0.0.0-20200812162917-85c65e2d0165/go.mod h1:c9O8+fp
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY= github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI=
github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32 h1:Mn26/9ZMNWSw9C9ERFA1PUxfmGpolnw2v0bKOREu5ew= github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32 h1:Mn26/9ZMNWSw9C9ERFA1PUxfmGpolnw2v0bKOREu5ew=
github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32/go.mod h1:GIjDIg/heH5DOkXY3YJ/wNhfHsQHoXGjl8G8amsYQ1I= github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32/go.mod h1:GIjDIg/heH5DOkXY3YJ/wNhfHsQHoXGjl8G8amsYQ1I=
github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/mock v1.5.0 h1:jlYHihg//f7RRwuPfptm04yp4s7O6Kw8EZiVYIGcH0g= github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
@@ -59,6 +70,7 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
@@ -69,8 +81,9 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
@@ -83,6 +96,7 @@ github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0U
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/h12w/go-socks5 v0.0.0-20200522160539-76189e178364 h1:5XxdakFhqd9dnXoAZy1Mb2R/DZ6D1e+0bGC/JhucGYI= github.com/h12w/go-socks5 v0.0.0-20200522160539-76189e178364 h1:5XxdakFhqd9dnXoAZy1Mb2R/DZ6D1e+0bGC/JhucGYI=
github.com/h12w/go-socks5 v0.0.0-20200522160539-76189e178364/go.mod h1:eDJQioIyy4Yn3MVivT7rv/39gAJTrA7lgmYr8EW950c= github.com/h12w/go-socks5 v0.0.0-20200522160539-76189e178364/go.mod h1:eDJQioIyy4Yn3MVivT7rv/39gAJTrA7lgmYr8EW950c=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
@@ -96,39 +110,44 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/lucas-clemente/quic-go v0.20.0 h1:FSU3YN5VnLafHR27Ejs1r1CYMS7XMyIVDzRewkDLNBw= github.com/lucas-clemente/quic-go v0.23.0 h1:5vFnKtZ6nHDFsc/F3uuiF4T3y/AXaQdxjUqiVw26GZE=
github.com/lucas-clemente/quic-go v0.20.0/go.mod h1:fZq/HUDIM+mW6X6wtzORjC0E/WDBMKe5Hf9bgjISwLk= github.com/lucas-clemente/quic-go v0.23.0/go.mod h1:paZuzjXCE5mj6sikVLMvqXk8lJV2AsqtJ6bDhjEfxx0=
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/marten-seemann/qpack v0.2.1/go.mod h1:F7Gl5L1jIgN1D11ucXefiuJS9UMVP2opoCp2jDKb7wc= github.com/marten-seemann/qpack v0.2.1/go.mod h1:F7Gl5L1jIgN1D11ucXefiuJS9UMVP2opoCp2jDKb7wc=
github.com/marten-seemann/qtls-go1-15 v0.1.4 h1:RehYMOyRW8hPVEja1KBVsFVNSm35Jj9Mvs5yNoZZ28A=
github.com/marten-seemann/qtls-go1-15 v0.1.4/go.mod h1:GyFwywLKkRt+6mfU99csTEY1joMZz5vmB1WNZH3P81I= github.com/marten-seemann/qtls-go1-15 v0.1.4/go.mod h1:GyFwywLKkRt+6mfU99csTEY1joMZz5vmB1WNZH3P81I=
github.com/marten-seemann/qtls-go1-16 v0.1.3 h1:XEZ1xGorVy9u+lJq+WXNE+hiqRYLNvJGYmwfwKQN2gU= github.com/marten-seemann/qtls-go1-16 v0.1.4 h1:xbHbOGGhrenVtII6Co8akhLEdrawwB2iHl5yhJRpnco=
github.com/marten-seemann/qtls-go1-16 v0.1.3/go.mod h1:gNpI2Ol+lRS3WwSOtIUUtRwZEQMXjYK+dQSBFbethAk= github.com/marten-seemann/qtls-go1-16 v0.1.4/go.mod h1:gNpI2Ol+lRS3WwSOtIUUtRwZEQMXjYK+dQSBFbethAk=
github.com/marten-seemann/qtls-go1-17 v0.1.0 h1:P9ggrs5xtwiqXv/FHNwntmuLMNq3KaSIG93AtAZ48xk=
github.com/marten-seemann/qtls-go1-17 v0.1.0/go.mod h1:fz4HIxByo+LlWcreM4CZOYNuz3taBQ8rN2X6FqvaWo8=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
github.com/miekg/dns v1.1.41 h1:WMszZWJG0XmzbK9FEmzH2TVcqYzFesusSIB41b8KHxY= github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg=
github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA=
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E=
github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak=
github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY=
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
github.com/pelletier/go-toml v1.8.1 h1:1Nf83orprkJyknT6h7zbuEGUEjcyVlCxSUGTENmNCRM= github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM=
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 h1:JhzVVoYvbOACxoUmOs6V/G4D5nPVUW73rKvXxP4XUJc= github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 h1:JhzVVoYvbOACxoUmOs6V/G4D5nPVUW73rKvXxP4XUJc=
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE= github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
github.com/pires/go-proxyproto v0.5.0 h1:A4Jv4ZCaV3AFJeGh5mGwkz4iuWUYMlQ7IoO/GTuSuLo= github.com/pires/go-proxyproto v0.6.0 h1:cLJUPnuQdiNf7P/wbeOKmM1khVdaMgTFDLj8h9ZrVYk=
github.com/pires/go-proxyproto v0.5.0/go.mod h1:Odh9VFOZJCf9G8cLW5o435Xf1J95Jw9Gw5rnCjcwzAY= github.com/pires/go-proxyproto v0.6.0/go.mod h1:Odh9VFOZJCf9G8cLW5o435Xf1J95Jw9Gw5rnCjcwzAY=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
@@ -137,8 +156,9 @@ github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/refraction-networking/utls v0.0.0-20201210053706-2179f286686b h1:lzo71oHzQEz0fKMSjR0BpVzuh2hOHvJTxnN3Rnikmtg= github.com/refraction-networking/utls v0.0.0-20210713165636-0b2885c8c0d4 h1:n9NMHJusHylTmtaJ0Qe0VV9dkTZLiwAxHmrI/l98GeE=
github.com/refraction-networking/utls v0.0.0-20201210053706-2179f286686b/go.mod h1:tz9gX959MEFfFN5whTIocCLUG57WiILqtdVxI8c6Wj0= github.com/refraction-networking/utls v0.0.0-20210713165636-0b2885c8c0d4/go.mod h1:tz9gX959MEFfFN5whTIocCLUG57WiILqtdVxI8c6Wj0=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/seiflotfy/cuckoofilter v0.0.0-20201222105146-bc6005554a0c h1:pqy40B3MQWYrza7YZXOXgl0Nf0QGFqrOC0BKae1UNAA= github.com/seiflotfy/cuckoofilter v0.0.0-20201222105146-bc6005554a0c h1:pqy40B3MQWYrza7YZXOXgl0Nf0QGFqrOC0BKae1UNAA=
github.com/seiflotfy/cuckoofilter v0.0.0-20201222105146-bc6005554a0c/go.mod h1:bR6DqgcAl1zTcOX8/pE2Qkj9XO00eCNqmKb7lXP8EAg= github.com/seiflotfy/cuckoofilter v0.0.0-20201222105146-bc6005554a0c/go.mod h1:bR6DqgcAl1zTcOX8/pE2Qkj9XO00eCNqmKb7lXP8EAg=
@@ -167,6 +187,7 @@ github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYED
github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw= github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw=
github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE=
github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
@@ -178,9 +199,12 @@ github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49u
github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM=
github.com/xtls/go v0.0.0-20201118062508-3632bf3b7499 h1:QHESTXtfgc1ABV+ArlbPVqUx9Ht5I0dDkYhxYoXFxNo= github.com/xtls/go v0.0.0-20201118062508-3632bf3b7499 h1:QHESTXtfgc1ABV+ArlbPVqUx9Ht5I0dDkYhxYoXFxNo=
github.com/xtls/go v0.0.0-20201118062508-3632bf3b7499/go.mod h1:5TB2+k58gx4A4g2Nf5miSHNDF6CuAzHKpWBooLAshTs= github.com/xtls/go v0.0.0-20201118062508-3632bf3b7499/go.mod h1:5TB2+k58gx4A4g2Nf5miSHNDF6CuAzHKpWBooLAshTs=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
go.starlark.net v0.0.0-20210312235212-74c10e2c17dc h1:pVkptfeOTFfx+zXZo7HEHN3d5LmhatBFvHdm/f2QnpY= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
go.starlark.net v0.0.0-20210312235212-74c10e2c17dc/go.mod h1:t3mmBBPzAVvK0L0n1drDmrQsJ8FoIx4INCqVMTr/Zo0= go.starlark.net v0.0.0-20210901212718-87f333178d59 h1:F8ArBy9n1l7HE1JjzOIYqweEqoUlywy5+L3bR0tIa9g=
go.starlark.net v0.0.0-20210901212718-87f333178d59/go.mod h1:t3mmBBPzAVvK0L0n1drDmrQsJ8FoIx4INCqVMTr/Zo0=
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw= golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
@@ -189,14 +213,19 @@ golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACk
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.5.0 h1:UG21uOlmZabA4fW5i7ZX6bjw1xELEGg/ZLgZq9auk/Q=
golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -210,20 +239,25 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210330230544-e57232859fb2 h1:nGCZOty+lVDsc4H2qPFksI5Se296+V+GhMiL/TzmYNk= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210330230544-e57232859fb2/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f h1:w6wWR0H+nyVpbSAQbzVEIACVyr/h8l/BEkY6Sokc7Eg=
golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw= golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -240,16 +274,24 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201231184435-2d18734c6014/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44 h1:Bli41pIlzTzf3KEY06n+xnzK/BESIg2ze4Pgfh/aI8c=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34 h1:GkvMjFtXUmahfDtashnc1mnrCtuBVcwse5QV2lUk/tI=
golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -261,6 +303,11 @@ golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -279,8 +326,10 @@ google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoA
google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg= google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg=
google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83 h1:3V2dxSZpz4zozWWUq36vUxXEKnSYitEH2LdsAx+RUmg=
google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
@@ -288,8 +337,10 @@ google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZi
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.36.1 h1:cmUfbeGKnz9+2DD/UYsMQXeqbHZqZDs4eQwW0sFOpBY= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.40.0 h1:AGJ0Ih4mHjSeibYkFGh1dD9KJ/eOtZ93I6hoHhukQ5Q=
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@@ -300,8 +351,9 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -311,15 +363,18 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkep
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c h1:grhR+C34yXImVGp7EzNk+DTIk+323eIUWOmEevy6bDo=
gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o=
h12.io/socks v1.0.2 h1:cZhhbV8+DE0Y1kotwhr1a3RC3kFO7AtuZ4GLr3qKSc8= h12.io/socks v1.0.3 h1:Ka3qaQewws4j4/eDQnOdpr4wXsC//dXtWvftlIcCQUo=
h12.io/socks v1.0.2/go.mod h1:AIhxy1jOId/XCz9BO+EIgNL2rQiPTBNnOfnVnQ+3Eck= h12.io/socks v1.0.3/go.mod h1:AIhxy1jOId/XCz9BO+EIgNL2rQiPTBNnOfnVnQ+3Eck=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

View File

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

View File

@@ -2,7 +2,6 @@ package conf_test
import ( import (
"encoding/json" "encoding/json"
"github.com/xtls/xray-core/infra/conf"
"os" "os"
"testing" "testing"
@@ -12,11 +11,12 @@ import (
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/protocol" "github.com/xtls/xray-core/common/protocol"
. "github.com/xtls/xray-core/infra/conf"
) )
func TestStringListUnmarshalError(t *testing.T) { func TestStringListUnmarshalError(t *testing.T) {
rawJSON := `1234` rawJSON := `1234`
list := new(conf.StringList) list := new(StringList)
err := json.Unmarshal([]byte(rawJSON), list) err := json.Unmarshal([]byte(rawJSON), list)
if err == nil { if err == nil {
t.Error("expected error, but got nil") t.Error("expected error, but got nil")
@@ -25,7 +25,7 @@ func TestStringListUnmarshalError(t *testing.T) {
func TestStringListLen(t *testing.T) { func TestStringListLen(t *testing.T) {
rawJSON := `"a, b, c, d"` rawJSON := `"a, b, c, d"`
var list conf.StringList var list StringList
err := json.Unmarshal([]byte(rawJSON), &list) err := json.Unmarshal([]byte(rawJSON), &list)
common.Must(err) common.Must(err)
if r := cmp.Diff([]string(list), []string{"a", " b", " c", " d"}); r != "" { if r := cmp.Diff([]string(list), []string{"a", " b", " c", " d"}); r != "" {
@@ -35,7 +35,7 @@ func TestStringListLen(t *testing.T) {
func TestIPParsing(t *testing.T) { func TestIPParsing(t *testing.T) {
rawJSON := "\"8.8.8.8\"" rawJSON := "\"8.8.8.8\""
var address conf.Address var address Address
err := json.Unmarshal([]byte(rawJSON), &address) err := json.Unmarshal([]byte(rawJSON), &address)
common.Must(err) common.Must(err)
if r := cmp.Diff(address.IP(), net.IP{8, 8, 8, 8}); r != "" { if r := cmp.Diff(address.IP(), net.IP{8, 8, 8, 8}); r != "" {
@@ -45,7 +45,7 @@ func TestIPParsing(t *testing.T) {
func TestDomainParsing(t *testing.T) { func TestDomainParsing(t *testing.T) {
rawJSON := "\"example.com\"" rawJSON := "\"example.com\""
var address conf.Address var address Address
common.Must(json.Unmarshal([]byte(rawJSON), &address)) common.Must(json.Unmarshal([]byte(rawJSON), &address))
if address.Domain() != "example.com" { if address.Domain() != "example.com" {
t.Error("domain: ", address.Domain()) t.Error("domain: ", address.Domain())
@@ -55,7 +55,7 @@ func TestDomainParsing(t *testing.T) {
func TestURLParsing(t *testing.T) { func TestURLParsing(t *testing.T) {
{ {
rawJSON := "\"https://dns.google/dns-query\"" rawJSON := "\"https://dns.google/dns-query\""
var address conf.Address var address Address
common.Must(json.Unmarshal([]byte(rawJSON), &address)) common.Must(json.Unmarshal([]byte(rawJSON), &address))
if address.Domain() != "https://dns.google/dns-query" { if address.Domain() != "https://dns.google/dns-query" {
t.Error("URL: ", address.Domain()) t.Error("URL: ", address.Domain())
@@ -63,7 +63,7 @@ func TestURLParsing(t *testing.T) {
} }
{ {
rawJSON := "\"https+local://dns.google/dns-query\"" rawJSON := "\"https+local://dns.google/dns-query\""
var address conf.Address var address Address
common.Must(json.Unmarshal([]byte(rawJSON), &address)) common.Must(json.Unmarshal([]byte(rawJSON), &address))
if address.Domain() != "https+local://dns.google/dns-query" { if address.Domain() != "https+local://dns.google/dns-query" {
t.Error("URL: ", address.Domain()) t.Error("URL: ", address.Domain())
@@ -73,7 +73,7 @@ func TestURLParsing(t *testing.T) {
func TestInvalidAddressJson(t *testing.T) { func TestInvalidAddressJson(t *testing.T) {
rawJSON := "1234" rawJSON := "1234"
var address conf.Address var address Address
err := json.Unmarshal([]byte(rawJSON), &address) err := json.Unmarshal([]byte(rawJSON), &address)
if err == nil { if err == nil {
t.Error("nil error") t.Error("nil error")
@@ -81,7 +81,7 @@ func TestInvalidAddressJson(t *testing.T) {
} }
func TestStringNetwork(t *testing.T) { func TestStringNetwork(t *testing.T) {
var network conf.Network var network Network
common.Must(json.Unmarshal([]byte(`"tcp"`), &network)) common.Must(json.Unmarshal([]byte(`"tcp"`), &network))
if v := network.Build(); v != net.Network_TCP { if v := network.Build(); v != net.Network_TCP {
t.Error("network: ", v) t.Error("network: ", v)
@@ -89,7 +89,7 @@ func TestStringNetwork(t *testing.T) {
} }
func TestArrayNetworkList(t *testing.T) { func TestArrayNetworkList(t *testing.T) {
var list conf.NetworkList var list NetworkList
common.Must(json.Unmarshal([]byte("[\"Tcp\"]"), &list)) common.Must(json.Unmarshal([]byte("[\"Tcp\"]"), &list))
nlist := list.Build() nlist := list.Build()
@@ -102,7 +102,7 @@ func TestArrayNetworkList(t *testing.T) {
} }
func TestStringNetworkList(t *testing.T) { func TestStringNetworkList(t *testing.T) {
var list conf.NetworkList var list NetworkList
common.Must(json.Unmarshal([]byte("\"TCP, ip\""), &list)) common.Must(json.Unmarshal([]byte("\"TCP, ip\""), &list))
nlist := list.Build() nlist := list.Build()
@@ -115,7 +115,7 @@ func TestStringNetworkList(t *testing.T) {
} }
func TestInvalidNetworkJson(t *testing.T) { func TestInvalidNetworkJson(t *testing.T) {
var list conf.NetworkList var list NetworkList
err := json.Unmarshal([]byte("0"), &list) err := json.Unmarshal([]byte("0"), &list)
if err == nil { if err == nil {
t.Error("nil error") t.Error("nil error")
@@ -123,10 +123,10 @@ func TestInvalidNetworkJson(t *testing.T) {
} }
func TestIntPort(t *testing.T) { func TestIntPort(t *testing.T) {
var portRange conf.PortRange var portRange PortRange
common.Must(json.Unmarshal([]byte("1234"), &portRange)) common.Must(json.Unmarshal([]byte("1234"), &portRange))
if r := cmp.Diff(portRange, conf.PortRange{ if r := cmp.Diff(portRange, PortRange{
From: 1234, To: 1234, From: 1234, To: 1234,
}); r != "" { }); r != "" {
t.Error(r) t.Error(r)
@@ -134,7 +134,7 @@ func TestIntPort(t *testing.T) {
} }
func TestOverRangeIntPort(t *testing.T) { func TestOverRangeIntPort(t *testing.T) {
var portRange conf.PortRange var portRange PortRange
err := json.Unmarshal([]byte("70000"), &portRange) err := json.Unmarshal([]byte("70000"), &portRange)
if err == nil { if err == nil {
t.Error("nil error") t.Error("nil error")
@@ -149,10 +149,10 @@ func TestOverRangeIntPort(t *testing.T) {
func TestEnvPort(t *testing.T) { func TestEnvPort(t *testing.T) {
common.Must(os.Setenv("PORT", "1234")) common.Must(os.Setenv("PORT", "1234"))
var portRange conf.PortRange var portRange PortRange
common.Must(json.Unmarshal([]byte("\"env:PORT\""), &portRange)) common.Must(json.Unmarshal([]byte("\"env:PORT\""), &portRange))
if r := cmp.Diff(portRange, conf.PortRange{ if r := cmp.Diff(portRange, PortRange{
From: 1234, To: 1234, From: 1234, To: 1234,
}); r != "" { }); r != "" {
t.Error(r) t.Error(r)
@@ -160,10 +160,10 @@ func TestEnvPort(t *testing.T) {
} }
func TestSingleStringPort(t *testing.T) { func TestSingleStringPort(t *testing.T) {
var portRange conf.PortRange var portRange PortRange
common.Must(json.Unmarshal([]byte("\"1234\""), &portRange)) common.Must(json.Unmarshal([]byte("\"1234\""), &portRange))
if r := cmp.Diff(portRange, conf.PortRange{ if r := cmp.Diff(portRange, PortRange{
From: 1234, To: 1234, From: 1234, To: 1234,
}); r != "" { }); r != "" {
t.Error(r) t.Error(r)
@@ -171,10 +171,10 @@ func TestSingleStringPort(t *testing.T) {
} }
func TestStringPairPort(t *testing.T) { func TestStringPairPort(t *testing.T) {
var portRange conf.PortRange var portRange PortRange
common.Must(json.Unmarshal([]byte("\"1234-5678\""), &portRange)) common.Must(json.Unmarshal([]byte("\"1234-5678\""), &portRange))
if r := cmp.Diff(portRange, conf.PortRange{ if r := cmp.Diff(portRange, PortRange{
From: 1234, To: 5678, From: 1234, To: 5678,
}); r != "" { }); r != "" {
t.Error(r) t.Error(r)
@@ -182,7 +182,7 @@ func TestStringPairPort(t *testing.T) {
} }
func TestOverRangeStringPort(t *testing.T) { func TestOverRangeStringPort(t *testing.T) {
var portRange conf.PortRange var portRange PortRange
err := json.Unmarshal([]byte("\"65536\""), &portRange) err := json.Unmarshal([]byte("\"65536\""), &portRange)
if err == nil { if err == nil {
t.Error("nil error") t.Error("nil error")
@@ -205,7 +205,7 @@ func TestOverRangeStringPort(t *testing.T) {
} }
func TestUserParsing(t *testing.T) { func TestUserParsing(t *testing.T) {
user := new(conf.User) user := new(User)
common.Must(json.Unmarshal([]byte(`{ common.Must(json.Unmarshal([]byte(`{
"id": "96edb838-6d68-42ef-a933-25f7ac3a9d09", "id": "96edb838-6d68-42ef-a933-25f7ac3a9d09",
"email": "love@example.com", "email": "love@example.com",
@@ -223,7 +223,7 @@ func TestUserParsing(t *testing.T) {
} }
func TestInvalidUserJson(t *testing.T) { func TestInvalidUserJson(t *testing.T) {
user := new(conf.User) user := new(User)
err := json.Unmarshal([]byte(`{"email": 1234}`), user) err := json.Unmarshal([]byte(`{"email": 1234}`), user)
if err == nil { if err == nil {
t.Error("nil error") t.Error("nil error")

View File

@@ -2,25 +2,19 @@ package conf
import ( import (
"encoding/json" "encoding/json"
"sort" "sort"
"strings" "strings"
"github.com/xtls/xray-core/app/dns" "github.com/xtls/xray-core/app/dns"
dm "github.com/xtls/xray-core/common/matcher/domain" "github.com/xtls/xray-core/app/router"
"github.com/xtls/xray-core/common/matcher/domain/conf"
"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/net"
) )
type NameServerConfig struct { type NameServerConfig struct {
Address *Address Address *Address
ClientIP *Address Port uint16
Port uint16 Domains []string
SkipFallback bool ExpectIPs StringList
Domains []string
ExpectIPs StringList
} }
func (c *NameServerConfig) UnmarshalJSON(data []byte) error { func (c *NameServerConfig) UnmarshalJSON(data []byte) error {
@@ -31,18 +25,14 @@ func (c *NameServerConfig) UnmarshalJSON(data []byte) error {
} }
var advanced struct { var advanced struct {
Address *Address `json:"address"` Address *Address `json:"address"`
ClientIP *Address `json:"clientIp"` Port uint16 `json:"port"`
Port uint16 `json:"port"` Domains []string `json:"domains"`
SkipFallback bool `json:"skipFallback"` ExpectIPs StringList `json:"expectIps"`
Domains []string `json:"domains"`
ExpectIPs StringList `json:"expectIps"`
} }
if err := json.Unmarshal(data, &advanced); err == nil { if err := json.Unmarshal(data, &advanced); err == nil {
c.Address = advanced.Address c.Address = advanced.Address
c.ClientIP = advanced.ClientIP
c.Port = advanced.Port c.Port = advanced.Port
c.SkipFallback = advanced.SkipFallback
c.Domains = advanced.Domains c.Domains = advanced.Domains
c.ExpectIPs = advanced.ExpectIPs c.ExpectIPs = advanced.ExpectIPs
return nil return nil
@@ -51,24 +41,39 @@ func (c *NameServerConfig) UnmarshalJSON(data []byte) error {
return newError("failed to parse name server: ", string(data)) return newError("failed to parse name server: ", string(data))
} }
func toDomainMatchingType(t router.Domain_Type) dns.DomainMatchingType {
switch t {
case router.Domain_Domain:
return dns.DomainMatchingType_Subdomain
case router.Domain_Full:
return dns.DomainMatchingType_Full
case router.Domain_Plain:
return dns.DomainMatchingType_Keyword
case router.Domain_Regex:
return dns.DomainMatchingType_Regex
default:
panic("unknown domain type")
}
}
func (c *NameServerConfig) Build() (*dns.NameServer, error) { func (c *NameServerConfig) Build() (*dns.NameServer, error) {
if c.Address == nil { if c.Address == nil {
return nil, newError("NameServer address is not specified.") return nil, newError("NameServer address is not specified.")
} }
var domains []*dm.Domain var domains []*dns.NameServer_PriorityDomain
var originalRules []*dns.NameServer_OriginalRule var originalRules []*dns.NameServer_OriginalRule
for _, rule := range c.Domains { for _, rule := range c.Domains {
parsedDomain, err := conf.ParseDomainRule(rule) parsedDomain, err := parseDomainRule(rule)
if err != nil { if err != nil {
return nil, newError("invalid domain rule: ", rule).Base(err) return nil, newError("invalid domain rule: ", rule).Base(err)
} }
for _, pd := range parsedDomain { for _, pd := range parsedDomain {
domains = append(domains, &dm.Domain{ domains = append(domains, &dns.NameServer_PriorityDomain{
Type: pd.Type, Type: toDomainMatchingType(pd.Type),
Value: pd.Value, Domain: pd.Value,
}) })
} }
originalRules = append(originalRules, &dns.NameServer_OriginalRule{ originalRules = append(originalRules, &dns.NameServer_OriginalRule{
@@ -77,100 +82,54 @@ func (c *NameServerConfig) Build() (*dns.NameServer, error) {
}) })
} }
geoipList, err := geoip.ParseIPList(c.ExpectIPs) geoipList, err := toCidrList(c.ExpectIPs)
if err != nil { if err != nil {
return nil, newError("invalid IP rule: ", c.ExpectIPs).Base(err) return nil, newError("invalid IP rule: ", c.ExpectIPs).Base(err)
} }
var myClientIP []byte
if c.ClientIP != nil {
if !c.ClientIP.Family().IsIP() {
return nil, newError("not an IP address:", c.ClientIP.String())
}
myClientIP = []byte(c.ClientIP.IP())
}
return &dns.NameServer{ return &dns.NameServer{
Address: &net.Endpoint{ Address: &net.Endpoint{
Network: net.Network_UDP, Network: net.Network_UDP,
Address: c.Address.Build(), Address: c.Address.Build(),
Port: uint32(c.Port), Port: uint32(c.Port),
}, },
ClientIp: myClientIP,
SkipFallback: c.SkipFallback,
PrioritizedDomain: domains, PrioritizedDomain: domains,
Geoip: geoipList, Geoip: geoipList,
OriginalRules: originalRules, OriginalRules: originalRules,
}, nil }, nil
} }
var typeMap = map[router.Domain_Type]dns.DomainMatchingType{
router.Domain_Full: dns.DomainMatchingType_Full,
router.Domain_Domain: dns.DomainMatchingType_Subdomain,
router.Domain_Plain: dns.DomainMatchingType_Keyword,
router.Domain_Regex: dns.DomainMatchingType_Regex,
}
// DNSConfig is a JSON serializable object for dns.Config. // DNSConfig is a JSON serializable object for dns.Config.
type DNSConfig struct { type DNSConfig struct {
Servers []*NameServerConfig `json:"servers"` Servers []*NameServerConfig `json:"servers"`
Hosts map[string]*HostAddress `json:"hosts"` Hosts map[string]*Address `json:"hosts"`
ClientIP *Address `json:"clientIp"` ClientIP *Address `json:"clientIp"`
Tag string `json:"tag"` Tag string `json:"tag"`
QueryStrategy string `json:"queryStrategy"`
CacheStrategy string `json:"cacheStrategy"`
DisableCache bool `json:"disableCache"`
DisableFallback bool `json:"disableFallback"`
} }
type HostAddress struct { func getHostMapping(addr *Address) *dns.Config_HostMapping {
addr *Address if addr.Family().IsIP() {
addrs []*Address
}
// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON
func (h *HostAddress) UnmarshalJSON(data []byte) error {
addr := new(Address)
var addrs []*Address
switch {
case json.Unmarshal(data, &addr) == nil:
h.addr = addr
case json.Unmarshal(data, &addrs) == nil:
h.addrs = addrs
default:
return newError("invalid address")
}
return nil
}
func getHostMapping(ha *HostAddress) *dns.Config_HostMapping {
if ha.addr != nil {
if ha.addr.Family().IsDomain() {
return &dns.Config_HostMapping{
ProxiedDomain: ha.addr.Domain(),
}
}
return &dns.Config_HostMapping{ return &dns.Config_HostMapping{
Ip: [][]byte{ha.addr.IP()}, Ip: [][]byte{[]byte(addr.IP())},
} }
} } else {
return &dns.Config_HostMapping{
ips := make([][]byte, 0, len(ha.addrs)) ProxiedDomain: addr.Domain(),
for _, addr := range ha.addrs {
if addr.Family().IsDomain() {
return &dns.Config_HostMapping{
ProxiedDomain: addr.Domain(),
}
} }
ips = append(ips, []byte(addr.IP()))
}
return &dns.Config_HostMapping{
Ip: ips,
} }
} }
// Build implements Buildable // Build implements Buildable
func (c *DNSConfig) Build() (*dns.Config, error) { func (c *DNSConfig) Build() (*dns.Config, error) {
config := &dns.Config{ config := &dns.Config{
Tag: c.Tag, Tag: c.Tag,
CacheStrategy: dns.CacheStrategy_Cache_ALL,
DisableFallback: c.DisableFallback,
}
if c.DisableCache {
config.CacheStrategy = dns.CacheStrategy_Cache_DISABLE
} }
if c.ClientIP != nil { if c.ClientIP != nil {
@@ -180,25 +139,6 @@ func (c *DNSConfig) Build() (*dns.Config, error) {
config.ClientIp = []byte(c.ClientIP.IP()) config.ClientIp = []byte(c.ClientIP.IP())
} }
config.QueryStrategy = dns.QueryStrategy_USE_IP
switch strings.ToLower(c.QueryStrategy) {
case "useip", "use_ip", "use-ip":
config.QueryStrategy = dns.QueryStrategy_USE_IP
case "useip4", "useipv4", "use_ip4", "use_ipv4", "use_ip_v4", "use-ip4", "use-ipv4", "use-ip-v4":
config.QueryStrategy = dns.QueryStrategy_USE_IP4
case "useip6", "useipv6", "use_ip6", "use_ipv6", "use_ip_v6", "use-ip6", "use-ipv6", "use-ip-v6":
config.QueryStrategy = dns.QueryStrategy_USE_IP6
}
switch strings.ToLower(c.CacheStrategy) {
case "noerror":
config.CacheStrategy = dns.CacheStrategy_Cache_NOERROR
case "all":
config.CacheStrategy = dns.CacheStrategy_Cache_ALL
case "disable", "none":
config.CacheStrategy = dns.CacheStrategy_Cache_DISABLE
}
for _, server := range c.Servers { for _, server := range c.Servers {
ns, err := server.Build() ns, err := server.Build()
if err != nil { if err != nil {
@@ -224,7 +164,7 @@ func (c *DNSConfig) Build() (*dns.Config, error) {
return nil, newError("empty domain type of rule: ", domain) return nil, newError("empty domain type of rule: ", domain)
} }
mapping := getHostMapping(addr) mapping := getHostMapping(addr)
mapping.Type = dm.MatchingType_Subdomain mapping.Type = dns.DomainMatchingType_Subdomain
mapping.Domain = domainName mapping.Domain = domainName
mappings = append(mappings, mapping) mappings = append(mappings, mapping)
@@ -233,13 +173,13 @@ func (c *DNSConfig) Build() (*dns.Config, error) {
if len(listName) == 0 { if len(listName) == 0 {
return nil, newError("empty geosite rule: ", domain) return nil, newError("empty geosite rule: ", domain)
} }
domains, err := geosite.LoadGeositeWithAttr("geosite.dat", listName) domains, err := loadGeositeWithAttr("geosite.dat", listName)
if err != nil { if err != nil {
return nil, newError("failed to load geosite: ", listName).Base(err) return nil, newError("failed to load geosite: ", listName).Base(err)
} }
for _, d := range domains { for _, d := range domains {
mapping := getHostMapping(addr) mapping := getHostMapping(addr)
mapping.Type = d.Type mapping.Type = typeMap[d.Type]
mapping.Domain = d.Value mapping.Domain = d.Value
mappings = append(mappings, mapping) mappings = append(mappings, mapping)
} }
@@ -250,7 +190,7 @@ func (c *DNSConfig) Build() (*dns.Config, error) {
return nil, newError("empty regexp type of rule: ", domain) return nil, newError("empty regexp type of rule: ", domain)
} }
mapping := getHostMapping(addr) mapping := getHostMapping(addr)
mapping.Type = dm.MatchingType_Regex mapping.Type = dns.DomainMatchingType_Regex
mapping.Domain = regexpVal mapping.Domain = regexpVal
mappings = append(mappings, mapping) mappings = append(mappings, mapping)
@@ -260,7 +200,7 @@ func (c *DNSConfig) Build() (*dns.Config, error) {
return nil, newError("empty keyword type of rule: ", domain) return nil, newError("empty keyword type of rule: ", domain)
} }
mapping := getHostMapping(addr) mapping := getHostMapping(addr)
mapping.Type = dm.MatchingType_Keyword mapping.Type = dns.DomainMatchingType_Keyword
mapping.Domain = keywordVal mapping.Domain = keywordVal
mappings = append(mappings, mapping) mappings = append(mappings, mapping)
@@ -270,13 +210,13 @@ func (c *DNSConfig) Build() (*dns.Config, error) {
return nil, newError("empty full domain type of rule: ", domain) return nil, newError("empty full domain type of rule: ", domain)
} }
mapping := getHostMapping(addr) mapping := getHostMapping(addr)
mapping.Type = dm.MatchingType_Full mapping.Type = dns.DomainMatchingType_Full
mapping.Domain = fullVal mapping.Domain = fullVal
mappings = append(mappings, mapping) mappings = append(mappings, mapping)
case strings.HasPrefix(domain, "dotless:"): case strings.HasPrefix(domain, "dotless:"):
mapping := getHostMapping(addr) mapping := getHostMapping(addr)
mapping.Type = dm.MatchingType_Regex mapping.Type = dns.DomainMatchingType_Regex
switch substr := domain[8:]; { switch substr := domain[8:]; {
case substr == "": case substr == "":
mapping.Domain = "^[^.]*$" mapping.Domain = "^[^.]*$"
@@ -294,20 +234,20 @@ func (c *DNSConfig) Build() (*dns.Config, error) {
} }
filename := kv[0] filename := kv[0]
list := kv[1] list := kv[1]
domains, err := geosite.LoadGeositeWithAttr(filename, list) domains, err := loadGeositeWithAttr(filename, list)
if err != nil { if err != nil {
return nil, newError("failed to load domain list: ", list, " from ", filename).Base(err) return nil, newError("failed to load domain list: ", list, " from ", filename).Base(err)
} }
for _, d := range domains { for _, d := range domains {
mapping := getHostMapping(addr) mapping := getHostMapping(addr)
mapping.Type = d.Type mapping.Type = typeMap[d.Type]
mapping.Domain = d.Value mapping.Domain = d.Value
mappings = append(mappings, mapping) mappings = append(mappings, mapping)
} }
default: default:
mapping := getHostMapping(addr) mapping := getHostMapping(addr)
mapping.Type = dm.MatchingType_Full mapping.Type = dns.DomainMatchingType_Full
mapping.Domain = domain mapping.Domain = domain
mappings = append(mappings, mapping) mappings = append(mappings, mapping)
} }

View File

@@ -8,9 +8,8 @@ import (
"github.com/golang/protobuf/proto" "github.com/golang/protobuf/proto"
"github.com/xtls/xray-core/app/dns" "github.com/xtls/xray-core/app/dns"
"github.com/xtls/xray-core/app/router"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/matcher/domain"
"github.com/xtls/xray-core/common/matcher/geosite"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/platform" "github.com/xtls/xray-core/common/platform"
"github.com/xtls/xray-core/common/platform/filesystem" "github.com/xtls/xray-core/common/platform/filesystem"
@@ -31,12 +30,12 @@ func init() {
common.Must(err) common.Must(err)
defer geositeFile.Close() defer geositeFile.Close()
list := &geosite.GeoSiteList{ list := &router.GeoSiteList{
Entry: []*geosite.GeoSite{ Entry: []*router.GeoSite{
{ {
CountryCode: "TEST", CountryCode: "TEST",
Domain: []*geosite.Domain{ Domain: []*router.Domain{
{Type: geosite.Domain_Full, Value: "example.com"}, {Type: router.Domain_Full, Value: "example.com"},
}, },
}, },
}, },
@@ -68,23 +67,17 @@ func TestDNSConfigParsing(t *testing.T) {
Input: `{ Input: `{
"servers": [{ "servers": [{
"address": "8.8.8.8", "address": "8.8.8.8",
"clientIp": "10.0.0.1",
"port": 5353, "port": 5353,
"skipFallback": true,
"domains": ["domain:example.com"] "domains": ["domain:example.com"]
}], }],
"hosts": { "hosts": {
"example.com": "127.0.0.1", "example.com": "127.0.0.1",
"xtls.github.io": ["1.2.3.4", "5.6.7.8"],
"domain:example.com": "google.com", "domain:example.com": "google.com",
"geosite:test": ["127.0.0.1", "127.0.0.2"], "geosite:test": "10.0.0.1",
"keyword:google": ["8.8.8.8", "8.8.4.4"], "keyword:google": "8.8.8.8",
"regexp:.*\\.com": "8.8.4.4" "regexp:.*\\.com": "8.8.4.4"
}, },
"clientIp": "10.0.0.1", "clientIp": "10.0.0.1"
"queryStrategy": "UseIPv4",
"cacheStrategy": "disable",
"disableFallback": true
}`, }`,
Parser: parserCreator(), Parser: parserCreator(),
Output: &dns.Config{ Output: &dns.Config{
@@ -99,12 +92,10 @@ func TestDNSConfigParsing(t *testing.T) {
Network: net.Network_UDP, Network: net.Network_UDP,
Port: 5353, Port: 5353,
}, },
ClientIp: []byte{10, 0, 0, 1}, PrioritizedDomain: []*dns.NameServer_PriorityDomain{
SkipFallback: true,
PrioritizedDomain: []*domain.Domain{
{ {
Type: domain.MatchingType_Subdomain, Type: dns.DomainMatchingType_Subdomain,
Value: "example.com", Domain: "example.com",
}, },
}, },
OriginalRules: []*dns.NameServer_OriginalRule{ OriginalRules: []*dns.NameServer_OriginalRule{
@@ -117,40 +108,32 @@ func TestDNSConfigParsing(t *testing.T) {
}, },
StaticHosts: []*dns.Config_HostMapping{ StaticHosts: []*dns.Config_HostMapping{
{ {
Type: domain.MatchingType_Subdomain, Type: dns.DomainMatchingType_Subdomain,
Domain: "example.com", Domain: "example.com",
ProxiedDomain: "google.com", ProxiedDomain: "google.com",
}, },
{ {
Type: domain.MatchingType_Full, Type: dns.DomainMatchingType_Full,
Domain: "example.com", Domain: "example.com",
Ip: [][]byte{{127, 0, 0, 1}}, Ip: [][]byte{{127, 0, 0, 1}},
}, },
{ {
Type: domain.MatchingType_Full, Type: dns.DomainMatchingType_Full,
Domain: "example.com", Domain: "example.com",
Ip: [][]byte{{127, 0, 0, 1}, {127, 0, 0, 2}}, Ip: [][]byte{{10, 0, 0, 1}},
}, },
{ {
Type: domain.MatchingType_Keyword, Type: dns.DomainMatchingType_Keyword,
Domain: "google", Domain: "google",
Ip: [][]byte{{8, 8, 8, 8}, {8, 8, 4, 4}}, Ip: [][]byte{{8, 8, 8, 8}},
}, },
{ {
Type: domain.MatchingType_Regex, Type: dns.DomainMatchingType_Regex,
Domain: ".*\\.com", Domain: ".*\\.com",
Ip: [][]byte{{8, 8, 4, 4}}, Ip: [][]byte{{8, 8, 4, 4}},
}, },
{
Type: domain.MatchingType_Full,
Domain: "xtls.github.io",
Ip: [][]byte{{1, 2, 3, 4}, {5, 6, 7, 8}},
},
}, },
ClientIp: []byte{10, 0, 0, 1}, ClientIp: []byte{10, 0, 0, 1},
QueryStrategy: dns.QueryStrategy_USE_IP4,
CacheStrategy: dns.CacheStrategy_Cache_DISABLE,
DisableFallback: true,
}, },
}, },
}) })

View File

@@ -22,11 +22,11 @@ func (c *FreedomConfig) Build() (proto.Message, error) {
config := new(freedom.Config) config := new(freedom.Config)
config.DomainStrategy = freedom.Config_AS_IS config.DomainStrategy = freedom.Config_AS_IS
switch strings.ToLower(c.DomainStrategy) { switch strings.ToLower(c.DomainStrategy) {
case "useip", "use_ip", "use-ip": case "useip", "use_ip":
config.DomainStrategy = freedom.Config_USE_IP config.DomainStrategy = freedom.Config_USE_IP
case "useip4", "useipv4", "use_ip4", "use_ipv4", "use_ip_v4", "use-ip4", "use-ipv4", "use-ip-v4": case "useip4", "useipv4", "use_ipv4", "use_ip_v4", "use_ip4":
config.DomainStrategy = freedom.Config_USE_IP4 config.DomainStrategy = freedom.Config_USE_IP4
case "useip6", "useipv6", "use_ip6", "use_ipv6", "use_ip_v6", "use-ip6", "use-ipv6", "use-ip-v6": case "useip6", "useipv6", "use_ipv6", "use_ip_v6", "use_ip6":
config.DomainStrategy = freedom.Config_USE_IP6 config.DomainStrategy = freedom.Config_USE_IP6
} }

View File

@@ -7,10 +7,25 @@ import (
) )
type GRPCConfig struct { type GRPCConfig struct {
ServiceName string `json:"serviceName"` ServiceName string `json:"serviceName" `
MultiMode bool `json:"multiMode"` MultiMode bool `json:"multiMode"`
IdleTimeout int32 `json:"idle_timeout"`
HealthCheckTimeout int32 `json:"health_check_timeout"`
PermitWithoutStream bool `json:"permit_without_stream"`
} }
func (g GRPCConfig) Build() (proto.Message, error) { func (g *GRPCConfig) Build() (proto.Message, error) {
return &grpc.Config{ServiceName: g.ServiceName, MultiMode: g.MultiMode}, nil if g.IdleTimeout <= 0 {
g.IdleTimeout = 0
}
if g.HealthCheckTimeout <= 0 {
g.HealthCheckTimeout = 0
}
return &grpc.Config{
ServiceName: g.ServiceName,
MultiMode: g.MultiMode,
IdleTimeout: g.IdleTimeout,
HealthCheckTimeout: g.HealthCheckTimeout,
PermitWithoutStream: g.PermitWithoutStream,
}, nil
} }

View File

@@ -2,14 +2,15 @@ package conf
import ( import (
"encoding/json" "encoding/json"
"runtime"
"strconv" "strconv"
"strings" "strings"
"github.com/golang/protobuf/proto"
"github.com/xtls/xray-core/app/router" "github.com/xtls/xray-core/app/router"
"github.com/xtls/xray-core/common/matcher/domain/conf"
"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/net"
"github.com/xtls/xray-core/common/platform/filesystem"
) )
type RouterRulesConfig struct { type RouterRulesConfig struct {
@@ -52,11 +53,11 @@ func (c *RouterConfig) getDomainStrategy() router.Config_DomainStrategy {
} }
switch strings.ToLower(ds) { switch strings.ToLower(ds) {
case "alwaysip", "always_ip", "always-ip": case "alwaysip":
return router.Config_UseIp return router.Config_UseIp
case "ipifnonmatch", "ip_if_non_match", "ip-if-non-match": case "ipifnonmatch":
return router.Config_IpIfNonMatch return router.Config_IpIfNonMatch
case "ipondemand", "ip_on_demand", "ip-on-demand": case "ipondemand":
return router.Config_IpOnDemand return router.Config_IpOnDemand
default: default:
return router.Config_AsIs return router.Config_AsIs
@@ -94,13 +95,14 @@ func (c *RouterConfig) Build() (*router.Config, error) {
} }
type RouterRule struct { type RouterRule struct {
Type string `json:"type"` Type string `json:"type"`
OutboundTag string `json:"outboundTag"` OutboundTag string `json:"outboundTag"`
BalancerTag string `json:"balancerTag"` BalancerTag string `json:"balancerTag"`
DomainMatcher string `json:"domainMatcher"` DomainMatcher string `json:"domainMatcher"`
} }
func ParseIP(s string) (*geoip.CIDR, error) { func ParseIP(s string) (*router.CIDR, error) {
var addr, mask string var addr, mask string
i := strings.Index(s, "/") i := strings.Index(s, "/")
if i < 0 { if i < 0 {
@@ -123,7 +125,7 @@ func ParseIP(s string) (*geoip.CIDR, error) {
if bits > 32 { if bits > 32 {
return nil, newError("invalid network mask for router: ", bits) return nil, newError("invalid network mask for router: ", bits)
} }
return &geoip.CIDR{ return &router.CIDR{
Ip: []byte(ip.IP()), Ip: []byte(ip.IP()),
Prefix: bits, Prefix: bits,
}, nil }, nil
@@ -139,8 +141,8 @@ func ParseIP(s string) (*geoip.CIDR, error) {
if bits > 128 { if bits > 128 {
return nil, newError("invalid network mask for router: ", bits) return nil, newError("invalid network mask for router: ", bits)
} }
return &geoip.CIDR{ return &router.CIDR{
Ip: ip.IP(), Ip: []byte(ip.IP()),
Prefix: bits, Prefix: bits,
}, nil }, nil
default: default:
@@ -148,6 +150,314 @@ func ParseIP(s string) (*geoip.CIDR, error) {
} }
} }
func loadGeoIP(code string) ([]*router.CIDR, error) {
return loadIP("geoip.dat", code)
}
var (
FileCache = make(map[string][]byte)
IPCache = make(map[string]*router.GeoIP)
SiteCache = make(map[string]*router.GeoSite)
)
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 loadIP(file, code string) ([]*router.CIDR, error) {
index := file + ":" + code
if IPCache[index] == nil {
bs, err := loadFile(file)
if err != nil {
return nil, newError("failed to load file: ", file).Base(err)
}
bs = find(bs, []byte(code))
if bs == nil {
return nil, newError("code not found in ", file, ": ", code)
}
var geoip router.GeoIP
if err := proto.Unmarshal(bs, &geoip); err != nil {
return nil, newError("error unmarshal IP in ", file, ": ", code).Base(err)
}
defer runtime.GC() // or debug.FreeOSMemory()
return geoip.Cidr, nil // do not cache geoip
IPCache[index] = &geoip
}
return IPCache[index].Cidr, nil
}
func loadSite(file, code string) ([]*router.Domain, error) {
index := file + ":" + code
if SiteCache[index] == nil {
bs, err := loadFile(file)
if err != nil {
return nil, newError("failed to load file: ", file).Base(err)
}
bs = find(bs, []byte(code))
if bs == nil {
return nil, newError("list not found in ", file, ": ", code)
}
var geosite router.GeoSite
if err := proto.Unmarshal(bs, &geosite); err != nil {
return nil, newError("error unmarshal Site in ", file, ": ", code).Base(err)
}
defer runtime.GC() // or debug.FreeOSMemory()
return geosite.Domain, nil // do not cache geosite
SiteCache[index] = &geosite
}
return SiteCache[index].Domain, nil
}
func find(data, code []byte) []byte {
codeL := len(code)
if codeL == 0 {
return nil
}
for {
dataL := len(data)
if dataL < 2 {
return nil
}
x, y := proto.DecodeVarint(data[1:])
if x == 0 && y == 0 {
return nil
}
headL, bodyL := 1+y, int(x)
dataL -= headL
if dataL < bodyL {
return nil
}
data = data[headL:]
if int(data[1]) == codeL {
for i := 0; i < codeL && data[2+i] == code[i]; i++ {
if i+1 == codeL {
return data[:bodyL]
}
}
}
if dataL == bodyL {
return nil
}
data = data[bodyL:]
}
}
type AttributeMatcher interface {
Match(*router.Domain) bool
}
type BooleanMatcher string
func (m BooleanMatcher) Match(domain *router.Domain) bool {
for _, attr := range domain.Attribute {
if attr.Key == string(m) {
return true
}
}
return false
}
type AttributeList struct {
matcher []AttributeMatcher
}
func (al *AttributeList) Match(domain *router.Domain) bool {
for _, matcher := range al.matcher {
if !matcher.Match(domain) {
return false
}
}
return true
}
func (al *AttributeList) IsEmpty() bool {
return len(al.matcher) == 0
}
func parseAttrs(attrs []string) *AttributeList {
al := new(AttributeList)
for _, attr := range attrs {
lc := strings.ToLower(attr)
al.matcher = append(al.matcher, BooleanMatcher(lc))
}
return al
}
func loadGeositeWithAttr(file string, siteWithAttr string) ([]*router.Domain, error) {
parts := strings.Split(siteWithAttr, "@")
if len(parts) == 0 {
return nil, newError("empty site")
}
country := strings.ToUpper(parts[0])
attrs := parseAttrs(parts[1:])
domains, err := loadSite(file, country)
if err != nil {
return nil, err
}
if attrs.IsEmpty() {
return domains, nil
}
filteredDomains := make([]*router.Domain, 0, len(domains))
for _, domain := range domains {
if attrs.Match(domain) {
filteredDomains = append(filteredDomains, domain)
}
}
return filteredDomains, nil
}
func parseDomainRule(domain string) ([]*router.Domain, error) {
if strings.HasPrefix(domain, "geosite:") {
country := strings.ToUpper(domain[8:])
domains, err := loadGeositeWithAttr("geosite.dat", country)
if err != nil {
return nil, newError("failed to load geosite: ", country).Base(err)
}
return domains, nil
}
var isExtDatFile = 0
{
const prefix = "ext:"
if strings.HasPrefix(domain, prefix) {
isExtDatFile = len(prefix)
}
const prefixQualified = "ext-domain:"
if strings.HasPrefix(domain, prefixQualified) {
isExtDatFile = len(prefixQualified)
}
}
if isExtDatFile != 0 {
kv := strings.Split(domain[isExtDatFile:], ":")
if len(kv) != 2 {
return nil, newError("invalid external resource: ", domain)
}
filename := kv[0]
country := kv[1]
domains, err := loadGeositeWithAttr(filename, country)
if err != nil {
return nil, newError("failed to load external sites: ", country, " from ", filename).Base(err)
}
return domains, nil
}
domainRule := new(router.Domain)
switch {
case strings.HasPrefix(domain, "regexp:"):
domainRule.Type = router.Domain_Regex
domainRule.Value = domain[7:]
case strings.HasPrefix(domain, "domain:"):
domainRule.Type = router.Domain_Domain
domainRule.Value = domain[7:]
case strings.HasPrefix(domain, "full:"):
domainRule.Type = router.Domain_Full
domainRule.Value = domain[5:]
case strings.HasPrefix(domain, "keyword:"):
domainRule.Type = router.Domain_Plain
domainRule.Value = domain[8:]
case strings.HasPrefix(domain, "dotless:"):
domainRule.Type = router.Domain_Regex
switch substr := domain[8:]; {
case substr == "":
domainRule.Value = "^[^.]*$"
case !strings.Contains(substr, "."):
domainRule.Value = "^[^.]*" + substr + "[^.]*$"
default:
return nil, newError("substr in dotless rule should not contain a dot: ", substr)
}
default:
domainRule.Type = router.Domain_Plain
domainRule.Value = domain
}
return []*router.Domain{domainRule}, nil
}
func toCidrList(ips StringList) ([]*router.GeoIP, error) {
var geoipList []*router.GeoIP
var customCidrs []*router.CIDR
for _, ip := range ips {
if strings.HasPrefix(ip, "geoip:") {
country := ip[6:]
geoip, err := loadGeoIP(strings.ToUpper(country))
if err != nil {
return nil, newError("failed to load GeoIP: ", country).Base(err)
}
geoipList = append(geoipList, &router.GeoIP{
CountryCode: strings.ToUpper(country),
Cidr: geoip,
})
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]
geoip, err := loadIP(filename, strings.ToUpper(country))
if err != nil {
return nil, newError("failed to load IPs: ", country, " from ", filename).Base(err)
}
geoipList = append(geoipList, &router.GeoIP{
CountryCode: strings.ToUpper(filename + "_" + country),
Cidr: geoip,
})
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, &router.GeoIP{
Cidr: customCidrs,
})
}
return geoipList, nil
}
func parseFieldRule(msg json.RawMessage) (*router.RoutingRule, error) { func parseFieldRule(msg json.RawMessage) (*router.RoutingRule, error) {
type RawFieldRule struct { type RawFieldRule struct {
RouterRule RouterRule
@@ -189,7 +499,7 @@ func parseFieldRule(msg json.RawMessage) (*router.RoutingRule, error) {
if rawFieldRule.Domain != nil { if rawFieldRule.Domain != nil {
for _, domain := range *rawFieldRule.Domain { for _, domain := range *rawFieldRule.Domain {
rules, err := conf.ParseDomainRule(domain) rules, err := parseDomainRule(domain)
if err != nil { if err != nil {
return nil, newError("failed to parse domain rule: ", domain).Base(err) return nil, newError("failed to parse domain rule: ", domain).Base(err)
} }
@@ -199,7 +509,7 @@ func parseFieldRule(msg json.RawMessage) (*router.RoutingRule, error) {
if rawFieldRule.Domains != nil { if rawFieldRule.Domains != nil {
for _, domain := range *rawFieldRule.Domains { for _, domain := range *rawFieldRule.Domains {
rules, err := conf.ParseDomainRule(domain) rules, err := parseDomainRule(domain)
if err != nil { if err != nil {
return nil, newError("failed to parse domain rule: ", domain).Base(err) return nil, newError("failed to parse domain rule: ", domain).Base(err)
} }
@@ -208,7 +518,7 @@ func parseFieldRule(msg json.RawMessage) (*router.RoutingRule, error) {
} }
if rawFieldRule.IP != nil { if rawFieldRule.IP != nil {
geoipList, err := geoip.ParseIPList(*rawFieldRule.IP) geoipList, err := toCidrList(*rawFieldRule.IP)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -224,7 +534,7 @@ func parseFieldRule(msg json.RawMessage) (*router.RoutingRule, error) {
} }
if rawFieldRule.SourceIP != nil { if rawFieldRule.SourceIP != nil {
geoipList, err := geoip.ParseIPList(*rawFieldRule.SourceIP) geoipList, err := toCidrList(*rawFieldRule.SourceIP)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -266,21 +576,21 @@ func ParseRule(msg json.RawMessage) (*router.RoutingRule, error) {
if err != nil { if err != nil {
return nil, newError("invalid router rule").Base(err) return nil, newError("invalid router rule").Base(err)
} }
if strings.EqualFold(rawRule.Type, "field") { if rawRule.Type == "field" {
fieldrule, err := parseFieldRule(msg) fieldrule, err := parseFieldRule(msg)
if err != nil { if err != nil {
return nil, newError("invalid field rule").Base(err) return nil, newError("invalid field rule").Base(err)
} }
return fieldrule, nil return fieldrule, nil
} }
if strings.EqualFold(rawRule.Type, "chinaip") { if rawRule.Type == "chinaip" {
chinaiprule, err := parseChinaIPRule(msg) chinaiprule, err := parseChinaIPRule(msg)
if err != nil { if err != nil {
return nil, newError("invalid chinaip rule").Base(err) return nil, newError("invalid chinaip rule").Base(err)
} }
return chinaiprule, nil return chinaiprule, nil
} }
if strings.EqualFold(rawRule.Type, "chinasites") { if rawRule.Type == "chinasites" {
chinasitesrule, err := parseChinaSitesRule(msg) chinasitesrule, err := parseChinaSitesRule(msg)
if err != nil { if err != nil {
return nil, newError("invalid chinasites rule").Base(err) return nil, newError("invalid chinasites rule").Base(err)
@@ -296,7 +606,7 @@ func parseChinaIPRule(data []byte) (*router.RoutingRule, error) {
if err != nil { if err != nil {
return nil, newError("invalid router rule").Base(err) return nil, newError("invalid router rule").Base(err)
} }
chinaIPs, err := geoip.LoadGeoIP("CN") chinaIPs, err := loadGeoIP("CN")
if err != nil { if err != nil {
return nil, newError("failed to load geoip:cn").Base(err) return nil, newError("failed to load geoip:cn").Base(err)
} }
@@ -314,7 +624,7 @@ func parseChinaSitesRule(data []byte) (*router.RoutingRule, error) {
if err != nil { if err != nil {
return nil, newError("invalid router rule").Base(err).AtError() return nil, newError("invalid router rule").Base(err).AtError()
} }
domains, err := geosite.LoadGeositeWithAttr("geosite.dat", "CN") domains, err := loadGeositeWithAttr("geosite.dat", "CN")
if err != nil { if err != nil {
return nil, newError("failed to load geosite:cn.").Base(err) return nil, newError("failed to load geosite:cn.").Base(err)
} }

View File

@@ -7,8 +7,6 @@ import (
"github.com/golang/protobuf/proto" "github.com/golang/protobuf/proto"
"github.com/xtls/xray-core/app/router" "github.com/xtls/xray-core/app/router"
"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/common/net"
. "github.com/xtls/xray-core/infra/conf" . "github.com/xtls/xray-core/infra/conf"
) )
@@ -75,13 +73,13 @@ func TestRouterConfig(t *testing.T) {
}, },
Rule: []*router.RoutingRule{ Rule: []*router.RoutingRule{
{ {
Domain: []*domain.Domain{ Domain: []*router.Domain{
{ {
Type: domain.MatchingType_Keyword, Type: router.Domain_Plain,
Value: "baidu.com", Value: "baidu.com",
}, },
{ {
Type: domain.MatchingType_Keyword, Type: router.Domain_Plain,
Value: "qq.com", Value: "qq.com",
}, },
}, },
@@ -90,9 +88,9 @@ func TestRouterConfig(t *testing.T) {
}, },
}, },
{ {
Geoip: []*geoip.GeoIP{ Geoip: []*router.GeoIP{
{ {
Cidr: []*geoip.CIDR{ Cidr: []*router.CIDR{
{ {
Ip: []byte{10, 0, 0, 0}, Ip: []byte{10, 0, 0, 0},
Prefix: 8, Prefix: 8,
@@ -163,13 +161,13 @@ func TestRouterConfig(t *testing.T) {
DomainStrategy: router.Config_IpIfNonMatch, DomainStrategy: router.Config_IpIfNonMatch,
Rule: []*router.RoutingRule{ Rule: []*router.RoutingRule{
{ {
Domain: []*domain.Domain{ Domain: []*router.Domain{
{ {
Type: domain.MatchingType_Keyword, Type: router.Domain_Plain,
Value: "baidu.com", Value: "baidu.com",
}, },
{ {
Type: domain.MatchingType_Keyword, Type: router.Domain_Plain,
Value: "qq.com", Value: "qq.com",
}, },
}, },
@@ -178,9 +176,9 @@ func TestRouterConfig(t *testing.T) {
}, },
}, },
{ {
Geoip: []*geoip.GeoIP{ Geoip: []*router.GeoIP{
{ {
Cidr: []*geoip.CIDR{ Cidr: []*router.CIDR{
{ {
Ip: []byte{10, 0, 0, 0}, Ip: []byte{10, 0, 0, 0},
Prefix: 8, Prefix: 8,
@@ -226,13 +224,13 @@ func TestRouterConfig(t *testing.T) {
DomainStrategy: router.Config_AsIs, DomainStrategy: router.Config_AsIs,
Rule: []*router.RoutingRule{ Rule: []*router.RoutingRule{
{ {
Domain: []*domain.Domain{ Domain: []*router.Domain{
{ {
Type: domain.MatchingType_Keyword, Type: router.Domain_Plain,
Value: "baidu.com", Value: "baidu.com",
}, },
{ {
Type: domain.MatchingType_Keyword, Type: router.Domain_Plain,
Value: "qq.com", Value: "qq.com",
}, },
}, },
@@ -241,9 +239,9 @@ func TestRouterConfig(t *testing.T) {
}, },
}, },
{ {
Geoip: []*geoip.GeoIP{ Geoip: []*router.GeoIP{
{ {
Cidr: []*geoip.CIDR{ Cidr: []*router.CIDR{
{ {
Ip: []byte{10, 0, 0, 0}, Ip: []byte{10, 0, 0, 0},
Prefix: 8, Prefix: 8,

View File

@@ -179,14 +179,24 @@ func (c *WebSocketConfig) Build() (proto.Message, error) {
} }
type HTTPConfig struct { type HTTPConfig struct {
Host *StringList `json:"host"` Host *StringList `json:"host"`
Path string `json:"path"` Path string `json:"path"`
ReadIdleTimeout int32 `json:"read_idle_timeout"`
HealthCheckTimeout int32 `json:"health_check_timeout"`
} }
// Build implements Buildable. // Build implements Buildable.
func (c *HTTPConfig) Build() (proto.Message, error) { func (c *HTTPConfig) Build() (proto.Message, error) {
if c.ReadIdleTimeout <= 0 {
c.ReadIdleTimeout = 0
}
if c.HealthCheckTimeout <= 0 {
c.HealthCheckTimeout = 0
}
config := &http.Config{ config := &http.Config{
Path: c.Path, Path: c.Path,
IdleTimeout: c.ReadIdleTimeout,
HealthCheckTimeout: c.HealthCheckTimeout,
} }
if c.Host != nil { if c.Host != nil {
config.Host = []string(*c.Host) config.Host = []string(*c.Host)
@@ -322,6 +332,7 @@ type TLSConfig struct {
CipherSuites string `json:"cipherSuites"` CipherSuites string `json:"cipherSuites"`
PreferServerCipherSuites bool `json:"preferServerCipherSuites"` PreferServerCipherSuites bool `json:"preferServerCipherSuites"`
Fingerprint string `json:"fingerprint"` Fingerprint string `json:"fingerprint"`
RejectUnknownSNI bool `json:"rejectUnknownSni"`
} }
// Build implements Buildable. // Build implements Buildable.
@@ -350,6 +361,7 @@ func (c *TLSConfig) Build() (proto.Message, error) {
config.CipherSuites = c.CipherSuites config.CipherSuites = c.CipherSuites
config.PreferServerCipherSuites = c.PreferServerCipherSuites config.PreferServerCipherSuites = c.PreferServerCipherSuites
config.Fingerprint = strings.ToLower(c.Fingerprint) config.Fingerprint = strings.ToLower(c.Fingerprint)
config.RejectUnknownSni = c.RejectUnknownSNI
return config, nil return config, nil
} }
@@ -413,6 +425,7 @@ type XTLSConfig struct {
MaxVersion string `json:"maxVersion"` MaxVersion string `json:"maxVersion"`
CipherSuites string `json:"cipherSuites"` CipherSuites string `json:"cipherSuites"`
PreferServerCipherSuites bool `json:"preferServerCipherSuites"` PreferServerCipherSuites bool `json:"preferServerCipherSuites"`
RejectUnknownSNI bool `json:"rejectUnknownSni"`
} }
// Build implements Buildable. // Build implements Buildable.
@@ -440,6 +453,7 @@ func (c *XTLSConfig) Build() (proto.Message, error) {
config.MaxVersion = c.MaxVersion config.MaxVersion = c.MaxVersion
config.CipherSuites = c.CipherSuites config.CipherSuites = c.CipherSuites
config.PreferServerCipherSuites = c.PreferServerCipherSuites config.PreferServerCipherSuites = c.PreferServerCipherSuites
config.RejectUnknownSni = c.RejectUnknownSNI
return config, nil return config, nil
} }

View File

@@ -2,7 +2,7 @@ package conf
import ( import (
"encoding/json" "encoding/json"
"github.com/xtls/xray-core/transport/internet"
"log" "log"
"os" "os"
"strings" "strings"
@@ -10,12 +10,8 @@ import (
"github.com/xtls/xray-core/app/dispatcher" "github.com/xtls/xray-core/app/dispatcher"
"github.com/xtls/xray-core/app/proxyman" "github.com/xtls/xray-core/app/proxyman"
"github.com/xtls/xray-core/app/stats" "github.com/xtls/xray-core/app/stats"
"github.com/xtls/xray-core/common/matcher/domain"
"github.com/xtls/xray-core/common/matcher/domain/conf"
"github.com/xtls/xray-core/common/matcher/geoip"
"github.com/xtls/xray-core/common/serial" "github.com/xtls/xray-core/common/serial"
core "github.com/xtls/xray-core/core" core "github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/transport/internet"
"github.com/xtls/xray-core/transport/internet/xtls" "github.com/xtls/xray-core/transport/internet/xtls"
) )
@@ -66,7 +62,6 @@ type SniffingConfig struct {
Enabled bool `json:"enabled"` Enabled bool `json:"enabled"`
DestOverride *StringList `json:"destOverride"` DestOverride *StringList `json:"destOverride"`
DomainsExcluded *StringList `json:"domainsExcluded"` DomainsExcluded *StringList `json:"domainsExcluded"`
IPsExcluded *StringList `json:"ipsExcluded"`
MetadataOnly bool `json:"metadataOnly"` MetadataOnly bool `json:"metadataOnly"`
} }
@@ -88,31 +83,17 @@ func (c *SniffingConfig) Build() (*proxyman.SniffingConfig, error) {
} }
} }
var exDomain []*domain.Domain var d []string
if c.DomainsExcluded != nil { if c.DomainsExcluded != nil {
for _, dmr := range *c.DomainsExcluded { for _, domain := range *c.DomainsExcluded {
if dm, err := conf.ParseDomainRule(dmr); err == nil { d = append(d, strings.ToLower(domain))
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.ParseIPList(*c.IPsExcluded)
if err != nil {
return nil, newError("failed to parse excluded ip").Base(err)
}
exIP = exip
}
return &proxyman.SniffingConfig{ return &proxyman.SniffingConfig{
Enabled: c.Enabled, Enabled: c.Enabled,
DestinationOverride: p, DestinationOverride: p,
DomainsExcluded: exDomain, DomainsExcluded: d,
IpsExcluded: exIP,
MetadataOnly: c.MetadataOnly, MetadataOnly: c.MetadataOnly,
}, nil }, nil
} }

View File

@@ -2,7 +2,6 @@ package conf_test
import ( import (
"encoding/json" "encoding/json"
"github.com/xtls/xray-core/common/matcher/domain"
"reflect" "reflect"
"testing" "testing"
@@ -14,7 +13,6 @@ import (
"github.com/xtls/xray-core/app/router" "github.com/xtls/xray-core/app/router"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
clog "github.com/xtls/xray-core/common/log" clog "github.com/xtls/xray-core/common/log"
"github.com/xtls/xray-core/common/matcher/geoip"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/protocol" "github.com/xtls/xray-core/common/protocol"
"github.com/xtls/xray-core/common/serial" "github.com/xtls/xray-core/common/serial"
@@ -156,9 +154,9 @@ func TestXrayConfig(t *testing.T) {
DomainStrategy: router.Config_AsIs, DomainStrategy: router.Config_AsIs,
Rule: []*router.RoutingRule{ Rule: []*router.RoutingRule{
{ {
Geoip: []*geoip.GeoIP{ Geoip: []*router.GeoIP{
{ {
Cidr: []*geoip.CIDR{ Cidr: []*router.CIDR{
{ {
Ip: []byte{10, 0, 0, 0}, Ip: []byte{10, 0, 0, 0},
Prefix: 8, Prefix: 8,
@@ -373,52 +371,6 @@ 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) { func TestConfig_Override(t *testing.T) {
tests := []struct { tests := []struct {
name string name string

View File

@@ -43,7 +43,6 @@ type Handler struct {
func (h *Handler) Init(config *Config, dnsClient dns.Client) error { func (h *Handler) Init(config *Config, dnsClient dns.Client) error {
h.client = dnsClient h.client = dnsClient
if v, ok := dnsClient.(ownLinkVerifier); ok { if v, ok := dnsClient.(ownLinkVerifier); ok {
h.ownLinkVerifier = v h.ownLinkVerifier = v
} }
@@ -199,16 +198,22 @@ func (h *Handler) handleIPQuery(id uint16, qType dnsmessage.Type, domain string,
var err error var err error
var ttl uint32 = 600 var ttl uint32 = 600
var opt dns.Option
switch qType { switch qType {
case dnsmessage.TypeA: case dnsmessage.TypeA:
opt = dns.LookupIPv4Only ips, err = h.client.LookupIP(domain, dns.IPOption{
IPv4Enable: true,
IPv6Enable: false,
FakeEnable: true,
})
case dnsmessage.TypeAAAA: case dnsmessage.TypeAAAA:
opt = dns.LookupIPv6Only ips, err = h.client.LookupIP(domain, dns.IPOption{
IPv4Enable: false,
IPv6Enable: true,
FakeEnable: true,
})
} }
ips, err = h.client.LookupOptions(domain, opt, dns.LookupFake)
rcode := dns.RCodeFromError(err) rcode := dns.RCodeFromError(err)
if rcode == 0 && len(ips) == 0 && err != dns.ErrEmptyResponse { if rcode == 0 && len(ips) == 0 && err != dns.ErrEmptyResponse {
newError("ip query").Base(err).WriteToLog() newError("ip query").Base(err).WriteToLog()
@@ -223,6 +228,7 @@ func (h *Handler) handleIPQuery(id uint16, qType dnsmessage.Type, domain string,
RecursionAvailable: true, RecursionAvailable: true,
RecursionDesired: true, RecursionDesired: true,
Response: true, Response: true,
Authoritative: true,
}) })
builder.EnableCompression() builder.EnableCompression()
common.Must(builder.StartQuestions()) common.Must(builder.StartQuestions())

View File

@@ -59,14 +59,26 @@ func (h *Handler) policy() policy.Session {
} }
func (h *Handler) resolveIP(ctx context.Context, domain string, localAddr net.Address) net.Address { func (h *Handler) resolveIP(ctx context.Context, domain string, localAddr net.Address) net.Address {
var opt dns.Option var option dns.IPOption = dns.IPOption{
IPv4Enable: true,
IPv6Enable: true,
FakeEnable: false,
}
if h.config.DomainStrategy == Config_USE_IP4 || (localAddr != nil && localAddr.Family().IsIPv4()) { if h.config.DomainStrategy == Config_USE_IP4 || (localAddr != nil && localAddr.Family().IsIPv4()) {
opt = dns.LookupIPv4Only option = dns.IPOption{
IPv4Enable: true,
IPv6Enable: false,
FakeEnable: false,
}
} else if h.config.DomainStrategy == Config_USE_IP6 || (localAddr != nil && localAddr.Family().IsIPv6()) { } else if h.config.DomainStrategy == Config_USE_IP6 || (localAddr != nil && localAddr.Family().IsIPv6()) {
opt = dns.LookupIPv6Only option = dns.IPOption{
IPv4Enable: false,
IPv6Enable: true,
FakeEnable: false,
}
} }
ips, err := h.dns.LookupOptions(domain, opt, dns.LookupNoFake) ips, err := h.dns.LookupIP(domain, option)
if err != nil { if err != nil {
newError("failed to get IP address for domain ", domain).Base(err).WriteToLog(session.ExportIDToError(ctx)) newError("failed to get IP address for domain ", domain).Base(err).WriteToLog(session.ExportIDToError(ctx))
} }

View File

@@ -5,37 +5,36 @@
package mocks package mocks
import ( import (
net "net"
reflect "reflect"
gomock "github.com/golang/mock/gomock" gomock "github.com/golang/mock/gomock"
dns "github.com/xtls/xray-core/features/dns" dns "github.com/xtls/xray-core/features/dns"
net "net"
reflect "reflect"
) )
// DNSClient is a mock of Client interface. // DNSClient is a mock of Client interface
type DNSClient struct { type DNSClient struct {
ctrl *gomock.Controller ctrl *gomock.Controller
recorder *DNSClientMockRecorder recorder *DNSClientMockRecorder
} }
// DNSClientMockRecorder is the mock recorder for DNSClient. // DNSClientMockRecorder is the mock recorder for DNSClient
type DNSClientMockRecorder struct { type DNSClientMockRecorder struct {
mock *DNSClient mock *DNSClient
} }
// NewDNSClient creates a new mock instance. // NewDNSClient creates a new mock instance
func NewDNSClient(ctrl *gomock.Controller) *DNSClient { func NewDNSClient(ctrl *gomock.Controller) *DNSClient {
mock := &DNSClient{ctrl: ctrl} mock := &DNSClient{ctrl: ctrl}
mock.recorder = &DNSClientMockRecorder{mock} mock.recorder = &DNSClientMockRecorder{mock}
return mock return mock
} }
// EXPECT returns an object that allows the caller to indicate expected use. // EXPECT returns an object that allows the caller to indicate expected use
func (m *DNSClient) EXPECT() *DNSClientMockRecorder { func (m *DNSClient) EXPECT() *DNSClientMockRecorder {
return m.recorder return m.recorder
} }
// Close mocks base method. // Close mocks base method
func (m *DNSClient) Close() error { func (m *DNSClient) Close() error {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Close") ret := m.ctrl.Call(m, "Close")
@@ -43,48 +42,28 @@ func (m *DNSClient) Close() error {
return ret0 return ret0
} }
// Close indicates an expected call of Close. // Close indicates an expected call of Close
func (mr *DNSClientMockRecorder) Close() *gomock.Call { func (mr *DNSClientMockRecorder) Close() *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*DNSClient)(nil).Close)) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*DNSClient)(nil).Close))
} }
// LookupIP mocks base method. // LookupIP mocks base method
func (m *DNSClient) LookupIP(arg0 string) ([]net.IP, error) { func (m *DNSClient) LookupIP(arg0 string, arg1 dns.IPOption) ([]net.IP, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "LookupIP", arg0) ret := m.ctrl.Call(m, "LookupIP", arg0, arg1)
ret0, _ := ret[0].([]net.IP) ret0, _ := ret[0].([]net.IP)
ret1, _ := ret[1].(error) ret1, _ := ret[1].(error)
return ret0, ret1 return ret0, ret1
} }
// LookupIP indicates an expected call of LookupIP. // LookupIP indicates an expected call of LookupIP
func (mr *DNSClientMockRecorder) LookupIP(arg0 interface{}) *gomock.Call { func (mr *DNSClientMockRecorder) LookupIP(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LookupIP", reflect.TypeOf((*DNSClient)(nil).LookupIP), arg0) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LookupIP", reflect.TypeOf((*DNSClient)(nil).LookupIP), arg0, arg1)
} }
// LookupOptions mocks base method. // Start mocks base method
func (m *DNSClient) LookupOptions(arg0 string, arg1 ...dns.Option) ([]net.IP, error) {
m.ctrl.T.Helper()
varargs := []interface{}{arg0}
for _, a := range arg1 {
varargs = append(varargs, a)
}
ret := m.ctrl.Call(m, "LookupOptions", varargs...)
ret0, _ := ret[0].([]net.IP)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// LookupOptions indicates an expected call of LookupOptions.
func (mr *DNSClientMockRecorder) LookupOptions(arg0 interface{}, arg1 ...interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
varargs := append([]interface{}{arg0}, arg1...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LookupOptions", reflect.TypeOf((*DNSClient)(nil).LookupOptions), varargs...)
}
// Start mocks base method.
func (m *DNSClient) Start() error { func (m *DNSClient) Start() error {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Start") ret := m.ctrl.Call(m, "Start")
@@ -92,13 +71,13 @@ func (m *DNSClient) Start() error {
return ret0 return ret0
} }
// Start indicates an expected call of Start. // Start indicates an expected call of Start
func (mr *DNSClientMockRecorder) Start() *gomock.Call { func (mr *DNSClientMockRecorder) Start() *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Start", reflect.TypeOf((*DNSClient)(nil).Start)) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Start", reflect.TypeOf((*DNSClient)(nil).Start))
} }
// Type mocks base method. // Type mocks base method
func (m *DNSClient) Type() interface{} { func (m *DNSClient) Type() interface{} {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Type") ret := m.ctrl.Call(m, "Type")
@@ -106,7 +85,7 @@ func (m *DNSClient) Type() interface{} {
return ret0 return ret0
} }
// Type indicates an expected call of Type. // Type indicates an expected call of Type
func (mr *DNSClientMockRecorder) Type() *gomock.Call { func (mr *DNSClientMockRecorder) Type() *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Type", reflect.TypeOf((*DNSClient)(nil).Type)) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Type", reflect.TypeOf((*DNSClient)(nil).Type))

View File

@@ -5,35 +5,34 @@
package mocks package mocks
import ( import (
reflect "reflect"
gomock "github.com/golang/mock/gomock" gomock "github.com/golang/mock/gomock"
reflect "reflect"
) )
// Reader is a mock of Reader interface. // Reader is a mock of Reader interface
type Reader struct { type Reader struct {
ctrl *gomock.Controller ctrl *gomock.Controller
recorder *ReaderMockRecorder recorder *ReaderMockRecorder
} }
// ReaderMockRecorder is the mock recorder for Reader. // ReaderMockRecorder is the mock recorder for Reader
type ReaderMockRecorder struct { type ReaderMockRecorder struct {
mock *Reader mock *Reader
} }
// NewReader creates a new mock instance. // NewReader creates a new mock instance
func NewReader(ctrl *gomock.Controller) *Reader { func NewReader(ctrl *gomock.Controller) *Reader {
mock := &Reader{ctrl: ctrl} mock := &Reader{ctrl: ctrl}
mock.recorder = &ReaderMockRecorder{mock} mock.recorder = &ReaderMockRecorder{mock}
return mock return mock
} }
// EXPECT returns an object that allows the caller to indicate expected use. // EXPECT returns an object that allows the caller to indicate expected use
func (m *Reader) EXPECT() *ReaderMockRecorder { func (m *Reader) EXPECT() *ReaderMockRecorder {
return m.recorder return m.recorder
} }
// Read mocks base method. // Read mocks base method
func (m *Reader) Read(arg0 []byte) (int, error) { func (m *Reader) Read(arg0 []byte) (int, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Read", arg0) ret := m.ctrl.Call(m, "Read", arg0)
@@ -42,36 +41,36 @@ func (m *Reader) Read(arg0 []byte) (int, error) {
return ret0, ret1 return ret0, ret1
} }
// Read indicates an expected call of Read. // Read indicates an expected call of Read
func (mr *ReaderMockRecorder) Read(arg0 interface{}) *gomock.Call { func (mr *ReaderMockRecorder) Read(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Read", reflect.TypeOf((*Reader)(nil).Read), arg0) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Read", reflect.TypeOf((*Reader)(nil).Read), arg0)
} }
// Writer is a mock of Writer interface. // Writer is a mock of Writer interface
type Writer struct { type Writer struct {
ctrl *gomock.Controller ctrl *gomock.Controller
recorder *WriterMockRecorder recorder *WriterMockRecorder
} }
// WriterMockRecorder is the mock recorder for Writer. // WriterMockRecorder is the mock recorder for Writer
type WriterMockRecorder struct { type WriterMockRecorder struct {
mock *Writer mock *Writer
} }
// NewWriter creates a new mock instance. // NewWriter creates a new mock instance
func NewWriter(ctrl *gomock.Controller) *Writer { func NewWriter(ctrl *gomock.Controller) *Writer {
mock := &Writer{ctrl: ctrl} mock := &Writer{ctrl: ctrl}
mock.recorder = &WriterMockRecorder{mock} mock.recorder = &WriterMockRecorder{mock}
return mock return mock
} }
// EXPECT returns an object that allows the caller to indicate expected use. // EXPECT returns an object that allows the caller to indicate expected use
func (m *Writer) EXPECT() *WriterMockRecorder { func (m *Writer) EXPECT() *WriterMockRecorder {
return m.recorder return m.recorder
} }
// Write mocks base method. // Write mocks base method
func (m *Writer) Write(arg0 []byte) (int, error) { func (m *Writer) Write(arg0 []byte) (int, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Write", arg0) ret := m.ctrl.Call(m, "Write", arg0)
@@ -80,7 +79,7 @@ func (m *Writer) Write(arg0 []byte) (int, error) {
return ret0, ret1 return ret0, ret1
} }
// Write indicates an expected call of Write. // Write indicates an expected call of Write
func (mr *WriterMockRecorder) Write(arg0 interface{}) *gomock.Call { func (mr *WriterMockRecorder) Write(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Write", reflect.TypeOf((*Writer)(nil).Write), arg0) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Write", reflect.TypeOf((*Writer)(nil).Write), arg0)

View File

@@ -5,42 +5,41 @@
package mocks package mocks
import ( import (
reflect "reflect"
gomock "github.com/golang/mock/gomock" gomock "github.com/golang/mock/gomock"
log "github.com/xtls/xray-core/common/log" log "github.com/xtls/xray-core/common/log"
reflect "reflect"
) )
// LogHandler is a mock of Handler interface. // LogHandler is a mock of Handler interface
type LogHandler struct { type LogHandler struct {
ctrl *gomock.Controller ctrl *gomock.Controller
recorder *LogHandlerMockRecorder recorder *LogHandlerMockRecorder
} }
// LogHandlerMockRecorder is the mock recorder for LogHandler. // LogHandlerMockRecorder is the mock recorder for LogHandler
type LogHandlerMockRecorder struct { type LogHandlerMockRecorder struct {
mock *LogHandler mock *LogHandler
} }
// NewLogHandler creates a new mock instance. // NewLogHandler creates a new mock instance
func NewLogHandler(ctrl *gomock.Controller) *LogHandler { func NewLogHandler(ctrl *gomock.Controller) *LogHandler {
mock := &LogHandler{ctrl: ctrl} mock := &LogHandler{ctrl: ctrl}
mock.recorder = &LogHandlerMockRecorder{mock} mock.recorder = &LogHandlerMockRecorder{mock}
return mock return mock
} }
// EXPECT returns an object that allows the caller to indicate expected use. // EXPECT returns an object that allows the caller to indicate expected use
func (m *LogHandler) EXPECT() *LogHandlerMockRecorder { func (m *LogHandler) EXPECT() *LogHandlerMockRecorder {
return m.recorder return m.recorder
} }
// Handle mocks base method. // Handle mocks base method
func (m *LogHandler) Handle(arg0 log.Message) { func (m *LogHandler) Handle(arg0 log.Message) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
m.ctrl.Call(m, "Handle", arg0) m.ctrl.Call(m, "Handle", arg0)
} }
// Handle indicates an expected call of Handle. // Handle indicates an expected call of Handle
func (mr *LogHandlerMockRecorder) Handle(arg0 interface{}) *gomock.Call { func (mr *LogHandlerMockRecorder) Handle(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Handle", reflect.TypeOf((*LogHandler)(nil).Handle), arg0) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Handle", reflect.TypeOf((*LogHandler)(nil).Handle), arg0)

View File

@@ -5,36 +5,35 @@
package mocks package mocks
import ( import (
reflect "reflect"
gomock "github.com/golang/mock/gomock" gomock "github.com/golang/mock/gomock"
mux "github.com/xtls/xray-core/common/mux" mux "github.com/xtls/xray-core/common/mux"
reflect "reflect"
) )
// MuxClientWorkerFactory is a mock of ClientWorkerFactory interface. // MuxClientWorkerFactory is a mock of ClientWorkerFactory interface
type MuxClientWorkerFactory struct { type MuxClientWorkerFactory struct {
ctrl *gomock.Controller ctrl *gomock.Controller
recorder *MuxClientWorkerFactoryMockRecorder recorder *MuxClientWorkerFactoryMockRecorder
} }
// MuxClientWorkerFactoryMockRecorder is the mock recorder for MuxClientWorkerFactory. // MuxClientWorkerFactoryMockRecorder is the mock recorder for MuxClientWorkerFactory
type MuxClientWorkerFactoryMockRecorder struct { type MuxClientWorkerFactoryMockRecorder struct {
mock *MuxClientWorkerFactory mock *MuxClientWorkerFactory
} }
// NewMuxClientWorkerFactory creates a new mock instance. // NewMuxClientWorkerFactory creates a new mock instance
func NewMuxClientWorkerFactory(ctrl *gomock.Controller) *MuxClientWorkerFactory { func NewMuxClientWorkerFactory(ctrl *gomock.Controller) *MuxClientWorkerFactory {
mock := &MuxClientWorkerFactory{ctrl: ctrl} mock := &MuxClientWorkerFactory{ctrl: ctrl}
mock.recorder = &MuxClientWorkerFactoryMockRecorder{mock} mock.recorder = &MuxClientWorkerFactoryMockRecorder{mock}
return mock return mock
} }
// EXPECT returns an object that allows the caller to indicate expected use. // EXPECT returns an object that allows the caller to indicate expected use
func (m *MuxClientWorkerFactory) EXPECT() *MuxClientWorkerFactoryMockRecorder { func (m *MuxClientWorkerFactory) EXPECT() *MuxClientWorkerFactoryMockRecorder {
return m.recorder return m.recorder
} }
// Create mocks base method. // Create mocks base method
func (m *MuxClientWorkerFactory) Create() (*mux.ClientWorker, error) { func (m *MuxClientWorkerFactory) Create() (*mux.ClientWorker, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Create") ret := m.ctrl.Call(m, "Create")
@@ -43,7 +42,7 @@ func (m *MuxClientWorkerFactory) Create() (*mux.ClientWorker, error) {
return ret0, ret1 return ret0, ret1
} }
// Create indicates an expected call of Create. // Create indicates an expected call of Create
func (mr *MuxClientWorkerFactoryMockRecorder) Create() *gomock.Call { func (mr *MuxClientWorkerFactoryMockRecorder) Create() *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Create", reflect.TypeOf((*MuxClientWorkerFactory)(nil).Create)) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Create", reflect.TypeOf((*MuxClientWorkerFactory)(nil).Create))

View File

@@ -6,36 +6,35 @@ package mocks
import ( import (
context "context" context "context"
reflect "reflect"
gomock "github.com/golang/mock/gomock" gomock "github.com/golang/mock/gomock"
outbound "github.com/xtls/xray-core/features/outbound" outbound "github.com/xtls/xray-core/features/outbound"
reflect "reflect"
) )
// OutboundManager is a mock of Manager interface. // OutboundManager is a mock of Manager interface
type OutboundManager struct { type OutboundManager struct {
ctrl *gomock.Controller ctrl *gomock.Controller
recorder *OutboundManagerMockRecorder recorder *OutboundManagerMockRecorder
} }
// OutboundManagerMockRecorder is the mock recorder for OutboundManager. // OutboundManagerMockRecorder is the mock recorder for OutboundManager
type OutboundManagerMockRecorder struct { type OutboundManagerMockRecorder struct {
mock *OutboundManager mock *OutboundManager
} }
// NewOutboundManager creates a new mock instance. // NewOutboundManager creates a new mock instance
func NewOutboundManager(ctrl *gomock.Controller) *OutboundManager { func NewOutboundManager(ctrl *gomock.Controller) *OutboundManager {
mock := &OutboundManager{ctrl: ctrl} mock := &OutboundManager{ctrl: ctrl}
mock.recorder = &OutboundManagerMockRecorder{mock} mock.recorder = &OutboundManagerMockRecorder{mock}
return mock return mock
} }
// EXPECT returns an object that allows the caller to indicate expected use. // EXPECT returns an object that allows the caller to indicate expected use
func (m *OutboundManager) EXPECT() *OutboundManagerMockRecorder { func (m *OutboundManager) EXPECT() *OutboundManagerMockRecorder {
return m.recorder return m.recorder
} }
// AddHandler mocks base method. // AddHandler mocks base method
func (m *OutboundManager) AddHandler(arg0 context.Context, arg1 outbound.Handler) error { func (m *OutboundManager) AddHandler(arg0 context.Context, arg1 outbound.Handler) error {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "AddHandler", arg0, arg1) ret := m.ctrl.Call(m, "AddHandler", arg0, arg1)
@@ -43,13 +42,13 @@ func (m *OutboundManager) AddHandler(arg0 context.Context, arg1 outbound.Handler
return ret0 return ret0
} }
// AddHandler indicates an expected call of AddHandler. // AddHandler indicates an expected call of AddHandler
func (mr *OutboundManagerMockRecorder) AddHandler(arg0, arg1 interface{}) *gomock.Call { func (mr *OutboundManagerMockRecorder) AddHandler(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddHandler", reflect.TypeOf((*OutboundManager)(nil).AddHandler), arg0, arg1) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddHandler", reflect.TypeOf((*OutboundManager)(nil).AddHandler), arg0, arg1)
} }
// Close mocks base method. // Close mocks base method
func (m *OutboundManager) Close() error { func (m *OutboundManager) Close() error {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Close") ret := m.ctrl.Call(m, "Close")
@@ -57,13 +56,13 @@ func (m *OutboundManager) Close() error {
return ret0 return ret0
} }
// Close indicates an expected call of Close. // Close indicates an expected call of Close
func (mr *OutboundManagerMockRecorder) Close() *gomock.Call { func (mr *OutboundManagerMockRecorder) Close() *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*OutboundManager)(nil).Close)) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*OutboundManager)(nil).Close))
} }
// GetDefaultHandler mocks base method. // GetDefaultHandler mocks base method
func (m *OutboundManager) GetDefaultHandler() outbound.Handler { func (m *OutboundManager) GetDefaultHandler() outbound.Handler {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetDefaultHandler") ret := m.ctrl.Call(m, "GetDefaultHandler")
@@ -71,13 +70,13 @@ func (m *OutboundManager) GetDefaultHandler() outbound.Handler {
return ret0 return ret0
} }
// GetDefaultHandler indicates an expected call of GetDefaultHandler. // GetDefaultHandler indicates an expected call of GetDefaultHandler
func (mr *OutboundManagerMockRecorder) GetDefaultHandler() *gomock.Call { func (mr *OutboundManagerMockRecorder) GetDefaultHandler() *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDefaultHandler", reflect.TypeOf((*OutboundManager)(nil).GetDefaultHandler)) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDefaultHandler", reflect.TypeOf((*OutboundManager)(nil).GetDefaultHandler))
} }
// GetHandler mocks base method. // GetHandler mocks base method
func (m *OutboundManager) GetHandler(arg0 string) outbound.Handler { func (m *OutboundManager) GetHandler(arg0 string) outbound.Handler {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetHandler", arg0) ret := m.ctrl.Call(m, "GetHandler", arg0)
@@ -85,13 +84,13 @@ func (m *OutboundManager) GetHandler(arg0 string) outbound.Handler {
return ret0 return ret0
} }
// GetHandler indicates an expected call of GetHandler. // GetHandler indicates an expected call of GetHandler
func (mr *OutboundManagerMockRecorder) GetHandler(arg0 interface{}) *gomock.Call { func (mr *OutboundManagerMockRecorder) GetHandler(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetHandler", reflect.TypeOf((*OutboundManager)(nil).GetHandler), arg0) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetHandler", reflect.TypeOf((*OutboundManager)(nil).GetHandler), arg0)
} }
// RemoveHandler mocks base method. // RemoveHandler mocks base method
func (m *OutboundManager) RemoveHandler(arg0 context.Context, arg1 string) error { func (m *OutboundManager) RemoveHandler(arg0 context.Context, arg1 string) error {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "RemoveHandler", arg0, arg1) ret := m.ctrl.Call(m, "RemoveHandler", arg0, arg1)
@@ -99,13 +98,13 @@ func (m *OutboundManager) RemoveHandler(arg0 context.Context, arg1 string) error
return ret0 return ret0
} }
// RemoveHandler indicates an expected call of RemoveHandler. // RemoveHandler indicates an expected call of RemoveHandler
func (mr *OutboundManagerMockRecorder) RemoveHandler(arg0, arg1 interface{}) *gomock.Call { func (mr *OutboundManagerMockRecorder) RemoveHandler(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveHandler", reflect.TypeOf((*OutboundManager)(nil).RemoveHandler), arg0, arg1) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveHandler", reflect.TypeOf((*OutboundManager)(nil).RemoveHandler), arg0, arg1)
} }
// Start mocks base method. // Start mocks base method
func (m *OutboundManager) Start() error { func (m *OutboundManager) Start() error {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Start") ret := m.ctrl.Call(m, "Start")
@@ -113,13 +112,13 @@ func (m *OutboundManager) Start() error {
return ret0 return ret0
} }
// Start indicates an expected call of Start. // Start indicates an expected call of Start
func (mr *OutboundManagerMockRecorder) Start() *gomock.Call { func (mr *OutboundManagerMockRecorder) Start() *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Start", reflect.TypeOf((*OutboundManager)(nil).Start)) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Start", reflect.TypeOf((*OutboundManager)(nil).Start))
} }
// Type mocks base method. // Type mocks base method
func (m *OutboundManager) Type() interface{} { func (m *OutboundManager) Type() interface{} {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Type") ret := m.ctrl.Call(m, "Type")
@@ -127,36 +126,36 @@ func (m *OutboundManager) Type() interface{} {
return ret0 return ret0
} }
// Type indicates an expected call of Type. // Type indicates an expected call of Type
func (mr *OutboundManagerMockRecorder) Type() *gomock.Call { func (mr *OutboundManagerMockRecorder) Type() *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Type", reflect.TypeOf((*OutboundManager)(nil).Type)) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Type", reflect.TypeOf((*OutboundManager)(nil).Type))
} }
// OutboundHandlerSelector is a mock of HandlerSelector interface. // OutboundHandlerSelector is a mock of HandlerSelector interface
type OutboundHandlerSelector struct { type OutboundHandlerSelector struct {
ctrl *gomock.Controller ctrl *gomock.Controller
recorder *OutboundHandlerSelectorMockRecorder recorder *OutboundHandlerSelectorMockRecorder
} }
// OutboundHandlerSelectorMockRecorder is the mock recorder for OutboundHandlerSelector. // OutboundHandlerSelectorMockRecorder is the mock recorder for OutboundHandlerSelector
type OutboundHandlerSelectorMockRecorder struct { type OutboundHandlerSelectorMockRecorder struct {
mock *OutboundHandlerSelector mock *OutboundHandlerSelector
} }
// NewOutboundHandlerSelector creates a new mock instance. // NewOutboundHandlerSelector creates a new mock instance
func NewOutboundHandlerSelector(ctrl *gomock.Controller) *OutboundHandlerSelector { func NewOutboundHandlerSelector(ctrl *gomock.Controller) *OutboundHandlerSelector {
mock := &OutboundHandlerSelector{ctrl: ctrl} mock := &OutboundHandlerSelector{ctrl: ctrl}
mock.recorder = &OutboundHandlerSelectorMockRecorder{mock} mock.recorder = &OutboundHandlerSelectorMockRecorder{mock}
return mock return mock
} }
// EXPECT returns an object that allows the caller to indicate expected use. // EXPECT returns an object that allows the caller to indicate expected use
func (m *OutboundHandlerSelector) EXPECT() *OutboundHandlerSelectorMockRecorder { func (m *OutboundHandlerSelector) EXPECT() *OutboundHandlerSelectorMockRecorder {
return m.recorder return m.recorder
} }
// Select mocks base method. // Select mocks base method
func (m *OutboundHandlerSelector) Select(arg0 []string) []string { func (m *OutboundHandlerSelector) Select(arg0 []string) []string {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Select", arg0) ret := m.ctrl.Call(m, "Select", arg0)
@@ -164,7 +163,7 @@ func (m *OutboundHandlerSelector) Select(arg0 []string) []string {
return ret0 return ret0
} }
// Select indicates an expected call of Select. // Select indicates an expected call of Select
func (mr *OutboundHandlerSelectorMockRecorder) Select(arg0 interface{}) *gomock.Call { func (mr *OutboundHandlerSelectorMockRecorder) Select(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Select", reflect.TypeOf((*OutboundHandlerSelector)(nil).Select), arg0) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Select", reflect.TypeOf((*OutboundHandlerSelector)(nil).Select), arg0)

Some files were not shown because too many files have changed in this diff Show More