github.com/xraypb/Xray-core@v1.8.1/app/dns/fakedns/fake.go (about)

     1  package fakedns
     2  
     3  import (
     4  	"context"
     5  	"math"
     6  	"math/big"
     7  	gonet "net"
     8  	"sync"
     9  	"time"
    10  
    11  	"github.com/xraypb/Xray-core/common"
    12  	"github.com/xraypb/Xray-core/common/cache"
    13  	"github.com/xraypb/Xray-core/common/net"
    14  	"github.com/xraypb/Xray-core/features/dns"
    15  )
    16  
    17  type Holder struct {
    18  	domainToIP cache.Lru
    19  	ipRange    *gonet.IPNet
    20  	mu         *sync.Mutex
    21  
    22  	config *FakeDnsPool
    23  }
    24  
    25  func (fkdns *Holder) IsIPInIPPool(ip net.Address) bool {
    26  	if ip.Family().IsDomain() {
    27  		return false
    28  	}
    29  	return fkdns.ipRange.Contains(ip.IP())
    30  }
    31  
    32  func (fkdns *Holder) GetFakeIPForDomain3(domain string, ipv4, ipv6 bool) []net.Address {
    33  	isIPv6 := fkdns.ipRange.IP.To4() == nil
    34  	if (isIPv6 && ipv6) || (!isIPv6 && ipv4) {
    35  		return fkdns.GetFakeIPForDomain(domain)
    36  	}
    37  	return []net.Address{}
    38  }
    39  
    40  func (*Holder) Type() interface{} {
    41  	return (*dns.FakeDNSEngine)(nil)
    42  }
    43  
    44  func (fkdns *Holder) Start() error {
    45  	if fkdns.config != nil && fkdns.config.IpPool != "" && fkdns.config.LruSize != 0 {
    46  		return fkdns.initializeFromConfig()
    47  	}
    48  	return newError("invalid fakeDNS setting")
    49  }
    50  
    51  func (fkdns *Holder) Close() error {
    52  	fkdns.domainToIP = nil
    53  	fkdns.ipRange = nil
    54  	fkdns.mu = nil
    55  	return nil
    56  }
    57  
    58  func NewFakeDNSHolder() (*Holder, error) {
    59  	var fkdns *Holder
    60  	var err error
    61  
    62  	if fkdns, err = NewFakeDNSHolderConfigOnly(nil); err != nil {
    63  		return nil, newError("Unable to create Fake Dns Engine").Base(err).AtError()
    64  	}
    65  	err = fkdns.initialize(dns.FakeIPv4Pool, 65535)
    66  	if err != nil {
    67  		return nil, err
    68  	}
    69  	return fkdns, nil
    70  }
    71  
    72  func NewFakeDNSHolderConfigOnly(conf *FakeDnsPool) (*Holder, error) {
    73  	return &Holder{nil, nil, nil, conf}, nil
    74  }
    75  
    76  func (fkdns *Holder) initializeFromConfig() error {
    77  	return fkdns.initialize(fkdns.config.IpPool, int(fkdns.config.LruSize))
    78  }
    79  
    80  func (fkdns *Holder) initialize(ipPoolCidr string, lruSize int) error {
    81  	var ipRange *gonet.IPNet
    82  	var err error
    83  
    84  	if _, ipRange, err = gonet.ParseCIDR(ipPoolCidr); err != nil {
    85  		return newError("Unable to parse CIDR for Fake DNS IP assignment").Base(err).AtError()
    86  	}
    87  
    88  	ones, bits := ipRange.Mask.Size()
    89  	rooms := bits - ones
    90  	if math.Log2(float64(lruSize)) >= float64(rooms) {
    91  		return newError("LRU size is bigger than subnet size").AtError()
    92  	}
    93  	fkdns.domainToIP = cache.NewLru(lruSize)
    94  	fkdns.ipRange = ipRange
    95  	fkdns.mu = new(sync.Mutex)
    96  	return nil
    97  }
    98  
    99  // GetFakeIPForDomain checks and generates a fake IP for a domain name
   100  func (fkdns *Holder) GetFakeIPForDomain(domain string) []net.Address {
   101  	fkdns.mu.Lock()
   102  	defer fkdns.mu.Unlock()
   103  	if v, ok := fkdns.domainToIP.Get(domain); ok {
   104  		return []net.Address{v.(net.Address)}
   105  	}
   106  	currentTimeMillis := uint64(time.Now().UnixNano() / 1e6)
   107  	ones, bits := fkdns.ipRange.Mask.Size()
   108  	rooms := bits - ones
   109  	if rooms < 64 {
   110  		currentTimeMillis %= (uint64(1) << rooms)
   111  	}
   112  	bigIntIP := big.NewInt(0).SetBytes(fkdns.ipRange.IP)
   113  	bigIntIP = bigIntIP.Add(bigIntIP, new(big.Int).SetUint64(currentTimeMillis))
   114  	var ip net.Address
   115  	for {
   116  		ip = net.IPAddress(bigIntIP.Bytes())
   117  
   118  		// if we run for a long time, we may go back to beginning and start seeing the IP in use
   119  		if _, ok := fkdns.domainToIP.PeekKeyFromValue(ip); !ok {
   120  			break
   121  		}
   122  
   123  		bigIntIP = bigIntIP.Add(bigIntIP, big.NewInt(1))
   124  		if !fkdns.ipRange.Contains(bigIntIP.Bytes()) {
   125  			bigIntIP = big.NewInt(0).SetBytes(fkdns.ipRange.IP)
   126  		}
   127  	}
   128  	fkdns.domainToIP.Put(domain, ip)
   129  	return []net.Address{ip}
   130  }
   131  
   132  // GetDomainFromFakeDNS checks if an IP is a fake IP and have corresponding domain name
   133  func (fkdns *Holder) GetDomainFromFakeDNS(ip net.Address) string {
   134  	if !ip.Family().IsIP() || !fkdns.ipRange.Contains(ip.IP()) {
   135  		return ""
   136  	}
   137  	if k, ok := fkdns.domainToIP.GetKeyFromValue(ip); ok {
   138  		return k.(string)
   139  	}
   140  	newError("A fake ip request to ", ip, ", however there is no matching domain name in fake DNS").AtInfo().WriteToLog()
   141  	return ""
   142  }
   143  
   144  type HolderMulti struct {
   145  	holders []*Holder
   146  
   147  	config *FakeDnsPoolMulti
   148  }
   149  
   150  func (h *HolderMulti) IsIPInIPPool(ip net.Address) bool {
   151  	if ip.Family().IsDomain() {
   152  		return false
   153  	}
   154  	for _, v := range h.holders {
   155  		if v.IsIPInIPPool(ip) {
   156  			return true
   157  		}
   158  	}
   159  	return false
   160  }
   161  
   162  func (h *HolderMulti) GetFakeIPForDomain3(domain string, ipv4, ipv6 bool) []net.Address {
   163  	var ret []net.Address
   164  	for _, v := range h.holders {
   165  		ret = append(ret, v.GetFakeIPForDomain3(domain, ipv4, ipv6)...)
   166  	}
   167  	return ret
   168  }
   169  
   170  func (h *HolderMulti) GetFakeIPForDomain(domain string) []net.Address {
   171  	var ret []net.Address
   172  	for _, v := range h.holders {
   173  		ret = append(ret, v.GetFakeIPForDomain(domain)...)
   174  	}
   175  	return ret
   176  }
   177  
   178  func (h *HolderMulti) GetDomainFromFakeDNS(ip net.Address) string {
   179  	for _, v := range h.holders {
   180  		if domain := v.GetDomainFromFakeDNS(ip); domain != "" {
   181  			return domain
   182  		}
   183  	}
   184  	return ""
   185  }
   186  
   187  func (h *HolderMulti) Type() interface{} {
   188  	return (*dns.FakeDNSEngine)(nil)
   189  }
   190  
   191  func (h *HolderMulti) Start() error {
   192  	for _, v := range h.holders {
   193  		if v.config != nil && v.config.IpPool != "" && v.config.LruSize != 0 {
   194  			if err := v.Start(); err != nil {
   195  				return newError("Cannot start all fake dns pools").Base(err)
   196  			}
   197  		} else {
   198  			return newError("invalid fakeDNS setting")
   199  		}
   200  	}
   201  	return nil
   202  }
   203  
   204  func (h *HolderMulti) Close() error {
   205  	for _, v := range h.holders {
   206  		if err := v.Close(); err != nil {
   207  			return newError("Cannot close all fake dns pools").Base(err)
   208  		}
   209  	}
   210  	return nil
   211  }
   212  
   213  func (h *HolderMulti) createHolderGroups() error {
   214  	for _, v := range h.config.Pools {
   215  		holder, err := NewFakeDNSHolderConfigOnly(v)
   216  		if err != nil {
   217  			return err
   218  		}
   219  		h.holders = append(h.holders, holder)
   220  	}
   221  	return nil
   222  }
   223  
   224  func NewFakeDNSHolderMulti(conf *FakeDnsPoolMulti) (*HolderMulti, error) {
   225  	holderMulti := &HolderMulti{nil, conf}
   226  	if err := holderMulti.createHolderGroups(); err != nil {
   227  		return nil, err
   228  	}
   229  	return holderMulti, nil
   230  }
   231  
   232  func init() {
   233  	common.Must(common.RegisterConfig((*FakeDnsPool)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
   234  		var f *Holder
   235  		var err error
   236  		if f, err = NewFakeDNSHolderConfigOnly(config.(*FakeDnsPool)); err != nil {
   237  			return nil, err
   238  		}
   239  		return f, nil
   240  	}))
   241  
   242  	common.Must(common.RegisterConfig((*FakeDnsPoolMulti)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
   243  		var f *HolderMulti
   244  		var err error
   245  		if f, err = NewFakeDNSHolderMulti(config.(*FakeDnsPoolMulti)); err != nil {
   246  			return nil, err
   247  		}
   248  		return f, nil
   249  	}))
   250  }