示例#1
0
        public DnsForwarderRecord(DnsTransportProtocol protocol, string forwarder)
        {
            _protocol  = protocol;
            _forwarder = forwarder;

            _nameServer = new NameServerAddress(_forwarder, _protocol);
        }
示例#2
0
        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 += "]";
                }

                responseInfo = " RCODE: " + response.RCODE.ToString() + "; ANSWER: " + answer;
            }

            Write(ep, protocol, question + ";" + responseInfo);
        }
示例#3
0
        public ForwarderZone(string name, DnsTransportProtocol forwarderProtocol, string forwarder)
            : base(name)
        {
            DnsResourceRecord fwdRecord = new DnsResourceRecord(name, DnsResourceRecordType.FWD, DnsClass.IN, 0, new DnsForwarderRecord(forwarderProtocol, forwarder));

            _entries[DnsResourceRecordType.FWD] = new DnsResourceRecord[] { fwdRecord };
        }
示例#4
0
            public void SetResponse(DnsDatagram response, NameServerAddress server, DnsTransportProtocol protocol)
            {
                if (_isZoneTransferRequest)
                {
                    if (_firstResponse is null)
                    {
                        _firstResponse = response;
                    }
                    else
                    {
                        _lastResponse.NextDatagram = response;
                    }

                    _lastResponse = response;

                    if ((_lastResponse.Answer.Count == 0) || (_lastResponse.Answer[_lastResponse.Answer.Count - 1].Type == DnsResourceRecordType.SOA))
                    {
                        //found last response
                        _stopwatch.Stop();

                        _firstResponse.SetMetadata(server, protocol, _stopwatch.Elapsed.TotalMilliseconds);

                        _responseTask.TrySetResult(_firstResponse);
                    }
                }
                else
                {
                    _stopwatch.Stop();

                    response.SetMetadata(server, protocol, _stopwatch.Elapsed.TotalMilliseconds);

                    _responseTask.TrySetResult(response);
                }
            }
        public NameServerAddress(EndPoint endPoint, DnsTransportProtocol protocol = DnsTransportProtocol.Udp)
        {
            switch (endPoint.AddressFamily)
            {
            case AddressFamily.InterNetwork:
            case AddressFamily.InterNetworkV6:
                _ipEndPoint = endPoint as IPEndPoint;
                break;

            case AddressFamily.Unspecified:
                _domainEndPoint = endPoint as DomainEndPoint;
                break;

            default:
                throw new NotSupportedException("AddressFamily not supported.");
            }

            _protocol = protocol;

            if (endPoint.AddressFamily == AddressFamily.InterNetworkV6)
            {
                _originalAddress = "[" + (endPoint as IPEndPoint).Address.ToString() + "]:" + (endPoint as IPEndPoint).Port;
            }
            else
            {
                _originalAddress = endPoint.ToString();
            }

            ValidateProtocol();
        }
示例#6
0
 public LogEntry(DateTime timestamp, DnsDatagram request, IPEndPoint remoteEP, DnsTransportProtocol protocol, DnsDatagram response)
 {
     Timestamp = timestamp;
     Request   = request;
     RemoteEP  = remoteEP;
     Protocol  = protocol;
     Response  = response;
 }
        public NameServerAddress(IPAddress address, DnsTransportProtocol protocol = DnsTransportProtocol.Udp)
        {
            _ipEndPoint = new IPEndPoint(address, 53);

            _protocol        = protocol;
            _originalAddress = address.ToString();

            ValidateProtocol();
        }
示例#8
0
        public static DnsClientConnection GetConnection(DnsTransportProtocol protocol, NameServerAddress server, NetProxy proxy)
        {
            switch (protocol)
            {
            case DnsTransportProtocol.Udp:
                return(new UdpClientConnection(server, proxy));

            case DnsTransportProtocol.Https:
                return(new HttpsClientConnection(server, proxy));

            case DnsTransportProtocol.HttpsJson:
                return(new HttpsJsonClientConnection(server, proxy));

            case DnsTransportProtocol.Tcp:
            {
                ConcurrentDictionary <NetProxy, DnsClientConnection> existingTcpConnection = _existingTcpConnections.GetOrAdd(server, delegate(NameServerAddress nameServer)
                    {
                        return(new ConcurrentDictionary <NetProxy, DnsClientConnection>());
                    });

                NetProxy proxyKey = proxy;

                if (proxyKey == null)
                {
                    proxyKey = NetProxy.None;
                }

                return(existingTcpConnection.GetOrAdd(proxyKey, delegate(NetProxy netProxyKey)
                    {
                        return new TcpClientConnection(server, proxy);
                    }));
            }

            case DnsTransportProtocol.Tls:
            {
                ConcurrentDictionary <NetProxy, DnsClientConnection> existingTlsConnection = _existingTlsConnections.GetOrAdd(server, delegate(NameServerAddress nameServer)
                    {
                        return(new ConcurrentDictionary <NetProxy, DnsClientConnection>());
                    });

                NetProxy proxyKey = proxy;

                if (proxyKey == null)
                {
                    proxyKey = NetProxy.None;
                }

                return(existingTlsConnection.GetOrAdd(proxyKey, delegate(NetProxy netProxyKey)
                    {
                        return new TlsClientConnection(server, proxy);
                    }));
            }

            default:
                throw new NotSupportedException("DnsClient protocol not supported: " + protocol.ToString());
            }
        }
