mirror of https://github.com/XTLS/Xray-core
				
				
				
			
		
			
				
	
	
		
			122 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			Go
		
	
	
			
		
		
	
	
			122 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			Go
		
	
	
package dispatcher
 | 
						|
 | 
						|
import (
 | 
						|
	"context"
 | 
						|
	"strings"
 | 
						|
 | 
						|
	"github.com/xtls/xray-core/common"
 | 
						|
	"github.com/xtls/xray-core/common/errors"
 | 
						|
	"github.com/xtls/xray-core/common/net"
 | 
						|
	"github.com/xtls/xray-core/common/session"
 | 
						|
	"github.com/xtls/xray-core/core"
 | 
						|
	"github.com/xtls/xray-core/features/dns"
 | 
						|
)
 | 
						|
 | 
						|
// newFakeDNSSniffer Creates a Fake DNS metadata sniffer
 | 
						|
func newFakeDNSSniffer(ctx context.Context) (protocolSnifferWithMetadata, error) {
 | 
						|
	var fakeDNSEngine dns.FakeDNSEngine
 | 
						|
	{
 | 
						|
		fakeDNSEngineFeat := core.MustFromContext(ctx).GetFeature((*dns.FakeDNSEngine)(nil))
 | 
						|
		if fakeDNSEngineFeat != nil {
 | 
						|
			fakeDNSEngine = fakeDNSEngineFeat.(dns.FakeDNSEngine)
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if fakeDNSEngine == nil {
 | 
						|
		errNotInit := errors.New("FakeDNSEngine is not initialized, but such a sniffer is used").AtError()
 | 
						|
		return protocolSnifferWithMetadata{}, errNotInit
 | 
						|
	}
 | 
						|
	return protocolSnifferWithMetadata{protocolSniffer: func(ctx context.Context, bytes []byte) (SniffResult, error) {
 | 
						|
		outbounds := session.OutboundsFromContext(ctx)
 | 
						|
		ob := outbounds[len(outbounds)-1]
 | 
						|
		if ob.Target.Network == net.Network_TCP || ob.Target.Network == net.Network_UDP {
 | 
						|
			domainFromFakeDNS := fakeDNSEngine.GetDomainFromFakeDNS(ob.Target.Address)
 | 
						|
			if domainFromFakeDNS != "" {
 | 
						|
				errors.LogInfo(ctx, "fake dns got domain: ", domainFromFakeDNS, " for ip: ", ob.Target.Address.String())
 | 
						|
				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(ob.Target.Address)
 | 
						|
				ipAddressInRangeValue.addressInRange = &inPool
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		return nil, common.ErrNoClue
 | 
						|
	}, metadataSniffer: true}, nil
 | 
						|
}
 | 
						|
 | 
						|
type fakeDNSSniffResult struct {
 | 
						|
	domainName string
 | 
						|
}
 | 
						|
 | 
						|
func (fakeDNSSniffResult) Protocol() string {
 | 
						|
	return "fakedns"
 | 
						|
}
 | 
						|
 | 
						|
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 {
 | 
						|
	return strings.HasPrefix(protocolName, f.protocolOriginalName)
 | 
						|
}
 | 
						|
 | 
						|
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,
 | 
						|
) { // nolint: unparam
 | 
						|
	// ctx may be used in the future
 | 
						|
	_ = ctx
 | 
						|
	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 {
 | 
						|
					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
 | 
						|
				}
 | 
						|
				errors.LogDebug(ctx, "ip address not in fake dns range, return as is")
 | 
						|
				return nil, common.ErrNoClue
 | 
						|
			}
 | 
						|
			errors.LogWarning(ctx, "fake dns sniffer did not set address in range option, assume false.")
 | 
						|
			return nil, common.ErrNoClue
 | 
						|
		},
 | 
						|
		metadataSniffer: false,
 | 
						|
	}, nil
 | 
						|
}
 |