public static DnsDatagram ResolveViaNameServers(DnsQuestionRecord question, NameServerAddress[] nameServers = null, IDnsCache cache = null, NetProxy proxy = null, bool preferIPv6 = false, bool tcp = false, int retries = 2, int maxStackCount = 10) { if ((nameServers != null) && (nameServers.Length > 0)) { //create copy of name servers array so that the values in original array are not messed due to shuffling feature NameServerAddress[] nameServersCopy = new NameServerAddress[nameServers.Length]; Array.Copy(nameServers, nameServersCopy, nameServers.Length); nameServers = nameServersCopy; } Stack <ResolverData> resolverStack = new Stack <ResolverData>(); int stackNameServerIndex = 0; while (true) //stack loop { if (resolverStack.Count > maxStackCount) { while (resolverStack.Count > 0) { ResolverData data = resolverStack.Pop(); question = data.Question; } throw new DnsClientException("DnsClient exceeded the maximum stack count to resolve the domain: " + question.Name); } if (cache != null) { DnsDatagram request = new DnsDatagram(new DnsHeader(0, false, DnsOpcode.StandardQuery, false, false, true, false, false, false, DnsResponseCode.NoError, 1, 0, 0, 0), new DnsQuestionRecord[] { question }, null, null, null); DnsDatagram cacheResponse = cache.Query(request); switch (cacheResponse.Header.RCODE) { case DnsResponseCode.NoError: if (cacheResponse.Answer.Length > 0) { if (resolverStack.Count == 0) { return(cacheResponse); } else { ResolverData data = resolverStack.Pop(); question = data.Question; nameServers = data.NameServers; stackNameServerIndex = data.NameServerIndex; switch (cacheResponse.Answer[0].Type) { case DnsResourceRecordType.AAAA: nameServers[stackNameServerIndex] = new NameServerAddress(nameServers[stackNameServerIndex].Domain, (cacheResponse.Answer[0].RDATA as DnsAAAARecord).Address); break; case DnsResourceRecordType.A: nameServers[stackNameServerIndex] = new NameServerAddress(nameServers[stackNameServerIndex].Domain, (cacheResponse.Answer[0].RDATA as DnsARecord).Address); break; default: //didnt find IP for current name server stackNameServerIndex++; //increment to skip current name server break; } continue; //stack loop } } if (cacheResponse.Authority.Length > 0) { if (cacheResponse.Authority[0].Type == DnsResourceRecordType.SOA) { if (resolverStack.Count == 0) { return(cacheResponse); } else { if (question.Type == DnsResourceRecordType.AAAA) { question = new DnsQuestionRecord(question.Name, DnsResourceRecordType.A, question.Class); } else { //didnt find IP for current name server //pop and try next name server ResolverData data = resolverStack.Pop(); question = data.Question; nameServers = data.NameServers; stackNameServerIndex = data.NameServerIndex + 1; //increment to skip current name server } continue; //to stack loop } } if ((nameServers == null) || (nameServers.Length == 0)) { NameServerAddress[] cacheNameServers = NameServerAddress.GetNameServersFromResponse(cacheResponse, preferIPv6, true); if (cacheNameServers.Length > 0) { nameServers = cacheNameServers; } } } break; case DnsResponseCode.NameError: if (resolverStack.Count == 0) { return(cacheResponse); } else { //current name server domain doesnt exists //pop and try next name server ResolverData data = resolverStack.Pop(); question = data.Question; nameServers = data.NameServers; stackNameServerIndex = data.NameServerIndex + 1; //increment to skip current name server continue; //stack loop } } } if ((nameServers == null) || (nameServers.Length == 0)) { //create copy of root name servers array so that the values in original array are not messed due to shuffling feature if (preferIPv6) { nameServers = new NameServerAddress[ROOT_NAME_SERVERS_IPv6.Length]; Array.Copy(ROOT_NAME_SERVERS_IPv6, nameServers, ROOT_NAME_SERVERS_IPv6.Length); } else { nameServers = new NameServerAddress[ROOT_NAME_SERVERS_IPv4.Length]; Array.Copy(ROOT_NAME_SERVERS_IPv4, nameServers, ROOT_NAME_SERVERS_IPv4.Length); } } NameServerAddress.Shuffle(nameServers); int hopCount = 0; while ((hopCount++) < MAX_HOPS) //resolver loop { //copy and reset stack name server index since its one time use only after stack pop int i = stackNameServerIndex; stackNameServerIndex = 0; //query name servers one by one for (; i < nameServers.Length; i++) //retry next server loop { NameServerAddress currentNameServer = nameServers[i]; if (question.Name == currentNameServer.Domain) { continue; //obvious! } if (currentNameServer.EndPoint == null) { resolverStack.Push(new ResolverData(question, nameServers, i)); if (preferIPv6) { question = new DnsQuestionRecord(currentNameServer.Domain, DnsResourceRecordType.AAAA, question.Class); } else { question = new DnsQuestionRecord(currentNameServer.Domain, DnsResourceRecordType.A, question.Class); } nameServers = null; goto stackLoop; } DnsClient client = new DnsClient(currentNameServer); client._proxy = proxy; client._preferIPv6 = preferIPv6; client._tcp = tcp; client._retries = retries; DnsDatagram request = new DnsDatagram(new DnsHeader(0, false, DnsOpcode.StandardQuery, false, false, true, false, false, false, DnsResponseCode.NoError, 1, 0, 0, 0), new DnsQuestionRecord[] { question }, null, null, null); DnsDatagram response; try { response = client.Resolve(request); } catch (DnsClientException) { continue; //resolver loop } if (response.Header.Truncation) { if (tcp) { return(response); } client._tcp = true; response = client.Resolve(request); } if (cache != null) { cache.CacheResponse(response); } switch (response.Header.RCODE) { case DnsResponseCode.NoError: if (response.Answer.Length > 0) { if (!response.Answer[0].Name.Equals(question.Name, StringComparison.CurrentCultureIgnoreCase)) { continue; //continue to next name server since current name server may be misconfigured } if (resolverStack.Count == 0) { return(response); } else { ResolverData data = resolverStack.Pop(); question = data.Question; nameServers = data.NameServers; stackNameServerIndex = data.NameServerIndex; switch (response.Answer[0].Type) { case DnsResourceRecordType.AAAA: nameServers[stackNameServerIndex] = new NameServerAddress(nameServers[stackNameServerIndex].Domain, (response.Answer[0].RDATA as DnsAAAARecord).Address); break; case DnsResourceRecordType.A: nameServers[stackNameServerIndex] = new NameServerAddress(nameServers[stackNameServerIndex].Domain, (response.Answer[0].RDATA as DnsARecord).Address); break; default: //didnt find IP for current name server stackNameServerIndex++; //increment to skip current name server break; } goto resolverLoop; } } if (response.Authority.Length == 0) { continue; //continue to next name server since current name server may be misconfigured } if (response.Authority[0].Type == DnsResourceRecordType.SOA) { //no entry for given type if (resolverStack.Count == 0) { return(response); } else { if (question.Type == DnsResourceRecordType.AAAA) { question = new DnsQuestionRecord(question.Name, DnsResourceRecordType.A, question.Class); } else { //didnt find IP for current name server //pop and try next name server ResolverData data = resolverStack.Pop(); question = data.Question; nameServers = data.NameServers; stackNameServerIndex = data.NameServerIndex + 1; //increment to skip current name server } goto stackLoop; //goto stack loop } } nameServers = NameServerAddress.GetNameServersFromResponse(response, preferIPv6, false); if (nameServers.Length == 0) { continue; //continue to next name server since current name server may be misconfigured } goto resolverLoop; case DnsResponseCode.NameError: if (resolverStack.Count == 0) { return(response); } else { //current name server domain doesnt exists //pop and try next name server ResolverData data = resolverStack.Pop(); question = data.Question; nameServers = data.NameServers; stackNameServerIndex = data.NameServerIndex + 1; //increment to skip current name server goto stackLoop; //goto stack loop } default: continue; //continue to next name server since current name server may be misconfigured } } if (resolverStack.Count == 0) { throw new DnsClientException("DnsClient failed to resolve the request: no response from name servers."); } else { //didnt find IP for current name server //pop and try next name server ResolverData data = resolverStack.Pop(); question = data.Question; nameServers = data.NameServers; stackNameServerIndex = data.NameServerIndex + 1; //increment to skip current name server break; //to stack loop } resolverLoop :; } stackLoop :; } }
public DnsPTRRecord(string ptrDomainName) { DnsClient.IsDomainNameValid(ptrDomainName, true); _ptrDomainName = ptrDomainName; }
public DnsCNAMERecord(string cnameDomainName) { DnsClient.IsDomainNameValid(cnameDomainName, true); _cnameDomainName = cnameDomainName; }
public DnsNSRecord(string nsDomainName) { DnsClient.IsDomainNameValid(nsDomainName, true); _nsDomainName = nsDomainName; }
public void ResolveIPAddress(NameServerAddress[] nameServers = null, NetProxy proxy = null, bool preferIPv6 = false, int retries = 2, int timeout = 2000, DnsTransportProtocol protocol = DnsTransportProtocol.Udp) { lock (_ipEndPointResolverLock) { if (_ipEndPointExpires && (DateTime.UtcNow < _ipEndPointExpiresOn)) { return; } string domain; if (_dohEndPoint != null) { domain = _dohEndPoint.Host; } else if (_domainEndPoint != null) { domain = _domainEndPoint.Address; } else { return; } if (domain == "localhost") { _ipEndPoint = new IPEndPoint((preferIPv6 ? IPAddress.IPv6Loopback : IPAddress.Loopback), this.Port); return; } if (IPAddress.TryParse(domain, out IPAddress address)) { _ipEndPoint = new IPEndPoint(address, this.Port); return; } DnsClient dnsClient; if (nameServers == null) { dnsClient = new DnsClient(); } else { dnsClient = new DnsClient(nameServers); } dnsClient.Proxy = proxy; dnsClient.PreferIPv6 = preferIPv6; dnsClient.Protocol = protocol; dnsClient.Retries = retries; dnsClient.Timeout = timeout; IPAddress[] serverIPs = dnsClient.ResolveIP(domain, preferIPv6); if (serverIPs.Length == 0) { throw new DnsClientException("No IP address was found for name server: " + domain); } _ipEndPoint = new IPEndPoint(serverIPs[0], this.Port); _ipEndPointExpires = true; _ipEndPointExpiresOn = DateTime.UtcNow.AddSeconds(IP_ENDPOINT_DEFAULT_TTL); } }
public static NameServerAddress[] GetNameServersFromResponse(DnsDatagram response, bool preferIPv6, bool selectOnlyNameServersWithGlue) { List <NameServerAddress> nameServers = new List <NameServerAddress>(response.Authority.Length); DnsResourceRecord[] authorityRecords; if ((response.Question.Length > 0) && (response.Question[0].Type == DnsResourceRecordType.NS) && (response.Answer.Length > 0)) { authorityRecords = response.Answer; } else { authorityRecords = response.Authority; } foreach (DnsResourceRecord authorityRecord in authorityRecords) { if (authorityRecord.Type == DnsResourceRecordType.NS) { DnsNSRecord nsRecord = (DnsNSRecord)authorityRecord.RDATA; IPEndPoint endPoint = null; //find ip address of authoritative name server from additional records foreach (DnsResourceRecord rr in response.Additional) { if (nsRecord.NSDomainName.Equals(rr.Name, StringComparison.OrdinalIgnoreCase)) { switch (rr.Type) { case DnsResourceRecordType.A: endPoint = new IPEndPoint(((DnsARecord)rr.RDATA).Address, 53); nameServers.Add(new NameServerAddress(nsRecord.NSDomainName, endPoint)); break; case DnsResourceRecordType.AAAA: endPoint = new IPEndPoint(((DnsAAAARecord)rr.RDATA).Address, 53); if (preferIPv6) { nameServers.Add(new NameServerAddress(nsRecord.NSDomainName, endPoint)); } break; } } } if ((endPoint == null) && !selectOnlyNameServersWithGlue) { nameServers.Add(new NameServerAddress(new DomainEndPoint(nsRecord.NSDomainName, 53))); } } } NameServerAddress[] nsArray = nameServers.ToArray(); DnsClient.ShuffleArray(nsArray); if (preferIPv6) { Array.Sort(nsArray); } return(nsArray); }
public async Task RecursiveResolveDomainNameAsync(IDnsCache cache = null, NetProxy proxy = null, bool preferIPv6 = false, bool randomizeName = false, int retries = 2, int timeout = 2000) { if (_ipEndPoint != null) { try { IReadOnlyList <string> ptrDomains = DnsClient.ParseResponsePTR(await DnsClient.RecursiveResolveQueryAsync(new DnsQuestionRecord(_ipEndPoint.Address, DnsClass.IN), cache, proxy, preferIPv6, randomizeName, retries, timeout)); if (ptrDomains != null) { _domainEndPoint = new DomainEndPoint(ptrDomains[0], _ipEndPoint.Port); } } catch { } } }
public async Task ResolveIPAddressAsync(IReadOnlyList <NameServerAddress> nameServers = null, NetProxy proxy = null, bool preferIPv6 = false, bool randomizeName = false, int retries = 2, int timeout = 2000) { if (_ipEndPointExpires && (DateTime.UtcNow < _ipEndPointExpiresOn)) { return; } string domain; if (_dohEndPoint != null) { domain = _dohEndPoint.Host; } else if (_domainEndPoint != null) { domain = _domainEndPoint.Address; } else { return; } if (domain == "localhost") { _ipEndPoint = new IPEndPoint(preferIPv6 ? IPAddress.IPv6Loopback : IPAddress.Loopback, Port); return; } if (IPAddress.TryParse(domain, out IPAddress address)) { _ipEndPoint = new IPEndPoint(address, Port); return; } DnsClient dnsClient; if (nameServers == null) { dnsClient = new DnsClient(); } else { dnsClient = new DnsClient(nameServers); } dnsClient.Proxy = proxy; dnsClient.PreferIPv6 = preferIPv6; dnsClient.RandomizeName = randomizeName; dnsClient.Retries = retries; dnsClient.Timeout = timeout; IReadOnlyList <IPAddress> serverIPs = await dnsClient.ResolveIPAsync(domain, preferIPv6); if (serverIPs.Count == 0) { throw new DnsClientException("No IP address was found for name server: " + domain); } _ipEndPoint = new IPEndPoint(serverIPs[0], this.Port); _ipEndPointExpires = true; _ipEndPointExpiresOn = DateTime.UtcNow.AddSeconds(IP_ENDPOINT_DEFAULT_TTL); }
public void RecursiveResolveIPAddress(DnsCache cache = null, NetProxy proxy = null, bool preferIPv6 = false, DnsTransportProtocol protocol = DnsTransportProtocol.Udp, int retries = 2, int timeout = 2000, DnsTransportProtocol recursiveResolveProtocol = DnsTransportProtocol.Udp) { lock (_ipEndPointResolverLock) { if (_ipEndPointExpires && (DateTime.UtcNow < _ipEndPointExpiresOn)) { return; } string domain; if (_dohEndPoint != null) { domain = _dohEndPoint.Host; } else if (_domainEndPoint != null) { domain = _domainEndPoint.Address; } else { return; } if (domain == "localhost") { _ipEndPoint = new IPEndPoint((preferIPv6 ? IPAddress.IPv6Loopback : IPAddress.Loopback), this.Port); return; } if (IPAddress.TryParse(domain, out IPAddress address)) { _ipEndPoint = new IPEndPoint(address, this.Port); return; } IPEndPoint ipEndPoint = null; DateTime ipEndPointExpiresOn = DateTime.MinValue; if (preferIPv6) { DnsDatagram nsResponse = DnsClient.RecursiveResolve(new DnsQuestionRecord(domain, DnsResourceRecordType.AAAA, DnsClass.IN), null, cache, proxy, true, protocol, retries, timeout, recursiveResolveProtocol); if ((nsResponse.Header.RCODE == DnsResponseCode.NoError) && (nsResponse.Answer.Length > 0) && (nsResponse.Answer[0].Type == DnsResourceRecordType.AAAA)) { ipEndPoint = new IPEndPoint((nsResponse.Answer[0].RDATA as DnsAAAARecord).Address, this.Port); ipEndPointExpiresOn = DateTime.UtcNow.AddSeconds(nsResponse.Answer[0].TtlValue); } } if (ipEndPoint == null) { DnsDatagram nsResponse = DnsClient.RecursiveResolve(new DnsQuestionRecord(domain, DnsResourceRecordType.A, DnsClass.IN), null, cache, proxy, false, protocol, retries, timeout, recursiveResolveProtocol); if ((nsResponse.Header.RCODE == DnsResponseCode.NoError) && (nsResponse.Answer.Length > 0) && (nsResponse.Answer[0].Type == DnsResourceRecordType.A)) { ipEndPoint = new IPEndPoint((nsResponse.Answer[0].RDATA as DnsARecord).Address, this.Port); ipEndPointExpiresOn = DateTime.UtcNow.AddSeconds(nsResponse.Answer[0].TtlValue); } } if (ipEndPoint == null) { throw new DnsClientException("No IP address was found for name server: " + domain); } _ipEndPoint = ipEndPoint; _ipEndPointExpires = true; _ipEndPointExpiresOn = ipEndPointExpiresOn; } }