From 8d43f71fc79758ea22fab9cf53862168cb20f4ee Mon Sep 17 00:00:00 2001 From: Shreyas Zare Date: Sat, 13 Jun 2020 16:34:26 +0530 Subject: [PATCH] DnsServer: fixed AXFR permission issue in ProcessZoneTransferQuery() by checking remote ip against glue addresses for name servers. --- DnsServerCore/Dns/DnsServer.cs | 121 +++++++++++++++++++++------------ 1 file changed, 78 insertions(+), 43 deletions(-) diff --git a/DnsServerCore/Dns/DnsServer.cs b/DnsServerCore/Dns/DnsServer.cs index e496ae8e..9ceed5c7 100644 --- a/DnsServerCore/Dns/DnsServer.cs +++ b/DnsServerCore/Dns/DnsServer.cs @@ -17,6 +17,7 @@ along with this program. If not, see . */ +using DnsServerCore.Dns.ResourceRecords; using DnsServerCore.Dns.ZoneManagers; using DnsServerCore.Dns.Zones; using Newtonsoft.Json; @@ -981,63 +982,97 @@ namespace DnsServerCore.Dns if (axfrRecords.Count == 0) return new DnsDatagram(request.Identifier, true, DnsOpcode.StandardQuery, false, false, request.RecursionDesired, false, false, false, DnsResponseCode.Refused, request.Question) { Tag = StatsResponseType.Authoritative }; - bool isAxfrAllowed = false; - DnsResourceRecordType type; - - switch (remoteEP.AddressFamily) - { - case AddressFamily.InterNetwork: - type = DnsResourceRecordType.A; - break; - - case AddressFamily.InterNetworkV6: - type = DnsResourceRecordType.AAAA; - break; - - default: - throw new NotSupportedException("AddressFamily not supported."); - } - IPAddress remoteAddress = (remoteEP as IPEndPoint).Address; - if (IPAddress.IsLoopback(remoteAddress)) + bool isAxfrAllowed = IPAddress.IsLoopback(remoteAddress); + + if (!isAxfrAllowed) { - isAxfrAllowed = true; - } - else - { - foreach (DnsResourceRecord rr in axfrRecords) + //check glue records + foreach (DnsResourceRecord nsRecord in axfrRecords) { - if (rr.Type == DnsResourceRecordType.NS) + if (nsRecord.Type != DnsResourceRecordType.NS) + continue; + + foreach (DnsResourceRecord glueRecord in nsRecord.GetGlueRecords()) { - string nameServer = (rr.RDATA as DnsNSRecord).NameServer; + IPAddress address; - try + switch (glueRecord.Type) { - DnsDatagram response = DirectQuery(new DnsQuestionRecord(nameServer, type, DnsClass.IN)); - if (response == null) + case DnsResourceRecordType.A: + address = (glueRecord.RDATA as DnsARecord).Address; + break; + + case DnsResourceRecordType.AAAA: + address = (glueRecord.RDATA as DnsAAAARecord).Address; + break; + + default: continue; + } - IReadOnlyList addresses; + if (remoteAddress.Equals(address)) + { + isAxfrAllowed = true; + break; + } + } - if (type == DnsResourceRecordType.A) - addresses = DnsClient.ParseResponseA(response); - else - addresses = DnsClient.ParseResponseAAAA(response); + if (isAxfrAllowed) + break; + } + } - foreach (IPAddress address in addresses) + if (!isAxfrAllowed) + { + //check resolved address + DnsResourceRecordType type; + + switch (remoteEP.AddressFamily) + { + case AddressFamily.InterNetwork: + type = DnsResourceRecordType.A; + break; + + case AddressFamily.InterNetworkV6: + type = DnsResourceRecordType.AAAA; + break; + + default: + throw new NotSupportedException("AddressFamily not supported."); + } + + foreach (DnsResourceRecord nsRecord in axfrRecords) + { + if (nsRecord.Type != DnsResourceRecordType.NS) + continue; + + try + { + DnsDatagram response = DirectQuery(new DnsQuestionRecord((nsRecord.RDATA as DnsNSRecord).NameServer, type, DnsClass.IN)); + if (response == null) + continue; + + IReadOnlyList addresses; + + if (type == DnsResourceRecordType.A) + addresses = DnsClient.ParseResponseA(response); + else + addresses = DnsClient.ParseResponseAAAA(response); + + foreach (IPAddress address in addresses) + { + if (remoteAddress.Equals(address)) { - if (remoteAddress.Equals(address)) - { - isAxfrAllowed = true; - break; - } + isAxfrAllowed = true; + break; } } - catch - { - //ignore error - } + } + catch + { + //ignore error } if (isAxfrAllowed)