github.com/xmplusdev/xray-core@v1.8.10/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/xmplusdev/xray-core/common" 12 "github.com/xmplusdev/xray-core/common/cache" 13 "github.com/xmplusdev/xray-core/common/net" 14 "github.com/xmplusdev/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 }