github.com/v2fly/v2ray-core/v5@v5.16.2-0.20240507031116-8191faa6e095/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/v5" 11 "github.com/v2fly/v2ray-core/v5/common" 12 "github.com/v2fly/v2ray-core/v5/common/net" 13 "github.com/v2fly/v2ray-core/v5/common/session" 14 "github.com/v2fly/v2ray-core/v5/features/dns" 15 ) 16 17 // newFakeDNSSniffer Creates a Fake DNS metadata sniffer 18 func newFakeDNSSniffer(ctx context.Context) (protocolSnifferWithMetadata, error) { 19 var fakeDNSEngine dns.FakeDNSEngine 20 { 21 fakeDNSEngineFeat := core.MustFromContext(ctx).GetFeature((*dns.FakeDNSEngine)(nil)) 22 if fakeDNSEngineFeat != nil { 23 fakeDNSEngine = fakeDNSEngineFeat.(dns.FakeDNSEngine) 24 } 25 } 26 27 if fakeDNSEngine == nil { 28 errNotInit := newError("FakeDNSEngine is not initialized, but such a sniffer is used").AtError() 29 return protocolSnifferWithMetadata{}, errNotInit 30 } 31 return protocolSnifferWithMetadata{protocolSniffer: func(ctx context.Context, bytes []byte) (SniffResult, error) { 32 Target := session.OutboundFromContext(ctx).Target 33 if Target.Network == net.Network_TCP || Target.Network == net.Network_UDP { 34 domainFromFakeDNS := fakeDNSEngine.GetDomainFromFakeDNS(Target.Address) 35 if domainFromFakeDNS != "" { 36 newError("fake dns got domain: ", domainFromFakeDNS, " for ip: ", Target.Address.String()).WriteToLog(session.ExportIDToError(ctx)) 37 return &fakeDNSSniffResult{domainName: domainFromFakeDNS}, nil 38 } 39 } 40 41 if ipAddressInRangeValueI := ctx.Value(ipAddressInRange); ipAddressInRangeValueI != nil { 42 ipAddressInRangeValue := ipAddressInRangeValueI.(*ipAddressInRangeOpt) 43 if fkr0, ok := fakeDNSEngine.(dns.FakeDNSEngineRev0); ok { 44 inPool := fkr0.IsIPInIPPool(Target.Address) 45 ipAddressInRangeValue.addressInRange = &inPool 46 } 47 } 48 49 return nil, common.ErrNoClue 50 }, metadataSniffer: true}, nil 51 } 52 53 type fakeDNSSniffResult struct { 54 domainName string 55 } 56 57 func (fakeDNSSniffResult) Protocol() string { 58 return "fakedns" 59 } 60 61 func (f fakeDNSSniffResult) Domain() string { 62 return f.domainName 63 } 64 65 type fakeDNSExtraOpts int 66 67 const ipAddressInRange fakeDNSExtraOpts = 1 68 69 type ipAddressInRangeOpt struct { 70 addressInRange *bool 71 } 72 73 type DNSThenOthersSniffResult struct { 74 domainName string 75 protocolOriginalName string 76 } 77 78 func (f DNSThenOthersSniffResult) IsProtoSubsetOf(protocolName string) bool { 79 return strings.HasPrefix(protocolName, f.protocolOriginalName) 80 } 81 82 func (DNSThenOthersSniffResult) Protocol() string { 83 return "fakedns+others" 84 } 85 86 func (f DNSThenOthersSniffResult) Domain() string { 87 return f.domainName 88 } 89 90 func newFakeDNSThenOthers(ctx context.Context, fakeDNSSniffer protocolSnifferWithMetadata, others []protocolSnifferWithMetadata) (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 }