diff --git a/app/dns/config.pb.go b/app/dns/config.pb.go index 05fd6099..33dc904b 100644 --- a/app/dns/config.pb.go +++ b/app/dns/config.pb.go @@ -128,13 +128,14 @@ type NameServer struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - 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"` - SkipFallback bool `protobuf:"varint,6,opt,name=skipFallback,proto3" json:"skipFallback,omitempty"` - PrioritizedDomain []*NameServer_PriorityDomain `protobuf:"bytes,2,rep,name=prioritized_domain,json=prioritizedDomain,proto3" json:"prioritized_domain,omitempty"` - Geoip []*router.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"` - QueryStrategy QueryStrategy `protobuf:"varint,7,opt,name=query_strategy,json=queryStrategy,proto3,enum=xray.app.dns.QueryStrategy" json:"query_strategy,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"` + SkipFallback bool `protobuf:"varint,6,opt,name=skipFallback,proto3" json:"skipFallback,omitempty"` + PrioritizedDomain []*NameServer_PriorityDomain `protobuf:"bytes,2,rep,name=prioritized_domain,json=prioritizedDomain,proto3" json:"prioritized_domain,omitempty"` + Geoip []*router.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"` + QueryStrategy QueryStrategy `protobuf:"varint,7,opt,name=query_strategy,json=queryStrategy,proto3,enum=xray.app.dns.QueryStrategy" json:"query_strategy,omitempty"` + AllowUnexpectedIPs bool `protobuf:"varint,8,opt,name=allowUnexpectedIPs,proto3" json:"allowUnexpectedIPs,omitempty"` } func (x *NameServer) Reset() { @@ -216,6 +217,13 @@ func (x *NameServer) GetQueryStrategy() QueryStrategy { return QueryStrategy_USE_IP } +func (x *NameServer) GetAllowUnexpectedIPs() bool { + if x != nil { + return x.AllowUnexpectedIPs + } + return false +} + type Config struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -508,7 +516,7 @@ var file_app_dns_config_proto_rawDesc = []byte{ 0x2e, 0x64, 0x6e, 0x73, 0x1a, 0x1c, 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, 0x17, 0x61, 0x70, 0x70, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2f, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xb2, 0x04, 0x0a, 0x0a, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xe2, 0x04, 0x0a, 0x0a, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x33, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x45, 0x6e, @@ -534,7 +542,10 @@ var file_app_dns_config_proto_rawDesc = []byte{ 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x07, 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, 0x1a, 0x5e, 0x0a, 0x0e, 0x50, 0x72, 0x69, 0x6f, + 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x2e, 0x0a, 0x12, 0x61, 0x6c, 0x6c, 0x6f, + 0x77, 0x55, 0x6e, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x49, 0x50, 0x73, 0x18, 0x08, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x55, 0x6e, 0x65, 0x78, 0x70, + 0x65, 0x63, 0x74, 0x65, 0x64, 0x49, 0x50, 0x73, 0x1a, 0x5e, 0x0a, 0x0e, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 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, diff --git a/app/dns/config.proto b/app/dns/config.proto index 11e0c8de..ea4d5e31 100644 --- a/app/dns/config.proto +++ b/app/dns/config.proto @@ -28,6 +28,7 @@ message NameServer { repeated xray.app.router.GeoIP geoip = 3; repeated OriginalRule original_rules = 4; QueryStrategy query_strategy = 7; + bool allowUnexpectedIPs = 8; } enum DomainMatchingType { diff --git a/app/dns/nameserver.go b/app/dns/nameserver.go index b23cb186..e1f902bf 100644 --- a/app/dns/nameserver.go +++ b/app/dns/nameserver.go @@ -25,11 +25,12 @@ type Server interface { // Client is the interface for DNS client. type Client struct { - server Server - clientIP net.IP - skipFallback bool - domains []string - expectIPs []*router.GeoIPMatcher + server Server + clientIP net.IP + skipFallback bool + domains []string + expectIPs []*router.GeoIPMatcher + allowUnexpectedIPs bool } var errExpectedIPNonMatch = errors.New("expectIPs not match") @@ -166,6 +167,7 @@ func NewClient( client.skipFallback = ns.SkipFallback client.domains = rules client.expectIPs = matchers + client.allowUnexpectedIPs = ns.AllowUnexpectedIPs return nil }) return client, err @@ -203,6 +205,9 @@ func (c *Client) MatchExpectedIPs(domain string, ips []net.IP) ([]net.IP, error) } } if len(newIps) == 0 { + if c.allowUnexpectedIPs { + return ips, nil + } return nil, errExpectedIPNonMatch } errors.LogDebug(context.Background(), "domain ", domain, " expectIPs ", newIps, " matched at server ", c.Name()) diff --git a/infra/conf/dns.go b/infra/conf/dns.go index 65964f3d..b2289026 100644 --- a/infra/conf/dns.go +++ b/infra/conf/dns.go @@ -12,13 +12,14 @@ import ( ) type NameServerConfig struct { - Address *Address `json:"address"` - ClientIP *Address `json:"clientIp"` - Port uint16 `json:"port"` - SkipFallback bool `json:"skipFallback"` - Domains []string `json:"domains"` - ExpectIPs StringList `json:"expectIps"` - QueryStrategy string `json:"queryStrategy"` + Address *Address `json:"address"` + ClientIP *Address `json:"clientIp"` + Port uint16 `json:"port"` + SkipFallback bool `json:"skipFallback"` + Domains []string `json:"domains"` + ExpectIPs StringList `json:"expectIps"` + QueryStrategy string `json:"queryStrategy"` + AllowUnexpectedIPs bool `json:"allowUnexpectedIps"` } func (c *NameServerConfig) UnmarshalJSON(data []byte) error { @@ -29,13 +30,14 @@ func (c *NameServerConfig) UnmarshalJSON(data []byte) error { } var advanced struct { - Address *Address `json:"address"` - ClientIP *Address `json:"clientIp"` - Port uint16 `json:"port"` - SkipFallback bool `json:"skipFallback"` - Domains []string `json:"domains"` - ExpectIPs StringList `json:"expectIps"` - QueryStrategy string `json:"queryStrategy"` + Address *Address `json:"address"` + ClientIP *Address `json:"clientIp"` + Port uint16 `json:"port"` + SkipFallback bool `json:"skipFallback"` + Domains []string `json:"domains"` + ExpectIPs StringList `json:"expectIps"` + QueryStrategy string `json:"queryStrategy"` + AllowUnexpectedIPs bool `json:"allowUnexpectedIps"` } if err := json.Unmarshal(data, &advanced); err == nil { c.Address = advanced.Address @@ -45,6 +47,7 @@ func (c *NameServerConfig) UnmarshalJSON(data []byte) error { c.Domains = advanced.Domains c.ExpectIPs = advanced.ExpectIPs c.QueryStrategy = advanced.QueryStrategy + c.AllowUnexpectedIPs = advanced.AllowUnexpectedIPs return nil } @@ -111,12 +114,13 @@ func (c *NameServerConfig) Build() (*dns.NameServer, error) { Address: c.Address.Build(), Port: uint32(c.Port), }, - ClientIp: myClientIP, - SkipFallback: c.SkipFallback, - PrioritizedDomain: domains, - Geoip: geoipList, - OriginalRules: originalRules, - QueryStrategy: resolveQueryStrategy(c.QueryStrategy), + ClientIp: myClientIP, + SkipFallback: c.SkipFallback, + PrioritizedDomain: domains, + Geoip: geoipList, + OriginalRules: originalRules, + QueryStrategy: resolveQueryStrategy(c.QueryStrategy), + AllowUnexpectedIPs: c.AllowUnexpectedIPs, }, nil }