示例#9
0
        public DnsForwarderRecord(dynamic jsonResourceRecord)
        {
            _length = Convert.ToUInt16(jsonResourceRecord.data.Value.Length);

            string[] parts = (jsonResourceRecord.data.Value as string).Split(new char[] { ' ' }, 2);

            _protocol  = (DnsTransportProtocol)Enum.Parse(typeof(DnsTransportProtocol), parts[0], true);
            _forwarder = parts[1];
        }
示例#10
0
        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);
        }
示例#11
0
        public ForwarderZone(string name, DnsTransportProtocol forwarderProtocol, string forwarder)
            : base(name)
        {
            _zoneTransfer = AuthZoneTransfer.Deny;
            _notify       = AuthZoneNotify.None;

            DnsResourceRecord fwdRecord = new DnsResourceRecord(name, DnsResourceRecordType.FWD, DnsClass.IN, 0, new DnsForwarderRecord(forwarderProtocol, forwarder));

            _entries[DnsResourceRecordType.FWD] = new DnsResourceRecord[] { fwdRecord };
        }
示例#12
0
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;

            DnsTransportProtocol protocol = (DnsTransportProtocol)Enum.Parse(typeof(DnsTransportProtocol), Configuration.GetValue <string>("dnsServerProtocol"), true);

            _dnsServer = new NameServerAddress(Configuration.GetValue <string>("dnsServer"), protocol);
            _timeout   = Configuration.GetValue <int>("dnsTimeout");
            _debug     = Configuration.GetValue <bool>("debug");
        }
示例#13
0
        public AuthZoneInfo CreateForwarderZone(string domain, DnsTransportProtocol forwarderProtocol, string forwarder)
        {
            AuthZone authZone = new ForwarderZone(domain, forwarderProtocol, forwarder);

            if (_root.TryAdd(authZone))
            {
                return(new AuthZoneInfo(authZone));
            }

            return(null);
        }
        public DnsDatagramMetadata(NameServerAddress server, DnsTransportProtocol protocol, int size, double rtt)
        {
            _server   = server;
            _protocol = protocol;
            _size     = size;
            _rtt      = rtt;

            if (_rtt < 0.1)
            {
                _rtt = 0.1;
            }
        }
        public NameServerAddress(Uri dohEndPoint, DnsTransportProtocol protocol = DnsTransportProtocol.Https)
        {
            _dohEndPoint = dohEndPoint;

            if (IPAddress.TryParse(_dohEndPoint.Host, out IPAddress address))
            {
                _ipEndPoint = new IPEndPoint(address, _dohEndPoint.Port);
            }

            _protocol        = protocol;
            _originalAddress = _dohEndPoint.AbsoluteUri;

            ValidateProtocol();
        }
        public NameServerAddress(NameServerAddress nameServer, DnsTransportProtocol protocol)
        {
            _protocol        = protocol;
            _originalAddress = nameServer._originalAddress;

            _dohEndPoint    = nameServer._dohEndPoint;
            _domainEndPoint = nameServer._domainEndPoint;
            _ipEndPoint     = nameServer._ipEndPoint;

            _ipEndPointExpires   = nameServer._ipEndPointExpires;
            _ipEndPointExpiresOn = nameServer._ipEndPointExpiresOn;

            ValidateProtocol();
        }
        public NameServerAddress(BinaryReader bR)
        {
            switch (bR.ReadByte())
            {
            case 1:
                if (bR.ReadBoolean())
                {
                    _dohEndPoint = new Uri(bR.ReadShortString());
                }

                if (bR.ReadBoolean())
                {
                    _domainEndPoint = EndPointExtension.Parse(bR) as DomainEndPoint;
                }

                if (bR.ReadBoolean())
                {
                    _ipEndPoint = EndPointExtension.Parse(bR) as IPEndPoint;
                }

                if (_dohEndPoint != null)
                {
                    _originalAddress = _dohEndPoint.AbsoluteUri;
                }
                else if (_ipEndPoint != null)
                {
                    _originalAddress = _ipEndPoint.ToString();
                }
                else if (_domainEndPoint != null)
                {
                    _originalAddress = _domainEndPoint.ToString();
                }

                GuessProtocol();
                break;

            case 2:
                Parse(bR.ReadShortString());
                GuessProtocol();
                break;

            case 3:
                _protocol = (DnsTransportProtocol)bR.ReadByte();
                Parse(bR.ReadShortString());
                break;

            default:
                throw new InvalidDataException("NameServerAddress version not supported");
            }
        }
