diff --git a/app/dispatcher/default.go b/app/dispatcher/default.go index 53c5774ed..ef00f533e 100644 --- a/app/dispatcher/default.go +++ b/app/dispatcher/default.go @@ -186,6 +186,11 @@ func shouldOverride(result SniffResult, domainOverride []string) bool { if strings.HasPrefix(protocolString, p) { return true } + if resultSubset, ok := result.(SnifferIsProtoSubsetOf); ok { + if resultSubset.IsProtoSubsetOf(p) { + return true + } + } } return false } diff --git a/app/dispatcher/fakednssniffer.go b/app/dispatcher/fakednssniffer.go index 17d7811f1..0bc632472 100644 --- a/app/dispatcher/fakednssniffer.go +++ b/app/dispatcher/fakednssniffer.go @@ -4,6 +4,7 @@ package dispatcher import ( "context" + "strings" core "github.com/v2fly/v2ray-core/v4" "github.com/v2fly/v2ray-core/v4/common" @@ -34,6 +35,15 @@ func newFakeDNSSniffer(ctx context.Context) (protocolSnifferWithMetadata, error) return &fakeDNSSniffResult{domainName: domainFromFakeDNS}, nil } } + + if ipAddressInRangeValueI := ctx.Value(ipAddressInRange); ipAddressInRangeValueI != nil { + ipAddressInRangeValue := ipAddressInRangeValueI.(*ipAddressInRangeOpt) + if fkr0, ok := fakeDNSEngine.(dns.FakeDNSEngineRev0); ok { + inPool := fkr0.IsIPInIPPool(Target.Address) + ipAddressInRangeValue.addressInRange = &inPool + } + } + return nil, common.ErrNoClue }, metadataSniffer: true}, nil } @@ -49,3 +59,63 @@ func (fakeDNSSniffResult) Protocol() string { func (f fakeDNSSniffResult) Domain() string { return f.domainName } + +type fakeDnsExtraOpts int + +const ipAddressInRange fakeDnsExtraOpts = 1 + +type ipAddressInRangeOpt struct { + addressInRange *bool +} + +type DNSThenOthersSniffResult struct { + domainName string + protocolOriginalName string +} + +func (f DNSThenOthersSniffResult) IsProtoSubsetOf(protocolName string) bool { + if strings.HasPrefix(protocolName, f.protocolOriginalName) { + return true + } + return false +} + +func (DNSThenOthersSniffResult) Protocol() string { + return "fakedns+others" +} + +func (f DNSThenOthersSniffResult) Domain() string { + return f.domainName +} + +func newFakeDNSThenOthers(ctx context.Context, fakeDNSSniffer protocolSnifferWithMetadata, others []protocolSnifferWithMetadata) (protocolSnifferWithMetadata, error) { + return protocolSnifferWithMetadata{ + protocolSniffer: func(ctx context.Context, bytes []byte) (SniffResult, error) { + ipAddressInRangeValue := &ipAddressInRangeOpt{} + ctx = context.WithValue(ctx, ipAddressInRange, ipAddressInRangeValue) + result, err := fakeDNSSniffer.protocolSniffer(ctx, bytes) + if err == nil { + return result, nil + } + if ipAddressInRangeValue.addressInRange != nil { + if *ipAddressInRangeValue.addressInRange == true { + for _, v := range others { + if v.metadataSniffer || bytes != nil { + if result, err := v.protocolSniffer(ctx, bytes); err == nil { + return DNSThenOthersSniffResult{domainName: result.Domain(), protocolOriginalName: result.Protocol()}, nil + } + } + } + return nil, common.ErrNoClue + } else { + newError("ip address not in fake dns range, return as is").AtDebug().WriteToLog() + return nil, common.ErrNoClue + } + } else { + newError("fake dns sniffer did not set address in range option, assume false.").AtWarning().WriteToLog() + return nil, common.ErrNoClue + } + }, + metadataSniffer: false, + }, nil +} diff --git a/app/dispatcher/sniffer.go b/app/dispatcher/sniffer.go index 92f0d5beb..a0d35015e 100644 --- a/app/dispatcher/sniffer.go +++ b/app/dispatcher/sniffer.go @@ -39,7 +39,12 @@ func NewSniffer(ctx context.Context) *Sniffer { }, } if sniffer, err := newFakeDNSSniffer(ctx); err == nil { + others := ret.sniffer ret.sniffer = append(ret.sniffer, sniffer) + fakeDNSThenOthers, err := newFakeDNSThenOthers(ctx, sniffer, others) + if err == nil { + ret.sniffer = append([]protocolSnifferWithMetadata{fakeDNSThenOthers}, ret.sniffer...) + } } return ret } @@ -123,3 +128,7 @@ func (c compositeResult) ProtocolForDomainResult() string { type SnifferResultComposite interface { ProtocolForDomainResult() string } + +type SnifferIsProtoSubsetOf interface { + IsProtoSubsetOf(protocolName string) bool +} diff --git a/app/dns/fakedns/fake.go b/app/dns/fakedns/fake.go index 3987e1629..fdc925916 100644 --- a/app/dns/fakedns/fake.go +++ b/app/dns/fakedns/fake.go @@ -23,6 +23,18 @@ type Holder struct { config *FakeDnsPool } +func (fkdns *Holder) IsIPInIPPool(ip net.Address) bool { + return fkdns.ipRange.Contains(ip.IP()) +} + +func (fkdns *Holder) GetFakeIPForDomain3(domain string, IPv4, IPv6 bool) []net.Address { + isIPv6 := fkdns.ipRange.IP.To4() == nil + if (isIPv6 && IPv6) || (!isIPv6 && IPv4) { + return fkdns.GetFakeIPForDomain(domain) + } + return []net.Address{} +} + func (*Holder) Type() interface{} { return (*dns.FakeDNSEngine)(nil) } @@ -120,6 +132,89 @@ func (fkdns *Holder) GetDomainFromFakeDNS(ip net.Address) string { return "" } +type HolderMulti struct { + holders []*Holder + + config *FakeDnsPoolMulti +} + +func (h *HolderMulti) IsIPInIPPool(ip net.Address) bool { + for _, v := range h.holders { + if v.IsIPInIPPool(ip) { + return true + } + } + return false +} + +func (h *HolderMulti) GetFakeIPForDomain3(domain string, IPv4, IPv6 bool) []net.Address { + var ret []net.Address + for _, v := range h.holders { + ret = append(ret, v.GetFakeIPForDomain3(domain, IPv4, IPv6)...) + } + return ret +} + +func (h *HolderMulti) GetFakeIPForDomain(domain string) []net.Address { + var ret []net.Address + for _, v := range h.holders { + ret = append(ret, v.GetFakeIPForDomain(domain)...) + } + return ret +} + +func (h *HolderMulti) GetDomainFromFakeDNS(ip net.Address) string { + for _, v := range h.holders { + if domain := v.GetDomainFromFakeDNS(ip); domain != "" { + return domain + } + } + return "" +} + +func (h *HolderMulti) Type() interface{} { + return (*dns.FakeDNSEngine)(nil) +} + +func (h *HolderMulti) Start() error { + for _, v := range h.holders { + err := v.Start() + if err != nil { + return newError("Cannot start all fake dns pools").Base(err) + } + } + return nil +} + +func (h *HolderMulti) Close() error { + for _, v := range h.holders { + err := v.Start() + if err != nil { + return newError("Cannot close all fake dns pools").Base(err) + } + } + return nil +} + +func (h *HolderMulti) createHolderGroups() error { + for _, v := range h.config.Pools { + holder, err := NewFakeDNSHolderConfigOnly(v) + 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 { + return nil, err + } + return holderMulti, nil +} + func init() { common.Must(common.RegisterConfig((*FakeDnsPool)(nil), func(ctx context.Context, config interface{}) (interface{}, error) { var f *Holder @@ -129,4 +224,13 @@ func init() { } return f, nil })) + + common.Must(common.RegisterConfig((*FakeDnsPoolMulti)(nil), func(ctx context.Context, config interface{}) (interface{}, error) { + var f *HolderMulti + var err error + if f, err = NewFakeDNSHolderMulti(config.(*FakeDnsPoolMulti)); err != nil { + return nil, err + } + return f, nil + })) } diff --git a/app/dns/fakedns/fakedns.pb.go b/app/dns/fakedns/fakedns.pb.go index 4ffb298b8..41ce72387 100644 --- a/app/dns/fakedns/fakedns.pb.go +++ b/app/dns/fakedns/fakedns.pb.go @@ -75,6 +75,53 @@ func (x *FakeDnsPool) GetLruSize() int64 { return 0 } +type FakeDnsPoolMulti struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Pools []*FakeDnsPool `protobuf:"bytes,1,rep,name=pools,proto3" json:"pools,omitempty"` +} + +func (x *FakeDnsPoolMulti) Reset() { + *x = FakeDnsPoolMulti{} + if protoimpl.UnsafeEnabled { + mi := &file_app_dns_fakedns_fakedns_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FakeDnsPoolMulti) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FakeDnsPoolMulti) ProtoMessage() {} + +func (x *FakeDnsPoolMulti) ProtoReflect() protoreflect.Message { + mi := &file_app_dns_fakedns_fakedns_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FakeDnsPoolMulti.ProtoReflect.Descriptor instead. +func (*FakeDnsPoolMulti) Descriptor() ([]byte, []int) { + return file_app_dns_fakedns_fakedns_proto_rawDescGZIP(), []int{1} +} + +func (x *FakeDnsPoolMulti) GetPools() []*FakeDnsPool { + if x != nil { + return x.Pools + } + return nil +} + var File_app_dns_fakedns_fakedns_proto protoreflect.FileDescriptor var file_app_dns_fakedns_fakedns_proto_rawDesc = []byte{ @@ -85,15 +132,20 @@ var file_app_dns_fakedns_fakedns_proto_rawDesc = []byte{ 0x61, 0x6b, 0x65, 0x44, 0x6e, 0x73, 0x50, 0x6f, 0x6f, 0x6c, 0x12, 0x17, 0x0a, 0x07, 0x69, 0x70, 0x5f, 0x70, 0x6f, 0x6f, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x69, 0x70, 0x50, 0x6f, 0x6f, 0x6c, 0x12, 0x18, 0x0a, 0x07, 0x6c, 0x72, 0x75, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x6c, 0x72, 0x75, 0x53, 0x69, 0x7a, 0x65, 0x42, 0x6f, 0x0a, - 0x1e, 0x63, 0x6f, 0x6d, 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, 0x50, - 0x01, 0x5a, 0x2e, 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, - 0x34, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x64, 0x6e, 0x73, 0x2f, 0x66, 0x61, 0x6b, 0x65, 0x64, 0x6e, - 0x73, 0xaa, 0x02, 0x1a, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x41, - 0x70, 0x70, 0x2e, 0x44, 0x6e, 0x73, 0x2e, 0x46, 0x61, 0x6b, 0x65, 0x64, 0x6e, 0x73, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x6c, 0x72, 0x75, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x51, 0x0a, + 0x10, 0x46, 0x61, 0x6b, 0x65, 0x44, 0x6e, 0x73, 0x50, 0x6f, 0x6f, 0x6c, 0x4d, 0x75, 0x6c, 0x74, + 0x69, 0x12, 0x3d, 0x0a, 0x05, 0x70, 0x6f, 0x6f, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x27, 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, 0x52, 0x05, 0x70, 0x6f, 0x6f, 0x6c, 0x73, + 0x42, 0x6f, 0x0a, 0x1e, 0x63, 0x6f, 0x6d, 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, 0x50, 0x01, 0x5a, 0x2e, 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, 0x34, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x64, 0x6e, 0x73, 0x2f, 0x66, 0x61, 0x6b, + 0x65, 0x64, 0x6e, 0x73, 0xaa, 0x02, 0x1a, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, + 0x65, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x44, 0x6e, 0x73, 0x2e, 0x46, 0x61, 0x6b, 0x65, 0x64, 0x6e, + 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -108,16 +160,18 @@ func file_app_dns_fakedns_fakedns_proto_rawDescGZIP() []byte { return file_app_dns_fakedns_fakedns_proto_rawDescData } -var file_app_dns_fakedns_fakedns_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_app_dns_fakedns_fakedns_proto_msgTypes = make([]protoimpl.MessageInfo, 2) var file_app_dns_fakedns_fakedns_proto_goTypes = []interface{}{ - (*FakeDnsPool)(nil), // 0: v2ray.core.app.dns.fakedns.FakeDnsPool + (*FakeDnsPool)(nil), // 0: v2ray.core.app.dns.fakedns.FakeDnsPool + (*FakeDnsPoolMulti)(nil), // 1: v2ray.core.app.dns.fakedns.FakeDnsPoolMulti } var file_app_dns_fakedns_fakedns_proto_depIdxs = []int32{ - 0, // [0:0] is the sub-list for method output_type - 0, // [0:0] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name + 0, // 0: v2ray.core.app.dns.fakedns.FakeDnsPoolMulti.pools:type_name -> v2ray.core.app.dns.fakedns.FakeDnsPool + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name } func init() { file_app_dns_fakedns_fakedns_proto_init() } @@ -138,6 +192,18 @@ func file_app_dns_fakedns_fakedns_proto_init() { return nil } } + file_app_dns_fakedns_fakedns_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*FakeDnsPoolMulti); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -145,7 +211,7 @@ func file_app_dns_fakedns_fakedns_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_app_dns_fakedns_fakedns_proto_rawDesc, NumEnums: 0, - NumMessages: 1, + NumMessages: 2, NumExtensions: 0, NumServices: 0, }, diff --git a/app/dns/fakedns/fakedns.proto b/app/dns/fakedns/fakedns.proto index a7d90dab9..4878f6cca 100644 --- a/app/dns/fakedns/fakedns.proto +++ b/app/dns/fakedns/fakedns.proto @@ -10,3 +10,7 @@ message FakeDnsPool{ string ip_pool = 1; //CIDR of IP pool used as fake DNS IP int64 lruSize = 2; //Size of Pool for remembering relationship between domain name and IP address } + +message FakeDnsPoolMulti{ + repeated FakeDnsPool pools = 1; +} \ No newline at end of file diff --git a/app/dns/fakedns/fakedns_test.go b/app/dns/fakedns/fakedns_test.go index f2f3dc26a..e727bbbe5 100644 --- a/app/dns/fakedns/fakedns_test.go +++ b/app/dns/fakedns/fakedns_test.go @@ -3,6 +3,8 @@ package fakedns import ( "testing" + gonet "net" + "github.com/stretchr/testify/assert" "github.com/v2fly/v2ray-core/v4/common" @@ -113,3 +115,78 @@ func TestFakeDnsHolderCreateMappingAndRollOver(t *testing.T) { } } } + +func TestFakeDNSMulti(t *testing.T) { + fakeMulti, err := NewFakeDNSHolderMulti(&FakeDnsPoolMulti{ + Pools: []*FakeDnsPool{&FakeDnsPool{ + IpPool: "240.0.0.0/12", + LruSize: 256, + }, &FakeDnsPool{ + IpPool: "fddd:c5b4:ff5f:f4f0::/64", + LruSize: 256, + }}, + }, + ) + + err = fakeMulti.Start() + + common.Must(err) + + assert.Nil(t, err, "Should not throw error") + _ = fakeMulti + + t.Run("checkInRange", func(t *testing.T) { + t.Run("ipv4", func(t *testing.T) { + inPool := fakeMulti.IsIPInIPPool(net.IPAddress([]byte{240, 0, 0, 5})) + assert.True(t, inPool) + }) + t.Run("ipv6", func(t *testing.T) { + ip, err := gonet.ResolveIPAddr("ip", "fddd:c5b4:ff5f:f4f0::5") + assert.Nil(t, err) + inPool := fakeMulti.IsIPInIPPool(net.IPAddress(ip.IP)) + assert.True(t, inPool) + }) + t.Run("ipv4_inverse", func(t *testing.T) { + inPool := fakeMulti.IsIPInIPPool(net.IPAddress([]byte{241, 0, 0, 5})) + assert.False(t, inPool) + }) + t.Run("ipv6_inverse", func(t *testing.T) { + ip, err := gonet.ResolveIPAddr("ip", "fcdd:c5b4:ff5f:f4f0::5") + assert.Nil(t, err) + inPool := fakeMulti.IsIPInIPPool(net.IPAddress(ip.IP)) + assert.False(t, inPool) + }) + }) + + t.Run("allocateTwoAddressForTwoPool", func(t *testing.T) { + address := fakeMulti.GetFakeIPForDomain("fakednstest.v2fly.org") + assert.Len(t, address, 2, "should be 2 address one for each pool") + t.Run("eachOfThemShouldResolve:0", func(t *testing.T) { + domain := fakeMulti.GetDomainFromFakeDNS(address[0]) + assert.Equal(t, "fakednstest.v2fly.org", domain) + }) + t.Run("eachOfThemShouldResolve:1", func(t *testing.T) { + domain := fakeMulti.GetDomainFromFakeDNS(address[1]) + assert.Equal(t, "fakednstest.v2fly.org", domain) + }) + }) + + t.Run("understandIPTypeSelector", func(t *testing.T) { + t.Run("ipv4", func(t *testing.T) { + address := fakeMulti.GetFakeIPForDomain3("fakednstestipv4.v2fly.org", true, false) + assert.Len(t, address, 1, "should be 1 address") + assert.True(t, address[0].Family().IsIPv4()) + }) + t.Run("ipv6", func(t *testing.T) { + address := fakeMulti.GetFakeIPForDomain3("fakednstestipv6.v2fly.org", false, true) + assert.Len(t, address, 1, "should be 1 address") + assert.True(t, address[0].Family().IsIPv6()) + }) + t.Run("ipv46", func(t *testing.T) { + address := fakeMulti.GetFakeIPForDomain3("fakednstestipv46.v2fly.org", true, true) + assert.Len(t, address, 2, "should be 2 address") + assert.True(t, address[0].Family().IsIPv4()) + assert.True(t, address[1].Family().IsIPv6()) + }) + }) +} diff --git a/app/dns/nameserver_fakedns.go b/app/dns/nameserver_fakedns.go index 9fb48bebd..65a0ca1b6 100644 --- a/app/dns/nameserver_fakedns.go +++ b/app/dns/nameserver_fakedns.go @@ -22,7 +22,7 @@ func (FakeDNSServer) Name() string { return "FakeDNS" } -func (f *FakeDNSServer) QueryIP(ctx context.Context, domain string, _ net.IP, _ dns.IPOption, _ bool) ([]net.IP, error) { +func (f *FakeDNSServer) QueryIP(ctx context.Context, domain string, _ net.IP, opt dns.IPOption, _ bool) ([]net.IP, error) { if f.fakeDNSEngine == nil { if err := core.RequireFeatures(ctx, func(fd dns.FakeDNSEngine) { f.fakeDNSEngine = fd @@ -30,7 +30,12 @@ func (f *FakeDNSServer) QueryIP(ctx context.Context, domain string, _ net.IP, _ return nil, newError("Unable to locate a fake DNS Engine").Base(err).AtError() } } - ips := f.fakeDNSEngine.GetFakeIPForDomain(domain) + var ips []net.Address + if fkr0, ok := f.fakeDNSEngine.(dns.FakeDNSEngineRev0); ok { + ips = fkr0.GetFakeIPForDomain3(domain, opt.IPv4Enable, opt.IPv6Enable) + } else { + ips = f.fakeDNSEngine.GetFakeIPForDomain(domain) + } netIP, err := toNetIP(ips) if err != nil { diff --git a/features/dns/fakedns.go b/features/dns/fakedns.go index 1d83f57a1..8caf3b4ad 100644 --- a/features/dns/fakedns.go +++ b/features/dns/fakedns.go @@ -10,3 +10,8 @@ type FakeDNSEngine interface { GetFakeIPForDomain(domain string) []net.Address GetDomainFromFakeDNS(ip net.Address) string } + +type FakeDNSEngineRev0 interface { + IsIPInIPPool(ip net.Address) bool + GetFakeIPForDomain3(domain string, IPv4, IPv6 bool) []net.Address +} diff --git a/infra/conf/fakedns.go b/infra/conf/fakedns.go index 3d097f7fd..ab6aaa0be 100644 --- a/infra/conf/fakedns.go +++ b/infra/conf/fakedns.go @@ -6,12 +6,26 @@ import ( "github.com/v2fly/v2ray-core/v4/app/dns/fakedns" ) -type FakeDNSConfig struct { +type FakeDNSPoolElementConfig struct { IPPool string `json:"ipPool"` LruSize int64 `json:"poolSize"` } +type FakeDNSConfig struct { + IPPool string `json:"ipPool"` + LruSize int64 `json:"poolSize"` + Pools *[]FakeDNSPoolElementConfig `json:"pools,omitempty"` +} + func (f FakeDNSConfig) Build() (proto.Message, error) { + if f.Pools != nil { + fakeDNSPool := &fakedns.FakeDnsPoolMulti{} + for _, v := range *f.Pools { + fakeDNSPool.Pools = append(fakeDNSPool.Pools, &fakedns.FakeDnsPool{IpPool: v.IPPool, LruSize: v.LruSize}) + } + return fakeDNSPool, nil + } + return &fakedns.FakeDnsPool{ IpPool: f.IPPool, LruSize: f.LruSize, diff --git a/infra/conf/v2ray.go b/infra/conf/v2ray.go index ea7e16012..af43b90e5 100644 --- a/infra/conf/v2ray.go +++ b/infra/conf/v2ray.go @@ -75,6 +75,8 @@ func (c *SniffingConfig) Build() (*proxyman.SniffingConfig, error) { p = append(p, "tls") case "fakedns": p = append(p, "fakedns") + case "fakedns+others": + p = append(p, "fakedns+others") default: return nil, newError("unknown protocol: ", domainOverride) }