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