示例#18
0
        public ForwarderZone(string name, DnsTransportProtocol forwarderProtocol, string forwarder, bool dnssecValidation, NetProxyType proxyType, string proxyAddress, ushort proxyPort, string proxyUsername, string proxyPassword, string fwdRecordComments)
            : base(name)
        {
            _zoneTransfer = AuthZoneTransfer.Deny;
            _notify       = AuthZoneNotify.None;

            DnsResourceRecord fwdRecord = new DnsResourceRecord(name, DnsResourceRecordType.FWD, DnsClass.IN, 0, new DnsForwarderRecordData(forwarderProtocol, forwarder, dnssecValidation, proxyType, proxyAddress, proxyPort, proxyUsername, proxyPassword));

            if (!string.IsNullOrEmpty(fwdRecordComments))
            {
                fwdRecord.SetComments(fwdRecordComments);
            }

            _entries[DnsResourceRecordType.FWD] = new DnsResourceRecord[] { fwdRecord };
        }
示例#19
0
        public AuthZoneInfo CreateForwarderZone(string domain, DnsTransportProtocol forwarderProtocol, string forwarder)
        {
            AuthZone authZone = new ForwarderZone(domain, forwarderProtocol, forwarder);

            if (_root.TryAdd(authZone))
            {
                return(new AuthZoneInfo(authZone));
            }

            if (_root.TryGet(domain, out AuthZone existingZone) && (existingZone is SubDomainZone))
            {
                _root[domain] = authZone;
                return(new AuthZoneInfo(authZone));
            }

            return(null);
        }
        public NameServerAddress(string domain, IPAddress address, DnsTransportProtocol protocol = DnsTransportProtocol.Udp)
        {
            _domainEndPoint = new DomainEndPoint(domain, 53);
            _ipEndPoint     = new IPEndPoint(address, 53);

            _protocol = protocol;

            if (address.AddressFamily == AddressFamily.InterNetworkV6)
            {
                _originalAddress = domain + " ([" + address.ToString() + "])";
            }
            else
            {
                _originalAddress = domain + " (" + address.ToString() + ")";
            }

            ValidateProtocol();
        }
        public NameServerAddress(Uri dohEndPoint, IPAddress address, DnsTransportProtocol protocol = DnsTransportProtocol.Https)
        {
            _dohEndPoint = dohEndPoint;
            _ipEndPoint  = new IPEndPoint(address, _dohEndPoint.Port);

            _protocol = protocol;

            if (address.AddressFamily == AddressFamily.InterNetworkV6)
            {
                _originalAddress = _dohEndPoint.AbsoluteUri + " ([" + address.ToString() + "])";
            }
            else
            {
                _originalAddress = _dohEndPoint.AbsoluteUri + " (" + address.ToString() + ")";
            }

            ValidateProtocol();
        }
        public NameServerAddress(string domain, IPEndPoint ipEndPoint, DnsTransportProtocol protocol = DnsTransportProtocol.Udp)
        {
            _domainEndPoint = new DomainEndPoint(domain, ipEndPoint.Port);
            _ipEndPoint     = ipEndPoint;

            _protocol = protocol;

            if (ipEndPoint.AddressFamily == AddressFamily.InterNetworkV6)
            {
                _originalAddress = domain + " ([" + ipEndPoint.Address.ToString() + "]:" + ipEndPoint.Port + ")";
            }
            else
            {
                _originalAddress = domain + " (" + ipEndPoint.ToString() + ")";
            }

            ValidateProtocol();
        }
示例#23
0
        public void Write(IPEndPoint ep, DnsTransportProtocol protocol, string message)
        {
            string ipInfo;

            if (ep == null)
            {
                ipInfo = "";
            }
            else if (ep.Address.IsIPv4MappedToIPv6)
            {
                ipInfo = "[" + ep.Address.MapToIPv4().ToString() + ":" + ep.Port + "] ";
            }
            else
            {
                ipInfo = "[" + ep.ToString() + "] ";
            }

            Write(ipInfo + "[" + protocol.ToString().ToUpper() + "] " + message);
        }
        private void GuessProtocol()
        {
            if (_dohEndPoint != null)
            {
                _protocol = DnsTransportProtocol.Https;
            }
            else
            {
                switch (Port)
                {
                case 853:
                    _protocol = DnsTransportProtocol.Tls;
                    break;

                default:
                    _protocol = DnsTransportProtocol.Udp;
                    break;
                }
            }
        }
