internal void ResolveAddress(IDnsCache cache, NetProxy proxy, bool preferIPv6, bool tcp, int retries) { if ((_domain != null) && (_endPoint == null)) { if (preferIPv6) { try { DnsDatagram nsResponse = DnsClient.ResolveViaNameServers(new DnsQuestionRecord(_domain, DnsResourceRecordType.AAAA, DnsClass.IN), null, cache, proxy, true, tcp, retries); if ((nsResponse.Header.RCODE == DnsResponseCode.NoError) && (nsResponse.Answer.Length > 0) && (nsResponse.Answer[0].Type == DnsResourceRecordType.AAAA)) { _endPoint = new IPEndPoint((nsResponse.Answer[0].RDATA as DnsAAAARecord).Address, 53); } } catch { } } if (_endPoint == null) { try { DnsDatagram nsResponse = DnsClient.ResolveViaNameServers(new DnsQuestionRecord(_domain, DnsResourceRecordType.A, DnsClass.IN), null, cache, proxy, false, tcp, retries); if ((nsResponse.Header.RCODE == DnsResponseCode.NoError) && (nsResponse.Answer.Length > 0) && (nsResponse.Answer[0].Type == DnsResourceRecordType.A)) { _endPoint = new IPEndPoint((nsResponse.Answer[0].RDATA as DnsARecord).Address, 53); } } catch { } } } }
public void RecursiveResolveIPAddress(IDnsCache cache = null, NetProxy proxy = null, bool preferIPv6 = false, DnsTransportProtocol protocol = DnsTransportProtocol.Udp, int retries = 2, int timeout = 2000, DnsTransportProtocol recursiveResolveProtocol = DnsTransportProtocol.Udp) { 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; } 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); } } 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); } } if (_ipEndPoint == null) { throw new DnsClientException("No IP address was found for name server: " + domain); } }
public async Task RecursiveResolveIPAddressAsync(IDnsCache cache = 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), this.Port); return; } if (IPAddress.TryParse(domain, out IPAddress address)) { _ipEndPoint = new IPEndPoint(address, this.Port); return; } IPEndPoint ipEndPoint = null; IReadOnlyList <IPAddress> addresses = await DnsClient.RecursiveResolveIPAsync(domain, cache, proxy, preferIPv6, randomizeName, retries, timeout); if (addresses.Count > 0) { ipEndPoint = new IPEndPoint(addresses[0], this.Port); } if (ipEndPoint == null) { throw new DnsClientException("No IP address was found for name server: " + domain); } _ipEndPoint = ipEndPoint; _ipEndPointExpires = true; _ipEndPointExpiresOn = DateTime.UtcNow.AddSeconds(IP_ENDPOINT_DEFAULT_TTL); }
public DnsServer(IPEndPoint localEP) { _localEP = localEP; _dnsCache = new DnsCache(_cacheZoneRoot); //set min threads since the default value is too small { int minWorker, minIOC; ThreadPool.GetMinThreads(out minWorker, out minIOC); minWorker = Environment.ProcessorCount * 32; ThreadPool.SetMinThreads(minWorker, minIOC); } }
public void RecursiveResolveDomainName(IDnsCache cache = null, NetProxy proxy = null, bool preferIPv6 = false, DnsTransportProtocol protocol = DnsTransportProtocol.Udp, int retries = 2, int timeout = 2000, DnsTransportProtocol recursiveResolveProtocol = DnsTransportProtocol.Udp) { if (_ipEndPoint != null) { try { DnsDatagram nsResponse = DnsClient.RecursiveResolve(new DnsQuestionRecord(_ipEndPoint.Address, DnsClass.IN), null, cache, proxy, preferIPv6, protocol, retries, timeout, recursiveResolveProtocol); if ((nsResponse.Header.RCODE == DnsResponseCode.NoError) && (nsResponse.Answer.Length > 0) && (nsResponse.Answer[0].Type == DnsResourceRecordType.PTR)) { _domainEndPoint = new DomainEndPoint((nsResponse.Answer[0].RDATA as DnsPTRRecord).PTRDomainName, _ipEndPoint.Port); } } catch { } } }
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 DnsDatagram Resolve(DnsDatagram request) { int bytesRecv; byte[] responseBuffer = null; int nextServerIndex = 0; int retries = _retries; byte[] requestBuffer; IDnsCache dnsCache = null; //serialize request using (MemoryStream mS = new MemoryStream(32)) { if (_tcp) { mS.Position = 2; } //write dns datagram request.WriteTo(mS); requestBuffer = mS.ToArray(); if (_tcp) { byte[] length = BitConverter.GetBytes(Convert.ToUInt16(requestBuffer.Length - 2)); requestBuffer[0] = length[1]; requestBuffer[1] = length[0]; } } //init server selection parameters if (_servers.Length > 1) { retries = retries * _servers.Length; //retries on per server basis byte[] select = new byte[1]; _rnd.GetBytes(select); nextServerIndex = select[0] % _servers.Length; } int retry = 0; while (retry < retries) { //select server NameServerAddress server; if (_servers.Length > 1) { server = _servers[nextServerIndex]; nextServerIndex = (nextServerIndex + 1) % _servers.Length; } else { server = _servers[0]; } if (server.EndPoint == null) { if (dnsCache == null) { dnsCache = new SimpleDnsCache(); } server.ResolveAddress(dnsCache, _proxy, _preferIPv6, _tcp, _retries); if (server.EndPoint == null) { retry++; continue; } } //query server Socket _socket = null; SocksUdpAssociateRequestHandler proxyRequestHandler = null; try { retry++; DateTime sentAt = DateTime.UtcNow; bool dnsTcp; if (_proxy == null) { if (_tcp) { _socket = new Socket(server.EndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); _socket.NoDelay = true; _socket.SendTimeout = _sendTimeout; _socket.ReceiveTimeout = _recvTimeout; IAsyncResult result = _socket.BeginConnect(server.EndPoint, null, null); if (!result.AsyncWaitHandle.WaitOne(_connectionTimeout)) { throw new SocketException((int)SocketError.TimedOut); } if (!_socket.Connected) { throw new SocketException((int)SocketError.ConnectionRefused); } } else { _socket = new Socket(server.EndPoint.AddressFamily, SocketType.Dgram, ProtocolType.Udp); _socket.SendTimeout = _sendTimeout; _socket.ReceiveTimeout = _recvTimeout; } dnsTcp = _tcp; } else { switch (_proxy.Type) { case NetProxyType.Http: _socket = _proxy.HttpProxy.Connect(server.EndPoint, _connectionTimeout); _socket.NoDelay = true; _socket.SendTimeout = _sendTimeout; _socket.ReceiveTimeout = _recvTimeout; dnsTcp = true; break; case NetProxyType.Socks5: if (!_tcp) { try { proxyRequestHandler = _proxy.SocksProxy.UdpAssociate(_connectionTimeout); proxyRequestHandler.ReceiveTimeout = _recvTimeout; dnsTcp = false; break; } catch (SocksClientException) { } } using (SocksConnectRequestHandler requestHandler = _proxy.SocksProxy.Connect(server.EndPoint, _connectionTimeout)) { _socket = requestHandler.GetSocket(); _socket.NoDelay = true; _socket.SendTimeout = _sendTimeout; _socket.ReceiveTimeout = _recvTimeout; dnsTcp = true; } break; default: throw new NotSupportedException("Proxy type not supported by DnsClient."); } } if (dnsTcp) { _socket.Send(requestBuffer); if ((responseBuffer == null) || (responseBuffer.Length == 512)) { responseBuffer = new byte[64 * 1024]; } bytesRecv = _socket.Receive(responseBuffer, 0, 2, SocketFlags.None); if (bytesRecv < 1) { throw new SocketException((int)SocketError.ConnectionReset); } Array.Reverse(responseBuffer, 0, 2); ushort length = BitConverter.ToUInt16(responseBuffer, 0); int offset = 0; while (offset < length) { bytesRecv = _socket.Receive(responseBuffer, offset, length, SocketFlags.None); if (bytesRecv < 1) { throw new SocketException((int)SocketError.ConnectionReset); } offset += bytesRecv; } bytesRecv = length; } else { if (responseBuffer == null) { responseBuffer = new byte[512]; } if (proxyRequestHandler == null) { _socket.SendTo(requestBuffer, server.EndPoint); EndPoint remoteEP; if (server.EndPoint.AddressFamily == AddressFamily.InterNetworkV6) { remoteEP = new IPEndPoint(IPAddress.IPv6Any, 0); } else { remoteEP = new IPEndPoint(IPAddress.Any, 0); } bytesRecv = _socket.ReceiveFrom(responseBuffer, ref remoteEP); } else { proxyRequestHandler.SendTo(requestBuffer, 0, requestBuffer.Length, new SocksEndPoint(server.EndPoint)); bytesRecv = proxyRequestHandler.ReceiveFrom(responseBuffer, 0, responseBuffer.Length, out SocksEndPoint socksRemoteEP); } } //parse response using (MemoryStream mS = new MemoryStream(responseBuffer, 0, bytesRecv, false)) { double rtt = (DateTime.UtcNow - sentAt).TotalMilliseconds; DnsDatagram response = new DnsDatagram(mS, server, (_tcp ? ProtocolType.Tcp : ProtocolType.Udp), rtt); if (response.Header.Identifier == request.Header.Identifier) { return(response); } } } catch (SocketException) { } finally { if (_socket != null) { _socket.Dispose(); } if (proxyRequestHandler != null) { proxyRequestHandler.Dispose(); } } } throw new DnsClientException("DnsClient failed to resolve the request: no response from name servers."); }
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 static DnsDatagram ResolveViaNameServers(string domain, DnsResourceRecordType queryType, NameServerAddress[] nameServers = null, IDnsCache cache = null, NetProxy proxy = null, bool preferIPv6 = false, bool tcp = false, int retries = 2, int maxStackCount = 10) { DnsQuestionRecord question; if (queryType == DnsResourceRecordType.PTR) { question = new DnsQuestionRecord(IPAddress.Parse(domain), DnsClass.IN); } else { question = new DnsQuestionRecord(domain, queryType, DnsClass.IN); } return(ResolveViaNameServers(question, nameServers, cache, proxy, preferIPv6, tcp, retries, maxStackCount)); }
public static DnsDatagram ResolveViaRootNameServers(string domain, DnsResourceRecordType queryType, IDnsCache cache = null, NetProxy proxy = null, bool preferIPv6 = false, bool tcp = false, int retries = 2, int maxStackCount = 10) { return(ResolveViaNameServers(domain, queryType, null, cache, proxy, preferIPv6, tcp, retries, maxStackCount)); }
public DnsServer(IPEndPoint localEP) { _localEP = localEP; _dnsCache = new DnsCache(_cacheZoneRoot); }