github.com/v2fly/v2ray-core/v4@v4.45.2/app/dispatcher/fakednssniffer.go (about) 1 //go:build !confonly 2 // +build !confonly 3 4 package dispatcher 5 6 import ( 7 "context" 8 "strings" 9 10 core "github.com/v2fly/v2ray-core/v4" 11 "github.com/v2fly/v2ray-core/v4/common" 12 "github.com/v2fly/v2ray-core/v4/common/net" 13 "github.com/v2fly/v2ray-core/v4/common/session" 14 "github.com/v2fly/v2ray-core/v4/features/dns" 15 ) 16 17 // newFakeDNSSniffer Create a Fake DNS metadata sniffer 18 func newFakeDNSSniffer(ctx context.Context) (protocolSnifferWithMetadata, error) { 19 var fakeDNSEngine dns.FakeDNSEngine 20 err := core.RequireFeatures(ctx, func(fdns dns.FakeDNSEngine) { 21 fakeDNSEngine = fdns 22 }) 23 if err != nil { 24 return protocolSnifferWithMetadata{}, err 25 } 26 if fakeDNSEngine == nil { 27 errNotInit := newError("FakeDNSEngine is not initialized, but such a sniffer is used").AtError() 28 return protocolSnifferWithMetadata{}, errNotInit 29 } 30 return protocolSnifferWithMetadata{protocolSniffer: func(ctx context.Context, bytes []byte) (SniffResult, error) { 31 Target := session.OutboundFromContext(ctx).Target 32 if Target.Network == net.Network_TCP || Target.Network == net.Network_UDP { 33 domainFromFakeDNS := fakeDNSEngine.GetDomainFromFakeDNS(Target.Address) 34 if domainFromFakeDNS != "" { 35 newError("fake dns got domain: ", domainFromFakeDNS, " for ip: ", Target.Address.String()).WriteToLog(session.ExportIDToError(ctx)) 36 return &fakeDNSSniffResult{domainName: domainFromFakeDNS}, nil 37 } 38 } 39 40 if ipAddressInRangeValueI := ctx.Value(ipAddressInRange); ipAddressInRangeValueI != nil { 41 ipAddressInRangeValue := ipAddressInRangeValueI.(*ipAddressInRangeOpt) 42 if fkr0, ok := fakeDNSEngine.(dns.FakeDNSEngineRev0); ok { 43 inPool := fkr0.IsIPInIPPool(Target.Address) 44 ipAddressInRangeValue.addressInRange = &inPool 45 } 46 } 47 48 return nil, common.ErrNoClue 49 }, metadataSniffer: true}, nil 50 } 51 52 type fakeDNSSniffResult struct { 53 domainName string 54 } 55 56 func (fakeDNSSniffResult) Protocol() string { 57 return "fakedns" 58 } 59 60 func (f fakeDNSSniffResult) Domain() string { 61 return f.domainName 62 } 63 64 type fakeDNSExtraOpts int 65 66 const ipAddressInRange fakeDNSExtraOpts = 1 67 68 type ipAddressInRangeOpt struct { 69 addressInRange *bool 70 } 71 72 type DNSThenOthersSniffResult struct { 73 domainName string 74 protocolOriginalName string 75 } 76 77 func (f DNSThenOthersSniffResult) IsProtoSubsetOf(protocolName string) bool { 78 return strings.HasPrefix(protocolName, f.protocolOriginalName) 79 } 80 81 func (DNSThenOthersSniffResult) Protocol() string { 82 return "fakedns+others" 83 } 84 85 func (f DNSThenOthersSniffResult) Domain() string { 86 return f.domainName 87 } 88 89 func newFakeDNSThenOthers(ctx context.Context, fakeDNSSniffer protocolSnifferWithMetadata, others []protocolSnifferWithMetadata) ( 90 protocolSnifferWithMetadata, error) { // nolint: unparam 91 // ctx may be used in the future 92 _ = ctx 93 return protocolSnifferWithMetadata{ 94 protocolSniffer: func(ctx context.Context, bytes []byte) (SniffResult, error) { 95 ipAddressInRangeValue := &ipAddressInRangeOpt{} 96 ctx = context.WithValue(ctx, ipAddressInRange, ipAddressInRangeValue) 97 result, err := fakeDNSSniffer.protocolSniffer(ctx, bytes) 98 if err == nil { 99 return result, nil 100 } 101 if ipAddressInRangeValue.addressInRange != nil { 102 if *ipAddressInRangeValue.addressInRange { 103 for _, v := range others { 104 if v.metadataSniffer || bytes != nil { 105 if result, err := v.protocolSniffer(ctx, bytes); err == nil { 106 return DNSThenOthersSniffResult{domainName: result.Domain(), protocolOriginalName: result.Protocol()}, nil 107 } 108 } 109 } 110 return nil, common.ErrNoClue 111 } 112 newError("ip address not in fake dns range, return as is").AtDebug().WriteToLog() 113 return nil, common.ErrNoClue 114 } 115 newError("fake dns sniffer did not set address in range option, assume false.").AtWarning().WriteToLog() 116 return nil, common.ErrNoClue 117 }, 118 metadataSniffer: false, 119 }, nil 120 }