mirror of
https://github.com/XTLS/Xray-core.git
synced 2024-12-01 09:36:03 +03:00
017f53b5fc
* Add session context outbounds as slice slice is needed for dialer proxy where two outbounds work on top of each other There are two sets of target addr for example It also enable Xtls to correctly do splice copy by checking both outbounds are ready to do direct copy * Fill outbound tag info * Splice now checks capalibility from all outbounds * Fix unit tests
121 lines
3.8 KiB
Go
121 lines
3.8 KiB
Go
package dispatcher
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
|
|
"github.com/xtls/xray-core/common"
|
|
"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 := newError("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 != "" {
|
|
newError("fake dns got domain: ", domainFromFakeDNS, " for ip: ", ob.Target.Address.String()).WriteToLog(session.ExportIDToError(ctx))
|
|
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
|
|
}
|
|
newError("ip address not in fake dns range, return as is").AtDebug().WriteToLog()
|
|
return nil, common.ErrNoClue
|
|
}
|
|
newError("fake dns sniffer did not set address in range option, assume false.").AtWarning().WriteToLog()
|
|
return nil, common.ErrNoClue
|
|
},
|
|
metadataSniffer: false,
|
|
}, nil
|
|
}
|