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  }