public void Write(IPEndPoint ep, DnsTransportProtocol protocol, DnsDatagram request, DnsDatagram response) { DnsQuestionRecord q = null; if (request.Header.QDCOUNT > 0) { q = request.Question[0]; } string question; if (q == null) { question = "MISSING QUESTION!"; } else { question = "QNAME: " + q.Name + "; QTYPE: " + q.Type.ToString() + "; QCLASS: " + q.Class; } string responseInfo; if (response == null) { responseInfo = " NO RESPONSE FROM SERVER!"; } else { string answer; if (response.Header.ANCOUNT == 0) { answer = "[]"; } else { answer = "["; for (int i = 0; i < response.Answer.Length; i++) { if (i != 0) { answer += ", "; } answer += response.Answer[i].RDATA.ToString(); } answer += "]"; } responseInfo = " RCODE: " + response.Header.RCODE.ToString() + "; ANSWER: " + answer; } Write(ep, protocol, question + ";" + responseInfo); }
private void GetAnswers(dynamic jsonAddresses, DnsQuestionRecord question, uint appRecordTtl, string healthCheck, Uri healthCheckUrl, List <DnsResourceRecord> answers) { if (jsonAddresses == null) { return; } switch (question.Type) { case DnsResourceRecordType.A: foreach (dynamic jsonAddress in jsonAddresses) { IPAddress address = IPAddress.Parse(jsonAddress.Value); if (address.AddressFamily == AddressFamily.InterNetwork) { HealthCheckResponse response = _healthService.QueryStatus(address, healthCheck, healthCheckUrl, true); switch (response.Status) { case HealthStatus.Unknown: answers.Add(new DnsResourceRecord(question.Name, DnsResourceRecordType.A, question.Class, 30, new DnsARecord(address))); break; case HealthStatus.Healthy: answers.Add(new DnsResourceRecord(question.Name, DnsResourceRecordType.A, question.Class, appRecordTtl, new DnsARecord(address))); break; } } } break; case DnsResourceRecordType.AAAA: foreach (dynamic jsonAddress in jsonAddresses) { IPAddress address = IPAddress.Parse(jsonAddress.Value); if (address.AddressFamily == AddressFamily.InterNetworkV6) { HealthCheckResponse response = _healthService.QueryStatus(address, healthCheck, healthCheckUrl, true); switch (response.Status) { case HealthStatus.Unknown: answers.Add(new DnsResourceRecord(question.Name, DnsResourceRecordType.AAAA, question.Class, 30, new DnsAAAARecord(address))); break; case HealthStatus.Healthy: answers.Add(new DnsResourceRecord(question.Name, DnsResourceRecordType.AAAA, question.Class, appRecordTtl, new DnsAAAARecord(address))); break; } } } break; } }
public static async Task <StubZone> CreateAsync(DnsServer dnsServer, string name, string primaryNameServerAddresses = null) { StubZone stubZone = new StubZone(dnsServer, name); DnsQuestionRecord soaQuestion = new DnsQuestionRecord(name, DnsResourceRecordType.SOA, DnsClass.IN); DnsDatagram soaResponse; if (primaryNameServerAddresses == null) { soaResponse = await stubZone._dnsServer.DirectQueryAsync(soaQuestion); } else { DnsClient dnsClient = new DnsClient(primaryNameServerAddresses); foreach (NameServerAddress nameServerAddress in dnsClient.Servers) { if (nameServerAddress.IsIPEndPointStale) { await nameServerAddress.ResolveIPAddressAsync(stubZone._dnsServer, stubZone._dnsServer.PreferIPv6); } } dnsClient.Proxy = stubZone._dnsServer.Proxy; dnsClient.PreferIPv6 = stubZone._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); soaResponse = await dnsClient.ResolveAsync(soaRequest); } if ((soaResponse.Answer.Count == 0) || (soaResponse.Answer[0].Type != DnsResourceRecordType.SOA)) { throw new DnsServerException("DNS Server failed to find SOA record for: " + name); } DnsSOARecordData receivedSoa = soaResponse.Answer[0].RDATA as DnsSOARecordData; DnsSOARecordData soa = new DnsSOARecordData(receivedSoa.PrimaryNameServer, receivedSoa.ResponsiblePerson, 0u, 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].SetPrimaryNameServers(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 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) { try { 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.FindFirstAuthorityType() == 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)); } } } catch (Exception ex) { if (_log is not null) { _log.Write(ex); } } } //get parent domain int i = currentDomain.IndexOf('.'); if (i < 0) { break; } currentDomain = currentDomain.Substring(i + 1); } return(null); }
public DnsDatagram Query(DnsDatagram request) { DnsQuestionRecord question = request.Question[0]; List <Uri> blockLists = IsZoneBlocked(question.Name); if (blockLists == null) { return(null); //zone not blocked } //zone is blocked if (_dnsServer.UseNxDomainForBlocking && (question.Type != DnsResourceRecordType.TXT)) { return(new DnsDatagram(request.Identifier, true, DnsOpcode.StandardQuery, false, false, request.RecursionDesired, true, false, false, DnsResponseCode.NxDomain, request.Question)); } DnsResourceRecord[] answers = null; DnsResourceRecord[] authority = null; switch (question.Type) { case DnsResourceRecordType.A: answers = new DnsResourceRecord[] { new DnsResourceRecord(question.Name, DnsResourceRecordType.A, question.Class, 60, _aRecord) }; break; case DnsResourceRecordType.AAAA: answers = new DnsResourceRecord[] { new DnsResourceRecord(question.Name, DnsResourceRecordType.AAAA, question.Class, 60, _aaaaRecord) }; break; case DnsResourceRecordType.NS: answers = new DnsResourceRecord[] { new DnsResourceRecord(question.Name, DnsResourceRecordType.NS, question.Class, 60, _nsRecord) }; break; case DnsResourceRecordType.TXT: answers = new DnsResourceRecord[blockLists.Count]; for (int i = 0; i < answers.Length; i++) { answers[i] = new DnsResourceRecord(question.Name, DnsResourceRecordType.TXT, question.Class, 60, new DnsTXTRecord("blockList=" + blockLists[i].AbsoluteUri + "; domain=" + question.Name)); } break; default: authority = new DnsResourceRecord[] { new DnsResourceRecord(question.Name, DnsResourceRecordType.SOA, question.Class, 60, _soaRecord) }; break; } return(new DnsDatagram(request.Identifier, true, DnsOpcode.StandardQuery, false, false, request.RecursionDesired, true, false, false, DnsResponseCode.NoError, request.Question, answers, authority)); }
public bool Matches(DnsQuestionRecord question) { if ((_name is not null) && !_name.Equals(question.Name, StringComparison.OrdinalIgnoreCase)) { return(false); } if ((_type != DnsResourceRecordType.Unknown) && (_type != question.Type)) { return(false); } return(true); }
private void GetAnswers(dynamic jsonAddresses, DnsQuestionRecord question, uint appRecordTtl, string healthCheck, List <DnsResourceRecord> answers) { if (jsonAddresses == null) { return; } switch (question.Type) { case DnsResourceRecordType.A: foreach (dynamic jsonAddress in jsonAddresses) { IPAddress address = IPAddress.Parse(jsonAddress.Value); if (address.AddressFamily == AddressFamily.InterNetwork) { HealthCheckStatus status = _healthMonitor.QueryStatus(address, healthCheck, true); if (status is null) { answers.Add(new DnsResourceRecord(question.Name, DnsResourceRecordType.A, question.Class, 30, new DnsARecord(address))); } else if (status.IsHealthy) { answers.Add(new DnsResourceRecord(question.Name, DnsResourceRecordType.A, question.Class, appRecordTtl, new DnsARecord(address))); } } } break; case DnsResourceRecordType.AAAA: foreach (dynamic jsonAddress in jsonAddresses) { IPAddress address = IPAddress.Parse(jsonAddress.Value); if (address.AddressFamily == AddressFamily.InterNetworkV6) { HealthCheckStatus status = _healthMonitor.QueryStatus(address, healthCheck, true); if (status is null) { answers.Add(new DnsResourceRecord(question.Name, DnsResourceRecordType.AAAA, question.Class, 30, new DnsAAAARecord(address))); } else if (status.IsHealthy) { answers.Add(new DnsResourceRecord(question.Name, DnsResourceRecordType.AAAA, question.Class, appRecordTtl, new DnsAAAARecord(address))); } } } break; } }
public Task <DnsRequestControllerAction> GetRequestActionAsync(DnsDatagram request, IPEndPoint remoteEP, DnsTransportProtocol protocol) { if (!_enableBlocking) { return(Task.FromResult(DnsRequestControllerAction.Allow)); } if (_dropMalformedRequests && (request.ParsingException is not null)) { return(Task.FromResult(DnsRequestControllerAction.DropSilently)); } 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)); }
private void LoadZoneFiles() { string[] zoneFiles = Directory.GetFiles(ConfigFolder, "*.zone"); if (zoneFiles.Length == 0) { { CreateZone("localhost"); _dnsServer.AuthoritativeZoneRoot.SetRecords("localhost", DnsResourceRecordType.A, 3600, new DnsResourceRecordData[] { new DnsARecord(IPAddress.Loopback) }); _dnsServer.AuthoritativeZoneRoot.SetRecords("localhost", DnsResourceRecordType.AAAA, 3600, new DnsResourceRecordData[] { new DnsAAAARecord(IPAddress.IPv6Loopback) }); SaveZoneFile("localhost"); } { string prtDomain = new DnsQuestionRecord(IPAddress.Loopback, DnsClass.IN).Name; CreateZone(prtDomain); _dnsServer.AuthoritativeZoneRoot.SetRecords(prtDomain, DnsResourceRecordType.PTR, 3600, new DnsResourceRecordData[] { new DnsPTRRecord("localhost") }); SaveZoneFile(prtDomain); } { string prtDomain = new DnsQuestionRecord(IPAddress.IPv6Loopback, DnsClass.IN).Name; CreateZone(prtDomain); _dnsServer.AuthoritativeZoneRoot.SetRecords(prtDomain, DnsResourceRecordType.PTR, 3600, new DnsResourceRecordData[] { new DnsPTRRecord("localhost") }); SaveZoneFile(prtDomain); } } else { foreach (string zoneFile in zoneFiles) { try { LoadZoneFile(zoneFile); } catch (Exception ex) { _log.Write("Failed to loaded zone file: " + zoneFile + "\r\n" + ex.ToString()); } } } }
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); }
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); }
private void GetStatusAnswers(string domain, bool primary, DnsQuestionRecord question, uint appRecordTtl, string healthCheck, List <DnsResourceRecord> answers) { { HealthCheckStatus status = _healthMonitor.QueryStatus(domain, DnsResourceRecordType.A, healthCheck, false); string text = "app=failover; cnameType=" + (primary ? "primary" : "secondary") + "; domain=" + domain + "; qType: A; healthCheck=" + healthCheck; if (status is null) { text += "; healthStatus=Unknown;"; } else if (status.IsHealthy) { text += "; healthStatus=Healthy;"; } else { text += "; healthStatus=Failed; failureReason=" + status.FailureReason + ";"; } answers.Add(new DnsResourceRecord(question.Name, DnsResourceRecordType.TXT, question.Class, appRecordTtl, new DnsTXTRecord(text))); } { HealthCheckStatus status = _healthMonitor.QueryStatus(domain, DnsResourceRecordType.AAAA, healthCheck, false); string text = "app=failover; cnameType=" + (primary ? "primary" : "secondary") + "; domain=" + domain + "; qType: AAAA; healthCheck=" + healthCheck; if (status is null) { text += "; healthStatus=Unknown;"; } else if (status.IsHealthy) { text += "; healthStatus=Healthy;"; } else { text += "; healthStatus=Failed; failureReason=" + status.FailureReason + ";"; } answers.Add(new DnsResourceRecord(question.Name, DnsResourceRecordType.TXT, question.Class, appRecordTtl, new DnsTXTRecord(text))); } }
/// <summary> /// Creates a new object initialized with all the log entry parameters. /// </summary> /// <param name="rowNumber">The row number of the entry in the selected data set.</param> /// <param name="timestamp">The time stamp of the log entry.</param> /// <param name="clientIpAddress">The client IP address of the request.</param> /// <param name="protocol">The DNS transport protocol of the request.</param> /// <param name="responseType">The type of response sent by the DNS server.</param> /// <param name="rcode">The response code sent by the DNS server.</param> /// <param name="question">The question section in the request.</param> /// <param name="answer">The answer in text format sent by the DNS server.</param> public DnsLogEntry(long rowNumber, DateTime timestamp, IPAddress clientIpAddress, DnsTransportProtocol protocol, DnsServerResponseType responseType, DnsResponseCode rcode, DnsQuestionRecord question, string answer) { _rowNumber = rowNumber; _timestamp = timestamp; _clientIpAddress = clientIpAddress; _protocol = protocol; _responseType = responseType; _rcode = rcode; _question = question; _answer = answer; switch (_timestamp.Kind) { case DateTimeKind.Local: _timestamp = _timestamp.ToUniversalTime(); break; case DateTimeKind.Unspecified: _timestamp = DateTime.SpecifyKind(_timestamp, DateTimeKind.Utc); break; } }
private void GetStatusAnswers(dynamic jsonAddresses, FailoverType type, DnsQuestionRecord question, uint appRecordTtl, string healthCheck, Uri healthCheckUrl, List <DnsResourceRecord> answers) { if (jsonAddresses == null) { return; } foreach (dynamic jsonAddress in jsonAddresses) { IPAddress address = IPAddress.Parse(jsonAddress.Value); HealthCheckResponse response = _healthService.QueryStatus(address, healthCheck, healthCheckUrl, false); string text = "app=failover; addressType=" + type.ToString() + "; address=" + address.ToString() + "; healthCheck=" + healthCheck + (healthCheckUrl is null ? "" : "; healthCheckUrl=" + healthCheckUrl.AbsoluteUri) + "; healthStatus=" + response.Status.ToString() + ";"; if (response.Status == HealthStatus.Failed) { text += " failureReason=" + response.FailureReason + ";"; } answers.Add(new DnsResourceRecord(question.Name, DnsResourceRecordType.TXT, question.Class, appRecordTtl, new DnsTXTRecord(text))); } }
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).WithTimeout(2000); } else { DnsClient dnsClient = new DnsClient(primaryNameServerAddresses); dnsClient.Proxy = secondaryZone._dnsServer.Proxy; dnsClient.PreferIPv6 = secondaryZone._dnsServer.PreferIPv6; if (string.IsNullOrEmpty(tsigKeyName)) { soaResponse = await dnsClient.ResolveAsync(soaQuestion); } else if ((dnsServer.TsigKeys is not null) && dnsServer.TsigKeys.TryGetValue(tsigKeyName, out TsigKey key)) { soaResponse = await dnsClient.ResolveAsync(soaQuestion, key, REFRESH_TSIG_FUDGE); }
public Task <DnsDatagram> DirectQueryAsync(DnsQuestionRecord question, int timeout = 2000) { return(_dnsServer.DirectQueryAsync(question, timeout)); }
public Task <DnsDatagram> ResolveAsync(DnsQuestionRecord question) { return(_dnsServer.DirectQueryAsync(question)); }
public Task <DnsDatagram> ResolveAsync(DnsQuestionRecord question, CancellationToken cancellationToken = default) { return(_dnsServer.DirectQueryAsync(question)); }
public Task <DnsDatagram> ProcessRequestAsync(DnsDatagram request, IPEndPoint remoteEP, string zoneName, uint appRecordTtl, string appRecordData, bool isRecursionAllowed, IDnsServer dnsServer) { DnsQuestionRecord question = request.Question[0]; dynamic jsonAppRecordData = JsonConvert.DeserializeObject(appRecordData); string healthCheck = jsonAppRecordData.healthCheck?.Value; IReadOnlyList <DnsResourceRecord> answers; if (question.Type == DnsResourceRecordType.TXT) { bool allowTxtStatus; if (jsonAppRecordData.allowTxtStatus == null) { allowTxtStatus = false; } else { allowTxtStatus = jsonAppRecordData.allowTxtStatus.Value; } if (!allowTxtStatus) { return(Task.FromResult <DnsDatagram>(null)); } List <DnsResourceRecord> txtAnswers = new List <DnsResourceRecord>(); GetStatusAnswers(jsonAppRecordData.primary.Value, true, question, 30, healthCheck, txtAnswers); foreach (dynamic jsonDomain in jsonAppRecordData.secondary) { GetStatusAnswers(jsonDomain.Value, false, question, 30, healthCheck, txtAnswers); } answers = txtAnswers; } else { answers = GetAnswers(jsonAppRecordData.primary.Value, question, zoneName, appRecordTtl, healthCheck); if (answers is null) { foreach (dynamic jsonDomain in jsonAppRecordData.secondary) { answers = GetAnswers(jsonDomain.Value, question, zoneName, appRecordTtl, healthCheck); if (answers is not null) { break; } } if (answers is null) { 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, answers))); }
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); string healthCheck = jsonAppRecordData.healthCheck?.Value; Uri healthCheckUrl = null; if (_healthService.HealthChecks.TryGetValue(healthCheck, out HealthCheck hc) && ((hc.Type == HealthCheckType.Https) || (hc.Type == HealthCheckType.Http)) && (hc.Url is null)) { //read health check url only for http/https type checks and only when app config does not have an url configured if ((jsonAppRecordData.healthCheckUrl is not null) && (jsonAppRecordData.healthCheckUrl.Value is not null)) { healthCheckUrl = new Uri(jsonAppRecordData.healthCheckUrl.Value); } else { if (hc.Type == HealthCheckType.Https) { healthCheckUrl = new Uri("https://" + question.Name); } else { healthCheckUrl = new Uri("http://" + question.Name); } } } List <DnsResourceRecord> answers = new List <DnsResourceRecord>(); GetAnswers(jsonAppRecordData.primary, question, appRecordTtl, healthCheck, healthCheckUrl, answers); if (answers.Count == 0) { GetAnswers(jsonAppRecordData.secondary, question, appRecordTtl, healthCheck, healthCheckUrl, answers); if (answers.Count == 0) { if (jsonAppRecordData.serverDown is not null) { if (question.Type == DnsResourceRecordType.A) { foreach (dynamic jsonAddress in jsonAppRecordData.serverDown) { IPAddress address = IPAddress.Parse(jsonAddress.Value); if (address.AddressFamily == AddressFamily.InterNetwork) { answers.Add(new DnsResourceRecord(question.Name, DnsResourceRecordType.A, question.Class, 30, new DnsARecord(address))); } } } else { foreach (dynamic jsonAddress in jsonAppRecordData.serverDown) { IPAddress address = IPAddress.Parse(jsonAddress.Value); if (address.AddressFamily == AddressFamily.InterNetworkV6) { answers.Add(new DnsResourceRecord(question.Name, DnsResourceRecordType.AAAA, question.Class, 30, new DnsAAAARecord(address))); } } } } 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))); }
public ResolverPrefetchDnsCache(AuthZoneManager authZoneManager, CacheZoneManager cacheZoneManager, DnsQuestionRecord prefetchQuery) : base(authZoneManager, cacheZoneManager) { _prefetchQuery = prefetchQuery; }
public Task <DnsDatagram> ProcessRequestAsync(DnsDatagram request, IPEndPoint remoteEP, string zoneName, uint appRecordTtl, string appRecordData, bool isRecursionAllowed, IDnsServer dnsServer) { DnsQuestionRecord question = request.Question[0]; switch (question.Type) { case DnsResourceRecordType.A: case DnsResourceRecordType.AAAA: { dynamic jsonAppRecordData = JsonConvert.DeserializeObject(appRecordData); string healthCheck = jsonAppRecordData.healthCheck?.Value; List <DnsResourceRecord> answers = new List <DnsResourceRecord>(); GetAnswers(jsonAppRecordData.primary, question, appRecordTtl, healthCheck, answers); if (answers.Count == 0) { GetAnswers(jsonAppRecordData.secondary, question, appRecordTtl, healthCheck, answers); 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))); } case DnsResourceRecordType.TXT: { dynamic jsonAppRecordData = JsonConvert.DeserializeObject(appRecordData); bool allowTxtStatus; if (jsonAppRecordData.allowTxtStatus == null) { allowTxtStatus = false; } else { allowTxtStatus = jsonAppRecordData.allowTxtStatus.Value; } if (!allowTxtStatus) { return(Task.FromResult <DnsDatagram>(null)); } string healthCheck = jsonAppRecordData.healthCheck?.Value; List <DnsResourceRecord> answers = new List <DnsResourceRecord>(); GetStatusAnswers(jsonAppRecordData.primary, true, question, 30, healthCheck, answers); GetStatusAnswers(jsonAppRecordData.secondary, false, question, 30, healthCheck, answers); 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 LoadAllZoneFiles() { _root.Clear(); string zonesFolder = Path.Combine(_dnsServer.ConfigFolder, "zones"); if (!Directory.Exists(zonesFolder)) { Directory.CreateDirectory(zonesFolder); } //move zone files to new folder { string[] oldZoneFiles = Directory.GetFiles(_dnsServer.ConfigFolder, "*.zone"); foreach (string oldZoneFile in oldZoneFiles) { File.Move(oldZoneFile, Path.Combine(zonesFolder, Path.GetFileName(oldZoneFile))); } } //remove old internal zones { string[] oldZoneFiles = new string[] { "localhost.zone", "1.0.0.127.in-addr.arpa.zone", "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.zone" }; foreach (string oldZoneFile in oldZoneFiles) { string filePath = Path.Combine(zonesFolder, oldZoneFile); if (File.Exists(filePath)) { try { File.Delete(filePath); } catch { } } } } //load system zones { { CreatePrimaryZone("localhost", _dnsServer.ServerDomain, true); SetRecords("localhost", DnsResourceRecordType.A, 3600, new DnsResourceRecordData[] { new DnsARecord(IPAddress.Loopback) }); SetRecords("localhost", DnsResourceRecordType.AAAA, 3600, new DnsResourceRecordData[] { new DnsAAAARecord(IPAddress.IPv6Loopback) }); } { string prtDomain = "0.in-addr.arpa"; CreatePrimaryZone(prtDomain, _dnsServer.ServerDomain, true); } { string prtDomain = "255.in-addr.arpa"; CreatePrimaryZone(prtDomain, _dnsServer.ServerDomain, true); } { string prtDomain = "127.in-addr.arpa"; CreatePrimaryZone(prtDomain, _dnsServer.ServerDomain, true); SetRecords("1.0.0.127.in-addr.arpa", DnsResourceRecordType.PTR, 3600, new DnsResourceRecordData[] { new DnsPTRRecord("localhost") }); } { string prtDomain = new DnsQuestionRecord(IPAddress.IPv6Loopback, DnsClass.IN).Name; CreatePrimaryZone(prtDomain, _dnsServer.ServerDomain, true); SetRecords(prtDomain, DnsResourceRecordType.PTR, 3600, new DnsResourceRecordData[] { new DnsPTRRecord("localhost") }); } } //load zone files string[] zoneFiles = Directory.GetFiles(zonesFolder, "*.zone"); foreach (string zoneFile in zoneFiles) { try { using (FileStream fS = new FileStream(zoneFile, FileMode.Open, FileAccess.Read)) { LoadZoneFrom(fS); } LogManager log = _dnsServer.LogManager; if (log != null) { log.Write("DNS Server successfully loaded zone file: " + zoneFile); } } catch (Exception ex) { LogManager log = _dnsServer.LogManager; if (log != null) { log.Write("DNS Server failed to load zone file: " + zoneFile + "\r\n" + ex.ToString()); } } } }
private void BulkInsertLogs() { try { List <LogEntry> logs = new List <LogEntry>(BULK_INSERT_COUNT); while (true) { while ((logs.Count < BULK_INSERT_COUNT) && _queuedLogs.TryDequeue(out LogEntry log)) { logs.Add(log); } if (logs.Count < 1) { break; } using (SqliteConnection connection = new SqliteConnection(_connectionString)) { connection.Open(); using (SqliteTransaction transaction = connection.BeginTransaction()) { using (SqliteCommand command = connection.CreateCommand()) { command.CommandText = "INSERT INTO dns_logs (timestamp, client_ip, protocol, response_type, rcode, qname, qtype, qclass, answer) VALUES (@timestamp, @client_ip, @protocol, @response_type, @rcode, @qname, @qtype, @qclass, @answer);"; SqliteParameter paramTimestamp = command.Parameters.Add("@timestamp", SqliteType.Text); SqliteParameter paramClientIp = command.Parameters.Add("@client_ip", SqliteType.Text); SqliteParameter paramProtocol = command.Parameters.Add("@protocol", SqliteType.Integer); SqliteParameter paramResponseType = command.Parameters.Add("@response_type", SqliteType.Integer); SqliteParameter paramRcode = command.Parameters.Add("@rcode", SqliteType.Integer); SqliteParameter paramQname = command.Parameters.Add("@qname", SqliteType.Text); SqliteParameter paramQtype = command.Parameters.Add("@qtype", SqliteType.Integer); SqliteParameter paramQclass = command.Parameters.Add("@qclass", SqliteType.Integer); SqliteParameter paramAnswer = command.Parameters.Add("@answer", SqliteType.Text); foreach (LogEntry log in logs) { paramTimestamp.Value = log.Timestamp.ToString("yyyy-MM-dd HH:mm:ss.FFFFFFF"); paramClientIp.Value = log.RemoteEP.Address.ToString(); paramProtocol.Value = (int)log.Protocol; if (log.Response.Tag == null) { paramResponseType.Value = (int)DnsServerResponseType.Recursive; } else { paramResponseType.Value = (int)(DnsServerResponseType)log.Response.Tag; } paramRcode.Value = (int)log.Response.RCODE; if (log.Request.Question.Count > 0) { DnsQuestionRecord query = log.Request.Question[0]; paramQname.Value = query.Name.ToLower(); paramQtype.Value = (int)query.Type; paramQclass.Value = (int)query.Class; } else { paramQname.Value = DBNull.Value; paramQtype.Value = DBNull.Value; paramQclass.Value = DBNull.Value; } if (log.Response.Answer.Count == 0) { paramAnswer.Value = DBNull.Value; } else if ((log.Response.Answer.Count > 2) && log.Response.IsZoneTransfer) { paramAnswer.Value = "[ZONE TRANSFER]"; } else { string answer = null; for (int i = 0; i < log.Response.Answer.Count; i++) { if (answer is null) { answer = log.Response.Answer[i].RDATA.ToString(); } else { answer += ", " + log.Response.Answer[i].RDATA.ToString(); } } paramAnswer.Value = answer; } command.ExecuteNonQuery(); } transaction.Commit(); } } } logs.Clear(); } } catch (Exception ex) { if (_dnsServer is not null) { _dnsServer.WriteLog(ex); } } }
public Task <DnsLogPage> QueryLogsAsync(long pageNumber, int entriesPerPage, bool descendingOrder, DateTime?start, DateTime?end, IPAddress clientIpAddress, DnsTransportProtocol?protocol, DnsServerResponseType?responseType, DnsResponseCode?rcode, string qname, DnsResourceRecordType?qtype, DnsClass?qclass) { if (pageNumber < 0) { pageNumber = long.MaxValue; } else if (pageNumber == 0) { pageNumber = 1; } if (qname is not null) { qname = qname.ToLower(); } string whereClause = string.Empty; if (start is not null) { whereClause += "timestamp >= @start AND "; } if (end is not null) { whereClause += "timestamp <= @end AND "; } if (clientIpAddress is not null) { whereClause += "client_ip = @client_ip AND "; } if (protocol is not null) { whereClause += "protocol = @protocol AND "; } if (responseType is not null) { whereClause += "response_type = @response_type AND "; } if (rcode is not null) { whereClause += "rcode = @rcode AND "; } if (qname is not null) { whereClause += "qname = @qname AND "; } if (qtype is not null) { whereClause += "qtype = @qtype AND "; } if (qclass is not null) { whereClause += "qclass = @qclass AND "; } if (!string.IsNullOrEmpty(whereClause)) { whereClause = whereClause.Substring(0, whereClause.Length - 5); } using (SqliteConnection connection = new SqliteConnection(_connectionString)) { connection.Open(); //find total entries long totalEntries; using (SqliteCommand command = connection.CreateCommand()) { command.CommandText = "SELECT Count(*) FROM dns_logs" + (string.IsNullOrEmpty(whereClause) ? ";" : " WHERE " + whereClause + ";"); if (start is not null) { command.Parameters.AddWithValue("@start", start); } if (end is not null) { command.Parameters.AddWithValue("@end", end); } if (clientIpAddress is not null) { command.Parameters.AddWithValue("@client_ip", clientIpAddress.ToString()); } if (protocol is not null) { command.Parameters.AddWithValue("@protocol", (byte)protocol); } if (responseType is not null) { command.Parameters.AddWithValue("@response_type", (byte)responseType); } if (rcode is not null) { command.Parameters.AddWithValue("@rcode", (byte)rcode); } if (qname is not null) { command.Parameters.AddWithValue("@qname", qname); } if (qtype is not null) { command.Parameters.AddWithValue("@qtype", (ushort)qtype); } if (qclass is not null) { command.Parameters.AddWithValue("@qclass", (ushort)qclass); } totalEntries = (long)command.ExecuteScalar(); } long totalPages = (totalEntries / entriesPerPage) + (totalEntries % entriesPerPage > 0 ? 1 : 0); if (pageNumber > totalPages) { pageNumber = totalPages; } long endRowNum; long startRowNum; if (descendingOrder) { endRowNum = totalEntries - ((pageNumber - 1) * entriesPerPage); startRowNum = endRowNum - entriesPerPage; } else { endRowNum = pageNumber * entriesPerPage; startRowNum = endRowNum - entriesPerPage; } List <DnsLogEntry> entries = new List <DnsLogEntry>(entriesPerPage); using (SqliteCommand command = connection.CreateCommand()) { command.CommandText = @" SELECT * FROM ( SELECT ROW_NUMBER() OVER ( ORDER BY timestamp ) row_num, timestamp, client_ip, protocol, response_type, rcode, qname, qtype, qclass, answer FROM dns_logs " + (string.IsNullOrEmpty(whereClause) ? "" : "WHERE " + whereClause) + @" ORDER BY row_num" + (descendingOrder ? " DESC" : "") + @" ) t WHERE row_num > @start_row_num AND row_num <= @end_row_num "; command.Parameters.AddWithValue("@start_row_num", startRowNum); command.Parameters.AddWithValue("@end_row_num", endRowNum); if (start is not null) { command.Parameters.AddWithValue("@start", start); } if (end is not null) { command.Parameters.AddWithValue("@end", end); } if (clientIpAddress is not null) { command.Parameters.AddWithValue("@client_ip", clientIpAddress.ToString()); } if (protocol is not null) { command.Parameters.AddWithValue("@protocol", (byte)protocol); } if (responseType is not null) { command.Parameters.AddWithValue("@response_type", (byte)responseType); } if (rcode is not null) { command.Parameters.AddWithValue("@rcode", (byte)rcode); } if (qname is not null) { command.Parameters.AddWithValue("@qname", qname); } if (qtype is not null) { command.Parameters.AddWithValue("@qtype", (ushort)qtype); } if (qclass is not null) { command.Parameters.AddWithValue("@qclass", (ushort)qclass); } using (SqliteDataReader reader = command.ExecuteReader()) { while (reader.Read()) { DnsQuestionRecord question; if (reader.IsDBNull(6)) { question = null; } else { question = new DnsQuestionRecord(reader.GetString(6), (DnsResourceRecordType)reader.GetInt32(7), (DnsClass)reader.GetInt32(8)); } string answer; if (reader.IsDBNull(9)) { answer = null; } else { answer = reader.GetString(9); } entries.Add(new DnsLogEntry(reader.GetInt64(0), reader.GetDateTime(1), IPAddress.Parse(reader.GetString(2)), (DnsTransportProtocol)reader.GetByte(3), (DnsServerResponseType)reader.GetByte(4), (DnsResponseCode)reader.GetByte(5), question, answer)); } } } return(Task.FromResult(new DnsLogPage(pageNumber, totalPages, totalEntries, entries))); } }
public void Write(IPEndPoint ep, DnsTransportProtocol protocol, DnsDatagram request, DnsDatagram response) { DnsQuestionRecord q = null; if (request.Question.Count > 0) { q = request.Question[0]; } string question; if (q is null) { question = "MISSING QUESTION!"; } else { question = "QNAME: " + q.Name + "; QTYPE: " + q.Type.ToString() + "; QCLASS: " + q.Class; } string responseInfo; if (response is null) { responseInfo = " NO RESPONSE FROM SERVER!"; } else { string answer; if (response.Answer.Count == 0) { answer = "[]"; } else if ((response.Answer.Count > 2) && response.IsZoneTransfer) { answer = "[ZONE TRANSFER]"; } else { answer = "["; for (int i = 0; i < response.Answer.Count; i++) { if (i > 0) { answer += ", "; } answer += response.Answer[i].RDATA.ToString(); } answer += "]"; if (response.Additional.Count > 0) { switch (q.Type) { case DnsResourceRecordType.NS: case DnsResourceRecordType.MX: case DnsResourceRecordType.SRV: answer += "; ADDITIONAL: ["; for (int i = 0; i < response.Additional.Count; i++) { DnsResourceRecord additional = response.Additional[i]; switch (additional.Type) { case DnsResourceRecordType.A: case DnsResourceRecordType.AAAA: if (i > 0) { answer += ", "; } answer += additional.Name + " (" + additional.RDATA.ToString() + ")"; break; } } answer += "]"; break; } } } responseInfo = " RCODE: " + response.RCODE.ToString() + "; ANSWER: " + answer; } Write(ep, protocol, question + ";" + responseInfo); }
public void Configure(IApplicationBuilder app, IHostEnvironment env) { int staticFilesCachePeriod; if (env.IsDevelopment()) { staticFilesCachePeriod = 60; app.UseDeveloperExceptionPage(); } else { staticFilesCachePeriod = 14400; } app.UseDefaultFiles(); app.UseStaticFiles(new StaticFileOptions() { OnPrepareResponse = delegate(StaticFileResponseContext ctx) { ctx.Context.Response.Headers.Append("Cache-Control", $"public, max-age={staticFilesCachePeriod}"); } }); app.Run(async(context) => { HttpRequest request = context.Request; HttpResponse response = context.Response; if (request.Path == "/api/dnsclient/") { try { string server = request.Query["server"]; string domain = request.Query["domain"]; DnsResourceRecordType type = (DnsResourceRecordType)Enum.Parse(typeof(DnsResourceRecordType), request.Query["type"], true); domain = domain.Trim(); if (domain.EndsWith(".")) { domain = domain.Substring(0, domain.Length - 1); } bool preferIpv6 = Configuration.GetValue <bool>("PreferIpv6"); bool randomizeName = false; bool qnameMinimization = false; int retries = Configuration.GetValue <int>("Retries"); int timeout = Configuration.GetValue <int>("Timeout"); DnsDatagram dnsResponse; if (server == "recursive-resolver") { DnsQuestionRecord question; if ((type == DnsResourceRecordType.PTR) && IPAddress.TryParse(domain, out IPAddress address)) { question = new DnsQuestionRecord(address, DnsClass.IN); } else { question = new DnsQuestionRecord(domain, type, DnsClass.IN); } dnsResponse = await DnsClient.RecursiveResolveAsync(question, null, null, preferIpv6, randomizeName, qnameMinimization, retries, timeout); } else { DnsTransportProtocol protocol = (DnsTransportProtocol)Enum.Parse(typeof(DnsTransportProtocol), request.Query["protocol"], true); if ((protocol == DnsTransportProtocol.Tls) && !server.Contains(":853")) { server += ":853"; } NameServerAddress nameServer = new NameServerAddress(server, protocol); if (nameServer.IPEndPoint == null) { await nameServer.ResolveIPAddressAsync(null, null, preferIpv6); } else if (nameServer.DomainEndPoint == null) { try { await nameServer.ResolveDomainNameAsync(null, null, preferIpv6); } catch { } } DnsClient dnsClient = new DnsClient(nameServer); dnsClient.PreferIPv6 = preferIpv6; dnsClient.RandomizeName = randomizeName; dnsClient.Retries = retries; dnsClient.Timeout = timeout; dnsResponse = await dnsClient.ResolveAsync(domain, type); } string jsonResponse = JsonConvert.SerializeObject(dnsResponse, new StringEnumConverter()); response.Headers.Add("Content-Type", "application/json; charset=utf-8"); await response.WriteAsync("{\"status\":\"ok\", \"response\":" + jsonResponse + "}"); } catch (Exception ex) { string jsonResponse = JsonConvert.SerializeObject(ex); response.Headers.Add("Content-Type", "application/json; charset=utf-8"); await response.WriteAsync("{\"status\":\"error\", \"response\":" + jsonResponse + "}"); } } }); }
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 DnsDatagram Query(DnsDatagram request) { DnsQuestionRecord question = request.Question[0]; List <Uri> blockLists = IsZoneBlocked(question.Name, out string blockedDomain); if (blockLists is null) { return(null); //zone not blocked } //zone is blocked if (_dnsServer.AllowTxtBlockingReport && (question.Type == DnsResourceRecordType.TXT)) { //return meta data DnsResourceRecord[] answer = new DnsResourceRecord[blockLists.Count]; for (int i = 0; i < answer.Length; i++) { answer[i] = new DnsResourceRecord(question.Name, DnsResourceRecordType.TXT, question.Class, 60, new DnsTXTRecord("source=block-list-zone; blockListUrl=" + blockLists[i].AbsoluteUri + "; domain=" + blockedDomain)); } return(new DnsDatagram(request.Identifier, true, DnsOpcode.StandardQuery, false, false, request.RecursionDesired, true, false, false, DnsResponseCode.NoError, request.Question, answer)); } else { IReadOnlyCollection <DnsARecord> aRecords; IReadOnlyCollection <DnsAAAARecord> aaaaRecords; switch (_dnsServer.BlockingType) { case DnsServerBlockingType.AnyAddress: aRecords = _aRecords; aaaaRecords = _aaaaRecords; break; case DnsServerBlockingType.CustomAddress: aRecords = _dnsServer.CustomBlockingARecords; aaaaRecords = _dnsServer.CustomBlockingAAAARecords; break; case DnsServerBlockingType.NxDomain: string parentDomain = GetParentZone(blockedDomain); if (parentDomain is null) { parentDomain = string.Empty; } return(new DnsDatagram(request.Identifier, true, DnsOpcode.StandardQuery, false, false, request.RecursionDesired, true, false, false, DnsResponseCode.NxDomain, request.Question, null, new DnsResourceRecord[] { new DnsResourceRecord(parentDomain, DnsResourceRecordType.SOA, question.Class, 60, _soaRecord) })); default: throw new InvalidOperationException(); } IReadOnlyList <DnsResourceRecord> answer = null; IReadOnlyList <DnsResourceRecord> authority = null; switch (question.Type) { case DnsResourceRecordType.A: { List <DnsResourceRecord> rrList = new List <DnsResourceRecord>(aRecords.Count); foreach (DnsARecord record in aRecords) { rrList.Add(new DnsResourceRecord(question.Name, DnsResourceRecordType.A, question.Class, 60, record)); } answer = rrList; } break; case DnsResourceRecordType.AAAA: { List <DnsResourceRecord> rrList = new List <DnsResourceRecord>(aaaaRecords.Count); foreach (DnsAAAARecord record in aaaaRecords) { rrList.Add(new DnsResourceRecord(question.Name, DnsResourceRecordType.AAAA, question.Class, 60, record)); } answer = rrList; } break; case DnsResourceRecordType.NS: if (question.Name.Equals(blockedDomain, StringComparison.OrdinalIgnoreCase)) { answer = new DnsResourceRecord[] { new DnsResourceRecord(blockedDomain, DnsResourceRecordType.NS, question.Class, 60, _nsRecord) } } ; else { authority = new DnsResourceRecord[] { new DnsResourceRecord(blockedDomain, DnsResourceRecordType.SOA, question.Class, 60, _soaRecord) } }; break; default: authority = new DnsResourceRecord[] { new DnsResourceRecord(blockedDomain, DnsResourceRecordType.SOA, question.Class, 60, _soaRecord) }; break; } return(new DnsDatagram(request.Identifier, true, DnsOpcode.StandardQuery, false, false, request.RecursionDesired, true, false, false, DnsResponseCode.NoError, request.Question, answer, authority)); } }