github.com/v2fly/v2ray-core/v5@v5.16.2-0.20240507031116-8191faa6e095/app/dns/fakedns/fake.go (about)

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