示例#25
0
        public NameServerAddress ChangeProtocol(DnsTransportProtocol protocol)
        {
            NameServerAddress nsAddress = new NameServerAddress();

            switch (protocol)
            {
            case DnsTransportProtocol.Udp:
            case DnsTransportProtocol.Tcp:
                if ((_dohEndPoint is not null) && !IPAddress.TryParse(_dohEndPoint.Host, out _))
                {
                    nsAddress._domainEndPoint = new DomainEndPoint(_dohEndPoint.Host, 53);
                }
                else if (_domainEndPoint is not null)
                {
                    nsAddress._domainEndPoint = new DomainEndPoint(_domainEndPoint.Address, 53);
                }

                if ((_dohEndPoint is not null) && IPAddress.TryParse(_dohEndPoint.Host, out IPAddress address1))
                {
                    nsAddress._ipEndPoint = new IPEndPoint(address1, 53);
                }
示例#26
0
        protected override void Parse(Stream s)
        {
            int b = s.ReadByte();

            if (b < 0)
            {
                throw new EndOfStreamException();
            }

            _protocol = (DnsTransportProtocol)b;

            b = s.ReadByte();
            if (b < 0)
            {
                throw new EndOfStreamException();
            }

            _forwarder = Encoding.ASCII.GetString(s.ReadBytes(b));

            _nameServer = new NameServerAddress(_forwarder, _protocol);
        }
示例#27
0
        /// <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;
            }
        }
示例#28
0
        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 DnsResourceRecordInfo(BinaryReader bR, bool isSoa)
        {
            byte version = bR.ReadByte();

            switch (version)
            {
            case 1:
                _disabled = bR.ReadBoolean();
                break;

            case 2:
            case 3:
            case 4:
            case 5:
            case 6:
            case 7:
                _disabled = bR.ReadBoolean();

                if ((version < 5) && isSoa)
                {
                    //read old glue records as NameServerAddress in case of SOA record
                    int count = bR.ReadByte();
                    if (count > 0)
                    {
                        NameServerAddress[] primaryNameServers = new NameServerAddress[count];

                        for (int i = 0; i < primaryNameServers.Length; i++)
                        {
                            DnsResourceRecord glueRecord = new DnsResourceRecord(bR.BaseStream);

                            IPAddress address;

                            switch (glueRecord.Type)
                            {
                            case DnsResourceRecordType.A:
                                address = (glueRecord.RDATA as DnsARecordData).Address;
                                break;

                            case DnsResourceRecordType.AAAA:
                                address = (glueRecord.RDATA as DnsAAAARecordData).Address;
                                break;

                            default:
                                continue;
                            }

                            primaryNameServers[i] = new NameServerAddress(address);
                        }

                        _primaryNameServers = primaryNameServers;
                    }
                }
                else
                {
                    int count = bR.ReadByte();
                    if (count > 0)
                    {
                        DnsResourceRecord[] glueRecords = new DnsResourceRecord[count];

                        for (int i = 0; i < glueRecords.Length; i++)
                        {
                            glueRecords[i] = new DnsResourceRecord(bR.BaseStream);
                        }

                        _glueRecords = glueRecords;
                    }
                }

                if (version >= 3)
                {
                    _comments = bR.ReadShortString();
                }

                if (version >= 4)
                {
                    _deletedOn = bR.ReadDateTime();
                }

                if (version >= 5)
                {
                    int count = bR.ReadByte();
                    if (count > 0)
                    {
                        NameServerAddress[] primaryNameServers = new NameServerAddress[count];

                        for (int i = 0; i < primaryNameServers.Length; i++)
                        {
                            primaryNameServers[i] = new NameServerAddress(bR);
                        }

                        _primaryNameServers = primaryNameServers;
                    }
                }

                if (version >= 7)
                {
                    _zoneTransferProtocol = (DnsTransportProtocol)bR.ReadByte();

                    _tsigKeyName = bR.ReadShortString();
                }
                else if (version >= 6)
                {
                    _zoneTransferProtocol = (DnsTransportProtocol)bR.ReadByte();

                    _tsigKeyName = bR.ReadShortString();
                    _            = bR.ReadShortString(); //_tsigSharedSecret (obsolete)
                    _            = bR.ReadShortString(); //_tsigAlgorithm (obsolete)
                }

                break;

            default:
                throw new InvalidDataException("DnsResourceRecordInfo format version not supported.");
            }
        }
示例#30
0
        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)));
            }