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  }