From f4ea8427229c13422db2e81b49cb1b616cd657cd Mon Sep 17 00:00:00 2001 From: Shreyas Zare Date: Sun, 29 Oct 2023 19:10:33 +0530 Subject: [PATCH] DnsServer: Added zone transfer allowed networks feature. Added blocking bypass list feature. Added separate logger for resolver error logs. Updated implementation to set metadata for requests with details of the local end point. Added support for ALIAS record. Implemented support for IDnsRequestBlockingHandler feature. Code refactoring changes done. --- DnsServerCore/Dns/DnsServer.cs | 322 +++++++++++++++++++++++---------- 1 file changed, 222 insertions(+), 100 deletions(-) diff --git a/DnsServerCore/Dns/DnsServer.cs b/DnsServerCore/Dns/DnsServer.cs index d23715ae..e1a86eca 100644 --- a/DnsServerCore/Dns/DnsServer.cs +++ b/DnsServerCore/Dns/DnsServer.cs @@ -26,6 +26,7 @@ using DnsServerCore.Dns.Zones; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Extensions; using Microsoft.AspNetCore.Server.Kestrel.Core; using Microsoft.AspNetCore.StaticFiles; using Microsoft.Extensions.FileProviders; @@ -120,8 +121,10 @@ namespace DnsServerCore.Dns readonly DnsApplicationManager _dnsApplicationManager; readonly ResolverDnsCache _dnsCache; + readonly ResolverDnsCache _dnsCacheSkipDnsApps; //to prevent request reaching apps again readonly StatsManager _stats; + IReadOnlyCollection _zoneTransferAllowedNetworks; bool _preferIPv6; ushort _udpPayloadSize = DnsDatagram.EDNS_DEFAULT_UDP_PAYLOAD_SIZE; bool _dnssecValidation = true; @@ -181,6 +184,7 @@ namespace DnsServerCore.Dns bool _enableBlocking = true; bool _allowTxtBlockingReport = true; + IReadOnlyCollection _blockingBypassList; DnsServerBlockingType _blockingType = DnsServerBlockingType.NxDomain; IReadOnlyCollection _customBlockingARecords = Array.Empty(); IReadOnlyCollection _customBlockingAAAARecords = Array.Empty(); @@ -191,6 +195,7 @@ namespace DnsServerCore.Dns int _forwarderTimeout = 2000; int _forwarderConcurrency = 2; + LogManager _resolverLog; LogManager _queryLog; Timer _cachePrefetchSamplingTimer; @@ -266,7 +271,8 @@ namespace DnsServerCore.Dns _cacheZoneManager = new CacheZoneManager(this); _dnsApplicationManager = new DnsApplicationManager(this); - _dnsCache = new ResolverDnsCache(_dnsApplicationManager, _authZoneManager, _cacheZoneManager, _log, false); + _dnsCache = new ResolverDnsCache(this, false); + _dnsCacheSkipDnsApps = new ResolverDnsCache(this, true); //to prevent request reaching apps again //init stats _stats = new StatsManager(this); @@ -323,6 +329,7 @@ namespace DnsServerCore.Dns try { + int localPort = (udpListener.LocalEndPoint as IPEndPoint).Port; EndPoint epAny; switch (udpListener.AddressFamily) @@ -339,7 +346,7 @@ namespace DnsServerCore.Dns throw new NotSupportedException("AddressFamily not supported."); } - SocketReceiveFromResult result; + SocketReceiveMessageFromResult result; while (true) { @@ -347,7 +354,7 @@ namespace DnsServerCore.Dns try { - result = await udpListener.ReceiveFromAsync(recvBuffer, SocketFlags.None, epAny); + result = await udpListener.ReceiveMessageFromAsync(recvBuffer, SocketFlags.None, epAny); } catch (SocketException ex) { @@ -395,6 +402,7 @@ namespace DnsServerCore.Dns continue; DnsDatagram request = DnsDatagram.ReadFrom(recvBufferStream); + request.SetMetadata(new NameServerAddress(new IPEndPoint(result.PacketInformation.Address, localPort), DnsTransportProtocol.Udp)); _ = ProcessUdpRequestAsync(udpListener, remoteEP, returnEP, protocol, request); } @@ -572,14 +580,14 @@ namespace DnsServerCore.Dns switch (protocol) { case DnsTransportProtocol.Tcp: - await ReadStreamRequestAsync(new NetworkStream(socket), remoteEP, protocol); + await ReadStreamRequestAsync(new NetworkStream(socket), remoteEP, new NameServerAddress(socket.LocalEndPoint, DnsTransportProtocol.Tcp), protocol); break; case DnsTransportProtocol.Tls: SslStream tlsStream = new SslStream(new NetworkStream(socket)); await tlsStream.AuthenticateAsServerAsync(_sslServerAuthenticationOptions).WithTimeout(_tcpReceiveTimeout); - await ReadStreamRequestAsync(tlsStream, remoteEP, protocol); + await ReadStreamRequestAsync(tlsStream, remoteEP, new NameServerAddress(socket.LocalEndPoint, DnsTransportProtocol.Tls), protocol); break; case DnsTransportProtocol.TcpProxy: @@ -593,7 +601,7 @@ namespace DnsServerCore.Dns ProxyProtocolStream proxyStream = await ProxyProtocolStream.CreateAsServerAsync(new NetworkStream(socket)).WithTimeout(_tcpReceiveTimeout); remoteEP = new IPEndPoint(proxyStream.SourceAddress, proxyStream.SourcePort); - await ReadStreamRequestAsync(proxyStream, remoteEP, protocol); + await ReadStreamRequestAsync(proxyStream, remoteEP, new NameServerAddress(socket.LocalEndPoint, DnsTransportProtocol.Tcp), protocol); break; default: @@ -618,7 +626,7 @@ namespace DnsServerCore.Dns } } - private async Task ReadStreamRequestAsync(Stream stream, IPEndPoint remoteEP, DnsTransportProtocol protocol) + private async Task ReadStreamRequestAsync(Stream stream, IPEndPoint remoteEP, NameServerAddress dnsEP, DnsTransportProtocol protocol) { try { @@ -648,6 +656,7 @@ namespace DnsServerCore.Dns cancellationTokenSource.Cancel(); //cancel delay task request = await task; + request.SetMetadata(dnsEP); } //process request async @@ -740,6 +749,8 @@ namespace DnsServerCore.Dns { try { + NameServerAddress dnsEP = new NameServerAddress(quicConnection.LocalEndPoint, DnsTransportProtocol.Quic); + while (true) { if (IsQpmLimitCrossed(quicConnection.RemoteEndPoint.Address)) @@ -747,7 +758,7 @@ namespace DnsServerCore.Dns QuicStream quicStream = await quicConnection.AcceptInboundStreamAsync(); - _ = ProcessQuicStreamRequestAsync(quicStream, quicConnection.RemoteEndPoint); + _ = ProcessQuicStreamRequestAsync(quicStream, quicConnection.RemoteEndPoint, dnsEP); } } catch (QuicException ex) @@ -774,7 +785,7 @@ namespace DnsServerCore.Dns } } - private async Task ProcessQuicStreamRequestAsync(QuicStream quicStream, IPEndPoint remoteEP) + private async Task ProcessQuicStreamRequestAsync(QuicStream quicStream, IPEndPoint remoteEP, NameServerAddress dnsEP) { MemoryStream sharedBuffer = new MemoryStream(512); DnsDatagram request = null; @@ -796,6 +807,7 @@ namespace DnsServerCore.Dns cancellationTokenSource.Cancel(); //cancel delay task request = await task; + request.SetMetadata(dnsEP); } //process request async @@ -907,6 +919,7 @@ namespace DnsServerCore.Dns using (MemoryStream mS = new MemoryStream(Convert.FromBase64String(dnsRequestBase64Url))) { dnsRequest = DnsDatagram.ReadFrom(mS); + dnsRequest.SetMetadata(new NameServerAddress(new Uri(context.Request.GetDisplayUrl()), context.GetLocalIpAddress(), DnsTransportProtocol.Https)); } break; @@ -925,6 +938,7 @@ namespace DnsServerCore.Dns mS.Position = 0; dnsRequest = DnsDatagram.ReadFrom(mS); + dnsRequest.SetMetadata(new NameServerAddress(new Uri(context.Request.GetDisplayUrl()), context.GetLocalIpAddress(), DnsTransportProtocol.Https)); } break; @@ -1267,12 +1281,12 @@ namespace DnsServerCore.Dns bool IsSpecifiedIpAddressAllowed() { IPAddress remoteAddress = remoteEP.Address; - IReadOnlyCollection specifiedIpAddresses = authZoneInfo.UpdateIpAddresses; + IReadOnlyCollection specifiedIpAddresses = authZoneInfo.UpdateIpAddresses; if (specifiedIpAddresses is not null) { - foreach (IPAddress specifiedIpAddress in specifiedIpAddresses) + foreach (NetworkAddress networkAddress in specifiedIpAddresses) { - if (specifiedIpAddress.Equals(remoteAddress)) + if (networkAddress.Equals(remoteAddress)) return true; } } @@ -1852,12 +1866,12 @@ namespace DnsServerCore.Dns bool IsSpecifiedNameServerAllowed() { IPAddress remoteAddress = remoteEP.Address; - IReadOnlyCollection specifiedNameServers = authZoneInfo.ZoneTransferNameServers; + IReadOnlyCollection specifiedNameServers = authZoneInfo.ZoneTransferNameServers; if (specifiedNameServers is not null) { - foreach (IPAddress specifiedNameServer in specifiedNameServers) + foreach (NetworkAddress specifiedNetwork in specifiedNameServers) { - if (specifiedNameServer.Equals(remoteAddress)) + if (specifiedNetwork.Contains(remoteAddress)) return true; } } @@ -1865,45 +1879,64 @@ namespace DnsServerCore.Dns return false; } - bool isZoneTransferAllowed = false; + bool isInZoneTransferAllowedList = false; - switch (authZoneInfo.ZoneTransfer) + if (_zoneTransferAllowedNetworks is not null) { - case AuthZoneTransfer.Deny: - break; + IPAddress remoteAddress = remoteEP.Address; - case AuthZoneTransfer.Allow: - isZoneTransferAllowed = true; - break; - - case AuthZoneTransfer.AllowOnlyZoneNameServers: - isZoneTransferAllowed = await IsZoneNameServerAllowedAsync(); - break; - - case AuthZoneTransfer.AllowOnlySpecifiedNameServers: - isZoneTransferAllowed = IsSpecifiedNameServerAllowed(); - break; - - case AuthZoneTransfer.AllowBothZoneAndSpecifiedNameServers: - isZoneTransferAllowed = IsSpecifiedNameServerAllowed() || await IsZoneNameServerAllowedAsync(); - break; - } - - if (!isZoneTransferAllowed) - { - _log?.Write(remoteEP, protocol, "DNS Server refused a zone transfer request since the request IP address is not allowed by the zone: " + (authZoneInfo.Name == "" ? "" : authZoneInfo.Name)); - - return new DnsDatagram(request.Identifier, true, DnsOpcode.StandardQuery, false, false, request.RecursionDesired, false, false, false, DnsResponseCode.Refused, request.Question) { Tag = DnsServerResponseType.Authoritative }; - } - - if ((authZoneInfo.ZoneTransferTsigKeyNames is not null) && (authZoneInfo.ZoneTransferTsigKeyNames.Count > 0)) - { - if ((tsigAuthenticatedKeyName is null) || !authZoneInfo.ZoneTransferTsigKeyNames.ContainsKey(tsigAuthenticatedKeyName.ToLower())) + foreach (NetworkAddress networkAddress in _zoneTransferAllowedNetworks) { - _log?.Write(remoteEP, protocol, "DNS Server refused a zone transfer request since the request is missing TSIG auth required by the zone: " + (authZoneInfo.Name == "" ? "" : authZoneInfo.Name)); + if (networkAddress.Contains(remoteAddress)) + { + isInZoneTransferAllowedList = true; + break; + } + } + } + + if (!isInZoneTransferAllowedList) + { + bool isZoneTransferAllowed = false; + + switch (authZoneInfo.ZoneTransfer) + { + case AuthZoneTransfer.Deny: + break; + + case AuthZoneTransfer.Allow: + isZoneTransferAllowed = true; + break; + + case AuthZoneTransfer.AllowOnlyZoneNameServers: + isZoneTransferAllowed = await IsZoneNameServerAllowedAsync(); + break; + + case AuthZoneTransfer.AllowOnlySpecifiedNameServers: + isZoneTransferAllowed = IsSpecifiedNameServerAllowed(); + break; + + case AuthZoneTransfer.AllowBothZoneAndSpecifiedNameServers: + isZoneTransferAllowed = IsSpecifiedNameServerAllowed() || await IsZoneNameServerAllowedAsync(); + break; + } + + if (!isZoneTransferAllowed) + { + _log?.Write(remoteEP, protocol, "DNS Server refused a zone transfer request since the request IP address is not allowed by the zone: " + (authZoneInfo.Name == "" ? "" : authZoneInfo.Name)); return new DnsDatagram(request.Identifier, true, DnsOpcode.StandardQuery, false, false, request.RecursionDesired, false, false, false, DnsResponseCode.Refused, request.Question) { Tag = DnsServerResponseType.Authoritative }; } + + if ((authZoneInfo.ZoneTransferTsigKeyNames is not null) && (authZoneInfo.ZoneTransferTsigKeyNames.Count > 0)) + { + if ((tsigAuthenticatedKeyName is null) || !authZoneInfo.ZoneTransferTsigKeyNames.ContainsKey(tsigAuthenticatedKeyName.ToLower())) + { + _log?.Write(remoteEP, protocol, "DNS Server refused a zone transfer request since the request is missing TSIG auth required by the zone: " + (authZoneInfo.Name == "" ? "" : authZoneInfo.Name)); + + return new DnsDatagram(request.Identifier, true, DnsOpcode.StandardQuery, false, false, request.RecursionDesired, false, false, false, DnsResponseCode.Refused, request.Question) { Tag = DnsServerResponseType.Authoritative }; + } + } } _log?.Write(remoteEP, protocol, "DNS Server received zone transfer request for zone: " + (authZoneInfo.Name == "" ? "" : authZoneInfo.Name)); @@ -1954,6 +1987,7 @@ namespace DnsServerCore.Dns return await ProcessCNAMEAsync(request, remoteEP, response, isRecursionAllowed, protocol, false, skipDnsAppAuthoritativeRequestHandlers); case DnsResourceRecordType.ANAME: + case DnsResourceRecordType.ALIAS: return await ProcessANAMEAsync(request, remoteEP, response, isRecursionAllowed, protocol, skipDnsAppAuthoritativeRequestHandlers); } } @@ -2164,7 +2198,7 @@ namespace DnsServerCore.Dns break; } } - else if ((newResponse.Answer.Count > 0) && (newResponse.GetLastAnswerRecord().Type == DnsResourceRecordType.ANAME)) + else if ((newResponse.Answer.Count > 0) && (newResponse.GetLastAnswerRecord() is DnsResourceRecord lastAnswer) && ((lastAnswer.Type == DnsResourceRecordType.ANAME) || (lastAnswer.Type == DnsResourceRecordType.ALIAS))) { newResponse = await ProcessANAMEAsync(request, remoteEP, newResponse, isRecursionAllowed, protocol, skipDnsAppAuthoritativeRequestHandlers); } @@ -2221,11 +2255,11 @@ namespace DnsServerCore.Dns } } + newAnswer.AddRange(newResponse.Answer); + if (foundRepeat) break; //loop detected - newAnswer.AddRange(newResponse.Answer); - lastResponse = newResponse; } while (++queryCount < MAX_CNAME_HOPS); @@ -2351,31 +2385,33 @@ namespace DnsServerCore.Dns return answers; } - if (lastRR.Type == DnsResourceRecordType.ANAME) + switch (lastRR.Type) { - if (newResponse.Answer.Count == 1) - { - lastDomain = (lastRR.RDATA as DnsANAMERecordData).Domain; - } - else - { - //resolve multiple ANAME records async - queryCount++; //increment since one query was done already + case DnsResourceRecordType.ANAME: + case DnsResourceRecordType.ALIAS: + if (newResponse.Answer.Count == 1) + { + lastDomain = (lastRR.RDATA as DnsANAMERecordData).Domain; + } + else + { + //resolve multiple ANAME records async + queryCount++; //increment since one query was done already - foreach (DnsResourceRecord newAnswer in newResponse.Answer) - resolveQueue.Enqueue(ResolveANAMEAsync(newAnswer, queryCount)); + foreach (DnsResourceRecord newAnswer in newResponse.Answer) + resolveQueue.Enqueue(ResolveANAMEAsync(newAnswer, queryCount)); + return Array.Empty(); + } + break; + + case DnsResourceRecordType.CNAME: + lastDomain = (lastRR.RDATA as DnsCNAMERecordData).Domain; + break; + + default: + //aname/cname was resolved, but no answer found return Array.Empty(); - } - } - else if (lastRR.Type == DnsResourceRecordType.CNAME) - { - lastDomain = (lastRR.RDATA as DnsCNAMERecordData).Domain; - } - else - { - //aname/cname was resolved, but no answer found - return Array.Empty(); } } while (++queryCount < MAX_CNAME_HOPS); @@ -2388,14 +2424,18 @@ namespace DnsServerCore.Dns foreach (DnsResourceRecord answer in response.Answer) { - if (answer.Type == DnsResourceRecordType.ANAME) + switch (answer.Type) { - resolveQueue.Enqueue(ResolveANAMEAsync(answer)); - } - else - { - if (resolveQueue.Count == 0) - responseAnswer.Add(answer); + case DnsResourceRecordType.ANAME: + case DnsResourceRecordType.ALIAS: + resolveQueue.Enqueue(ResolveANAMEAsync(answer)); + break; + + default: + if (resolveQueue.Count == 0) + responseAnswer.Add(answer); + + break; } } @@ -2434,7 +2474,7 @@ namespace DnsServerCore.Dns return new DnsDatagram(request.Identifier, true, DnsOpcode.StandardQuery, true, false, request.RecursionDesired, isRecursionAllowed, false, false, rcode, request.Question, responseAnswer, authority, null) { Tag = response.Tag }; } - private DnsDatagram ProcessBlockedQuery(DnsDatagram request) + private DnsDatagram ProcessBlocked(DnsDatagram request) { DnsDatagram response = _blockedZoneManager.Query(request); if (response is null) @@ -2549,27 +2589,88 @@ namespace DnsServerCore.Dns } } + private async Task IsAllowedAsync(DnsDatagram request, IPEndPoint remoteEP, DnsTransportProtocol protocol) + { + if (_enableBlocking) + { + if (_blockingBypassList is not null) + { + IPAddress remoteIP = remoteEP.Address; + + foreach (NetworkAddress network in _blockingBypassList) + { + if (network.Contains(remoteIP)) + return true; + } + } + + if (_allowedZoneManager.IsAllowed(request) || _blockListZoneManager.IsAllowed(request)) + return true; + } + + foreach (IDnsRequestBlockingHandler blockingHandler in _dnsApplicationManager.DnsRequestBlockingHandlers) + { + try + { + if (await blockingHandler.IsAllowedAsync(request, remoteEP)) + return true; + } + catch (Exception ex) + { + _log?.Write(remoteEP, protocol, ex); + } + } + + return false; + } + + private async Task ProcessBlockedQueryAsync(DnsDatagram request, IPEndPoint remoteEP, DnsTransportProtocol protocol) + { + if (_enableBlocking) + { + DnsDatagram blockedResponse = ProcessBlocked(request); + if (blockedResponse is not null) + return blockedResponse; + } + + foreach (IDnsRequestBlockingHandler blockingHandler in _dnsApplicationManager.DnsRequestBlockingHandlers) + { + try + { + DnsDatagram appBlockedResponse = await blockingHandler.ProcessRequestAsync(request, remoteEP); + if (appBlockedResponse is not null) + { + if (appBlockedResponse.Tag is null) + appBlockedResponse.Tag = DnsServerResponseType.Blocked; + + return appBlockedResponse; + } + } + catch (Exception ex) + { + _log?.Write(remoteEP, protocol, ex); + } + } + + return null; + } + private async Task ProcessRecursiveQueryAsync(DnsDatagram request, IPEndPoint remoteEP, DnsTransportProtocol protocol, IReadOnlyList conditionalForwarders, bool dnssecValidation, bool cacheRefreshOperation, bool skipDnsAppAuthoritativeRequestHandlers) { - bool inAllowedZone; + bool isAllowed; if (cacheRefreshOperation) { //cache refresh operation should be able to refresh all the records in cache //this is since a blocked CNAME record could still be used by an allowed domain name and so must resolve - inAllowedZone = true; - } - else if (!_enableBlocking) - { - inAllowedZone = true; + isAllowed = true; } else { - inAllowedZone = _allowedZoneManager.IsAllowed(request) || _blockListZoneManager.IsAllowed(request); - if (!inAllowedZone) + isAllowed = await IsAllowedAsync(request, remoteEP, protocol); + if (!isAllowed) { - //check in blocked zone and block list zone - DnsDatagram blockedResponse = ProcessBlockedQuery(request); + DnsDatagram blockedResponse = await ProcessBlockedQueryAsync(request, remoteEP, protocol); if (blockedResponse is not null) return blockedResponse; } @@ -2585,7 +2686,7 @@ namespace DnsServerCore.Dns if ((lastRR.Type != questionType) && (lastRR.Type == DnsResourceRecordType.CNAME) && (questionType != DnsResourceRecordType.ANY)) response = await ProcessCNAMEAsync(request, remoteEP, response, true, protocol, cacheRefreshOperation, skipDnsAppAuthoritativeRequestHandlers); - if (!inAllowedZone) + if (!isAllowed) { //check for CNAME cloaking for (int i = 0; i < response.Answer.Count; i++) @@ -2597,13 +2698,16 @@ namespace DnsServerCore.Dns DnsDatagram newRequest = new DnsDatagram(0, false, DnsOpcode.StandardQuery, false, false, true, false, false, false, DnsResponseCode.NoError, new DnsQuestionRecord[] { new DnsQuestionRecord((record.RDATA as DnsCNAMERecordData).Domain, request.Question[0].Type, request.Question[0].Class) }, null, null, null, _udpPayloadSize); + if (request.Metadata is not null) + newRequest.SetMetadata(request.Metadata.NameServer); + //check allowed zone - inAllowedZone = _allowedZoneManager.IsAllowed(newRequest) || _blockListZoneManager.IsAllowed(newRequest); - if (inAllowedZone) + isAllowed = await IsAllowedAsync(newRequest, remoteEP, protocol); + if (isAllowed) break; //CNAME is in allowed zone //check blocked zone and block list zone - DnsDatagram blockedResponse = ProcessBlockedQuery(newRequest); + DnsDatagram blockedResponse = await ProcessBlockedQueryAsync(newRequest, remoteEP, protocol); if (blockedResponse is not null) { //found cname cloaking @@ -2810,9 +2914,9 @@ namespace DnsServerCore.Dns IDnsCache dnsCache; if (cachePrefetchOperation || cacheRefreshOperation) - dnsCache = new ResolverPrefetchDnsCache(_dnsApplicationManager, _authZoneManager, _cacheZoneManager, _log, skipDnsAppAuthoritativeRequestHandlers, question); + dnsCache = new ResolverPrefetchDnsCache(this, skipDnsAppAuthoritativeRequestHandlers, question); else if (skipDnsAppAuthoritativeRequestHandlers || conditionalForwardingClientSubnet) - dnsCache = new ResolverDnsCache(_dnsApplicationManager, _authZoneManager, _cacheZoneManager, _log, true); //to prevent request reaching apps again + dnsCache = _dnsCacheSkipDnsApps; //to prevent request reaching apps again else dnsCache = _dnsCache; @@ -2981,7 +3085,7 @@ namespace DnsServerCore.Dns } catch (Exception ex) { - if (_log is not null) + if (_resolverLog is not null) { string strForwarders = null; @@ -3008,7 +3112,7 @@ namespace DnsServerCore.Dns } } - _log.Write("DNS Server failed to resolve the request '" + question.ToString() + "'" + (strForwarders is null ? "" : " using forwarders: " + strForwarders) + ".\r\n" + ex.ToString()); + _resolverLog.Write("DNS Server failed to resolve the request '" + question.ToString() + "'" + (strForwarders is null ? "" : " using forwarders: " + strForwarders) + ".\r\n" + ex.ToString()); } if (_serveStale) @@ -3415,7 +3519,7 @@ namespace DnsServerCore.Dns } catch (Exception ex) { - _log?.Write(ex); + _resolverLog?.Write(ex); } } @@ -3445,7 +3549,7 @@ namespace DnsServerCore.Dns } catch (Exception ex) { - _log?.Write(ex); + _resolverLog?.Write(ex); cacheRefreshSampleList[sampleQuestionIndex] = sample; //put back into sample list to allow refreshing it again } @@ -3684,7 +3788,7 @@ namespace DnsServerCore.Dns } } - private bool IsQpmLimitCrossed(IPAddress remoteIP) + internal bool IsQpmLimitCrossed(IPAddress remoteIP) { if ((_qpmLimitRequests < 1) && (_qpmLimitErrors < 1)) return false; @@ -4444,6 +4548,12 @@ namespace DnsServerCore.Dns public StatsManager StatsManager { get { return _stats; } } + public IReadOnlyCollection ZoneTransferAllowedNetworks + { + get { return _zoneTransferAllowedNetworks; } + set { _zoneTransferAllowedNetworks = value; } + } + public bool PreferIPv6 { get { return _preferIPv6; } @@ -4980,6 +5090,12 @@ namespace DnsServerCore.Dns set { _allowTxtBlockingReport = value; } } + public IReadOnlyCollection BlockingBypassList + { + get { return _blockingBypassList; } + set { _blockingBypassList = value; } + } + public DnsServerBlockingType BlockingType { get { return _blockingType; } @@ -5058,6 +5174,12 @@ namespace DnsServerCore.Dns } } + public LogManager ResolverLogManager + { + get { return _resolverLog; } + set { _resolverLog = value; } + } + public LogManager QueryLogManager { get { return _queryLog; }