fakednssniffer.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. package dispatcher
  2. import (
  3. "context"
  4. "strings"
  5. "github.com/xtls/xray-core/common"
  6. "github.com/xtls/xray-core/common/errors"
  7. "github.com/xtls/xray-core/common/net"
  8. "github.com/xtls/xray-core/common/session"
  9. "github.com/xtls/xray-core/core"
  10. "github.com/xtls/xray-core/features/dns"
  11. )
  12. // newFakeDNSSniffer Creates a Fake DNS metadata sniffer
  13. func newFakeDNSSniffer(ctx context.Context) (protocolSnifferWithMetadata, error) {
  14. var fakeDNSEngine dns.FakeDNSEngine
  15. {
  16. fakeDNSEngineFeat := core.MustFromContext(ctx).GetFeature((*dns.FakeDNSEngine)(nil))
  17. if fakeDNSEngineFeat != nil {
  18. fakeDNSEngine = fakeDNSEngineFeat.(dns.FakeDNSEngine)
  19. }
  20. }
  21. if fakeDNSEngine == nil {
  22. errNotInit := errors.New("FakeDNSEngine is not initialized, but such a sniffer is used").AtError()
  23. return protocolSnifferWithMetadata{}, errNotInit
  24. }
  25. return protocolSnifferWithMetadata{protocolSniffer: func(ctx context.Context, bytes []byte) (SniffResult, error) {
  26. outbounds := session.OutboundsFromContext(ctx)
  27. ob := outbounds[len(outbounds)-1]
  28. if ob.Target.Network == net.Network_TCP || ob.Target.Network == net.Network_UDP {
  29. domainFromFakeDNS := fakeDNSEngine.GetDomainFromFakeDNS(ob.Target.Address)
  30. if domainFromFakeDNS != "" {
  31. errors.LogInfo(ctx, "fake dns got domain: ", domainFromFakeDNS, " for ip: ", ob.Target.Address.String())
  32. return &fakeDNSSniffResult{domainName: domainFromFakeDNS}, nil
  33. }
  34. }
  35. if ipAddressInRangeValueI := ctx.Value(ipAddressInRange); ipAddressInRangeValueI != nil {
  36. ipAddressInRangeValue := ipAddressInRangeValueI.(*ipAddressInRangeOpt)
  37. if fkr0, ok := fakeDNSEngine.(dns.FakeDNSEngineRev0); ok {
  38. inPool := fkr0.IsIPInIPPool(ob.Target.Address)
  39. ipAddressInRangeValue.addressInRange = &inPool
  40. }
  41. }
  42. return nil, common.ErrNoClue
  43. }, metadataSniffer: true}, nil
  44. }
  45. type fakeDNSSniffResult struct {
  46. domainName string
  47. }
  48. func (fakeDNSSniffResult) Protocol() string {
  49. return "fakedns"
  50. }
  51. func (f fakeDNSSniffResult) Domain() string {
  52. return f.domainName
  53. }
  54. type fakeDNSExtraOpts int
  55. const ipAddressInRange fakeDNSExtraOpts = 1
  56. type ipAddressInRangeOpt struct {
  57. addressInRange *bool
  58. }
  59. type DNSThenOthersSniffResult struct {
  60. domainName string
  61. protocolOriginalName string
  62. }
  63. func (f DNSThenOthersSniffResult) IsProtoSubsetOf(protocolName string) bool {
  64. return strings.HasPrefix(protocolName, f.protocolOriginalName)
  65. }
  66. func (DNSThenOthersSniffResult) Protocol() string {
  67. return "fakedns+others"
  68. }
  69. func (f DNSThenOthersSniffResult) Domain() string {
  70. return f.domainName
  71. }
  72. func newFakeDNSThenOthers(ctx context.Context, fakeDNSSniffer protocolSnifferWithMetadata, others []protocolSnifferWithMetadata) (
  73. protocolSnifferWithMetadata, error,
  74. ) { // nolint: unparam
  75. // ctx may be used in the future
  76. _ = ctx
  77. return protocolSnifferWithMetadata{
  78. protocolSniffer: func(ctx context.Context, bytes []byte) (SniffResult, error) {
  79. ipAddressInRangeValue := &ipAddressInRangeOpt{}
  80. ctx = context.WithValue(ctx, ipAddressInRange, ipAddressInRangeValue)
  81. result, err := fakeDNSSniffer.protocolSniffer(ctx, bytes)
  82. if err == nil {
  83. return result, nil
  84. }
  85. if ipAddressInRangeValue.addressInRange != nil {
  86. if *ipAddressInRangeValue.addressInRange {
  87. for _, v := range others {
  88. if v.metadataSniffer || bytes != nil {
  89. if result, err := v.protocolSniffer(ctx, bytes); err == nil {
  90. return DNSThenOthersSniffResult{domainName: result.Domain(), protocolOriginalName: result.Protocol()}, nil
  91. }
  92. }
  93. }
  94. return nil, common.ErrNoClue
  95. }
  96. errors.LogDebug(ctx, "ip address not in fake dns range, return as is")
  97. return nil, common.ErrNoClue
  98. }
  99. errors.LogWarning(ctx, "fake dns sniffer did not set address in range option, assume false.")
  100. return nil, common.ErrNoClue
  101. },
  102. metadataSniffer: false,
  103. }, nil
  104. }