diff --git a/app/dns/config.pb.go b/app/dns/config.pb.go index 66338f9d6..2963d31d6 100644 --- a/app/dns/config.pb.go +++ b/app/dns/config.pb.go @@ -1,6 +1,7 @@ package dns import ( + fakedns "github.com/v2fly/v2ray-core/v5/app/dns/fakedns" routercommon "github.com/v2fly/v2ray-core/v5/app/router/routercommon" net "github.com/v2fly/v2ray-core/v5/common/net" _ "github.com/v2fly/v2ray-core/v5/common/protoext" @@ -224,6 +225,7 @@ type NameServer struct { PrioritizedDomain []*NameServer_PriorityDomain `protobuf:"bytes,2,rep,name=prioritized_domain,json=prioritizedDomain,proto3" json:"prioritized_domain,omitempty"` Geoip []*routercommon.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"` + FakeDns *fakedns.FakeDnsPoolMulti `protobuf:"bytes,11,opt,name=fake_dns,json=fakeDns,proto3" json:"fake_dns,omitempty"` // Deprecated. Use fallback_strategy. // // Deprecated: Do not use. @@ -307,6 +309,13 @@ func (x *NameServer) GetOriginalRules() []*NameServer_OriginalRule { return nil } +func (x *NameServer) GetFakeDns() *fakedns.FakeDnsPoolMulti { + if x != nil { + return x.FakeDns + } + return nil +} + // Deprecated: Do not use. func (x *NameServer) GetSkipFallback() bool { if x != nil { @@ -429,8 +438,11 @@ type Config struct { Hosts map[string]*net.IPOrDomain `protobuf:"bytes,2,rep,name=Hosts,proto3" json:"Hosts,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` // Client IP for EDNS client subnet. Must be 4 bytes (IPv4) or 16 bytes // (IPv6). - ClientIp []byte `protobuf:"bytes,3,opt,name=client_ip,json=clientIp,proto3" json:"client_ip,omitempty"` + ClientIp []byte `protobuf:"bytes,3,opt,name=client_ip,json=clientIp,proto3" json:"client_ip,omitempty"` + // Static domain-ip mapping in DNS server. StaticHosts []*HostMapping `protobuf:"bytes,4,rep,name=static_hosts,json=staticHosts,proto3" json:"static_hosts,omitempty"` + // Global fakedns object. + FakeDns *fakedns.FakeDnsPoolMulti `protobuf:"bytes,16,opt,name=fake_dns,json=fakeDns,proto3" json:"fake_dns,omitempty"` // Tag is the inbound tag of DNS client. Tag string `protobuf:"bytes,6,opt,name=tag,proto3" json:"tag,omitempty"` // Domain matcher to use @@ -525,6 +537,13 @@ func (x *Config) GetStaticHosts() []*HostMapping { return nil } +func (x *Config) GetFakeDns() *fakedns.FakeDnsPoolMulti { + if x != nil { + return x.FakeDns + } + return nil +} + func (x *Config) GetTag() string { if x != nil { return x.Tag @@ -593,8 +612,11 @@ type SimplifiedConfig struct { NameServer []*SimplifiedNameServer `protobuf:"bytes,5,rep,name=name_server,json=nameServer,proto3" json:"name_server,omitempty"` // Client IP for EDNS client subnet. Must be 4 bytes (IPv4) or 16 bytes // (IPv6). - ClientIp string `protobuf:"bytes,3,opt,name=client_ip,json=clientIp,proto3" json:"client_ip,omitempty"` + ClientIp string `protobuf:"bytes,3,opt,name=client_ip,json=clientIp,proto3" json:"client_ip,omitempty"` + // Static domain-ip mapping in DNS server. StaticHosts []*HostMapping `protobuf:"bytes,4,rep,name=static_hosts,json=staticHosts,proto3" json:"static_hosts,omitempty"` + // Global fakedns object. + FakeDns *fakedns.FakeDnsPoolMulti `protobuf:"bytes,16,opt,name=fake_dns,json=fakeDns,proto3" json:"fake_dns,omitempty"` // Tag is the inbound tag of DNS client. Tag string `protobuf:"bytes,6,opt,name=tag,proto3" json:"tag,omitempty"` // Domain matcher to use @@ -673,6 +695,13 @@ func (x *SimplifiedConfig) GetStaticHosts() []*HostMapping { return nil } +func (x *SimplifiedConfig) GetFakeDns() *fakedns.FakeDnsPoolMulti { + if x != nil { + return x.FakeDns + } + return nil +} + func (x *SimplifiedConfig) GetTag() string { if x != nil { return x.Tag @@ -816,6 +845,7 @@ type SimplifiedNameServer struct { PrioritizedDomain []*SimplifiedNameServer_PriorityDomain `protobuf:"bytes,2,rep,name=prioritized_domain,json=prioritizedDomain,proto3" json:"prioritized_domain,omitempty"` Geoip []*routercommon.GeoIP `protobuf:"bytes,3,rep,name=geoip,proto3" json:"geoip,omitempty"` OriginalRules []*SimplifiedNameServer_OriginalRule `protobuf:"bytes,4,rep,name=original_rules,json=originalRules,proto3" json:"original_rules,omitempty"` + FakeDns *fakedns.FakeDnsPoolMulti `protobuf:"bytes,11,opt,name=fake_dns,json=fakeDns,proto3" json:"fake_dns,omitempty"` // Deprecated. Use fallback_strategy. // // Deprecated: Do not use. @@ -899,6 +929,13 @@ func (x *SimplifiedNameServer) GetOriginalRules() []*SimplifiedNameServer_Origin return nil } +func (x *SimplifiedNameServer) GetFakeDns() *fakedns.FakeDnsPoolMulti { + if x != nil { + return x.FakeDns + } + return nil +} + // Deprecated: Do not use. func (x *SimplifiedNameServer) GetSkipFallback() bool { if x != nil { @@ -1159,92 +1196,153 @@ var file_app_dns_config_proto_rawDesc = []byte{ 0x2f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x24, 0x61, 0x70, 0x70, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, - 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, - 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x65, 0x78, 0x74, 0x2f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, - 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xe1, 0x06, 0x0a, 0x0a, 0x4e, - 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x39, 0x0a, 0x07, 0x61, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x76, 0x32, 0x72, - 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, - 0x65, 0x74, 0x2e, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x07, 0x61, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, - 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, - 0x70, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, - 0x74, 0x61, 0x67, 0x12, 0x5c, 0x0a, 0x12, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x7a, - 0x65, 0x64, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x2d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, - 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, - 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x11, - 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x7a, 0x65, 0x64, 0x44, 0x6f, 0x6d, 0x61, 0x69, - 0x6e, 0x12, 0x3f, 0x0a, 0x05, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x29, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, - 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x63, - 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x52, 0x05, 0x67, 0x65, 0x6f, - 0x69, 0x70, 0x12, 0x52, 0x0a, 0x0e, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x72, - 0x75, 0x6c, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x76, 0x32, 0x72, - 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 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, 0x12, 0x26, 0x0a, 0x0c, 0x73, 0x6b, 0x69, 0x70, 0x46, 0x61, - 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x42, 0x02, 0x18, 0x01, - 0x52, 0x0c, 0x73, 0x6b, 0x69, 0x70, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x12, 0x4d, - 0x0a, 0x0e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, - 0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x21, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, - 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x51, 0x75, 0x65, 0x72, - 0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x48, 0x00, 0x52, 0x0d, 0x71, 0x75, 0x65, - 0x72, 0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x88, 0x01, 0x01, 0x12, 0x4d, 0x0a, - 0x0e, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, - 0x09, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x21, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, - 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x43, 0x61, 0x63, 0x68, 0x65, - 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x48, 0x01, 0x52, 0x0d, 0x63, 0x61, 0x63, 0x68, - 0x65, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x88, 0x01, 0x01, 0x12, 0x56, 0x0a, 0x11, - 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, - 0x79, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x24, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, - 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x46, 0x61, 0x6c, - 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x48, 0x02, 0x52, - 0x10, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, - 0x79, 0x88, 0x01, 0x01, 0x1a, 0x64, 0x0a, 0x0e, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, - 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x3a, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, - 0x65, 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, 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, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x73, 0x74, 0x72, - 0x61, 0x74, 0x65, 0x67, 0x79, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f, - 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x66, 0x61, 0x6c, - 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x22, 0x98, - 0x01, 0x0a, 0x0b, 0x48, 0x6f, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x3a, + 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1d, 0x61, 0x70, 0x70, 0x2f, 0x64, 0x6e, + 0x73, 0x2f, 0x66, 0x61, 0x6b, 0x65, 0x64, 0x6e, 0x73, 0x2f, 0x66, 0x61, 0x6b, 0x65, 0x64, 0x6e, + 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x65, 0x78, 0x74, 0x2f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, + 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xaa, 0x07, 0x0a, 0x0a, 0x4e, 0x61, + 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x39, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x76, 0x32, 0x72, 0x61, + 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, + 0x74, 0x2e, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x70, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x70, + 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, + 0x61, 0x67, 0x12, 0x5c, 0x0a, 0x12, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x7a, 0x65, + 0x64, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, + 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, + 0x64, 0x6e, 0x73, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x50, + 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x11, 0x70, + 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x7a, 0x65, 0x64, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, + 0x12, 0x3f, 0x0a, 0x05, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x29, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, + 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x63, 0x6f, + 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x52, 0x05, 0x67, 0x65, 0x6f, 0x69, + 0x70, 0x12, 0x52, 0x0a, 0x0e, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x72, 0x75, + 0x6c, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x76, 0x32, 0x72, 0x61, + 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 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, 0x12, 0x47, 0x0a, 0x08, 0x66, 0x61, 0x6b, 0x65, 0x5f, 0x64, 0x6e, + 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, + 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x66, 0x61, 0x6b, + 0x65, 0x64, 0x6e, 0x73, 0x2e, 0x46, 0x61, 0x6b, 0x65, 0x44, 0x6e, 0x73, 0x50, 0x6f, 0x6f, 0x6c, + 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x52, 0x07, 0x66, 0x61, 0x6b, 0x65, 0x44, 0x6e, 0x73, 0x12, 0x26, + 0x0a, 0x0c, 0x73, 0x6b, 0x69, 0x70, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x08, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0c, 0x73, 0x6b, 0x69, 0x70, 0x46, 0x61, + 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x12, 0x4d, 0x0a, 0x0e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, + 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x21, + 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, + 0x64, 0x6e, 0x73, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, + 0x79, 0x48, 0x00, 0x52, 0x0d, 0x71, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, + 0x67, 0x79, 0x88, 0x01, 0x01, 0x12, 0x4d, 0x0a, 0x0e, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x73, + 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x21, 0x2e, + 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, + 0x6e, 0x73, 0x2e, 0x43, 0x61, 0x63, 0x68, 0x65, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, + 0x48, 0x01, 0x52, 0x0d, 0x63, 0x61, 0x63, 0x68, 0x65, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, + 0x79, 0x88, 0x01, 0x01, 0x12, 0x56, 0x0a, 0x11, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, + 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0e, 0x32, + 0x24, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, + 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x53, 0x74, 0x72, + 0x61, 0x74, 0x65, 0x67, 0x79, 0x48, 0x02, 0x52, 0x10, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, + 0x6b, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x88, 0x01, 0x01, 0x1a, 0x64, 0x0a, 0x0e, + 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x3a, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 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, 0x22, 0xc7, 0x06, 0x0a, 0x06, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x12, 0x45, 0x0a, 0x0b, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, - 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x76, 0x32, 0x72, 0x61, - 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 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, 0x3f, 0x0a, 0x0b, 0x6e, - 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x1e, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 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, 0x3f, 0x0a, 0x05, - 0x48, 0x6f, 0x73, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x76, 0x32, - 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 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, 0x42, 0x0a, 0x0c, 0x73, 0x74, - 0x61, 0x74, 0x69, 0x63, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x1f, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, - 0x70, 0x2e, 0x64, 0x6e, 0x73, 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, + 0x69, 0x6e, 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, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x71, + 0x75, 0x65, 0x72, 0x79, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x42, 0x11, 0x0a, + 0x0f, 0x5f, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, + 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x5f, 0x73, 0x74, + 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x22, 0x98, 0x01, 0x0a, 0x0b, 0x48, 0x6f, 0x73, 0x74, 0x4d, + 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x3a, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, + 0x65, 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, 0x22, 0x90, 0x07, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x45, 0x0a, 0x0b, + 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x1f, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 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, 0x3f, 0x0a, 0x0b, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, + 0x2e, 0x63, 0x6f, 0x72, 0x65, 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, 0x3f, 0x0a, 0x05, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x18, 0x02, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, + 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, 0x42, 0x0a, 0x0c, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x5f, 0x68, 0x6f, 0x73, + 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, + 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 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, 0x47, 0x0a, 0x08, 0x66, 0x61, 0x6b, 0x65, 0x5f, 0x64, + 0x6e, 0x73, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, + 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x66, 0x61, + 0x6b, 0x65, 0x64, 0x6e, 0x73, 0x2e, 0x46, 0x61, 0x6b, 0x65, 0x44, 0x6e, 0x73, 0x50, 0x6f, 0x6f, + 0x6c, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x52, 0x07, 0x66, 0x61, 0x6b, 0x65, 0x44, 0x6e, 0x73, 0x12, + 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, + 0x67, 0x12, 0x25, 0x0a, 0x0e, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x74, 0x63, + 0x68, 0x65, 0x72, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x64, 0x6f, 0x6d, 0x61, 0x69, + 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x12, 0x26, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x61, + 0x62, 0x6c, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x42, 0x02, + 0x18, 0x01, 0x52, 0x0c, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, + 0x12, 0x2c, 0x0a, 0x0f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, + 0x61, 0x63, 0x6b, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0f, 0x64, + 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x12, 0x3a, + 0x0a, 0x16, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, + 0x6b, 0x49, 0x66, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x42, 0x02, + 0x18, 0x01, 0x52, 0x16, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, + 0x61, 0x63, 0x6b, 0x49, 0x66, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x48, 0x0a, 0x0e, 0x71, 0x75, + 0x65, 0x72, 0x79, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x09, 0x20, 0x01, + 0x28, 0x0e, 0x32, 0x21, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 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, 0x48, 0x0a, 0x0e, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x73, 0x74, + 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x21, 0x2e, 0x76, + 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 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, 0x51, + 0x0a, 0x11, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, + 0x65, 0x67, 0x79, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x24, 0x2e, 0x76, 0x32, 0x72, 0x61, + 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x46, + 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, + 0x10, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, + 0x79, 0x1a, 0x5b, 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, 0x37, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x21, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 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, 0x4a, 0x04, + 0x08, 0x07, 0x10, 0x08, 0x22, 0xe3, 0x05, 0x0a, 0x10, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x69, 0x66, + 0x69, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x49, 0x0a, 0x0b, 0x6e, 0x61, 0x6d, + 0x65, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, + 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, + 0x64, 0x6e, 0x73, 0x2e, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x64, 0x4e, 0x61, + 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x0a, 0x6e, 0x61, 0x6d, 0x65, 0x53, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, + 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, + 0x70, 0x12, 0x42, 0x0a, 0x0c, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x5f, 0x68, 0x6f, 0x73, 0x74, + 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, + 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 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, 0x47, 0x0a, 0x08, 0x66, 0x61, 0x6b, 0x65, 0x5f, 0x64, 0x6e, + 0x73, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, + 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x66, 0x61, 0x6b, + 0x65, 0x64, 0x6e, 0x73, 0x2e, 0x46, 0x61, 0x6b, 0x65, 0x44, 0x6e, 0x73, 0x50, 0x6f, 0x6f, 0x6c, + 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x52, 0x07, 0x66, 0x61, 0x6b, 0x65, 0x44, 0x6e, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x25, 0x0a, 0x0e, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, @@ -1272,143 +1370,102 @@ var file_app_dns_config_proto_rawDesc = []byte{ 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x10, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, - 0x1a, 0x5b, 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, 0x37, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x21, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 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, 0x4a, 0x04, 0x08, - 0x07, 0x10, 0x08, 0x22, 0x9a, 0x05, 0x0a, 0x10, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x69, 0x66, 0x69, - 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x49, 0x0a, 0x0b, 0x6e, 0x61, 0x6d, 0x65, - 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, - 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, - 0x6e, 0x73, 0x2e, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x64, 0x4e, 0x61, 0x6d, - 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x0a, 0x6e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, - 0x76, 0x65, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x70, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x70, - 0x12, 0x42, 0x0a, 0x0c, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x73, - 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, - 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 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, 0x25, 0x0a, 0x0e, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, - 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, - 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x12, 0x26, 0x0a, - 0x0c, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x18, 0x08, 0x20, - 0x01, 0x28, 0x08, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0c, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, - 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x2c, 0x0a, 0x0f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, - 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x42, 0x02, - 0x18, 0x01, 0x52, 0x0f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, - 0x61, 0x63, 0x6b, 0x12, 0x3a, 0x0a, 0x16, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, - 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x49, 0x66, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x0b, 0x20, - 0x01, 0x28, 0x08, 0x42, 0x02, 0x18, 0x01, 0x52, 0x16, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, - 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x49, 0x66, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, - 0x48, 0x0a, 0x0e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, - 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x21, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, - 0x63, 0x6f, 0x72, 0x65, 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, 0x48, 0x0a, 0x0e, 0x63, 0x61, 0x63, - 0x68, 0x65, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x0c, 0x20, 0x01, 0x28, + 0x3a, 0x16, 0x82, 0xb5, 0x18, 0x09, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x82, + 0xb5, 0x18, 0x05, 0x12, 0x03, 0x64, 0x6e, 0x73, 0x4a, 0x04, 0x08, 0x01, 0x10, 0x02, 0x4a, 0x04, + 0x08, 0x02, 0x10, 0x03, 0x4a, 0x04, 0x08, 0x07, 0x10, 0x08, 0x22, 0xa2, 0x01, 0x0a, 0x15, 0x53, + 0x69, 0x6d, 0x70, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x64, 0x48, 0x6f, 0x73, 0x74, 0x4d, 0x61, 0x70, + 0x70, 0x69, 0x6e, 0x67, 0x12, 0x3a, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 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, 0x09, 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, 0x22, + 0xc8, 0x07, 0x0a, 0x14, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x64, 0x4e, 0x61, + 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x39, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x76, 0x32, 0x72, 0x61, + 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, + 0x74, 0x2e, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x70, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x70, + 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, + 0x61, 0x67, 0x12, 0x66, 0x0a, 0x12, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x7a, 0x65, + 0x64, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x37, + 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, + 0x64, 0x6e, 0x73, 0x2e, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x64, 0x4e, 0x61, + 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, + 0x79, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x11, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, + 0x69, 0x7a, 0x65, 0x64, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x3f, 0x0a, 0x05, 0x67, 0x65, + 0x6f, 0x69, 0x70, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x76, 0x32, 0x72, 0x61, + 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, + 0x72, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x47, + 0x65, 0x6f, 0x49, 0x50, 0x52, 0x05, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x12, 0x5c, 0x0a, 0x0e, 0x6f, + 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x04, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, + 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x69, 0x66, + 0x69, 0x65, 0x64, 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, 0x12, 0x47, 0x0a, 0x08, 0x66, 0x61, 0x6b, + 0x65, 0x5f, 0x64, 0x6e, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x76, 0x32, + 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, + 0x2e, 0x66, 0x61, 0x6b, 0x65, 0x64, 0x6e, 0x73, 0x2e, 0x46, 0x61, 0x6b, 0x65, 0x44, 0x6e, 0x73, + 0x50, 0x6f, 0x6f, 0x6c, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x52, 0x07, 0x66, 0x61, 0x6b, 0x65, 0x44, + 0x6e, 0x73, 0x12, 0x26, 0x0a, 0x0c, 0x73, 0x6b, 0x69, 0x70, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, + 0x63, 0x6b, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0c, 0x73, 0x6b, + 0x69, 0x70, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x12, 0x4d, 0x0a, 0x0e, 0x71, 0x75, + 0x65, 0x72, 0x79, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x08, 0x20, 0x01, + 0x28, 0x0e, 0x32, 0x21, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, + 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x72, + 0x61, 0x74, 0x65, 0x67, 0x79, 0x48, 0x00, 0x52, 0x0d, 0x71, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, + 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x88, 0x01, 0x01, 0x12, 0x4d, 0x0a, 0x0e, 0x63, 0x61, 0x63, + 0x68, 0x65, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x21, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 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, 0x51, 0x0a, 0x11, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x5f, - 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x24, - 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, - 0x64, 0x6e, 0x73, 0x2e, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x53, 0x74, 0x72, 0x61, - 0x74, 0x65, 0x67, 0x79, 0x52, 0x10, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x53, 0x74, - 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x3a, 0x16, 0x82, 0xb5, 0x18, 0x09, 0x0a, 0x07, 0x73, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x82, 0xb5, 0x18, 0x05, 0x12, 0x03, 0x64, 0x6e, 0x73, 0x4a, 0x04, - 0x08, 0x01, 0x10, 0x02, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x4a, 0x04, 0x08, 0x07, 0x10, 0x08, - 0x22, 0xa2, 0x01, 0x0a, 0x15, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x64, 0x48, - 0x6f, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x3a, 0x0a, 0x04, 0x74, 0x79, - 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, - 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x44, 0x6f, + 0x74, 0x65, 0x67, 0x79, 0x48, 0x01, 0x52, 0x0d, 0x63, 0x61, 0x63, 0x68, 0x65, 0x53, 0x74, 0x72, + 0x61, 0x74, 0x65, 0x67, 0x79, 0x88, 0x01, 0x01, 0x12, 0x56, 0x0a, 0x11, 0x66, 0x61, 0x6c, 0x6c, + 0x62, 0x61, 0x63, 0x6b, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x0a, 0x20, + 0x01, 0x28, 0x0e, 0x32, 0x24, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, + 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, + 0x6b, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x48, 0x02, 0x52, 0x10, 0x66, 0x61, 0x6c, + 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x88, 0x01, 0x01, + 0x1a, 0x64, 0x0a, 0x0e, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x44, 0x6f, 0x6d, 0x61, + 0x69, 0x6e, 0x12, 0x3a, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x26, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 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, 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, 0x42, 0x11, + 0x0a, 0x0f, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, + 0x79, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x73, 0x74, 0x72, 0x61, + 0x74, 0x65, 0x67, 0x79, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, + 0x6b, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x2a, 0x45, 0x0a, 0x12, 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, 0x09, 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, 0x22, 0xff, 0x06, 0x0a, 0x14, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x69, - 0x66, 0x69, 0x65, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x39, - 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1f, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6d, - 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, - 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6c, 0x69, - 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6c, - 0x69, 0x65, 0x6e, 0x74, 0x49, 0x70, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x07, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x66, 0x0a, 0x12, 0x70, 0x72, 0x69, 0x6f, - 0x72, 0x69, 0x74, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, - 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x69, - 0x66, 0x69, 0x65, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x50, - 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x11, 0x70, - 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x7a, 0x65, 0x64, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, - 0x12, 0x3f, 0x0a, 0x05, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x29, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, - 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x63, 0x6f, - 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x52, 0x05, 0x67, 0x65, 0x6f, 0x69, - 0x70, 0x12, 0x5c, 0x0a, 0x0e, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x72, 0x75, - 0x6c, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x76, 0x32, 0x72, 0x61, - 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x53, - 0x69, 0x6d, 0x70, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x64, 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, 0x12, - 0x26, 0x0a, 0x0c, 0x73, 0x6b, 0x69, 0x70, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x18, - 0x06, 0x20, 0x01, 0x28, 0x08, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0c, 0x73, 0x6b, 0x69, 0x70, 0x46, - 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x12, 0x4d, 0x0a, 0x0e, 0x71, 0x75, 0x65, 0x72, 0x79, - 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32, - 0x21, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, - 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, - 0x67, 0x79, 0x48, 0x00, 0x52, 0x0d, 0x71, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x72, 0x61, 0x74, - 0x65, 0x67, 0x79, 0x88, 0x01, 0x01, 0x12, 0x4d, 0x0a, 0x0e, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f, - 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x21, - 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, - 0x64, 0x6e, 0x73, 0x2e, 0x43, 0x61, 0x63, 0x68, 0x65, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, - 0x79, 0x48, 0x01, 0x52, 0x0d, 0x63, 0x61, 0x63, 0x68, 0x65, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, - 0x67, 0x79, 0x88, 0x01, 0x01, 0x12, 0x56, 0x0a, 0x11, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, - 0x6b, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0e, - 0x32, 0x24, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, - 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x53, 0x74, - 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x48, 0x02, 0x52, 0x10, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, - 0x63, 0x6b, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x88, 0x01, 0x01, 0x1a, 0x64, 0x0a, - 0x0e, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, - 0x3a, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, - 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 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, 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, 0x42, 0x11, 0x0a, 0x0f, 0x5f, - 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x42, 0x11, - 0x0a, 0x0f, 0x5f, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, - 0x79, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x5f, 0x73, - 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 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, 0x2a, 0x35, - 0x0a, 0x0d, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, - 0x0a, 0x0a, 0x06, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x55, - 0x53, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, - 0x49, 0x50, 0x36, 0x10, 0x02, 0x2a, 0x34, 0x0a, 0x0d, 0x43, 0x61, 0x63, 0x68, 0x65, 0x53, 0x74, - 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x10, 0x0a, 0x0c, 0x43, 0x61, 0x63, 0x68, 0x65, 0x45, - 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x43, 0x61, 0x63, 0x68, - 0x65, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x10, 0x01, 0x2a, 0x45, 0x0a, 0x10, 0x46, - 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, - 0x0b, 0x0a, 0x07, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, - 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x10, 0x01, 0x12, 0x16, 0x0a, 0x12, 0x44, 0x69, - 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x49, 0x66, 0x41, 0x6e, 0x79, 0x4d, 0x61, 0x74, 0x63, 0x68, - 0x10, 0x02, 0x42, 0x57, 0x0a, 0x16, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, - 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x50, 0x01, 0x5a, 0x26, - 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, - 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x61, - 0x70, 0x70, 0x2f, 0x64, 0x6e, 0x73, 0xaa, 0x02, 0x12, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, - 0x6f, 0x72, 0x65, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x44, 0x6e, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x33, + 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, 0x2a, 0x35, 0x0a, 0x0d, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, + 0x67, 0x79, 0x12, 0x0a, 0x0a, 0x06, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x00, 0x12, 0x0b, + 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x55, + 0x53, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x10, 0x02, 0x2a, 0x34, 0x0a, 0x0d, 0x43, 0x61, 0x63, 0x68, + 0x65, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x10, 0x0a, 0x0c, 0x43, 0x61, 0x63, + 0x68, 0x65, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x43, + 0x61, 0x63, 0x68, 0x65, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x10, 0x01, 0x2a, 0x45, + 0x0a, 0x10, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, + 0x67, 0x79, 0x12, 0x0b, 0x0a, 0x07, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x10, 0x00, 0x12, + 0x0c, 0x0a, 0x08, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x10, 0x01, 0x12, 0x16, 0x0a, + 0x12, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x49, 0x66, 0x41, 0x6e, 0x79, 0x4d, 0x61, + 0x74, 0x63, 0x68, 0x10, 0x02, 0x42, 0x57, 0x0a, 0x16, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, + 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x50, + 0x01, 0x5a, 0x26, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, + 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, + 0x35, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x64, 0x6e, 0x73, 0xaa, 0x02, 0x12, 0x56, 0x32, 0x52, 0x61, + 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x44, 0x6e, 0x73, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1443,45 +1500,50 @@ var file_app_dns_config_proto_goTypes = []interface{}{ (*SimplifiedNameServer_OriginalRule)(nil), // 14: v2ray.core.app.dns.SimplifiedNameServer.OriginalRule (*net.Endpoint)(nil), // 15: v2ray.core.common.net.Endpoint (*routercommon.GeoIP)(nil), // 16: v2ray.core.app.router.routercommon.GeoIP - (*net.IPOrDomain)(nil), // 17: v2ray.core.common.net.IPOrDomain + (*fakedns.FakeDnsPoolMulti)(nil), // 17: v2ray.core.app.dns.fakedns.FakeDnsPoolMulti + (*net.IPOrDomain)(nil), // 18: v2ray.core.common.net.IPOrDomain } var file_app_dns_config_proto_depIdxs = []int32{ 15, // 0: v2ray.core.app.dns.NameServer.address:type_name -> v2ray.core.common.net.Endpoint 10, // 1: v2ray.core.app.dns.NameServer.prioritized_domain:type_name -> v2ray.core.app.dns.NameServer.PriorityDomain 16, // 2: v2ray.core.app.dns.NameServer.geoip:type_name -> v2ray.core.app.router.routercommon.GeoIP 11, // 3: v2ray.core.app.dns.NameServer.original_rules:type_name -> v2ray.core.app.dns.NameServer.OriginalRule - 1, // 4: v2ray.core.app.dns.NameServer.query_strategy:type_name -> v2ray.core.app.dns.QueryStrategy - 2, // 5: v2ray.core.app.dns.NameServer.cache_strategy:type_name -> v2ray.core.app.dns.CacheStrategy - 3, // 6: v2ray.core.app.dns.NameServer.fallback_strategy:type_name -> v2ray.core.app.dns.FallbackStrategy - 0, // 7: v2ray.core.app.dns.HostMapping.type:type_name -> v2ray.core.app.dns.DomainMatchingType - 15, // 8: v2ray.core.app.dns.Config.NameServers:type_name -> v2ray.core.common.net.Endpoint - 4, // 9: v2ray.core.app.dns.Config.name_server:type_name -> v2ray.core.app.dns.NameServer - 12, // 10: v2ray.core.app.dns.Config.Hosts:type_name -> v2ray.core.app.dns.Config.HostsEntry - 5, // 11: v2ray.core.app.dns.Config.static_hosts:type_name -> v2ray.core.app.dns.HostMapping - 1, // 12: v2ray.core.app.dns.Config.query_strategy:type_name -> v2ray.core.app.dns.QueryStrategy - 2, // 13: v2ray.core.app.dns.Config.cache_strategy:type_name -> v2ray.core.app.dns.CacheStrategy - 3, // 14: v2ray.core.app.dns.Config.fallback_strategy:type_name -> v2ray.core.app.dns.FallbackStrategy - 9, // 15: v2ray.core.app.dns.SimplifiedConfig.name_server:type_name -> v2ray.core.app.dns.SimplifiedNameServer - 5, // 16: v2ray.core.app.dns.SimplifiedConfig.static_hosts:type_name -> v2ray.core.app.dns.HostMapping - 1, // 17: v2ray.core.app.dns.SimplifiedConfig.query_strategy:type_name -> v2ray.core.app.dns.QueryStrategy - 2, // 18: v2ray.core.app.dns.SimplifiedConfig.cache_strategy:type_name -> v2ray.core.app.dns.CacheStrategy - 3, // 19: v2ray.core.app.dns.SimplifiedConfig.fallback_strategy:type_name -> v2ray.core.app.dns.FallbackStrategy - 0, // 20: v2ray.core.app.dns.SimplifiedHostMapping.type:type_name -> v2ray.core.app.dns.DomainMatchingType - 15, // 21: v2ray.core.app.dns.SimplifiedNameServer.address:type_name -> v2ray.core.common.net.Endpoint - 13, // 22: v2ray.core.app.dns.SimplifiedNameServer.prioritized_domain:type_name -> v2ray.core.app.dns.SimplifiedNameServer.PriorityDomain - 16, // 23: v2ray.core.app.dns.SimplifiedNameServer.geoip:type_name -> v2ray.core.app.router.routercommon.GeoIP - 14, // 24: v2ray.core.app.dns.SimplifiedNameServer.original_rules:type_name -> v2ray.core.app.dns.SimplifiedNameServer.OriginalRule - 1, // 25: v2ray.core.app.dns.SimplifiedNameServer.query_strategy:type_name -> v2ray.core.app.dns.QueryStrategy - 2, // 26: v2ray.core.app.dns.SimplifiedNameServer.cache_strategy:type_name -> v2ray.core.app.dns.CacheStrategy - 3, // 27: v2ray.core.app.dns.SimplifiedNameServer.fallback_strategy:type_name -> v2ray.core.app.dns.FallbackStrategy - 0, // 28: v2ray.core.app.dns.NameServer.PriorityDomain.type:type_name -> v2ray.core.app.dns.DomainMatchingType - 17, // 29: v2ray.core.app.dns.Config.HostsEntry.value:type_name -> v2ray.core.common.net.IPOrDomain - 0, // 30: v2ray.core.app.dns.SimplifiedNameServer.PriorityDomain.type:type_name -> v2ray.core.app.dns.DomainMatchingType - 31, // [31:31] is the sub-list for method output_type - 31, // [31:31] is the sub-list for method input_type - 31, // [31:31] is the sub-list for extension type_name - 31, // [31:31] is the sub-list for extension extendee - 0, // [0:31] is the sub-list for field type_name + 17, // 4: v2ray.core.app.dns.NameServer.fake_dns:type_name -> v2ray.core.app.dns.fakedns.FakeDnsPoolMulti + 1, // 5: v2ray.core.app.dns.NameServer.query_strategy:type_name -> v2ray.core.app.dns.QueryStrategy + 2, // 6: v2ray.core.app.dns.NameServer.cache_strategy:type_name -> v2ray.core.app.dns.CacheStrategy + 3, // 7: v2ray.core.app.dns.NameServer.fallback_strategy:type_name -> v2ray.core.app.dns.FallbackStrategy + 0, // 8: v2ray.core.app.dns.HostMapping.type:type_name -> v2ray.core.app.dns.DomainMatchingType + 15, // 9: v2ray.core.app.dns.Config.NameServers:type_name -> v2ray.core.common.net.Endpoint + 4, // 10: v2ray.core.app.dns.Config.name_server:type_name -> v2ray.core.app.dns.NameServer + 12, // 11: v2ray.core.app.dns.Config.Hosts:type_name -> v2ray.core.app.dns.Config.HostsEntry + 5, // 12: v2ray.core.app.dns.Config.static_hosts:type_name -> v2ray.core.app.dns.HostMapping + 17, // 13: v2ray.core.app.dns.Config.fake_dns:type_name -> v2ray.core.app.dns.fakedns.FakeDnsPoolMulti + 1, // 14: v2ray.core.app.dns.Config.query_strategy:type_name -> v2ray.core.app.dns.QueryStrategy + 2, // 15: v2ray.core.app.dns.Config.cache_strategy:type_name -> v2ray.core.app.dns.CacheStrategy + 3, // 16: v2ray.core.app.dns.Config.fallback_strategy:type_name -> v2ray.core.app.dns.FallbackStrategy + 9, // 17: v2ray.core.app.dns.SimplifiedConfig.name_server:type_name -> v2ray.core.app.dns.SimplifiedNameServer + 5, // 18: v2ray.core.app.dns.SimplifiedConfig.static_hosts:type_name -> v2ray.core.app.dns.HostMapping + 17, // 19: v2ray.core.app.dns.SimplifiedConfig.fake_dns:type_name -> v2ray.core.app.dns.fakedns.FakeDnsPoolMulti + 1, // 20: v2ray.core.app.dns.SimplifiedConfig.query_strategy:type_name -> v2ray.core.app.dns.QueryStrategy + 2, // 21: v2ray.core.app.dns.SimplifiedConfig.cache_strategy:type_name -> v2ray.core.app.dns.CacheStrategy + 3, // 22: v2ray.core.app.dns.SimplifiedConfig.fallback_strategy:type_name -> v2ray.core.app.dns.FallbackStrategy + 0, // 23: v2ray.core.app.dns.SimplifiedHostMapping.type:type_name -> v2ray.core.app.dns.DomainMatchingType + 15, // 24: v2ray.core.app.dns.SimplifiedNameServer.address:type_name -> v2ray.core.common.net.Endpoint + 13, // 25: v2ray.core.app.dns.SimplifiedNameServer.prioritized_domain:type_name -> v2ray.core.app.dns.SimplifiedNameServer.PriorityDomain + 16, // 26: v2ray.core.app.dns.SimplifiedNameServer.geoip:type_name -> v2ray.core.app.router.routercommon.GeoIP + 14, // 27: v2ray.core.app.dns.SimplifiedNameServer.original_rules:type_name -> v2ray.core.app.dns.SimplifiedNameServer.OriginalRule + 17, // 28: v2ray.core.app.dns.SimplifiedNameServer.fake_dns:type_name -> v2ray.core.app.dns.fakedns.FakeDnsPoolMulti + 1, // 29: v2ray.core.app.dns.SimplifiedNameServer.query_strategy:type_name -> v2ray.core.app.dns.QueryStrategy + 2, // 30: v2ray.core.app.dns.SimplifiedNameServer.cache_strategy:type_name -> v2ray.core.app.dns.CacheStrategy + 3, // 31: v2ray.core.app.dns.SimplifiedNameServer.fallback_strategy:type_name -> v2ray.core.app.dns.FallbackStrategy + 0, // 32: v2ray.core.app.dns.NameServer.PriorityDomain.type:type_name -> v2ray.core.app.dns.DomainMatchingType + 18, // 33: v2ray.core.app.dns.Config.HostsEntry.value:type_name -> v2ray.core.common.net.IPOrDomain + 0, // 34: v2ray.core.app.dns.SimplifiedNameServer.PriorityDomain.type:type_name -> v2ray.core.app.dns.DomainMatchingType + 35, // [35:35] is the sub-list for method output_type + 35, // [35:35] is the sub-list for method input_type + 35, // [35:35] is the sub-list for extension type_name + 35, // [35:35] is the sub-list for extension extendee + 0, // [0:35] is the sub-list for field type_name } func init() { file_app_dns_config_proto_init() } diff --git a/app/dns/config.proto b/app/dns/config.proto index acea75fe9..0de0100ad 100644 --- a/app/dns/config.proto +++ b/app/dns/config.proto @@ -9,6 +9,7 @@ option java_multiple_files = true; import "common/net/address.proto"; import "common/net/destination.proto"; import "app/router/routercommon/common.proto"; +import "app/dns/fakedns/fakedns.proto"; import "common/protoext/extensions.proto"; @@ -31,6 +32,8 @@ message NameServer { repeated v2ray.core.app.router.routercommon.GeoIP geoip = 3; repeated OriginalRule original_rules = 4; + v2ray.core.app.dns.fakedns.FakeDnsPoolMulti fake_dns = 11; + // Deprecated. Use fallback_strategy. bool skipFallback = 6 [deprecated = true]; @@ -91,8 +94,12 @@ message Config { // (IPv6). bytes client_ip = 3; + // Static domain-ip mapping in DNS server. repeated HostMapping static_hosts = 4; + // Global fakedns object. + v2ray.core.app.dns.fakedns.FakeDnsPoolMulti fake_dns = 16; + // Tag is the inbound tag of DNS client. string tag = 6; @@ -143,8 +150,12 @@ message SimplifiedConfig { // (IPv6). string client_ip = 3; + // Static domain-ip mapping in DNS server. repeated HostMapping static_hosts = 4; + // Global fakedns object. + v2ray.core.app.dns.fakedns.FakeDnsPoolMulti fake_dns = 16; + // Tag is the inbound tag of DNS client. string tag = 6; @@ -204,6 +215,8 @@ message SimplifiedNameServer { repeated v2ray.core.app.router.routercommon.GeoIP geoip = 3; repeated OriginalRule original_rules = 4; + v2ray.core.app.dns.fakedns.FakeDnsPoolMulti fake_dns = 11; + // Deprecated. Use fallback_strategy. bool skipFallback = 6 [deprecated = true]; diff --git a/app/dns/dns.go b/app/dns/dns.go index e3d43603d..a5b655a90 100644 --- a/app/dns/dns.go +++ b/app/dns/dns.go @@ -12,6 +12,8 @@ import ( "strings" "sync" + core "github.com/v2fly/v2ray-core/v5" + "github.com/v2fly/v2ray-core/v5/app/dns/fakedns" "github.com/v2fly/v2ray-core/v5/app/router" "github.com/v2fly/v2ray-core/v5/common" "github.com/v2fly/v2ray-core/v5/common/errors" @@ -28,11 +30,11 @@ import ( // DNS is a DNS rely server. type DNS struct { sync.Mutex - ipOption dns.IPOption hosts *StaticHosts clients []*Client ctx context.Context clientTags map[string]bool + fakeDNSEngine *FakeDNSEngine domainMatcher strmatcher.IndexMatcher matcherInfos []DomainMatcherInfo } @@ -78,31 +80,31 @@ func New(ctx context.Context, config *Config) (*DNS, error) { clients = append(clients, NewLocalDNSClient()) } - // Establish members related to global DNS state - domainMatcher, matcherInfos, err := establishDomainRules(config, clients, nsClientMap) - if err != nil { - return nil, err - } - if err := establishExpectedIPs(config, clients, nsClientMap); err != nil { - return nil, err - } - clientTags := make(map[string]bool) - for _, client := range clients { - clientTags[client.tag] = true + s := &DNS{ + hosts: hosts, + clients: clients, + ctx: ctx, } - return &DNS{ - ipOption: toIPOption(config.QueryStrategy), - hosts: hosts, - clients: clients, - ctx: ctx, - clientTags: clientTags, - domainMatcher: domainMatcher, - matcherInfos: matcherInfos, - }, nil + // Establish members related to global DNS state + s.clientTags = make(map[string]bool) + for _, client := range clients { + s.clientTags[client.tag] = true + } + if err := establishDomainRules(s, config, nsClientMap); err != nil { + return nil, err + } + if err := establishExpectedIPs(s, config, nsClientMap); err != nil { + return nil, err + } + if err := establishFakeDNS(s, config, nsClientMap); err != nil { + return nil, err + } + + return s, nil } -func establishDomainRules(config *Config, clients []*Client, nsClientMap map[int]int) (strmatcher.IndexMatcher, []DomainMatcherInfo, error) { +func establishDomainRules(s *DNS, config *Config, nsClientMap map[int]int) error { domainRuleCount := 0 for _, ns := range config.NameServer { domainRuleCount += len(ns.PrioritizedDomain) @@ -128,7 +130,7 @@ func establishDomainRules(config *Config, clients []*Client, nsClientMap map[int for _, domain := range ns.PrioritizedDomain { domainRule, err := toStrMatcher(domain.Type, domain.Domain) if err != nil { - return nil, nil, newError("failed to create prioritized domain").Base(err).AtWarning() + return newError("failed to create prioritized domain").Base(err).AtWarning() } originalRuleIdx := ruleCurr if ruleCurr < len(ns.OriginalRules) { @@ -151,18 +153,20 @@ func establishDomainRules(config *Config, clients []*Client, nsClientMap map[int domainRuleIdx: uint16(originalRuleIdx), } if err != nil { - return nil, nil, newError("failed to create prioritized domain").Base(err).AtWarning() + return newError("failed to create prioritized domain").Base(err).AtWarning() } } - clients[clientIdx].domains = rules + s.clients[clientIdx].domains = rules } if err := domainMatcher.Build(); err != nil { - return nil, nil, err + return err } - return domainMatcher, matcherInfos, nil + s.domainMatcher = domainMatcher + s.matcherInfos = matcherInfos + return nil } -func establishExpectedIPs(config *Config, clients []*Client, nsClientMap map[int]int) error { +func establishExpectedIPs(s *DNS, config *Config, nsClientMap map[int]int) error { geoipContainer := router.GeoIPMatcherContainer{} for nsIdx, ns := range config.NameServer { clientIdx := nsClientMap[nsIdx] @@ -174,11 +178,51 @@ func establishExpectedIPs(config *Config, clients []*Client, nsClientMap map[int } matchers = append(matchers, matcher) } - clients[clientIdx].expectIPs = matchers + s.clients[clientIdx].expectIPs = matchers } return nil } +func establishFakeDNS(s *DNS, config *Config, nsClientMap map[int]int) error { + fakeHolders := &fakedns.HolderMulti{} + fakeDefault := (*fakedns.HolderMulti)(nil) + if config.FakeDns != nil { + defaultEngine, err := fakeHolders.AddPoolMulti(config.FakeDns) + if err != nil { + return newError("fail to create fake dns").Base(err).AtWarning() + } + fakeDefault = defaultEngine + } + for nsIdx, ns := range config.NameServer { + clientIdx := nsClientMap[nsIdx] + if ns.FakeDns == nil { + continue + } + engine, err := fakeHolders.AddPoolMulti(ns.FakeDns) + if err != nil { + return newError("fail to create fake dns").Base(err).AtWarning() + } + s.clients[clientIdx].fakeDNS = NewFakeDNSServer(engine) + s.clients[clientIdx].queryStrategy.FakeEnable = true + } + // Do not create FakeDNSEngine feature if no FakeDNS server is configured + if fakeHolders.IsEmpty() { + return nil + } + // Add FakeDNSEngine feature when DNS feature is added for the first time + s.fakeDNSEngine = &FakeDNSEngine{dns: s, fakeHolders: fakeHolders, fakeDefault: fakeDefault} + return core.RequireFeatures(s.ctx, func(client dns.Client) error { + v := core.MustFromContext(s.ctx) + if v.GetFeature(dns.FakeDNSEngineType()) != nil { + return nil + } + if client, ok := client.(dns.ClientWithFakeDNS); ok { + return v.AddFeature(client.AsFakeDNSEngine()) + } + return nil + }) +} + // Type implements common.HasType. func (*DNS) Type() interface{} { return dns.ClientType() @@ -200,25 +244,29 @@ func (s *DNS) IsOwnLink(ctx context.Context) bool { return inbound != nil && s.clientTags[inbound.Tag] } +// AsFakeDNSClient implements dns.ClientWithFakeDNS. +func (s *DNS) AsFakeDNSClient() dns.Client { + return &FakeDNSClient{DNS: s} +} + +// AsFakeDNSEngine implements dns.ClientWithFakeDNS. +func (s *DNS) AsFakeDNSEngine() dns.FakeDNSEngine { + return s.fakeDNSEngine +} + // LookupIP implements dns.Client. func (s *DNS) LookupIP(domain string) ([]net.IP, error) { - return s.lookupIPInternal(domain, s.ipOption) + return s.lookupIPInternal(domain, dns.IPOption{IPv4Enable: true, IPv6Enable: true, FakeEnable: false}) } // LookupIPv4 implements dns.IPv4Lookup. func (s *DNS) LookupIPv4(domain string) ([]net.IP, error) { - if option := s.ipOption.With(dns.IPOption{IPv4Enable: true}); option.IsValid() { - return s.lookupIPInternal(domain, option) - } - return nil, dns.ErrEmptyResponse + return s.lookupIPInternal(domain, dns.IPOption{IPv4Enable: true, FakeEnable: false}) } // LookupIPv6 implements dns.IPv6Lookup. func (s *DNS) LookupIPv6(domain string) ([]net.IP, error) { - if option := s.ipOption.With(dns.IPOption{IPv6Enable: true}); option.IsValid() { - return s.lookupIPInternal(domain, option) - } - return nil, dns.ErrEmptyResponse + return s.lookupIPInternal(domain, dns.IPOption{IPv6Enable: true, FakeEnable: false}) } func (s *DNS) lookupIPInternal(domain string, option dns.IPOption) ([]net.IP, error) { @@ -257,33 +305,20 @@ func (s *DNS) lookupIPInternal(domain string, option dns.IPOption) ([]net.IP, er newError("failed to lookup ip for domain ", domain, " at server ", client.Name()).Base(err).WriteToLog() } if err != context.Canceled && err != context.DeadlineExceeded && err != errExpectedIPNonMatch { - return nil, err // Continues lookup for certain errors + return nil, err // Only continue lookup for certain errors } } + if len(errs) == 0 { + return nil, dns.ErrEmptyResponse + } return nil, newError("returning nil for domain ", domain).Base(errors.Combine(errs...)) } -// GetIPOption implements ClientWithIPOption. -func (s *DNS) GetIPOption() *dns.IPOption { - return &s.ipOption -} - -// SetQueryOption implements ClientWithIPOption. -func (s *DNS) SetQueryOption(isIPv4Enable, isIPv6Enable bool) { - s.ipOption.IPv4Enable = isIPv4Enable - s.ipOption.IPv6Enable = isIPv6Enable -} - -// SetFakeDNSOption implements ClientWithIPOption. -func (s *DNS) SetFakeDNSOption(isFakeEnable bool) { - s.ipOption.FakeEnable = isFakeEnable -} - 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)) + clientIdxs := make([]int, 0, len(s.clients)) domainRules := []string{} // Priority domain matching @@ -295,12 +330,12 @@ func (s *DNS) sortClients(domain string, option dns.IPOption) []*Client { switch { case clientUsed[info.clientIdx]: continue - case !option.FakeEnable && strings.EqualFold(client.Name(), "FakeDNS"): + case !option.FakeEnable && isFakeDNS(client.server): continue } clientUsed[info.clientIdx] = true clients = append(clients, client) - clientNames = append(clientNames, client.Name()) + clientIdxs = append(clientIdxs, int(info.clientIdx)) } // Default round-robin query @@ -309,7 +344,7 @@ func (s *DNS) sortClients(domain string, option dns.IPOption) []*Client { switch { case clientUsed[idx]: continue - case !option.FakeEnable && strings.EqualFold(client.Name(), "FakeDNS"): + case !option.FakeEnable && isFakeDNS(client.server): continue case client.fallbackStrategy == FallbackStrategy_Disabled: continue @@ -318,19 +353,42 @@ func (s *DNS) sortClients(domain string, option dns.IPOption) []*Client { } clientUsed[idx] = true clients = append(clients, client) - clientNames = append(clientNames, client.Name()) + clientIdxs = append(clientIdxs, idx) } 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, " ", toReqTypes(option)).AtDebug().WriteToLog() + if len(clientIdxs) > 0 { + newError("domain ", domain, " will use DNS in order: ", s.formatClientNames(clientIdxs, option), " ", toReqTypes(option)).AtDebug().WriteToLog() } return clients } +func (s *DNS) formatClientNames(clientIdxs []int, option dns.IPOption) []string { + clientNames := make([]string, 0, len(clientIdxs)) + counter := make(map[string]uint, len(clientIdxs)) + for _, clientIdx := range clientIdxs { + client := s.clients[clientIdx] + var name string + if option.With(client.queryStrategy).FakeEnable { + name = fmt.Sprintf("%s(DNS idx:%d)", client.fakeDNS.Name(), clientIdx) + } else { + name = client.Name() + } + counter[name]++ + clientNames = append(clientNames, name) + } + for idx, clientIdx := range clientIdxs { + name := clientNames[idx] + if counter[name] > 1 { + clientNames[idx] = fmt.Sprintf("%s(DNS idx:%d)", name, clientIdx) + } + } + return clientNames +} + func init() { common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) { return New(ctx, config.(*Config)) diff --git a/app/dns/dnscommon.go b/app/dns/dnscommon.go index 64c9d598a..41e60f7cc 100644 --- a/app/dns/dnscommon.go +++ b/app/dns/dnscommon.go @@ -226,3 +226,13 @@ L: return ipRecord, nil } + +func filterIP(ips []net.Address, option dns_feature.IPOption) []net.Address { + filtered := make([]net.Address, 0, len(ips)) + for _, ip := range ips { + if (ip.Family().IsIPv4() && option.IPv4Enable) || (ip.Family().IsIPv6() && option.IPv6Enable) { + filtered = append(filtered, ip) + } + } + return filtered +} diff --git a/app/dns/fakedns.go b/app/dns/fakedns.go new file mode 100644 index 000000000..81389daf2 --- /dev/null +++ b/app/dns/fakedns.go @@ -0,0 +1,87 @@ +//go:build !confonly +// +build !confonly + +package dns + +import ( + fakedns "github.com/v2fly/v2ray-core/v5/app/dns/fakedns" + "github.com/v2fly/v2ray-core/v5/common/net" + "github.com/v2fly/v2ray-core/v5/features/dns" +) + +// FakeDNSClient is an implementation of dns.Client with FakeDNS enabled. +type FakeDNSClient struct { + *DNS +} + +// LookupIP implements dns.Client. +func (s *FakeDNSClient) LookupIP(domain string) ([]net.IP, error) { + return s.lookupIPInternal(domain, dns.IPOption{IPv4Enable: true, IPv6Enable: true, FakeEnable: true}) +} + +// LookupIPv4 implements dns.IPv4Lookup. +func (s *FakeDNSClient) LookupIPv4(domain string) ([]net.IP, error) { + return s.lookupIPInternal(domain, dns.IPOption{IPv4Enable: true, FakeEnable: true}) +} + +// LookupIPv6 implements dns.IPv6Lookup. +func (s *FakeDNSClient) LookupIPv6(domain string) ([]net.IP, error) { + return s.lookupIPInternal(domain, dns.IPOption{IPv6Enable: true, FakeEnable: true}) +} + +// FakeDNSEngine is an implementation of dns.FakeDNSEngine based on a fully functional DNS. +type FakeDNSEngine struct { + dns *DNS + fakeHolders *fakedns.HolderMulti + fakeDefault *fakedns.HolderMulti +} + +// Type implements common.HasType. +func (*FakeDNSEngine) Type() interface{} { + return dns.FakeDNSEngineType() +} + +// Start implements common.Runnable. +func (f *FakeDNSEngine) Start() error { + return f.fakeHolders.Start() +} + +// Close implements common.Closable. +func (f *FakeDNSEngine) Close() error { + return f.fakeHolders.Close() +} + +// GetFakeIPForDomain implements dns.FakeDNSEngine. +func (f *FakeDNSEngine) GetFakeIPForDomain(domain string) []net.Address { + return f.GetFakeIPForDomain3(domain, true, true) +} + +// GetDomainFromFakeDNS implements dns.FakeDNSEngine. +func (f *FakeDNSEngine) GetDomainFromFakeDNS(ip net.Address) string { + return f.fakeHolders.GetDomainFromFakeDNS(ip) +} + +// IsIPInIPPool implements dns.FakeDNSEngineRev0. +func (f *FakeDNSEngine) IsIPInIPPool(ip net.Address) bool { + return f.fakeHolders.IsIPInIPPool(ip) +} + +// GetFakeIPForDomain3 implements dns.FakeDNSEngineRev0. +func (f *FakeDNSEngine) GetFakeIPForDomain3(domain string, IPv4 bool, IPv6 bool) []net.Address { // nolint: gocritic + option := dns.IPOption{IPv4Enable: IPv4, IPv6Enable: IPv6, FakeEnable: true} + for _, client := range f.dns.sortClients(domain, option) { + fakeServer, ok := client.fakeDNS.(*FakeDNSServer) + if !ok { + continue + } + fakeEngine, ok := fakeServer.fakeDNSEngine.(dns.FakeDNSEngineRev0) + if !ok { + return filterIP(fakeServer.fakeDNSEngine.GetFakeIPForDomain(domain), option) + } + return fakeEngine.GetFakeIPForDomain3(domain, IPv4, IPv6) + } + if f.fakeDefault != nil { + return f.fakeDefault.GetFakeIPForDomain3(domain, IPv4, IPv6) + } + return nil +} diff --git a/app/dns/fakedns/fake.go b/app/dns/fakedns/fake.go index b5ca89670..328a14778 100644 --- a/app/dns/fakedns/fake.go +++ b/app/dns/fakedns/fake.go @@ -42,7 +42,7 @@ func (fkdns *Holder) GetFakeIPForDomain3(domain string, ipv4, ipv6 bool) []net.A } func (*Holder) Type() interface{} { - return (*dns.FakeDNSEngine)(nil) + return dns.FakeDNSEngineType() } func (fkdns *Holder) Start() error { @@ -147,8 +147,6 @@ func (fkdns *Holder) GetDomainFromFakeDNS(ip net.Address) string { type HolderMulti struct { holders []*Holder - - config *FakeDnsPoolMulti } func (h *HolderMulti) IsIPInIPPool(ip net.Address) bool { @@ -188,18 +186,67 @@ func (h *HolderMulti) GetDomainFromFakeDNS(ip net.Address) string { return "" } +func (h *HolderMulti) IsEmpty() bool { + return len(h.holders) == 0 +} + +func (h *HolderMulti) AddPool(poolConfig *FakeDnsPool) (*Holder, error) { + _, newIPRange, err := gonet.ParseCIDR(poolConfig.IpPool) + if err != nil { + return nil, err + } + running := false + for _, v := range h.holders { + var ipRange *gonet.IPNet + if v.ipRange != nil { + ipRange = v.ipRange + running = true + } else { + _, ipRange, err = gonet.ParseCIDR(v.config.IpPool) + if err != nil { + return nil, err + } + } + if ipRange.String() == newIPRange.String() { + return v, nil + } + if ipRange.Contains(newIPRange.IP) || newIPRange.Contains(ipRange.IP) { + return nil, newError("Trying to add ip pool ", newIPRange, " that overlaps with existing ip pool ", ipRange) + } + } + holder, err := NewFakeDNSHolderConfigOnly(poolConfig) + if err != nil { + return nil, err + } + if running { + if err := holder.Start(); err != nil { + return nil, err + } + } + h.holders = append(h.holders, holder) + return holder, nil +} + +func (h *HolderMulti) AddPoolMulti(poolMultiConfig *FakeDnsPoolMulti) (*HolderMulti, error) { + holderMulti := &HolderMulti{} + for _, poolConfig := range poolMultiConfig.Pools { + pool, err := h.AddPool(poolConfig) + if err != nil { + return nil, err + } + holderMulti.holders = append(holderMulti.holders, pool) + } + return holderMulti, nil // Returned holderMulti holds references to pools managed by `h` +} + func (h *HolderMulti) Type() interface{} { - return (*dns.FakeDNSEngine)(nil) + return dns.FakeDNSEngineType() } func (h *HolderMulti) Start() error { for _, v := range h.holders { - if v.config != nil && v.config.IpPool != "" && v.config.LruSize != 0 { - if err := v.Start(); err != nil { - return newError("Cannot start all fake dns pools").Base(err) - } - } else { - return newError("invalid fakeDNS setting") + if err := v.Start(); err != nil { + return newError("Cannot start all fake dns pools").Base(err) } } return nil @@ -214,20 +261,19 @@ func (h *HolderMulti) Close() error { return nil } -func (h *HolderMulti) createHolderGroups() error { - for _, v := range h.config.Pools { - holder, err := NewFakeDNSHolderConfigOnly(v) +func (h *HolderMulti) createHolderGroups(conf *FakeDnsPoolMulti) error { + for _, pool := range conf.Pools { + _, err := h.AddPool(pool) if err != nil { return err } - h.holders = append(h.holders, holder) } return nil } func NewFakeDNSHolderMulti(conf *FakeDnsPoolMulti) (*HolderMulti, error) { - holderMulti := &HolderMulti{nil, conf} - if err := holderMulti.createHolderGroups(); err != nil { + holderMulti := &HolderMulti{} + if err := holderMulti.createHolderGroups(conf); err != nil { return nil, err } return holderMulti, nil diff --git a/app/dns/fakedns/fakedns_test.go b/app/dns/fakedns/fakedns_test.go index 9df481506..3d61dc71f 100644 --- a/app/dns/fakedns/fakedns_test.go +++ b/app/dns/fakedns/fakedns_test.go @@ -217,3 +217,99 @@ func TestFakeDNSMulti(t *testing.T) { }) }) } + +func TestFakeDNSMultiAddPool(t *testing.T) { + runTest := func(runTestBeforeStart bool) { + fakeMulti, err := NewFakeDNSHolderMulti(&FakeDnsPoolMulti{ + Pools: []*FakeDnsPool{{ + IpPool: "240.0.0.0/12", + LruSize: 256, + }, { + IpPool: "fddd:c5b4:ff5f:f4f0::/64", + LruSize: 256, + }}, + }) + common.Must(err) + if !runTestBeforeStart { + err = fakeMulti.Start() + common.Must(err) + } + t.Run("ipv4_return_existing", func(t *testing.T) { + pool, err := fakeMulti.AddPool(&FakeDnsPool{ + IpPool: "240.0.0.1/12", + LruSize: 256, + }) + common.Must(err) + if pool != fakeMulti.holders[0] { + t.Error("HolderMulti.AddPool not returning same holder for existing IPv4 pool") + } + }) + t.Run("ipv6_return_existing", func(t *testing.T) { + pool, err := fakeMulti.AddPool(&FakeDnsPool{ + IpPool: "fddd:c5b4:ff5f:f4f0::1/64", + LruSize: 256, + }) + common.Must(err) + if pool != fakeMulti.holders[1] { + t.Error("HolderMulti.AddPool not returning same holder for existing IPv6 pool") + } + }) + t.Run("ipv4_reject_overlap", func(t *testing.T) { + _, err := fakeMulti.AddPool(&FakeDnsPool{ + IpPool: "240.8.0.0/13", + LruSize: 256, + }) + if err == nil { + t.Error("HolderMulti.AddPool not rejecting IPv4 pool that is subnet of existing ones") + } + _, err = fakeMulti.AddPool(&FakeDnsPool{ + IpPool: "240.0.0.0/11", + LruSize: 256, + }) + if err == nil { + t.Error("HolderMulti.AddPool not rejecting IPv4 pool that contains existing ones") + } + }) + t.Run("new_pool", func(t *testing.T) { + pool, err := fakeMulti.AddPool(&FakeDnsPool{ + IpPool: "192.168.168.0/16", + LruSize: 256, + }) + common.Must(err) + if pool != fakeMulti.holders[2] { + t.Error("HolderMulti.AddPool not creating new holder for new IPv4 pool") + } + }) + t.Run("add_pool_multi", func(t *testing.T) { + pools, err := fakeMulti.AddPoolMulti(&FakeDnsPoolMulti{ + Pools: []*FakeDnsPool{{ + IpPool: "192.168.168.0/16", + LruSize: 256, + }, { + IpPool: "2001:1111::/64", + LruSize: 256, + }}, + }) + common.Must(err) + if len(pools.holders) != 2 { + t.Error("HolderMulti.AddPoolMutli not returning holderMulti that has the same length as passed PoolMulti config") + } + if pools.holders[0] != fakeMulti.holders[2] { + t.Error("HolderMulti.AddPoolMulti not returning same holder for existing IPv4 pool 192.168.168.0/16") + } + if pools.holders[1] != fakeMulti.holders[3] { + t.Error("HolderMulti.AddPoolMulti not creating new holder for new IPv6 pool 2001:1111::/64") + } + }) + if runTestBeforeStart { + err = fakeMulti.Start() + common.Must(err) + } + } + t.Run("addPoolBeforeStart", func(t *testing.T) { + runTest(true) + }) + t.Run("addPoolAfterStart", func(t *testing.T) { + runTest(false) + }) +} diff --git a/app/dns/fakedns_test.go b/app/dns/fakedns_test.go new file mode 100644 index 000000000..974288107 --- /dev/null +++ b/app/dns/fakedns_test.go @@ -0,0 +1,249 @@ +package dns_test + +import ( + "testing" + "time" + + "github.com/google/go-cmp/cmp" + "github.com/miekg/dns" + "google.golang.org/protobuf/types/known/anypb" + + core "github.com/v2fly/v2ray-core/v5" + "github.com/v2fly/v2ray-core/v5/app/dispatcher" + . "github.com/v2fly/v2ray-core/v5/app/dns" + "github.com/v2fly/v2ray-core/v5/app/dns/fakedns" + "github.com/v2fly/v2ray-core/v5/app/policy" + "github.com/v2fly/v2ray-core/v5/app/proxyman" + "github.com/v2fly/v2ray-core/v5/common" + "github.com/v2fly/v2ray-core/v5/common/net" + "github.com/v2fly/v2ray-core/v5/common/serial" + feature_dns "github.com/v2fly/v2ray-core/v5/features/dns" + "github.com/v2fly/v2ray-core/v5/proxy/freedom" + "github.com/v2fly/v2ray-core/v5/testing/servers/udp" +) + +func TestFakeDNS(t *testing.T) { + port := udp.PickPort() + + dnsServer := dns.Server{ + Addr: "127.0.0.1:" + port.String(), + Net: "udp", + Handler: &staticHandler{}, + UDPSize: 1200, + } + + go dnsServer.ListenAndServe() + time.Sleep(time.Second) + + config := &core.Config{ + App: []*anypb.Any{ + serial.ToTypedMessage(&Config{ + NameServer: []*NameServer{ + { // "fakedns" + Address: &net.Endpoint{ + Network: net.Network_UDP, + Address: &net.IPOrDomain{ + Address: &net.IPOrDomain_Domain{ + Domain: "fakedns", + }, + }, + Port: uint32(53), + }, + }, + { // { "address": "127.0.0.1", "port": "", "domains": ["domain:google.com"], "fakedns": "198.19.0.0/16", "fallbackStrategy": "disabled" } + Address: &net.Endpoint{ + Network: net.Network_UDP, + Address: &net.IPOrDomain{ + Address: &net.IPOrDomain_Ip{ + Ip: []byte{127, 0, 0, 1}, + }, + }, + Port: uint32(port), + }, + PrioritizedDomain: []*NameServer_PriorityDomain{ + {Type: DomainMatchingType_Subdomain, Domain: "google.com"}, + }, + FakeDns: &fakedns.FakeDnsPoolMulti{ + Pools: []*fakedns.FakeDnsPool{ + {IpPool: "198.19.0.0/16", LruSize: 256}, + }, + }, + FallbackStrategy: FallbackStrategy_Disabled.Enum(), + }, + }, + FakeDns: &fakedns.FakeDnsPoolMulti{ // "fakedns": "198.18.0.0/16" + Pools: []*fakedns.FakeDnsPool{ + {IpPool: "198.18.0.0/16", LruSize: 256}, + }, + }, + }), + serial.ToTypedMessage(&dispatcher.Config{}), + serial.ToTypedMessage(&proxyman.OutboundConfig{}), + serial.ToTypedMessage(&policy.Config{}), + }, + Outbound: []*core.OutboundHandlerConfig{ + { + ProxySettings: serial.ToTypedMessage(&freedom.Config{}), + }, + }, + } + + v, err := core.New(config) + common.Must(err) + common.Must(v.Start()) + + dnsClient := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client) + fakeClient := dnsClient.(feature_dns.ClientWithFakeDNS).AsFakeDNSClient() + + var fakeIPForFacebook net.IP + var fakeIPForGoogle net.IP + + { // Lookup facebook.com with Fake Client will return 198.18.0.0/16 (global fake pool) + ips, err := fakeClient.LookupIP("facebook.com") + if err != nil { + t.Fatal("unexpected error: ", err) + } + for _, ip := range ips { + if !(&net.IPNet{IP: net.IP{198, 18, 0, 0}, Mask: net.CIDRMask(16, 8*net.IPv4len)}).Contains(ip) { + t.Fatal("Lookup facebook.com with fake client not in global pool 198.18.0.0/16") + } + } + fakeIPForFacebook = ips[0] + } + { // Lookup facebook.com with Normal Client with return empty record (because UDP server matching "domain:google.com" are configured with fallback disabled) + _, err := dnsClient.LookupIP("facebook.com") + if err != feature_dns.ErrEmptyResponse { + t.Fatal("Lookup facebook.com with normal client not returning empty response") + } + } + { // Lookup google.com with Fake Client will return 198.19.0.0/16 (local fake pool) + ips, err := fakeClient.LookupIP("google.com") + if err != nil { + t.Fatal("unexpected error: ", err) + } + for _, ip := range ips { + if !(&net.IPNet{IP: net.IP{198, 19, 0, 0}, Mask: net.CIDRMask(16, 8*net.IPv4len)}).Contains(ip) { + t.Fatal("Lookup google.com with fake client not in global pool 198.19.0.0/16") + } + } + fakeIPForGoogle = ips[0] + } + { // Lookup google.com with Normal Client will return 8.8.8.8 + ips, err := dnsClient.LookupIP("google.com") + if err != nil { + t.Fatal("unexpected error: ", err) + } + if r := cmp.Diff(ips, []net.IP{{8, 8, 8, 8}}); r != "" { + t.Fatal("Lookup google.com with normal client not returning 8.8.8.8") + } + } + + fakeEngine := dnsClient.(feature_dns.ClientWithFakeDNS).AsFakeDNSEngine().(feature_dns.FakeDNSEngineRev0) + { + if !fakeEngine.IsIPInIPPool(net.IPAddress(fakeIPForFacebook)) { + t.Fatal("Fake IP of domain facebook.com not in FakeDNSEngine's pool.") + } + if !fakeEngine.IsIPInIPPool(net.IPAddress(fakeIPForGoogle)) { + t.Fatal("Fake IP of domain google.com not in FakeDNSEngine's pool.") + } + } + { + if domain := fakeEngine.GetDomainFromFakeDNS(net.IPAddress(fakeIPForFacebook)); domain != "facebook.com" { + t.Fatal("Recover fake IP to get domain facebook.com failed.") + } + if domain := fakeEngine.GetDomainFromFakeDNS(net.IPAddress(fakeIPForGoogle)); domain != "google.com" { + t.Fatal("Recover fake IP to get domain google.com failed.") + } + } + { + ips := fakeEngine.GetFakeIPForDomain("api.google.com") + for _, ip := range ips { + if !(&net.IPNet{IP: net.IP{198, 19, 0, 0}, Mask: net.CIDRMask(16, 8*net.IPv4len)}).Contains(ip.IP()) { + t.Fatal("Fake IP for api.google.com not in local pool 198.19.0.0/16") + } + } + } + { + ips := fakeEngine.GetFakeIPForDomain3("v2fly.org", true, false) + for _, ip := range ips { + if !(&net.IPNet{IP: net.IP{198, 18, 0, 0}, Mask: net.CIDRMask(16, 8*net.IPv4len)}).Contains(ip.IP()) { + t.Fatal("Fake IP for v2fly.org not in global pool 198.18.0.0/16") + } + } + } +} + +func TestFakeDNSEmptyGlobalConfig(t *testing.T) { + config := &core.Config{ + App: []*anypb.Any{ + serial.ToTypedMessage(&Config{ + NameServer: []*NameServer{ + { // "fakedns" + Address: &net.Endpoint{ + Network: net.Network_UDP, + Address: &net.IPOrDomain{ + Address: &net.IPOrDomain_Domain{ + Domain: "fakedns", + }, + }, + }, + QueryStrategy: QueryStrategy_USE_IP4.Enum(), + }, + { // "localhost" + Address: &net.Endpoint{ + Network: net.Network_UDP, + Address: &net.IPOrDomain{ + Address: &net.IPOrDomain_Domain{ + Domain: "localhost", + }, + }, + }, + QueryStrategy: QueryStrategy_USE_IP6.Enum(), + PrioritizedDomain: []*NameServer_PriorityDomain{ + {Type: DomainMatchingType_Subdomain, Domain: "google.com"}, + }, + FakeDns: &fakedns.FakeDnsPoolMulti{Pools: []*fakedns.FakeDnsPool{}}, // "fakedns": true + }, + }, + }), + serial.ToTypedMessage(&dispatcher.Config{}), + serial.ToTypedMessage(&proxyman.OutboundConfig{}), + serial.ToTypedMessage(&policy.Config{}), + }, + Outbound: []*core.OutboundHandlerConfig{ + { + ProxySettings: serial.ToTypedMessage(&freedom.Config{}), + }, + }, + } + + v, err := core.New(config) + common.Must(err) + common.Must(v.Start()) + + dnsClient := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client) + fakeClient := dnsClient.(feature_dns.ClientWithFakeDNS).AsFakeDNSClient() + + { // Lookup facebook.com will return 198.18.0.0/15 (default IPv4 pool) + ips, err := fakeClient.LookupIP("facebook.com") + if err != nil { + t.Fatal("unexpected error: ", err) + } + for _, ip := range ips { + if !(&net.IPNet{IP: net.IP{198, 18, 0, 0}, Mask: net.CIDRMask(15, 8*net.IPv4len)}).Contains(ip) { + t.Fatal("Lookup facebook.com with fake client not in default IPv4 pool 198.18.0.0/15") + } + } + } + { // Lookup google.com will return fc00::/18 (default IPv6 pool) + ips, err := fakeClient.LookupIP("google.com") + if err != nil { + t.Fatal("unexpected error: ", err) + } + for _, ip := range ips { + if !(&net.IPNet{IP: net.IP{0xfc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, Mask: net.CIDRMask(18, 8*net.IPv6len)}).Contains(ip) { + t.Fatal("Lookup google.com with fake client not in default IPv6 pool fc00::/18") + } + } + } +} diff --git a/app/dns/hosts.go b/app/dns/hosts.go index 2032ee1a1..6c230433b 100644 --- a/app/dns/hosts.go +++ b/app/dns/hosts.go @@ -67,16 +67,6 @@ func NewStaticHosts(hosts []*HostMapping, legacy map[string]*net.IPOrDomain) (*S return sh, nil } -func filterIP(ips []net.Address, option dns.IPOption) []net.Address { - filtered := make([]net.Address, 0, len(ips)) - for _, ip := range ips { - if (ip.Family().IsIPv4() && option.IPv4Enable) || (ip.Family().IsIPv6() && option.IPv6Enable) { - filtered = append(filtered, ip) - } - } - return filtered -} - func (h *StaticHosts) lookupInternal(domain string) []net.Address { var ips []net.Address for _, id := range h.matchers.Match(domain) { diff --git a/app/dns/nameserver.go b/app/dns/nameserver.go index 1af0844b4..13957a522 100644 --- a/app/dns/nameserver.go +++ b/app/dns/nameserver.go @@ -7,6 +7,7 @@ import ( "time" core "github.com/v2fly/v2ray-core/v5" + "github.com/v2fly/v2ray-core/v5/app/dns/fakedns" "github.com/v2fly/v2ray-core/v5/app/router" "github.com/v2fly/v2ray-core/v5/common/errors" "github.com/v2fly/v2ray-core/v5/common/net" @@ -36,41 +37,48 @@ type Client struct { domains []string expectIPs []*router.GeoIPMatcher + fakeDNS Server } var errExpectedIPNonMatch = errors.New("expectIPs not match") // NewServer creates a name server object according to the network destination url. -func NewServer(dest net.Destination, dispatcher routing.Dispatcher) (Server, error) { +func NewServer(ctx context.Context, dest net.Destination, onCreated func(Server) error) error { + onCreatedWithError := func(server Server, err error) error { + if err != nil { + return err + } + return onCreated(server) + } if address := dest.Address; address.Family().IsDomain() { u, err := url.Parse(address.Domain()) if err != nil { - return nil, err + return 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.Scheme, "tcp"): // DNS-over-TCP Remote mode - return NewTCPNameServer(u, dispatcher) - case strings.EqualFold(u.Scheme, "tcp+local"): // DNS-over-TCP Local mode - return NewTCPLocalNameServer(u) + return onCreated(NewLocalNameServer()) case strings.EqualFold(u.String(), "fakedns"): - return NewFakeDNSServer(), nil + return core.RequireFeatures(ctx, func(fakedns dns.FakeDNSEngine) error { return onCreated(NewFakeDNSServer(fakedns)) }) + case strings.EqualFold(u.Scheme, "https"): // DOH Remote mode + return core.RequireFeatures(ctx, func(dispatcher routing.Dispatcher) error { return onCreatedWithError(NewDoHNameServer(u, dispatcher)) }) + case strings.EqualFold(u.Scheme, "https+local"): // DOH Local mode + return onCreated(NewDoHLocalNameServer(u)) + case strings.EqualFold(u.Scheme, "tcp"): // DNS-over-TCP Remote mode + return core.RequireFeatures(ctx, func(dispatcher routing.Dispatcher) error { return onCreatedWithError(NewTCPNameServer(u, dispatcher)) }) + case strings.EqualFold(u.Scheme, "tcp+local"): // DNS-over-TCP Local mode + return onCreatedWithError(NewTCPLocalNameServer(u)) + case strings.EqualFold(u.Scheme, "quic+local"): // DNS-over-QUIC Local mode + return onCreatedWithError(NewQUICNameServer(u)) } } 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 core.RequireFeatures(ctx, func(dispatcher routing.Dispatcher) error { return onCreated(NewClassicNameServer(dest, dispatcher)) }) } - return nil, newError("No available name server could be created from ", dest).AtWarning() + return 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. @@ -78,12 +86,7 @@ func NewClient(ctx context.Context, ns *NameServer, dns *Config) (*Client, error client := &Client{} // Create DNS server instance - 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() - } + err := NewServer(ctx, ns.Address.AsDestination(), func(server Server) error { client.server = server return nil }) @@ -130,6 +133,27 @@ func NewClient(ctx context.Context, ns *NameServer, dns *Config) (*Client, error *ns.FallbackStrategy = FallbackStrategy_DisabledIfAnyMatch } } + if (ns.FakeDns != nil && len(ns.FakeDns.Pools) == 0) || // Use globally configured fake ip pool if: 1. `fakedns` config is set, but empty(represents { "fakedns": true } in JSON settings); + ns.FakeDns == nil && strings.EqualFold(ns.Address.Address.GetDomain(), "fakedns") { // 2. `fakedns` config not set, but server address is `fakedns`(represents { "address": "fakedns" } in JSON settings). + if dns.FakeDns != nil { + ns.FakeDns = dns.FakeDns + } else { + ns.FakeDns = &fakedns.FakeDnsPoolMulti{} + queryStrategy := toIPOption(*ns.QueryStrategy) + if queryStrategy.IPv4Enable { + ns.FakeDns.Pools = append(ns.FakeDns.Pools, &fakedns.FakeDnsPool{ + IpPool: "198.18.0.0/15", + LruSize: 65535, + }) + } + if queryStrategy.IPv6Enable { + ns.FakeDns.Pools = append(ns.FakeDns.Pools, &fakedns.FakeDnsPool{ + IpPool: "fc00::/18", + LruSize: 65535, + }) + } + } + } // Priotize local domains with specific TLDs or without any dot to local DNS if strings.EqualFold(ns.Address.Address.GetDomain(), "localhost") { @@ -154,21 +178,25 @@ func (c *Client) Name() string { return c.server.Name() } -// QueryIP send DNS query to the name server with the client's IP. +// QueryIP send DNS query to the name server with the client's IP and IP options. func (c *Client) QueryIP(ctx context.Context, domain string, option dns.IPOption) ([]net.IP, error) { queryOption := option.With(c.queryStrategy) if !queryOption.IsValid() { newError(c.server.Name(), " returns empty answer: ", domain, ". ", toReqTypes(option)).AtInfo().WriteToLog() return nil, dns.ErrEmptyResponse } + server := c.server + if queryOption.FakeEnable && c.fakeDNS != nil { + server = c.fakeDNS + } disableCache := c.cacheStrategy == CacheStrategy_CacheDisabled ctx = session.ContextWithInbound(ctx, &session.Inbound{Tag: c.tag}) ctx, cancel := context.WithTimeout(ctx, 4*time.Second) - ips, err := c.server.QueryIP(ctx, domain, c.clientIP, queryOption, disableCache) + ips, err := server.QueryIP(ctx, domain, c.clientIP, queryOption, disableCache) cancel() - if err != nil { + if err != nil || queryOption.FakeEnable { return ips, err } return c.MatchExpectedIPs(domain, ips) diff --git a/app/dns/nameserver_fakedns.go b/app/dns/nameserver_fakedns.go index 1b81fd0cc..018f3fa8d 100644 --- a/app/dns/nameserver_fakedns.go +++ b/app/dns/nameserver_fakedns.go @@ -15,15 +15,18 @@ type FakeDNSServer struct { fakeDNSEngine dns.FakeDNSEngine } -func NewFakeDNSServer() *FakeDNSServer { - return &FakeDNSServer{} +func NewFakeDNSServer(fakeDNSEngine dns.FakeDNSEngine) *FakeDNSServer { + return &FakeDNSServer{fakeDNSEngine: fakeDNSEngine} } func (FakeDNSServer) Name() string { - return "FakeDNS" + return "fakedns" } func (f *FakeDNSServer) QueryIP(ctx context.Context, domain string, _ net.IP, opt dns.IPOption, _ bool) ([]net.IP, error) { + if !opt.FakeEnable { + return nil, nil // Returning empty ip record with no error will continue DNS lookup, effectively indicating that this server is disabled. + } if f.fakeDNSEngine == nil { if err := core.RequireFeatures(ctx, func(fd dns.FakeDNSEngine) { f.fakeDNSEngine = fd @@ -35,7 +38,7 @@ func (f *FakeDNSServer) QueryIP(ctx context.Context, domain string, _ net.IP, op if fkr0, ok := f.fakeDNSEngine.(dns.FakeDNSEngineRev0); ok { ips = fkr0.GetFakeIPForDomain3(domain, opt.IPv4Enable, opt.IPv6Enable) } else { - ips = f.fakeDNSEngine.GetFakeIPForDomain(domain) + ips = filterIP(f.fakeDNSEngine.GetFakeIPForDomain(domain), opt) } netIP, err := toNetIP(ips) @@ -50,3 +53,8 @@ func (f *FakeDNSServer) QueryIP(ctx context.Context, domain string, _ net.IP, op } return nil, dns.ErrEmptyResponse } + +func isFakeDNS(server Server) bool { + _, ok := server.(*FakeDNSServer) + return ok +} diff --git a/common/net/system.go b/common/net/system.go index 84dd952e0..cb5657e96 100644 --- a/common/net/system.go +++ b/common/net/system.go @@ -19,6 +19,7 @@ var ( ListenUDP = net.ListenUDP ListenUnix = net.ListenUnix LookupIP = net.LookupIP + ParseCIDR = net.ParseCIDR ParseIP = net.ParseIP ResolveUDPAddr = net.ResolveUDPAddr ResolveUnixAddr = net.ResolveUnixAddr diff --git a/features/dns/client.go b/features/dns/client.go index 5fa5e2aa8..faeb71699 100644 --- a/features/dns/client.go +++ b/features/dns/client.go @@ -50,18 +50,30 @@ type IPv6Lookup interface { LookupIPv6(domain string) ([]net.IP, error) } -// ClientWithIPOption is an optional feature for querying DNS information. +// LookupIPWithOption is a helper function for querying DNS information from a dns.Client with dns.IPOption. // // v2ray:api:beta -type ClientWithIPOption interface { - // GetIPOption returns IPOption for the DNS client. - GetIPOption() *IPOption - - // SetQueryOption sets IPv4Enable and IPv6Enable for the DNS client. - SetQueryOption(isIPv4Enable, isIPv6Enable bool) - - // SetFakeDNSOption sets FakeEnable option for DNS client. - SetFakeDNSOption(isFakeEnable bool) +func LookupIPWithOption(client Client, domain string, option IPOption) ([]net.IP, error) { + if option.FakeEnable { + if clientWithFakeDNS, ok := client.(ClientWithFakeDNS); ok { + client = clientWithFakeDNS.AsFakeDNSClient() + } + } + if option.IPv4Enable && !option.IPv6Enable { + if ipv4Lookup, ok := client.(IPv4Lookup); ok { + return ipv4Lookup.LookupIPv4(domain) + } else { + return nil, errors.New("dns.Client doesn't implement IPv4Lookup") + } + } + if option.IPv6Enable && !option.IPv4Enable { + if ipv6Lookup, ok := client.(IPv6Lookup); ok { + return ipv6Lookup.LookupIPv6(domain) + } else { + return nil, errors.New("dns.Client doesn't implement IPv6Lookup") + } + } + return client.LookupIP(domain) } // ClientType returns the type of Client interface. Can be used for implementing common.HasType. diff --git a/features/dns/fakedns.go b/features/dns/fakedns.go index af54aabb9..a4715dfc1 100644 --- a/features/dns/fakedns.go +++ b/features/dns/fakedns.go @@ -5,14 +5,46 @@ import ( "github.com/v2fly/v2ray-core/v5/features" ) +// FakeDNSEngine is a V2Ray feature for converting between domain and fake IPs. +// +// v2ray:api:beta type FakeDNSEngine interface { features.Feature + + // GetFakeIPForDomain returns fake IP addresses for the given domain, and registers the domain with the returned IPs. GetFakeIPForDomain(domain string) []net.Address + + // GetDomainFromFakeDNS returns the bound domain name for the given fake IP. GetDomainFromFakeDNS(ip net.Address) string } +// FakeDNSEngineRev0 adds additional APIs for FakeDNSEngine. +// +// v2ray:api:beta type FakeDNSEngineRev0 interface { FakeDNSEngine + + // IsIPInIPPool tests whether the given IP address resides in managed fake IP pools. IsIPInIPPool(ip net.Address) bool - GetFakeIPForDomain3(domain string, IPv4, IPv6 bool) []net.Address + + // GetFakeIPForDomain3 registers and returns fake IP addresses for the given domain in IPv4 and/or IPv6. + GetFakeIPForDomain3(domain string, IPv4 bool, IPv6 bool) []net.Address +} + +// ClientWithFakeDNS is an optional feature for utilizing FakeDNS feature of DNS client. +// +// v2ray:api:beta +type ClientWithFakeDNS interface { + // AsFakeDNSClient converts the client to dns.Client that enables FakeDNS querying option. + AsFakeDNSClient() Client + + // AsFakeDNSEngine converts the client to dns.FakeDNSEngine that could serve FakeDNSEngine feature. + AsFakeDNSEngine() FakeDNSEngine +} + +// FakeDNSEngineType returns the type of FakeDNSEngine interface. Can be used for implementing common.HasType. +// +// v2ray:api:beta +func FakeDNSEngineType() interface{} { + return (*FakeDNSEngine)(nil) } diff --git a/features/routing/dns/context.go b/features/routing/dns/context.go index 2be975657..abf500c80 100644 --- a/features/routing/dns/context.go +++ b/features/routing/dns/context.go @@ -26,35 +26,7 @@ func (ctx *ResolvableContext) GetTargetIPs() []net.IP { } if domain := ctx.GetTargetDomain(); len(domain) != 0 { - lookupFunc := ctx.dnsClient.LookupIP - ipOption := &dns.IPOption{ - IPv4Enable: true, - IPv6Enable: true, - } - - if c, ok := ctx.dnsClient.(dns.ClientWithIPOption); ok { - ipOption = c.GetIPOption() - c.SetFakeDNSOption(false) // Skip FakeDNS. - } else { - newError("ctx.dnsClient doesn't implement ClientWithIPOption").AtDebug().WriteToLog() - } - - switch { - case ipOption.IPv4Enable && !ipOption.IPv6Enable: - if lookupIPv4, ok := ctx.dnsClient.(dns.IPv4Lookup); ok { - lookupFunc = lookupIPv4.LookupIPv4 - } else { - newError("ctx.dnsClient doesn't implement IPv4Lookup. Use LookupIP instead.").AtDebug().WriteToLog() - } - case !ipOption.IPv4Enable && ipOption.IPv6Enable: - if lookupIPv6, ok := ctx.dnsClient.(dns.IPv6Lookup); ok { - lookupFunc = lookupIPv6.LookupIPv6 - } else { - newError("ctx.dnsClient doesn't implement IPv6Lookup. Use LookupIP instead.").AtDebug().WriteToLog() - } - } - - ips, err := lookupFunc(domain) + ips, err := ctx.dnsClient.LookupIP(domain) if err == nil { ctx.resolvedIPs = ips return ips diff --git a/infra/conf/synthetic/dns/dns.go b/infra/conf/synthetic/dns/dns.go index 4aac359c0..e7519e364 100644 --- a/infra/conf/synthetic/dns/dns.go +++ b/infra/conf/synthetic/dns/dns.go @@ -9,6 +9,7 @@ import ( "strings" "github.com/v2fly/v2ray-core/v5/app/dns" + "github.com/v2fly/v2ray-core/v5/app/dns/fakedns" "github.com/v2fly/v2ray-core/v5/app/router/routercommon" "github.com/v2fly/v2ray-core/v5/common/net" "github.com/v2fly/v2ray-core/v5/common/platform" @@ -28,6 +29,7 @@ type NameServerConfig struct { SkipFallback bool Domains []string ExpectIPs cfgcommon.StringList + FakeDNS FakeDNSConfigExtend cfgctx context.Context } @@ -50,6 +52,7 @@ func (c *NameServerConfig) UnmarshalJSON(data []byte) error { SkipFallback bool `json:"skipFallback"` Domains []string `json:"domains"` ExpectIPs cfgcommon.StringList `json:"expectIps"` + FakeDNS FakeDNSConfigExtend `json:"fakedns"` } if err := json.Unmarshal(data, &advanced); err == nil { c.Address = advanced.Address @@ -62,6 +65,7 @@ func (c *NameServerConfig) UnmarshalJSON(data []byte) error { c.SkipFallback = advanced.SkipFallback c.Domains = advanced.Domains c.ExpectIPs = advanced.ExpectIPs + c.FakeDNS = advanced.FakeDNS return nil } @@ -121,6 +125,15 @@ func (c *NameServerConfig) Build() (*dns.NameServer, error) { return nil, newError("invalid IP rule: ", c.ExpectIPs).Base(err) } + var fakeDNS *fakedns.FakeDnsPoolMulti + if c.FakeDNS.FakeDNSConfig != nil { + fake, err := c.FakeDNS.FakeDNSConfig.Build() + if err != nil { + return nil, newError("failed to build fakedns").Base(err) + } + fakeDNS = fake + } + var myClientIP []byte if c.ClientIP != nil { if !c.ClientIP.Family().IsIP() { @@ -178,6 +191,7 @@ func (c *NameServerConfig) Build() (*dns.NameServer, error) { PrioritizedDomain: domains, Geoip: geoipList, OriginalRules: originalRules, + FakeDns: fakeDNS, }, nil } @@ -192,6 +206,7 @@ var typeMap = map[routercommon.Domain_Type]dns.DomainMatchingType{ type DNSConfig struct { // nolint: revive Servers []*NameServerConfig `json:"servers"` Hosts map[string]*HostAddress `json:"hosts"` + FakeDNS *FakeDNSConfig `json:"fakedns"` DomainMatcher string `json:"domainMatcher"` ClientIP *cfgcommon.Address `json:"clientIp"` Tag string `json:"tag"` @@ -435,5 +450,13 @@ func (c *DNSConfig) Build() (*dns.Config, error) { config.StaticHosts = append(config.StaticHosts, mappings...) } + if c.FakeDNS != nil { + fakeDNS, err := c.FakeDNS.Build() + if err != nil { + return nil, newError("failed to build fakedns").Base(err) + } + config.FakeDns = fakeDNS + } + return config, nil } diff --git a/infra/conf/synthetic/dns/dns_test.go b/infra/conf/synthetic/dns/dns_test.go index 022ab66d5..3abc28b84 100644 --- a/infra/conf/synthetic/dns/dns_test.go +++ b/infra/conf/synthetic/dns/dns_test.go @@ -11,6 +11,7 @@ import ( "google.golang.org/protobuf/runtime/protoiface" "github.com/v2fly/v2ray-core/v5/app/dns" + "github.com/v2fly/v2ray-core/v5/app/dns/fakedns" "github.com/v2fly/v2ray-core/v5/common" "github.com/v2fly/v2ray-core/v5/common/net" "github.com/v2fly/v2ray-core/v5/common/platform/filesystem" @@ -149,5 +150,141 @@ func TestDNSConfigParsing(t *testing.T) { DisableFallback: true, }, }, + { + Input: `{ + "servers": [{ + "address": "fakedns", + "tag": "fake", + "queryStrategy": "UseIPv6", + "fallbackStrategy": "disabledIfAnyMatch", + "fakedns": true + }, { + "address": "8.8.8.8", + "port": 5353, + "tag": "local", + "clientIp": "10.0.0.1", + "queryStrategy": "UseIP", + "cacheStrategy": "enabled", + "fallbackStrategy": "disabled", + "domains": ["domain:v2fly.org"], + "fakedns": ["198.19.0.0/16", "fc01::/18"] + }], + "hosts": { + "v2fly.org": "127.0.0.1", + "www.v2fly.org": ["1.2.3.4", "5.6.7.8"], + "domain:example.com": "google.com", + "geosite:test": ["127.0.0.1", "127.0.0.2"], + "keyword:google": ["8.8.8.8", "8.8.4.4"], + "regexp:.*\\.com": "8.8.4.4" + }, + "fakedns": [ + { "ipPool": "198.18.0.0/16", "poolSize": 32768 }, + { "ipPool": "fc00::/18", "poolSize": 32768 } + ], + "tag": "global", + "clientIp": "10.0.0.1", + "queryStrategy": "UseIPv4", + "cacheStrategy": "disabled", + "fallbackStrategy": "enabled" + }`, + Parser: parserCreator(), + Output: &dns.Config{ + NameServer: []*dns.NameServer{ + { + Address: &net.Endpoint{ + Address: &net.IPOrDomain{ + Address: &net.IPOrDomain_Domain{ + Domain: "fakedns", + }, + }, + Network: net.Network_UDP, + }, + Tag: "fake", + QueryStrategy: dns.QueryStrategy_USE_IP6.Enum(), + FallbackStrategy: dns.FallbackStrategy_DisabledIfAnyMatch.Enum(), + FakeDns: &fakedns.FakeDnsPoolMulti{ + Pools: []*fakedns.FakeDnsPool{}, + }, + }, + { + Address: &net.Endpoint{ + Address: &net.IPOrDomain{ + Address: &net.IPOrDomain_Ip{ + Ip: []byte{8, 8, 8, 8}, + }, + }, + Network: net.Network_UDP, + Port: 5353, + }, + Tag: "local", + ClientIp: []byte{10, 0, 0, 1}, + QueryStrategy: dns.QueryStrategy_USE_IP.Enum(), + CacheStrategy: dns.CacheStrategy_CacheEnabled.Enum(), + FallbackStrategy: dns.FallbackStrategy_Disabled.Enum(), + PrioritizedDomain: []*dns.NameServer_PriorityDomain{ + { + Type: dns.DomainMatchingType_Subdomain, + Domain: "v2fly.org", + }, + }, + OriginalRules: []*dns.NameServer_OriginalRule{ + { + Rule: "domain:v2fly.org", + Size: 1, + }, + }, + FakeDns: &fakedns.FakeDnsPoolMulti{ + Pools: []*fakedns.FakeDnsPool{ + {IpPool: "198.19.0.0/16", LruSize: 65535}, + {IpPool: "fc01::/18", LruSize: 65535}, + }, + }, + }, + }, + StaticHosts: []*dns.HostMapping{ + { + Type: dns.DomainMatchingType_Subdomain, + Domain: "example.com", + ProxiedDomain: "google.com", + }, + { + Type: dns.DomainMatchingType_Full, + Domain: "test.example.com", + Ip: [][]byte{{127, 0, 0, 1}, {127, 0, 0, 2}}, + }, + { + Type: dns.DomainMatchingType_Keyword, + Domain: "google", + Ip: [][]byte{{8, 8, 8, 8}, {8, 8, 4, 4}}, + }, + { + Type: dns.DomainMatchingType_Regex, + Domain: ".*\\.com", + Ip: [][]byte{{8, 8, 4, 4}}, + }, + { + Type: dns.DomainMatchingType_Full, + Domain: "v2fly.org", + Ip: [][]byte{{127, 0, 0, 1}}, + }, + { + Type: dns.DomainMatchingType_Full, + Domain: "www.v2fly.org", + Ip: [][]byte{{1, 2, 3, 4}, {5, 6, 7, 8}}, + }, + }, + FakeDns: &fakedns.FakeDnsPoolMulti{ + Pools: []*fakedns.FakeDnsPool{ + {IpPool: "198.18.0.0/16", LruSize: 32768}, + {IpPool: "fc00::/18", LruSize: 32768}, + }, + }, + Tag: "global", + ClientIp: []byte{10, 0, 0, 1}, + QueryStrategy: dns.QueryStrategy_USE_IP4, + CacheStrategy: dns.CacheStrategy_CacheDisabled, + FallbackStrategy: dns.FallbackStrategy_Enabled, + }, + }, }) } diff --git a/infra/conf/synthetic/dns/fakedns.go b/infra/conf/synthetic/dns/fakedns.go new file mode 100644 index 000000000..a3a41b6b5 --- /dev/null +++ b/infra/conf/synthetic/dns/fakedns.go @@ -0,0 +1,87 @@ +package dns + +import ( + "encoding/json" + "net" + + "github.com/v2fly/v2ray-core/v5/app/dns/fakedns" +) + +type FakeDNSPoolElementConfig struct { + IPPool string `json:"ipPool"` + LRUSize int64 `json:"poolSize"` +} + +type FakeDNSConfig struct { + pool *FakeDNSPoolElementConfig + pools []*FakeDNSPoolElementConfig +} + +// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON +func (f *FakeDNSConfig) UnmarshalJSON(data []byte) error { + var pool FakeDNSPoolElementConfig + var pools []*FakeDNSPoolElementConfig + var ipPools []string + switch { + case json.Unmarshal(data, &pool) == nil: + f.pool = &pool + case json.Unmarshal(data, &pools) == nil: + f.pools = pools + case json.Unmarshal(data, &ipPools) == nil: + f.pools = make([]*FakeDNSPoolElementConfig, 0, len(ipPools)) + for _, ipPool := range ipPools { + _, ipNet, err := net.ParseCIDR(ipPool) + if err != nil { + return err + } + ones, bits := ipNet.Mask.Size() + sizeInBits := bits - ones + if sizeInBits > 16 { // At most 65536 ips for a IP pool + sizeInBits = 16 + } + f.pools = append(f.pools, &FakeDNSPoolElementConfig{ + IPPool: ipPool, + LRUSize: (1 << sizeInBits) - 1, + }) + } + default: + return newError("invalid fakedns config") + } + return nil +} + +func (f *FakeDNSConfig) Build() (*fakedns.FakeDnsPoolMulti, error) { + fakeDNSPool := fakedns.FakeDnsPoolMulti{} + + if f.pool != nil { + fakeDNSPool.Pools = append(fakeDNSPool.Pools, &fakedns.FakeDnsPool{ + IpPool: f.pool.IPPool, + LruSize: f.pool.LRUSize, + }) + return &fakeDNSPool, nil + } + + if f.pools != nil { + for _, v := range f.pools { + fakeDNSPool.Pools = append(fakeDNSPool.Pools, &fakedns.FakeDnsPool{IpPool: v.IPPool, LruSize: v.LRUSize}) + } + return &fakeDNSPool, nil + } + + return nil, newError("no valid FakeDNS config") +} + +type FakeDNSConfigExtend struct { // Adds boolean value parsing for "fakedns" config + *FakeDNSConfig +} + +func (f *FakeDNSConfigExtend) UnmarshalJSON(data []byte) error { + var enabled bool + if json.Unmarshal(data, &enabled) == nil { + if enabled { + f.FakeDNSConfig = &FakeDNSConfig{pools: []*FakeDNSPoolElementConfig{}} + } + return nil + } + return json.Unmarshal(data, &f.FakeDNSConfig) +} diff --git a/infra/conf/v4/fakedns.go b/infra/conf/v4/fakedns.go deleted file mode 100644 index 9bde534eb..000000000 --- a/infra/conf/v4/fakedns.go +++ /dev/null @@ -1,129 +0,0 @@ -package v4 - -import ( - "encoding/json" - "strings" - - "github.com/v2fly/v2ray-core/v5/app/dns/fakedns" -) - -type FakeDNSPoolElementConfig struct { - IPPool string `json:"ipPool"` - LRUSize int64 `json:"poolSize"` -} - -type FakeDNSConfig struct { - pool *FakeDNSPoolElementConfig - pools []*FakeDNSPoolElementConfig -} - -// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON -func (f *FakeDNSConfig) UnmarshalJSON(data []byte) error { - var pool FakeDNSPoolElementConfig - var pools []*FakeDNSPoolElementConfig - switch { - case json.Unmarshal(data, &pool) == nil: - f.pool = &pool - case json.Unmarshal(data, &pools) == nil: - f.pools = pools - default: - return newError("invalid fakedns config") - } - return nil -} - -func (f *FakeDNSConfig) Build() (*fakedns.FakeDnsPoolMulti, error) { - fakeDNSPool := fakedns.FakeDnsPoolMulti{} - - if f.pool != nil { - fakeDNSPool.Pools = append(fakeDNSPool.Pools, &fakedns.FakeDnsPool{ - IpPool: f.pool.IPPool, - LruSize: f.pool.LRUSize, - }) - return &fakeDNSPool, nil - } - - if f.pools != nil { - for _, v := range f.pools { - fakeDNSPool.Pools = append(fakeDNSPool.Pools, &fakedns.FakeDnsPool{IpPool: v.IPPool, LruSize: v.LRUSize}) - } - return &fakeDNSPool, nil - } - - return nil, newError("no valid FakeDNS config") -} - -type FakeDNSPostProcessingStage struct{} - -func (FakeDNSPostProcessingStage) Process(config *Config) error { - fakeDNSInUse := false - isIPv4Enable, isIPv6Enable := true, true - - if config.DNSConfig != nil { - for _, v := range config.DNSConfig.Servers { - if v.Address.Family().IsDomain() && strings.EqualFold(v.Address.Domain(), "fakedns") { - fakeDNSInUse = true - } - } - - switch strings.ToLower(config.DNSConfig.QueryStrategy) { - case "useip4", "useipv4", "use_ip4", "use_ipv4", "use_ip_v4", "use-ip4", "use-ipv4", "use-ip-v4": - isIPv4Enable, isIPv6Enable = true, false - case "useip6", "useipv6", "use_ip6", "use_ipv6", "use_ip_v6", "use-ip6", "use-ipv6", "use-ip-v6": - isIPv4Enable, isIPv6Enable = false, true - } - } - - if fakeDNSInUse { - // Add a Fake DNS Config if there is none - if config.FakeDNS == nil { - config.FakeDNS = &FakeDNSConfig{} - switch { - case isIPv4Enable && isIPv6Enable: - config.FakeDNS.pools = []*FakeDNSPoolElementConfig{ - { - IPPool: "198.18.0.0/15", - LRUSize: 32768, - }, - { - IPPool: "fc00::/18", - LRUSize: 32768, - }, - } - case !isIPv4Enable && isIPv6Enable: - config.FakeDNS.pool = &FakeDNSPoolElementConfig{ - IPPool: "fc00::/18", - LRUSize: 65535, - } - case isIPv4Enable && !isIPv6Enable: - config.FakeDNS.pool = &FakeDNSPoolElementConfig{ - IPPool: "198.18.0.0/15", - LRUSize: 65535, - } - } - } - - found := false - // Check if there is a Outbound with necessary sniffer on - var inbounds []InboundDetourConfig - - if len(config.InboundConfigs) > 0 { - inbounds = append(inbounds, config.InboundConfigs...) - } - for _, v := range inbounds { - if v.SniffingConfig != nil && v.SniffingConfig.Enabled && v.SniffingConfig.DestOverride != nil { - for _, dov := range *v.SniffingConfig.DestOverride { - if strings.EqualFold(dov, "fakedns") || strings.EqualFold(dov, "fakedns+others") { - found = true - break - } - } - } - } - if !found { - newError("Defined FakeDNS but haven't enabled FakeDNS destOverride at any inbound.").AtWarning().WriteToLog() - } - } - - return nil -} diff --git a/infra/conf/v4/init.go b/infra/conf/v4/init.go deleted file mode 100644 index 01a3d9d4d..000000000 --- a/infra/conf/v4/init.go +++ /dev/null @@ -1,5 +0,0 @@ -package v4 - -func init() { - RegisterConfigureFilePostProcessingStage("FakeDNS", &FakeDNSPostProcessingStage{}) -} diff --git a/infra/conf/v4/v2ray.go b/infra/conf/v4/v2ray.go index 54df610b1..96dbcc5a2 100644 --- a/infra/conf/v4/v2ray.go +++ b/infra/conf/v4/v2ray.go @@ -11,6 +11,7 @@ import ( "github.com/v2fly/v2ray-core/v5/app/proxyman" "github.com/v2fly/v2ray-core/v5/app/stats" "github.com/v2fly/v2ray-core/v5/common/serial" + "github.com/v2fly/v2ray-core/v5/features" "github.com/v2fly/v2ray-core/v5/infra/conf/cfgcommon" "github.com/v2fly/v2ray-core/v5/infra/conf/cfgcommon/loader" "github.com/v2fly/v2ray-core/v5/infra/conf/cfgcommon/muxcfg" @@ -302,7 +303,7 @@ type Config struct { API *APIConfig `json:"api"` Stats *StatsConfig `json:"stats"` Reverse *ReverseConfig `json:"reverse"` - FakeDNS *FakeDNSConfig `json:"fakeDns"` + FakeDNS *dns.FakeDNSConfig `json:"fakeDns"` BrowserForwarder *BrowserForwarderConfig `json:"browserForwarder"` Observatory *ObservatoryConfig `json:"observatory"` BurstObservatory *BurstObservatoryConfig `json:"burstObservatory"` @@ -399,6 +400,17 @@ func (c *Config) Build() (*core.Config, error) { config.App = append(config.App, serial.ToTypedMessage(routerConfig)) } + if c.FakeDNS != nil { + features.PrintDeprecatedFeatureWarning("root fakedns settings") + if c.DNSConfig != nil { + c.DNSConfig.FakeDNS = c.FakeDNS + } else { + c.DNSConfig = &dns.DNSConfig{ + FakeDNS: c.FakeDNS, + } + } + } + if c.DNSConfig != nil { dnsApp, err := c.DNSConfig.Build() if err != nil { @@ -423,14 +435,6 @@ func (c *Config) Build() (*core.Config, error) { config.App = append(config.App, serial.ToTypedMessage(r)) } - if c.FakeDNS != nil { - r, err := c.FakeDNS.Build() - if err != nil { - return nil, err - } - config.App = append(config.App, serial.ToTypedMessage(r)) - } - if c.BrowserForwarder != nil { r, err := c.BrowserForwarder.Build() if err != nil { diff --git a/proxy/dns/dns.go b/proxy/dns/dns.go index 287996bc1..ef23d6f3f 100644 --- a/proxy/dns/dns.go +++ b/proxy/dns/dns.go @@ -56,6 +56,10 @@ type Handler struct { } func (h *Handler) Init(config *Config, dnsClient dns.Client, policyManager policy.Manager) error { + // Enable FakeDNS for DNS outbound + if clientWithFakeDNS, ok := dnsClient.(dns.ClientWithFakeDNS); ok { + dnsClient = clientWithFakeDNS.AsFakeDNSClient() + } h.client = dnsClient h.timeout = policyManager.ForLevel(config.UserLevel).Timeouts.ConnectionIdle @@ -236,13 +240,6 @@ func (h *Handler) handleIPQuery(id uint16, qType dnsmessage.Type, domain string, var ttl uint32 = 600 - // Do NOT skip FakeDNS - if c, ok := h.client.(dns.ClientWithIPOption); ok { - c.SetFakeDNSOption(true) - } else { - newError("dns.Client doesn't implement ClientWithIPOption") - } - switch qType { case dnsmessage.TypeA: ips, err = h.ipv4Lookup.LookupIPv4(domain) diff --git a/proxy/freedom/freedom.go b/proxy/freedom/freedom.go index 90b0fd927..20cfcee65 100644 --- a/proxy/freedom/freedom.go +++ b/proxy/freedom/freedom.go @@ -65,24 +65,11 @@ func (h *Handler) policy() policy.Session { } func (h *Handler) resolveIP(ctx context.Context, domain string, localAddr net.Address) net.Address { - if c, ok := h.dns.(dns.ClientWithIPOption); ok { - c.SetFakeDNSOption(false) // Skip FakeDNS - } else { - newError("DNS client doesn't implement ClientWithIPOption") - } - - lookupFunc := h.dns.LookupIP - if h.config.DomainStrategy == Config_USE_IP4 || (localAddr != nil && localAddr.Family().IsIPv4()) { - if lookupIPv4, ok := h.dns.(dns.IPv4Lookup); ok { - lookupFunc = lookupIPv4.LookupIPv4 - } - } else if h.config.DomainStrategy == Config_USE_IP6 || (localAddr != nil && localAddr.Family().IsIPv6()) { - if lookupIPv6, ok := h.dns.(dns.IPv6Lookup); ok { - lookupFunc = lookupIPv6.LookupIPv6 - } - } - - ips, err := lookupFunc(domain) + ips, err := dns.LookupIPWithOption(h.dns, domain, dns.IPOption{ + IPv4Enable: h.config.DomainStrategy == Config_USE_IP || h.config.DomainStrategy == Config_USE_IP4 || (localAddr != nil && localAddr.Family().IsIPv4()), + IPv6Enable: h.config.DomainStrategy == Config_USE_IP || h.config.DomainStrategy == Config_USE_IP6 || (localAddr != nil && localAddr.Family().IsIPv6()), + FakeEnable: false, + }) if err != nil { newError("failed to get IP address for domain ", domain).Base(err).WriteToLog(session.ExportIDToError(ctx)) } diff --git a/proxy/socks/client.go b/proxy/socks/client.go index bdb24e12c..11df62a8d 100644 --- a/proxy/socks/client.go +++ b/proxy/socks/client.go @@ -104,17 +104,7 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter switch c.version { case Version_SOCKS4: if request.Address.Family().IsDomain() { - if d, ok := c.dns.(dns.ClientWithIPOption); ok { - d.SetFakeDNSOption(false) // Skip FakeDNS - } else { - newError("DNS client doesn't implement ClientWithIPOption") - } - - lookupFunc := c.dns.LookupIP - if lookupIPv4, ok := c.dns.(dns.IPv4Lookup); ok { - lookupFunc = lookupIPv4.LookupIPv4 - } - ips, err := lookupFunc(request.Address.Domain()) + ips, err := dns.LookupIPWithOption(c.dns, request.Address.Domain(), dns.IPOption{IPv4Enable: true, IPv6Enable: false, FakeEnable: false}) if err != nil { return err } else if len(ips) == 0 {