internal static DnsResourceData Read(DnsDatagram dns, DnsType type, int offsetInDns, int length) { DnsResourceData prototype = TryGetPrototype(type); if (prototype != null) return prototype.CreateInstance(dns, offsetInDns, length); return new DnsResourceDataAnything(dns.Subsegment(offsetInDns, length)); }
internal override DnsResourceData CreateInstance(DnsDatagram dns, int offsetInDns, int length) { DnsDomainName mailingList; DnsDomainName errorMailbox; if (!TryRead(out mailingList, out errorMailbox, dns, offsetInDns, length)) return null; return new DnsResourceDataMailingListInfo(mailingList, errorMailbox); }
internal override DnsResourceData CreateInstance(DnsDatagram dns, int offsetInDns, int length) { ushort preference; DnsDomainName mailExchangeHost; if (!TryRead(out preference, out mailExchangeHost, dns, offsetInDns, length)) return null; return new DnsResourceDataMailExchange(preference, mailExchangeHost); }
internal override DnsResourceData CreateInstance(DnsDatagram dns, int offsetInDns, int length) { ushort preference; DnsDomainName intermediateHost; if (!TryRead(out preference, out intermediateHost, dns, offsetInDns, length)) return null; return new DnsResourceDataRouteThrough(preference, intermediateHost); }
internal override DnsResourceData CreateInstance(DnsDatagram dns, int offsetInDns, int length) { DnsDomainName mailbox; DnsDomainName textDomain; if (!TryRead(out mailbox, out textDomain, dns, offsetInDns, length)) return null; return new DnsResourceDataResponsiblePerson(mailbox, textDomain); }
internal override DnsResourceData CreateInstance(DnsDatagram dns, int offsetInDns, int length) { ushort subtype; DnsDomainName hostName; if (!TryRead(out subtype, out hostName, dns, offsetInDns, length)) return null; return new DnsResourceDataAfsDatabase((DnsAfsDatabaseSubtype)subtype, hostName); }
internal static bool TryRead(out DnsDomainName first, out DnsDomainName second, DnsDatagram dns, int offsetInDns, int length) { List<DnsDomainName> domainNames = ReadDomainNames(dns, offsetInDns, length, NumDomains); if (domainNames == null || domainNames.Count != NumDomains) { first = null; second = null; return false; } first = domainNames[0]; second = domainNames[1]; return true; }
public override DnsDatagram Query(DnsDatagram request) { //DoH JSON format request DateTime sentAt = DateTime.UtcNow; byte[] responseBuffer; using (WebClientEx wC = new WebClientEx()) { wC.AddHeader("accept", "application/dns-json"); wC.AddHeader("host", _server.DnsOverHttpEndPoint.Host + ":" + _server.DnsOverHttpEndPoint.Port); wC.UserAgent = "DoH client"; wC.Proxy = _proxy; wC.Timeout = _timeout; Uri queryUri; if (_proxy == null) { if (_server.IPEndPoint == null) { _server.RecursiveResolveIPAddress(); } queryUri = new Uri(_server.DnsOverHttpEndPoint.Scheme + "://" + _server.IPEndPoint.ToString() + _server.DnsOverHttpEndPoint.PathAndQuery); } else { queryUri = _server.DnsOverHttpEndPoint; } wC.QueryString.Clear(); wC.QueryString.Add("name", request.Question[0].Name); wC.QueryString.Add("type", Convert.ToString(((int)request.Question[0].Type))); responseBuffer = wC.DownloadData(queryUri); } //parse response dynamic jsonResponse = JsonConvert.DeserializeObject(Encoding.ASCII.GetString(responseBuffer)); DnsDatagram response = new DnsDatagram(jsonResponse); response.SetMetadata(new DnsDatagramMetadata(_server, _protocol, responseBuffer.Length, (DateTime.UtcNow - sentAt).TotalMilliseconds)); return(response); }
protected override void Parse(Stream s) { _algorithmName = DnsDatagram.DeserializeDomainName(s); _timeSigned = DnsDatagram.ReadUInt48NetworkOrder(s); _fudge = DnsDatagram.ReadUInt16NetworkOrder(s); ushort macSize = DnsDatagram.ReadUInt16NetworkOrder(s); _mac = s.ReadBytes(macSize); _originalID = DnsDatagram.ReadUInt16NetworkOrder(s); _error = (DnsTsigError)DnsDatagram.ReadUInt16NetworkOrder(s); ushort otherLen = DnsDatagram.ReadUInt16NetworkOrder(s); _otherData = s.ReadBytes(otherLen); }
public void Update(DnsDatagram response, IPAddress clientIpAddress) { StatsResponseType responseType; bool cacheHit; if ("blocked".Equals(response.Tag)) { responseType = StatsResponseType.Blocked; cacheHit = true; } else { switch (response.Header.RCODE) { case DnsResponseCode.NoError: responseType = StatsResponseType.NoError; break; case DnsResponseCode.ServerFailure: responseType = StatsResponseType.ServerFailure; break; case DnsResponseCode.NameError: responseType = StatsResponseType.NameError; break; case DnsResponseCode.Refused: responseType = StatsResponseType.Refused; break; default: return; } cacheHit = ("cacheHit".Equals(response.Tag)); } if (response.Header.QDCOUNT > 0) { Update(response.Question[0], responseType, cacheHit, clientIpAddress); } else { Update(new DnsQuestionRecord("", DnsResourceRecordType.ANY, DnsClass.IN), responseType, cacheHit, clientIpAddress); } }
private async Task ReadDnsDatagramAsync() { try { while (true) { //read response datagram DnsDatagram response = await DnsDatagram.ReadFromTcpAsync(_tcpStream, _recvBuffer).WithTimeout(ASYNC_RECEIVE_TIMEOUT); //signal waiting thread of response if (_transactions.TryGetValue(response.Identifier, out Transaction transaction)) { transaction.Stopwatch.Stop(); response.SetMetadata(new DnsDatagramMetadata(_server, _protocol, response.Size, transaction.Stopwatch.Elapsed.TotalMilliseconds)); transaction.ResponseTask.TrySetResult(response); } } } catch (Exception ex) { await _sendRequestSemaphore.WaitAsync(); try { if (_tcpStream != null) { _tcpStream.Dispose(); _tcpStream = null; } foreach (Transaction transaction in _transactions.Values) { transaction.Stopwatch.Stop(); transaction.ResponseTask.SetException(ex); } _transactions.Clear(); } finally { _sendRequestSemaphore.Release(); } } }
public static async Task <SecondaryZone> CreateAsync(DnsServer dnsServer, string name, string primaryNameServerAddresses = null, DnsTransportProtocol zoneTransferProtocol = DnsTransportProtocol.Tcp, string tsigKeyName = null) { switch (zoneTransferProtocol) { case DnsTransportProtocol.Tcp: case DnsTransportProtocol.Tls: break; default: throw new NotSupportedException("Zone transfer protocol is not supported: XFR-over-" + zoneTransferProtocol.ToString().ToUpper()); } SecondaryZone secondaryZone = new SecondaryZone(dnsServer, name); DnsQuestionRecord soaQuestion = new DnsQuestionRecord(name, DnsResourceRecordType.SOA, DnsClass.IN); DnsDatagram soaResponse; if (primaryNameServerAddresses == null) { soaResponse = await secondaryZone._dnsServer.DirectQueryAsync(soaQuestion); } else { DnsClient dnsClient = new DnsClient(primaryNameServerAddresses); foreach (NameServerAddress nameServerAddress in dnsClient.Servers) { if (nameServerAddress.IsIPEndPointStale) { await nameServerAddress.ResolveIPAddressAsync(secondaryZone._dnsServer, secondaryZone._dnsServer.PreferIPv6); } } dnsClient.Proxy = secondaryZone._dnsServer.Proxy; dnsClient.PreferIPv6 = secondaryZone._dnsServer.PreferIPv6; DnsDatagram soaRequest = new DnsDatagram(0, false, DnsOpcode.StandardQuery, false, false, false, false, false, false, DnsResponseCode.NoError, new DnsQuestionRecord[] { soaQuestion }, null, null, null, DnsDatagram.EDNS_DEFAULT_UDP_PAYLOAD_SIZE); if (string.IsNullOrEmpty(tsigKeyName)) { soaResponse = await dnsClient.ResolveAsync(soaRequest); } else if ((dnsServer.TsigKeys is not null) && dnsServer.TsigKeys.TryGetValue(tsigKeyName, out TsigKey key)) { soaResponse = await dnsClient.ResolveAsync(soaRequest, key, REFRESH_TSIG_FUDGE); }
public static async Task <StubZone> CreateAsync(DnsServer dnsServer, string name, string primaryNameServerAddresses = null) { StubZone stubZone = new StubZone(name); stubZone._dnsServer = dnsServer; DnsQuestionRecord soaQuestion = new DnsQuestionRecord(name, DnsResourceRecordType.SOA, DnsClass.IN); DnsDatagram soaResponse = null; if (primaryNameServerAddresses == null) { soaResponse = await stubZone._dnsServer.DirectQueryAsync(soaQuestion); } else { DnsClient dnsClient = new DnsClient(primaryNameServerAddresses); dnsClient.Proxy = stubZone._dnsServer.Proxy; dnsClient.PreferIPv6 = stubZone._dnsServer.PreferIPv6; soaResponse = await dnsClient.ResolveAsync(soaQuestion); } if ((soaResponse == null) || (soaResponse.Answer.Count == 0) || (soaResponse.Answer[0].Type != DnsResourceRecordType.SOA)) { throw new DnsServerException("DNS Server failed to find SOA record for: " + name); } DnsSOARecord receivedSoa = soaResponse.Answer[0].RDATA as DnsSOARecord; DnsSOARecord soa = new DnsSOARecord(receivedSoa.PrimaryNameServer, receivedSoa.ResponsiblePerson, receivedSoa.Serial - 1, receivedSoa.Refresh, receivedSoa.Retry, receivedSoa.Expire, receivedSoa.Minimum); DnsResourceRecord[] soaRR = new DnsResourceRecord[] { new DnsResourceRecord(stubZone._name, DnsResourceRecordType.SOA, DnsClass.IN, soa.Refresh, soa) }; if (!string.IsNullOrEmpty(primaryNameServerAddresses)) { soaRR[0].SetGlueRecords(primaryNameServerAddresses); } stubZone._entries[DnsResourceRecordType.SOA] = soaRR; stubZone._isExpired = true; //new stub zone is considered expired till it refreshes stubZone._refreshTimer = new Timer(stubZone.RefreshTimerCallback, null, Timeout.Infinite, Timeout.Infinite); return(stubZone); }
private DnsDatagram GetReferralResponse(DnsDatagram request, AuthZone delegationZone, bool isRecursionAllowed) { IReadOnlyList <DnsResourceRecord> authority; if (delegationZone is StubZone) { authority = delegationZone.GetRecords(DnsResourceRecordType.NS); //stub zone has no authority so cant query } else { authority = delegationZone.QueryRecords(DnsResourceRecordType.NS); } IReadOnlyList <DnsResourceRecord> additional = GetAdditionalRecords(authority); return(new DnsDatagram(request.Identifier, true, DnsOpcode.StandardQuery, false, false, request.RecursionDesired, isRecursionAllowed, false, false, DnsResponseCode.NoError, request.Question, null, authority, additional)); }
public DnsDatagram Query(DnsDatagram request) { List <Uri> blockLists = IsZoneBlocked(request.Question[0].Name.ToLower()); if (blockLists == null) { //zone not blocked return(null); } //zone is blocked DnsResourceRecord[] answers = null; DnsResourceRecord[] authority = null; switch (request.Question[0].Type) { case DnsResourceRecordType.A: answers = new DnsResourceRecord[] { new DnsResourceRecord(request.Question[0].Name, DnsResourceRecordType.A, request.Question[0].Class, 60, _aRecord) }; break; case DnsResourceRecordType.AAAA: answers = new DnsResourceRecord[] { new DnsResourceRecord(request.Question[0].Name, DnsResourceRecordType.AAAA, request.Question[0].Class, 60, _aaaaRecord) }; break; case DnsResourceRecordType.NS: answers = new DnsResourceRecord[] { new DnsResourceRecord(request.Question[0].Name, DnsResourceRecordType.NS, request.Question[0].Class, 60, _nsRecord) }; break; case DnsResourceRecordType.TXT: answers = new DnsResourceRecord[blockLists.Count]; for (int i = 0; i < answers.Length; i++) { answers[i] = new DnsResourceRecord(request.Question[0].Name, DnsResourceRecordType.TXT, request.Question[0].Class, 60, new DnsTXTRecord("blockList=" + blockLists[i].AbsoluteUri + "; domain=" + request.Question[0].Name)); } break; default: authority = new DnsResourceRecord[] { new DnsResourceRecord(request.Question[0].Name, DnsResourceRecordType.SOA, request.Question[0].Class, 60, _soaRecord) }; break; } return(new DnsDatagram(request.Identifier, true, DnsOpcode.StandardQuery, true, false, request.RecursionDesired, true, false, false, DnsResponseCode.NoError, request.Question, answers, authority)); }
public SecondaryZone(DnsServer dnsServer, string name, string primaryNameServerAddresses = null) : base(name) { _dnsServer = dnsServer; DnsQuestionRecord soaQuestion = new DnsQuestionRecord(name, DnsResourceRecordType.SOA, DnsClass.IN); DnsDatagram soaResponse = null; if (primaryNameServerAddresses == null) { soaResponse = _dnsServer.DirectQuery(soaQuestion); } else { DnsClient dnsClient = new DnsClient(primaryNameServerAddresses); dnsClient.Proxy = _dnsServer.Proxy; dnsClient.PreferIPv6 = _dnsServer.PreferIPv6; dnsClient.Retries = _dnsServer.Retries; dnsClient.Timeout = _dnsServer.Timeout; soaResponse = dnsClient.Resolve(soaQuestion); } if ((soaResponse == null) || (soaResponse.Answer.Count == 0) || (soaResponse.Answer[0].Type != DnsResourceRecordType.SOA)) { throw new DnsServerException("DNS Server failed to find SOA record for: " + name); } DnsSOARecord receivedSoa = soaResponse.Answer[0].RDATA as DnsSOARecord; DnsSOARecord soa = new DnsSOARecord(receivedSoa.PrimaryNameServer, receivedSoa.ResponsiblePerson, receivedSoa.Serial - 1, receivedSoa.Refresh, receivedSoa.Retry, receivedSoa.Expire, receivedSoa.Minimum); DnsResourceRecord[] soaRR = new DnsResourceRecord[] { new DnsResourceRecord(_name, DnsResourceRecordType.SOA, DnsClass.IN, soa.Refresh, soa) }; if (!string.IsNullOrEmpty(primaryNameServerAddresses)) { soaRR[0].SetGlueRecords(primaryNameServerAddresses); } _entries[DnsResourceRecordType.SOA] = soaRR; _isExpired = true; //new secondary zone is considered expired till it refreshes _refreshTimer = new Timer(RefreshTimerCallback, null, Timeout.Infinite, Timeout.Infinite); }
public DnsDatagram QueryClosestDelegation(DnsDatagram request) { _ = _root.FindZone(request.Question[0].Name, out CacheZone delegation, out _, out _); if (delegation is not null) { //return closest name servers in delegation IReadOnlyList <DnsResourceRecord> closestAuthority = delegation.QueryRecords(DnsResourceRecordType.NS, false, true); if ((closestAuthority.Count > 0) && (closestAuthority[0].Type == DnsResourceRecordType.NS) && (closestAuthority[0].Name.Length > 0)) //dont trust root name servers from cache! { IReadOnlyList <DnsResourceRecord> additional = GetAdditionalRecords(closestAuthority, false); return(new DnsDatagram(request.Identifier, true, DnsOpcode.StandardQuery, false, false, request.RecursionDesired, true, false, false, DnsResponseCode.NoError, request.Question, null, closestAuthority, additional)); } } //no cached delegation found return(null); }
public Task <DnsDatagram> ProcessRequestAsync(DnsDatagram request, IPEndPoint remoteEP, string zoneName, uint appRecordTtl, string appRecordData, bool isRecursionAllowed, IDnsServer dnsServer) { dynamic jsonAppRecordData = JsonConvert.DeserializeObject(appRecordData); dynamic jsonCountry; if (_mmCountryReader.TryCountry(remoteEP.Address, out CountryResponse response)) { jsonCountry = jsonAppRecordData[response.Country.IsoCode]; if (jsonCountry == null) { jsonCountry = jsonAppRecordData["default"]; } } else { jsonCountry = jsonAppRecordData["default"]; } if (jsonCountry == null) { return(Task.FromResult <DnsDatagram>(null)); } string cname = jsonCountry.Value; if (string.IsNullOrEmpty(cname)) { return(Task.FromResult <DnsDatagram>(null)); } IReadOnlyList <DnsResourceRecord> answers; if (request.Question[0].Name.Equals(zoneName, StringComparison.OrdinalIgnoreCase)) //check for zone apex { answers = new DnsResourceRecord[] { new DnsResourceRecord(request.Question[0].Name, DnsResourceRecordType.ANAME, DnsClass.IN, appRecordTtl, new DnsANAMERecord(cname)) } } ; //use ANAME else { answers = new DnsResourceRecord[] { new DnsResourceRecord(request.Question[0].Name, DnsResourceRecordType.CNAME, DnsClass.IN, appRecordTtl, new DnsCNAMERecord(cname)) } }; return(Task.FromResult(new DnsDatagram(request.Identifier, true, request.OPCODE, true, false, request.RecursionDesired, isRecursionAllowed, false, false, DnsResponseCode.NoError, request.Question, answers))); }
protected override void ParseOptionValue(Stream s) { if (s.Length < 3) { throw new InvalidDataException(); } int flags = s.ReadByte(); if (flags < 0) { throw new EndOfStreamException(); } _flags = (ClientFullyQualifiedDomainNameFlags)flags; int rcode; rcode = s.ReadByte(); if (rcode < 0) { throw new EndOfStreamException(); } _rcode1 = (byte)rcode; rcode = s.ReadByte(); if (rcode < 0) { throw new EndOfStreamException(); } _rcode2 = (byte)rcode; if (_flags.HasFlag(ClientFullyQualifiedDomainNameFlags.EncodeUsingCanonicalWireFormat)) { _domainName = DnsDatagram.DeserializeDomainName(s); } else { _domainName = Encoding.ASCII.GetString(s.ReadBytes((int)s.Length - 3)); } }
private DnsDatagram DnsApplicationQueryClosestDelegation(DnsDatagram request) { if ((_dnsApplicationManager.DnsAuthoritativeRequestHandlers.Count < 1) || (request.Question.Count != 1)) { return(null); } IPEndPoint localEP = new IPEndPoint(IPAddress.Any, 0); DnsQuestionRecord question = request.Question[0]; string currentDomain = question.Name; while (true) { DnsDatagram nsRequest = new DnsDatagram(0, false, DnsOpcode.StandardQuery, false, false, true, false, false, false, DnsResponseCode.NoError, new DnsQuestionRecord[] { new DnsQuestionRecord(currentDomain, DnsResourceRecordType.NS, DnsClass.IN) }); foreach (IDnsAuthoritativeRequestHandler requestHandler in _dnsApplicationManager.DnsAuthoritativeRequestHandlers) { DnsDatagram nsResponse = requestHandler.ProcessRequestAsync(nsRequest, localEP, DnsTransportProtocol.Tcp, false).Sync(); if (nsResponse is not null) { if ((nsResponse.Answer.Count > 0) && (nsResponse.Answer[0].Type == DnsResourceRecordType.NS)) { return(new DnsDatagram(request.Identifier, true, nsResponse.OPCODE, nsResponse.AuthoritativeAnswer, nsResponse.Truncation, nsResponse.RecursionDesired, nsResponse.RecursionAvailable, nsResponse.AuthenticData, nsResponse.CheckingDisabled, nsResponse.RCODE, request.Question, null, nsResponse.Answer, nsResponse.Additional)); } else if ((nsResponse.Authority.Count > 0) && (nsResponse.Authority[0].Type == DnsResourceRecordType.NS)) { return(new DnsDatagram(request.Identifier, true, nsResponse.OPCODE, nsResponse.AuthoritativeAnswer, nsResponse.Truncation, nsResponse.RecursionDesired, nsResponse.RecursionAvailable, nsResponse.AuthenticData, nsResponse.CheckingDisabled, nsResponse.RCODE, request.Question, null, nsResponse.Authority, nsResponse.Additional)); } } } //get parent domain int i = currentDomain.IndexOf('.'); if (i < 0) { break; } currentDomain = currentDomain.Substring(i + 1); } return(null); }
public Task <DnsRequestControllerAction> GetRequestActionAsync(DnsDatagram request, IPEndPoint remoteEP, DnsTransportProtocol protocol) { if (!_enableBlocking) { return(Task.FromResult(DnsRequestControllerAction.Allow)); } IPAddress remoteIp = remoteEP.Address; foreach (NetworkAddress allowedNetwork in _allowedNetworks) { if (allowedNetwork.Contains(remoteIp)) { return(Task.FromResult(DnsRequestControllerAction.Allow)); } } foreach (NetworkAddress blockedNetwork in _blockedNetworks) { if (blockedNetwork.Contains(remoteIp)) { return(Task.FromResult(DnsRequestControllerAction.DropSilently)); } } if (request.Question.Count != 1) { return(Task.FromResult(DnsRequestControllerAction.DropSilently)); } DnsQuestionRecord requestQuestion = request.Question[0]; foreach (BlockedQuestion blockedQuestion in _blockedQuestions) { if (blockedQuestion.Matches(requestQuestion)) { return(Task.FromResult(DnsRequestControllerAction.DropSilently)); } } return(Task.FromResult(DnsRequestControllerAction.Allow)); }
public void Update(DnsDatagram response, IPAddress clientIpAddress) { StatsResponseType responseType; if (response.Tag == "blocked") { responseType = StatsResponseType.Blocked; } else { switch (response.Header.RCODE) { case DnsResponseCode.NoError: responseType = StatsResponseType.NoError; break; case DnsResponseCode.ServerFailure: responseType = StatsResponseType.ServerFailure; break; case DnsResponseCode.NameError: responseType = StatsResponseType.NameError; break; case DnsResponseCode.Refused: responseType = StatsResponseType.Refused; break; default: return; } } if (response.Header.QDCOUNT > 0) { Update(response.Question[0].Name, response.Question[0].Type, responseType, clientIpAddress); } else { Update("", DnsResourceRecordType.ANY, responseType, clientIpAddress); } }
private async Task ReadDnsDatagramAsync() { try { while (true) { //read response datagram DnsDatagram response = await DnsDatagram.ReadFromTcpAsync(_tcpStream, _recvBuffer).WithTimeout(ASYNC_RECEIVE_TIMEOUT); //signal response if (_transactions.TryGetValue(response.Identifier, out Transaction transaction)) { transaction.SetResponse(response, _server, _protocol); } } } catch (Exception ex) { await _sendRequestSemaphore.WaitAsync(); try { if (_tcpStream != null) { _tcpStream.Dispose(); _tcpStream = null; } foreach (KeyValuePair <ushort, Transaction> transaction in _transactions) { transaction.Value.SetException(ex); } _transactions.Clear(); } finally { _sendRequestSemaphore.Release(); } } }
public Task <DnsDatagram> ProcessRequestAsync(DnsDatagram request, IPEndPoint remoteEP, string zoneName, uint appRecordTtl, string appRecordData, bool isRecursionAllowed, IDnsServer dnsServer) { DnsResourceRecord answer; switch (request.Question[0].Type) { case DnsResourceRecordType.A: if (remoteEP.AddressFamily == AddressFamily.InterNetwork) { answer = new DnsResourceRecord(request.Question[0].Name, DnsResourceRecordType.A, DnsClass.IN, appRecordTtl, new DnsARecord(remoteEP.Address)); } else { return(Task.FromResult <DnsDatagram>(null)); } break; case DnsResourceRecordType.AAAA: if (remoteEP.AddressFamily == AddressFamily.InterNetworkV6) { answer = new DnsResourceRecord(request.Question[0].Name, DnsResourceRecordType.AAAA, DnsClass.IN, appRecordTtl, new DnsAAAARecord(remoteEP.Address)); } else { return(Task.FromResult <DnsDatagram>(null)); } break; case DnsResourceRecordType.TXT: answer = new DnsResourceRecord(request.Question[0].Name, DnsResourceRecordType.TXT, DnsClass.IN, appRecordTtl, new DnsTXTRecord(remoteEP.Address.ToString())); break; default: return(Task.FromResult <DnsDatagram>(null)); } return(Task.FromResult(new DnsDatagram(request.Identifier, true, request.OPCODE, true, false, request.RecursionDesired, isRecursionAllowed, false, false, DnsResponseCode.NoError, request.Question, new DnsResourceRecord[] { answer }))); }
private void PacketHandler(Packet packet) { IpV4Datagram ip = packet.Ethernet.IpV4; DnsDatagram dns = ip.Udp.Dns; IEnumerable <DnsResourceRecord> queries = packet.Ethernet.IpV4.Udp.Dns.ResourceRecords; if (queries != null || queries.ToList().Count > 0) { if (dns.IsQuery) { Query query = new Query(dns.Id, ip.Source, ip.Destination, ip.Protocol, queries); repo.Events.Add(query); MessageHelper.PrintMessage(query.PrintOutQueryInfo()); } else if (dns.IsResponse) { Response res = new Response(dns.Id, dns.ResponseCode, dns.DataResourceRecords, ip.Source, ip.Destination, ip.Protocol, queries); repo.Events.Add(res); MessageHelper.PrintMessage(res.PrintOutQueryInfo()); } } }
public virtual DnsDatagram Query(DnsDatagram request, bool serveStale = false) { DnsDatagram authResponse = _authZoneManager.Query(request, true); if ((authResponse != null)) { if ((authResponse.Answer.Count > 0) || ((authResponse.Authority.Count > 0) && (authResponse.Authority[0].Type == DnsResourceRecordType.SOA))) { return(authResponse); } } DnsDatagram cacheResponse = _cacheZoneManager.Query(request, serveStale); if (cacheResponse != null) { if ((cacheResponse.Answer.Count > 0) || ((cacheResponse.Authority.Count > 0) && (cacheResponse.Authority[0].Type == DnsResourceRecordType.SOA))) { return(cacheResponse); } } if ((authResponse != null) && (authResponse.Authority.Count > 0)) { if ((cacheResponse != null) && (cacheResponse.Authority.Count > 0)) { if (cacheResponse.Authority[0].Name.Length > authResponse.Authority[0].Name.Length) { return(cacheResponse); } } return(authResponse); } else { return(cacheResponse); } }
private static async Task ResolveNameServerAddressesAsync(DnsServer dnsServer, string nsDomain, int port, DnsTransportProtocol protocol, List <NameServerAddress> outNameServers) { try { DnsDatagram response = await dnsServer.DirectQueryAsync(new DnsQuestionRecord(nsDomain, DnsResourceRecordType.A, DnsClass.IN)); if (response.Answer.Count > 0) { IReadOnlyList <IPAddress> addresses = DnsClient.ParseResponseA(response); foreach (IPAddress address in addresses) { outNameServers.Add(new NameServerAddress(nsDomain, new IPEndPoint(address, port), protocol)); } } } catch { } if (dnsServer.PreferIPv6) { try { DnsDatagram response = await dnsServer.DirectQueryAsync(new DnsQuestionRecord(nsDomain, DnsResourceRecordType.AAAA, DnsClass.IN)); if (response.Answer.Count > 0) { IReadOnlyList <IPAddress> addresses = DnsClient.ParseResponseAAAA(response); foreach (IPAddress address in addresses) { outNameServers.Add(new NameServerAddress(nsDomain, new IPEndPoint(address, port), protocol)); } } } catch { } } }
public DnsHINFORecord(dynamic jsonResourceRecord) { _rdLength = Convert.ToUInt16(jsonResourceRecord.data.Value.Length); string value = DnsDatagram.DecodeCharacterString(jsonResourceRecord.data.Value); string[] parts; if (value.Contains("\" \"")) { parts = value.Split(new string[] { "\" \"" }, StringSplitOptions.None); } else { parts = value.Split(new char[] { ' ' }, StringSplitOptions.None); } _cpu = parts[0]; if (parts.Length > 1) { _os = parts[1]; } }
public override async Task <DnsDatagram> QueryAsync(DnsDatagram request, int timeout, int retries, CancellationToken cancellationToken) { _lastQueried = DateTime.UtcNow; async Task <HttpRequestMessage> GetHttpRequest() { //serialize request byte[] requestBuffer; using (MemoryStream mS = new MemoryStream(32)) { request.WriteTo(mS); requestBuffer = mS.ToArray(); } Uri queryUri; if (_proxy == null) { if (_server.IsIPEndPointStale) { await _server.RecursiveResolveIPAddressAsync(); } queryUri = new Uri(_server.DnsOverHttpEndPoint.Scheme + "://" + _server.IPEndPoint.ToString() + _server.DnsOverHttpEndPoint.PathAndQuery); } else { if (_server.IPEndPoint == null) { queryUri = _server.DnsOverHttpEndPoint; } else { queryUri = new Uri(_server.DnsOverHttpEndPoint.Scheme + "://" + _server.IPEndPoint.ToString() + _server.DnsOverHttpEndPoint.PathAndQuery); } } HttpRequestMessage httpRequest = new HttpRequestMessage(HttpMethod.Post, queryUri); httpRequest.Content = new ByteArrayContent(requestBuffer); httpRequest.Content.Headers.ContentType = new MediaTypeHeaderValue("application/dns-message"); return(httpRequest); } //DoH wire format request Stopwatch stopwatch = new Stopwatch(); int retry = 0; while (retry < retries) //retry loop { retry++; if (cancellationToken.IsCancellationRequested) { return(await Task.FromCanceled <DnsDatagram>(cancellationToken)); //task cancelled } stopwatch.Start(); Task <HttpResponseMessage> task = _httpClient.SendAsync(await GetHttpRequest(), cancellationToken); using (CancellationTokenSource timeoutCancellationTokenSource = new CancellationTokenSource()) { using (CancellationTokenRegistration ctr = cancellationToken.Register(delegate() { timeoutCancellationTokenSource.Cancel(); })) { if (await Task.WhenAny(task, Task.Delay(timeout, timeoutCancellationTokenSource.Token)) != task) { continue; //request timed out; retry } } timeoutCancellationTokenSource.Cancel(); //to stop delay task } HttpResponseMessage httpResponse = await task; stopwatch.Stop(); httpResponse.EnsureSuccessStatusCode(); byte[] responseBuffer = await httpResponse.Content.ReadAsByteArrayAsync(cancellationToken); //parse response using (MemoryStream mS = new MemoryStream(responseBuffer, false)) { DnsDatagram response = DnsDatagram.ReadFrom(mS); response.SetMetadata(_server, _protocol, stopwatch.Elapsed.TotalMilliseconds); if (response.Identifier != request.Identifier) { throw new DnsClientResponseValidationException("Invalid response was received: query ID mismatch."); } if (response.Question.Count != request.Question.Count) { throw new DnsClientResponseValidationException("Invalid response was received: question count mismatch."); } for (int i = 0; i < response.Question.Count; i++) { if (request.Question[i].ZoneCut == null) { if (!response.Question[i].Name.Equals(request.Question[i].Name, StringComparison.Ordinal)) { throw new DnsClientResponseValidationException("Invalid response was received: QNAME mismatch."); } if (response.Question[i].Type != request.Question[i].Type) { throw new DnsClientResponseValidationException("Invalid response was received: QTYPE mismatch."); } } else { if (!response.Question[i].Name.Equals(request.Question[i].MinimizedName, StringComparison.Ordinal)) { throw new DnsClientResponseValidationException("Invalid response was received: QNAME mismatch."); } if (response.Question[i].Type != request.Question[i].MinimizedType) { throw new DnsClientResponseValidationException("Invalid response was received: QTYPE mismatch."); } } if (response.Question[i].Class != request.Question[i].Class) { throw new DnsClientResponseValidationException("Invalid response was received: QCLASS mismatch."); } } return(response); } } throw new DnsClientException("DnsClient failed to resolve the request: request timed out."); }
private static async Task <IReadOnlyList <NameServerAddress> > GetNameServerAddressesAsync(DnsServer dnsServer, DnsResourceRecord record) { string nsDomain; switch (record.Type) { case DnsResourceRecordType.NS: nsDomain = (record.RDATA as DnsNSRecord).NameServer; break; case DnsResourceRecordType.SOA: nsDomain = (record.RDATA as DnsSOARecord).PrimaryNameServer; break; default: throw new InvalidOperationException(); } List <NameServerAddress> nameServers = new List <NameServerAddress>(2); IReadOnlyList <DnsResourceRecord> glueRecords = record.GetGlueRecords(); if (glueRecords.Count > 0) { foreach (DnsResourceRecord glueRecord in glueRecords) { switch (glueRecord.Type) { case DnsResourceRecordType.A: nameServers.Add(new NameServerAddress(nsDomain, (glueRecord.RDATA as DnsARecord).Address)); break; case DnsResourceRecordType.AAAA: if (dnsServer.PreferIPv6) { nameServers.Add(new NameServerAddress(nsDomain, (glueRecord.RDATA as DnsAAAARecord).Address)); } break; } } } else { //resolve addresses try { DnsDatagram response = await dnsServer.DirectQueryAsync(new DnsQuestionRecord(nsDomain, DnsResourceRecordType.A, DnsClass.IN)); if ((response != null) && (response.Answer.Count > 0)) { IReadOnlyList <IPAddress> addresses = DnsClient.ParseResponseA(response); foreach (IPAddress address in addresses) { nameServers.Add(new NameServerAddress(nsDomain, address)); } } } catch { } if (dnsServer.PreferIPv6) { try { DnsDatagram response = await dnsServer.DirectQueryAsync(new DnsQuestionRecord(nsDomain, DnsResourceRecordType.AAAA, DnsClass.IN)); if ((response != null) && (response.Answer.Count > 0)) { IReadOnlyList <IPAddress> addresses = DnsClient.ParseResponseAAAA(response); foreach (IPAddress address in addresses) { nameServers.Add(new NameServerAddress(nsDomain, address)); } } } catch { } } } return(nameServers); }
protected override void WriteRecordData(Stream s, List <DnsDomainOffset> domainEntries) { DnsDatagram.WriteUInt16NetworkOrder(_preference, s); DnsDatagram.SerializeDomainName(_exchange, s, domainEntries); }
protected override void Parse(Stream s) { _preference = DnsDatagram.ReadUInt16NetworkOrder(s); _exchange = DnsDatagram.DeserializeDomainName(s); }
internal abstract DnsResourceData CreateInstance(DnsDatagram dns, int offsetInDns, int length);
private async Task <bool> RefreshZoneAsync(IReadOnlyList <NameServerAddress> primaryNameServers) { try { { LogManager log = _dnsServer.LogManager; if (log != null) { log.Write("DNS Server has started zone refresh for stub zone: " + _name); } } DnsClient client = new DnsClient(primaryNameServers); client.Timeout = REFRESH_TIMEOUT; client.Retries = REFRESH_RETRIES; DnsDatagram soaRequest = new DnsDatagram(0, false, DnsOpcode.StandardQuery, false, false, false, false, false, false, DnsResponseCode.NoError, new DnsQuestionRecord[] { new DnsQuestionRecord(_name, DnsResourceRecordType.SOA, DnsClass.IN) }); DnsDatagram soaResponse = await client.ResolveAsync(soaRequest); if (soaResponse.RCODE != DnsResponseCode.NoError) { LogManager log = _dnsServer.LogManager; if (log != null) { log.Write("DNS Server received RCODE=" + soaResponse.RCODE.ToString() + " for '" + _name + "' stub zone refresh from: " + soaResponse.Metadata.NameServerAddress.ToString()); } return(false); } if (soaResponse.Answer.Count < 1) { LogManager log = _dnsServer.LogManager; if (log != null) { log.Write("DNS Server received an empty response for SOA query for '" + _name + "' stub zone refresh from: " + soaResponse.Metadata.NameServerAddress.ToString()); } return(false); } DnsSOARecord currentSoaRecord = _entries[DnsResourceRecordType.SOA][0].RDATA as DnsSOARecord; DnsSOARecord receivedSoaRecord = soaResponse.Answer[0].RDATA as DnsSOARecord; //compare using sequence space arithmetic if (!currentSoaRecord.IsZoneUpdateAvailable(receivedSoaRecord)) { LogManager log = _dnsServer.LogManager; if (log != null) { log.Write("DNS Server successfully checked for update to '" + _name + "' stub zone from: " + soaResponse.Metadata.NameServerAddress.ToString()); } return(true); } //update available; do zone sync with TCP transport List <NameServerAddress> tcpNameServers = new List <NameServerAddress>(); foreach (NameServerAddress nameServer in primaryNameServers) { tcpNameServers.Add(new NameServerAddress(nameServer, DnsTransportProtocol.Tcp)); } primaryNameServers = tcpNameServers; client = new DnsClient(primaryNameServers); client.Timeout = REFRESH_TIMEOUT; client.Retries = REFRESH_RETRIES; DnsDatagram nsRequest = new DnsDatagram(0, false, DnsOpcode.StandardQuery, false, false, false, false, false, false, DnsResponseCode.NoError, new DnsQuestionRecord[] { new DnsQuestionRecord(_name, DnsResourceRecordType.NS, DnsClass.IN) }); DnsDatagram nsResponse = await client.ResolveAsync(nsRequest); if (nsResponse.RCODE != DnsResponseCode.NoError) { LogManager log = _dnsServer.LogManager; if (log != null) { log.Write("DNS Server received RCODE=" + nsResponse.RCODE.ToString() + " for '" + _name + "' stub zone refresh from: " + nsResponse.Metadata.NameServerAddress.ToString()); } return(false); } if (nsResponse.Answer.Count < 1) { LogManager log = _dnsServer.LogManager; if (log != null) { log.Write("DNS Server received an empty response for NS query for '" + _name + "' stub zone from: " + nsResponse.Metadata.NameServerAddress.ToString()); } return(false); } List <DnsResourceRecord> allRecords = new List <DnsResourceRecord>(); allRecords.AddRange(nsResponse.Answer); allRecords.AddRange(soaResponse.Answer); //to sync latest SOA record _dnsServer.AuthZoneManager.SyncRecords(_name, allRecords, nsResponse.Additional, true); { LogManager log = _dnsServer.LogManager; if (log != null) { log.Write("DNS Server successfully refreshed '" + _name + "' stub zone from: " + nsResponse.Metadata.NameServerAddress.ToString()); } } return(true); } catch (Exception ex) { LogManager log = _dnsServer.LogManager; if (log != null) { string strNameServers = null; foreach (NameServerAddress nameServer in primaryNameServers) { if (strNameServers == null) { strNameServers = nameServer.ToString(); } else { strNameServers += ", " + nameServer.ToString(); } } log.Write("DNS Server failed to refresh '" + _name + "' stub zone from: " + strNameServers); log.Write(ex); } return(false); } }
protected override void WriteRecordData(Stream s, List <DnsDomainOffset> domainEntries) { DnsDatagram.SerializeDomainName(_nameServer, s, domainEntries); }
public Task <DnsDatagram> ProcessRequestAsync(DnsDatagram request, IPEndPoint remoteEP, DnsTransportProtocol protocol, bool isRecursionAllowed, string zoneName, uint appRecordTtl, string appRecordData) { DnsQuestionRecord question = request.Question[0]; switch (question.Type) { case DnsResourceRecordType.A: case DnsResourceRecordType.AAAA: dynamic jsonAppRecordData = JsonConvert.DeserializeObject(appRecordData); dynamic jsonCountry; if (_maxMind.DatabaseReader.TryCountry(remoteEP.Address, out CountryResponse response)) { jsonCountry = jsonAppRecordData[response.Country.IsoCode]; if (jsonCountry == null) { jsonCountry = jsonAppRecordData["default"]; } } else { jsonCountry = jsonAppRecordData["default"]; } if (jsonCountry == null) { return(Task.FromResult <DnsDatagram>(null)); } List <DnsResourceRecord> answers = new List <DnsResourceRecord>(); switch (question.Type) { case DnsResourceRecordType.A: foreach (dynamic jsonAddress in jsonCountry) { IPAddress address = IPAddress.Parse(jsonAddress.Value); if (address.AddressFamily == AddressFamily.InterNetwork) { answers.Add(new DnsResourceRecord(question.Name, DnsResourceRecordType.A, DnsClass.IN, appRecordTtl, new DnsARecordData(address))); } } break; case DnsResourceRecordType.AAAA: foreach (dynamic jsonAddress in jsonCountry) { IPAddress address = IPAddress.Parse(jsonAddress.Value); if (address.AddressFamily == AddressFamily.InterNetworkV6) { answers.Add(new DnsResourceRecord(question.Name, DnsResourceRecordType.AAAA, DnsClass.IN, appRecordTtl, new DnsAAAARecordData(address))); } } break; } if (answers.Count == 0) { return(Task.FromResult <DnsDatagram>(null)); } if (answers.Count > 1) { answers.Shuffle(); } return(Task.FromResult(new DnsDatagram(request.Identifier, true, request.OPCODE, true, false, request.RecursionDesired, isRecursionAllowed, false, false, DnsResponseCode.NoError, request.Question, answers))); default: return(Task.FromResult <DnsDatagram>(null)); } }
public void CacheResponse(DnsDatagram response) { _cacheZoneManager.CacheResponse(response); }
internal sealed override DnsResourceData CreateInstance(DnsDatagram dns, int offsetInDns, int length) { return CreateInstance(dns.Subsegment(offsetInDns, length)); }
protected override void Parse(Stream s) { _nameServer = DnsDatagram.DeserializeDomainName(s); }
internal static bool TryParseBase(DnsDatagram dns, int offsetInDns, out DnsDomainName domainName, out DnsType type, out DnsClass dnsClass, out int numBytesRead) { type = DnsType.Any; dnsClass = DnsClass.Any; if (!DnsDomainName.TryParse(dns, offsetInDns, dns.Length - offsetInDns, out domainName, out numBytesRead)) return false; if (offsetInDns + numBytesRead + MinimumLengthAfterDomainName > dns.Length) return false; type = (DnsType)dns.ReadUShort(offsetInDns + numBytesRead + OffsetAfterDomainName.Type, Endianity.Big); dnsClass = (DnsClass)dns.ReadUShort(offsetInDns + numBytesRead + OffsetAfterDomainName.DnsClass, Endianity.Big); numBytesRead += MinimumLengthAfterDomainName; return true; }