Files
DnsServer-TechnitiumSoftware/DnsServerCore/DnsWebServiceLegacy.cs

1429 lines
56 KiB
C#

/*
Technitium DNS Server
Copyright (C) 2025 Shreyas Zare (shreyas@technitium.com)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using DnsServerCore.Dns;
using DnsServerCore.Dns.ZoneManagers;
using DnsServerCore.Dns.Zones;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Mail;
using System.Net.Sockets;
using System.Text;
using TechnitiumLibrary.IO;
using TechnitiumLibrary.Net;
using TechnitiumLibrary.Net.Dns;
using TechnitiumLibrary.Net.Dns.ClientConnection;
using TechnitiumLibrary.Net.Dns.ResourceRecords;
using TechnitiumLibrary.Net.Proxy;
namespace DnsServerCore
{
public partial class DnsWebService
{
#region legacy config
private bool TryLoadOldConfigFile()
{
string configFile = Path.Combine(_configFolder, "dns.config");
try
{
using (FileStream fS = new FileStream(configFile, FileMode.Open, FileAccess.Read))
{
if (TryLoadOldConfigFrom(fS))
{
_log.Write("Old DNS config file was loaded: " + configFile);
return true;
}
}
}
catch (FileNotFoundException)
{
//do nothing
}
catch (Exception ex)
{
_log.Write("DNS Server encountered an error while trying to load old DNS config file: " + configFile + "\r\n" + ex.ToString());
}
return false;
}
private bool TryLoadOldConfigFrom(Stream s)
{
BinaryReader bR = new BinaryReader(s);
if (Encoding.ASCII.GetString(bR.ReadBytes(2)) == "DS")
{
int version = bR.ReadByte();
ReadOldConfigFrom(bR, version);
s.Dispose();
_dnsServer.SaveConfigFileInternal();
return true;
}
return false;
}
private void ReadOldConfigFrom(BinaryReader bR, int version)
{
if ((version >= 28) && (version <= 42))
{
ReadConfigFromV42(bR, version);
}
else if ((version >= 2) && (version <= 27))
{
ReadConfigFromV27(bR, version);
//new default settings
DnsClientConnection.IPv4SourceAddresses = null;
DnsClientConnection.IPv6SourceAddresses = null;
_dnsServer.EnableUdpSocketPool = Environment.OSVersion.Platform == PlatformID.Win32NT;
UdpClientConnection.SocketPoolExcludedPorts = [(ushort)_webServiceTlsPort];
_dnsServer.MaxConcurrentResolutionsPerCore = 100;
_dnsServer.DnsApplicationManager.EnableAutomaticUpdate = true;
_webServiceEnableHttp3 = _webServiceEnableTls && IsQuicSupported();
_dnsServer.EnableDnsOverHttp3 = _dnsServer.EnableDnsOverHttps && IsQuicSupported();
_webServiceRealIpHeader = "X-Real-IP";
_dnsServer.DnsOverHttpRealIpHeader = "X-Real-IP";
_dnsServer.DefaultResponsiblePerson = null;
_dnsServer.AuthZoneManager.UseSoaSerialDateScheme = false;
_dnsServer.AuthZoneManager.MinSoaRefresh = 300;
_dnsServer.AuthZoneManager.MinSoaRetry = 300;
_dnsServer.ZoneTransferAllowedNetworks = null;
_dnsServer.NotifyAllowedNetworks = null;
_dnsServer.EDnsClientSubnet = false;
_dnsServer.EDnsClientSubnetIPv4PrefixLength = 24;
_dnsServer.EDnsClientSubnetIPv6PrefixLength = 56;
_dnsServer.EDnsClientSubnetIpv4Override = null;
_dnsServer.EDnsClientSubnetIpv6Override = null;
_dnsServer.QpmLimitBypassList = null;
if (_dnsServer.EnableDnsOverUdpProxy || _dnsServer.EnableDnsOverTcpProxy || _dnsServer.EnableDnsOverHttp)
{
_dnsServer.ReverseProxyNetworkACL =
[
new NetworkAccessControl(IPAddress.Parse("127.0.0.0"), 8),
new NetworkAccessControl(IPAddress.Parse("10.0.0.0"), 8),
new NetworkAccessControl(IPAddress.Parse("100.64.0.0"), 10),
new NetworkAccessControl(IPAddress.Parse("169.254.0.0"), 16),
new NetworkAccessControl(IPAddress.Parse("172.16.0.0"), 12),
new NetworkAccessControl(IPAddress.Parse("192.168.0.0"), 16),
new NetworkAccessControl(IPAddress.Parse("2000::"), 3, true),
new NetworkAccessControl(IPAddress.IPv6Any, 0)
];
}
_dnsServer.BlockingBypassList = null;
_dnsServer.BlockingAnswerTtl = 30;
_dnsServer.ResolverConcurrency = 2;
_dnsServer.CacheZoneManager.ServeStaleAnswerTtl = CacheZoneManager.SERVE_STALE_ANSWER_TTL;
_dnsServer.CacheZoneManager.ServeStaleResetTtl = CacheZoneManager.SERVE_STALE_RESET_TTL;
_dnsServer.ServeStaleMaxWaitTime = DnsServer.SERVE_STALE_MAX_WAIT_TIME;
_dnsServer.ConcurrentForwarding = true;
_dnsServer.ResolverLogManager = _log;
_dnsServer.StatsManager.EnableInMemoryStats = false;
}
else
{
throw new InvalidDataException("DNS Server config version not supported.");
}
}
private void ReadConfigFromV42(BinaryReader bR, int version)
{
//web service
{
_webServiceHttpPort = bR.ReadInt32();
_webServiceTlsPort = bR.ReadInt32();
{
int count = bR.ReadByte();
if (count > 0)
{
IPAddress[] localAddresses = new IPAddress[count];
for (int i = 0; i < count; i++)
localAddresses[i] = IPAddressExtensions.ReadFrom(bR);
_webServiceLocalAddresses = localAddresses;
}
else
{
_webServiceLocalAddresses = new IPAddress[] { IPAddress.Any, IPAddress.IPv6Any };
}
}
_webServiceEnableTls = bR.ReadBoolean();
if (version >= 33)
_webServiceEnableHttp3 = bR.ReadBoolean();
else
_webServiceEnableHttp3 = _webServiceEnableTls && IsQuicSupported();
_webServiceHttpToTlsRedirect = bR.ReadBoolean();
_webServiceUseSelfSignedTlsCertificate = bR.ReadBoolean();
_webServiceTlsCertificatePath = bR.ReadShortString();
_webServiceTlsCertificatePassword = bR.ReadShortString();
if (_webServiceTlsCertificatePath.Length == 0)
_webServiceTlsCertificatePath = null;
if (_webServiceTlsCertificatePath is null)
{
StopTlsCertificateUpdateTimer();
}
else
{
string webServiceTlsCertificatePath = ConvertToAbsolutePath(_webServiceTlsCertificatePath);
try
{
LoadWebServiceTlsCertificate(webServiceTlsCertificatePath, _webServiceTlsCertificatePassword);
}
catch (Exception ex)
{
_log.Write("DNS Server encountered an error while loading Web Service TLS certificate: " + webServiceTlsCertificatePath + "\r\n" + ex.ToString());
}
StartTlsCertificateUpdateTimer();
}
CheckAndLoadSelfSignedCertificate(false, false);
if (version >= 38)
_webServiceRealIpHeader = bR.ReadShortString();
else
_webServiceRealIpHeader = "X-Real-IP";
}
//dns
{
//general
_dnsServer.ServerDomain = bR.ReadShortString();
{
int count = bR.ReadByte();
if (count > 0)
{
List<IPEndPoint> localEndPoints = new List<IPEndPoint>(count);
for (int i = 0; i < count; i++)
{
IPEndPoint ep = EndPointExtensions.ReadFrom(bR) as IPEndPoint;
if (ep.Port == 853)
continue; //to avoid validation exception
localEndPoints.Add(ep);
}
_dnsServer.LocalEndPoints = localEndPoints;
}
else
{
_dnsServer.LocalEndPoints = new IPEndPoint[] { new IPEndPoint(IPAddress.Any, 53), new IPEndPoint(IPAddress.IPv6Any, 53) };
}
}
if (version >= 34)
{
DnsClientConnection.IPv4SourceAddresses = AuthZoneInfo.ReadNetworkAddressesFrom(bR);
DnsClientConnection.IPv6SourceAddresses = AuthZoneInfo.ReadNetworkAddressesFrom(bR);
}
else
{
DnsClientConnection.IPv4SourceAddresses = null;
DnsClientConnection.IPv6SourceAddresses = null;
}
_dnsServer.AuthZoneManager.DefaultRecordTtl = bR.ReadUInt32();
if (version >= 36)
{
string rp = bR.ReadString();
if (rp.Length == 0)
_dnsServer.DefaultResponsiblePerson = null;
else
_dnsServer.DefaultResponsiblePerson = new MailAddress(rp);
}
else
{
_dnsServer.DefaultResponsiblePerson = null;
}
if (version >= 33)
_dnsServer.AuthZoneManager.UseSoaSerialDateScheme = bR.ReadBoolean();
else
_dnsServer.AuthZoneManager.UseSoaSerialDateScheme = false;
if (version >= 40)
{
_dnsServer.AuthZoneManager.MinSoaRefresh = bR.ReadUInt32();
_dnsServer.AuthZoneManager.MinSoaRetry = bR.ReadUInt32();
}
else
{
_dnsServer.AuthZoneManager.MinSoaRefresh = 300;
_dnsServer.AuthZoneManager.MinSoaRetry = 300;
}
if (version >= 33)
_dnsServer.ZoneTransferAllowedNetworks = AuthZoneInfo.ReadNetworkAddressesFrom(bR);
else
_dnsServer.ZoneTransferAllowedNetworks = null;
if (version >= 34)
_dnsServer.NotifyAllowedNetworks = AuthZoneInfo.ReadNetworkAddressesFrom(bR);
else
_dnsServer.NotifyAllowedNetworks = null;
_dnsServer.DnsApplicationManager.EnableAutomaticUpdate = bR.ReadBoolean();
_dnsServer.PreferIPv6 = bR.ReadBoolean();
if (version >= 42)
{
_dnsServer.EnableUdpSocketPool = bR.ReadBoolean();
int count = bR.ReadUInt16();
ushort[] socketPoolExcludedPorts = new ushort[count];
for (int i = 0; i < count; i++)
socketPoolExcludedPorts[i] = bR.ReadUInt16();
UdpClientConnection.SocketPoolExcludedPorts = socketPoolExcludedPorts;
}
else
{
_dnsServer.EnableUdpSocketPool = Environment.OSVersion.Platform == PlatformID.Win32NT;
UdpClientConnection.SocketPoolExcludedPorts = [(ushort)_webServiceTlsPort];
}
_dnsServer.UdpPayloadSize = bR.ReadUInt16();
_dnsServer.DnssecValidation = bR.ReadBoolean();
if (version >= 29)
{
_dnsServer.EDnsClientSubnet = bR.ReadBoolean();
_dnsServer.EDnsClientSubnetIPv4PrefixLength = bR.ReadByte();
_dnsServer.EDnsClientSubnetIPv6PrefixLength = bR.ReadByte();
}
else
{
_dnsServer.EDnsClientSubnet = false;
_dnsServer.EDnsClientSubnetIPv4PrefixLength = 24;
_dnsServer.EDnsClientSubnetIPv6PrefixLength = 56;
}
if (version >= 35)
{
if (bR.ReadBoolean())
_dnsServer.EDnsClientSubnetIpv4Override = NetworkAddress.ReadFrom(bR);
else
_dnsServer.EDnsClientSubnetIpv4Override = null;
if (bR.ReadBoolean())
_dnsServer.EDnsClientSubnetIpv6Override = NetworkAddress.ReadFrom(bR);
else
_dnsServer.EDnsClientSubnetIpv6Override = null;
}
else
{
_dnsServer.EDnsClientSubnetIpv4Override = null;
_dnsServer.EDnsClientSubnetIpv6Override = null;
}
if (version >= 42)
{
{
int count = bR.ReadByte();
Dictionary<int, (int, int)> qpmPrefixLimitsIPv4 = new Dictionary<int, (int, int)>(count);
for (int i = 0; i < count; i++)
qpmPrefixLimitsIPv4.Add(bR.ReadInt32(), (bR.ReadInt32(), bR.ReadInt32()));
_dnsServer.QpmPrefixLimitsIPv4 = qpmPrefixLimitsIPv4;
}
{
int count = bR.ReadByte();
Dictionary<int, (int, int)> qpmPrefixLimitsIPv6 = new Dictionary<int, (int, int)>(count);
for (int i = 0; i < count; i++)
qpmPrefixLimitsIPv6.Add(bR.ReadInt32(), (bR.ReadInt32(), bR.ReadInt32()));
_dnsServer.QpmPrefixLimitsIPv6 = qpmPrefixLimitsIPv6;
}
_dnsServer.QpmLimitSampleMinutes = bR.ReadInt32();
_dnsServer.QpmLimitUdpTruncationPercentage = bR.ReadInt32();
}
else
{
int qpmLimitRequests = bR.ReadInt32();
_ = bR.ReadInt32(); //obsolete qpmLimitErrors
int qpmLimitSampleMinutes = bR.ReadInt32();
int qpmLimitIPv4PrefixLength = bR.ReadInt32();
int qpmLimitIPv6PrefixLength = bR.ReadInt32();
_dnsServer.QpmPrefixLimitsIPv4 = new Dictionary<int, (int, int)>()
{
{ qpmLimitIPv4PrefixLength, (qpmLimitRequests, qpmLimitRequests) }
};
_dnsServer.QpmPrefixLimitsIPv6 = new Dictionary<int, (int, int)>()
{
{ qpmLimitIPv6PrefixLength, (qpmLimitRequests, qpmLimitRequests) }
};
_dnsServer.QpmLimitSampleMinutes = qpmLimitSampleMinutes;
_dnsServer.QpmLimitUdpTruncationPercentage = 0;
}
if (version >= 34)
_dnsServer.QpmLimitBypassList = AuthZoneInfo.ReadNetworkAddressesFrom(bR);
else
_dnsServer.QpmLimitBypassList = null;
_dnsServer.ClientTimeout = bR.ReadInt32();
if (version < 34)
{
if (_dnsServer.ClientTimeout == 4000)
_dnsServer.ClientTimeout = 2000;
}
_dnsServer.TcpSendTimeout = bR.ReadInt32();
_dnsServer.TcpReceiveTimeout = bR.ReadInt32();
if (version >= 30)
{
_dnsServer.QuicIdleTimeout = bR.ReadInt32();
_dnsServer.QuicMaxInboundStreams = bR.ReadInt32();
_dnsServer.ListenBacklog = bR.ReadInt32();
}
else
{
_dnsServer.QuicIdleTimeout = 60000;
_dnsServer.QuicMaxInboundStreams = 100;
_dnsServer.ListenBacklog = 100;
}
if (version >= 40)
_dnsServer.MaxConcurrentResolutionsPerCore = bR.ReadUInt16();
else
_dnsServer.MaxConcurrentResolutionsPerCore = 100;
//optional protocols
if (version >= 32)
{
_dnsServer.EnableDnsOverUdpProxy = bR.ReadBoolean();
_dnsServer.EnableDnsOverTcpProxy = bR.ReadBoolean();
}
else
{
_dnsServer.EnableDnsOverUdpProxy = false;
_dnsServer.EnableDnsOverTcpProxy = false;
}
_dnsServer.EnableDnsOverHttp = bR.ReadBoolean();
_dnsServer.EnableDnsOverTls = bR.ReadBoolean();
_dnsServer.EnableDnsOverHttps = bR.ReadBoolean();
if (version >= 37)
_dnsServer.EnableDnsOverHttp3 = bR.ReadBoolean();
else
_dnsServer.EnableDnsOverHttp3 = _dnsServer.EnableDnsOverHttps && IsQuicSupported();
if (version >= 32)
{
_dnsServer.EnableDnsOverQuic = bR.ReadBoolean();
_dnsServer.DnsOverUdpProxyPort = bR.ReadInt32();
_dnsServer.DnsOverTcpProxyPort = bR.ReadInt32();
_dnsServer.DnsOverHttpPort = bR.ReadInt32();
_dnsServer.DnsOverTlsPort = bR.ReadInt32();
_dnsServer.DnsOverHttpsPort = bR.ReadInt32();
_dnsServer.DnsOverQuicPort = bR.ReadInt32();
}
else if (version >= 31)
{
_dnsServer.EnableDnsOverQuic = bR.ReadBoolean();
_dnsServer.DnsOverHttpPort = bR.ReadInt32();
_dnsServer.DnsOverTlsPort = bR.ReadInt32();
_dnsServer.DnsOverHttpsPort = bR.ReadInt32();
_dnsServer.DnsOverQuicPort = bR.ReadInt32();
}
else if (version >= 30)
{
_ = bR.ReadBoolean(); //removed EnableDnsOverHttpPort80 value
_dnsServer.EnableDnsOverQuic = bR.ReadBoolean();
_dnsServer.DnsOverHttpPort = bR.ReadInt32();
_dnsServer.DnsOverTlsPort = bR.ReadInt32();
_dnsServer.DnsOverHttpsPort = bR.ReadInt32();
_dnsServer.DnsOverQuicPort = bR.ReadInt32();
}
else
{
_dnsServer.EnableDnsOverQuic = false;
_dnsServer.DnsOverUdpProxyPort = 538;
_dnsServer.DnsOverTcpProxyPort = 538;
if (_dnsServer.EnableDnsOverHttps)
{
_dnsServer.EnableDnsOverHttp = true;
_dnsServer.DnsOverHttpPort = 80;
}
else if (_dnsServer.EnableDnsOverHttp)
{
_dnsServer.DnsOverHttpPort = 8053;
}
else
{
_dnsServer.DnsOverHttpPort = 80;
}
_dnsServer.DnsOverTlsPort = 853;
_dnsServer.DnsOverHttpsPort = 443;
_dnsServer.DnsOverQuicPort = 853;
}
if (version >= 39)
{
_dnsServer.ReverseProxyNetworkACL = AuthZoneInfo.ReadNetworkACLFrom(bR);
}
else
{
if (_dnsServer.EnableDnsOverUdpProxy || _dnsServer.EnableDnsOverTcpProxy || _dnsServer.EnableDnsOverHttp)
{
_dnsServer.ReverseProxyNetworkACL =
[
new NetworkAccessControl(IPAddress.Parse("127.0.0.0"), 8),
new NetworkAccessControl(IPAddress.Parse("10.0.0.0"), 8),
new NetworkAccessControl(IPAddress.Parse("100.64.0.0"), 10),
new NetworkAccessControl(IPAddress.Parse("169.254.0.0"), 16),
new NetworkAccessControl(IPAddress.Parse("172.16.0.0"), 12),
new NetworkAccessControl(IPAddress.Parse("192.168.0.0"), 16),
new NetworkAccessControl(IPAddress.Parse("2000::"), 3, true),
new NetworkAccessControl(IPAddress.IPv6Any, 0)
];
}
}
string dnsTlsCertificatePath = bR.ReadShortString();
string dnsTlsCertificatePassword = bR.ReadShortString();
if (dnsTlsCertificatePath.Length == 0)
dnsTlsCertificatePath = null;
if (dnsTlsCertificatePath is null)
_dnsServer.RemoveDnsTlsCertificate();
else
_dnsServer.SetDnsTlsCertificate(dnsTlsCertificatePath, dnsTlsCertificatePassword);
if (version >= 38)
_dnsServer.DnsOverHttpRealIpHeader = bR.ReadShortString();
else
_dnsServer.DnsOverHttpRealIpHeader = "X-Real-IP";
//tsig
{
int count = bR.ReadByte();
Dictionary<string, TsigKey> tsigKeys = new Dictionary<string, TsigKey>(count);
for (int i = 0; i < count; i++)
{
string keyName = bR.ReadShortString();
string sharedSecret = bR.ReadShortString();
TsigAlgorithm algorithm = (TsigAlgorithm)bR.ReadByte();
tsigKeys.Add(keyName, new TsigKey(keyName, sharedSecret, algorithm));
}
_dnsServer.TsigKeys = tsigKeys;
}
//recursion
_dnsServer.Recursion = (DnsServerRecursion)bR.ReadByte();
if (version >= 37)
{
_dnsServer.RecursionNetworkACL = AuthZoneInfo.ReadNetworkACLFrom(bR);
}
else
{
NetworkAddress[] recursionDeniedNetworks = AuthZoneInfo.ReadNetworkAddressesFrom(bR);
NetworkAddress[] recursionAllowedNetworks = AuthZoneInfo.ReadNetworkAddressesFrom(bR);
_dnsServer.RecursionNetworkACL = AuthZoneInfo.ConvertDenyAllowToACL(recursionDeniedNetworks, recursionAllowedNetworks);
}
_dnsServer.RandomizeName = bR.ReadBoolean();
_dnsServer.QnameMinimization = bR.ReadBoolean();
if (version <= 40)
_ = bR.ReadBoolean(); //removed NsRevalidation option
_dnsServer.ResolverRetries = bR.ReadInt32();
_dnsServer.ResolverTimeout = bR.ReadInt32();
if (version >= 37)
_dnsServer.ResolverConcurrency = bR.ReadInt32();
else
_dnsServer.ResolverConcurrency = 2;
_dnsServer.ResolverMaxStackCount = bR.ReadInt32();
//cache
if (version >= 30)
_dnsServer.SaveCacheToDisk = bR.ReadBoolean();
else
_dnsServer.SaveCacheToDisk = true;
_dnsServer.ServeStale = bR.ReadBoolean();
_dnsServer.CacheZoneManager.ServeStaleTtl = bR.ReadUInt32();
if (version >= 36)
{
_dnsServer.CacheZoneManager.ServeStaleAnswerTtl = bR.ReadUInt32();
_dnsServer.CacheZoneManager.ServeStaleResetTtl = bR.ReadUInt32();
_dnsServer.ServeStaleMaxWaitTime = bR.ReadInt32();
}
else
{
_dnsServer.CacheZoneManager.ServeStaleAnswerTtl = CacheZoneManager.SERVE_STALE_ANSWER_TTL;
_dnsServer.CacheZoneManager.ServeStaleResetTtl = CacheZoneManager.SERVE_STALE_RESET_TTL;
_dnsServer.ServeStaleMaxWaitTime = DnsServer.SERVE_STALE_MAX_WAIT_TIME;
}
_dnsServer.CacheZoneManager.MaximumEntries = bR.ReadInt64();
_dnsServer.CacheZoneManager.MinimumRecordTtl = bR.ReadUInt32();
_dnsServer.CacheZoneManager.MaximumRecordTtl = bR.ReadUInt32();
_dnsServer.CacheZoneManager.NegativeRecordTtl = bR.ReadUInt32();
_dnsServer.CacheZoneManager.FailureRecordTtl = bR.ReadUInt32();
_dnsServer.CachePrefetchEligibility = bR.ReadInt32();
_dnsServer.CachePrefetchTrigger = bR.ReadInt32();
_dnsServer.CachePrefetchSampleIntervalMinutes = bR.ReadInt32();
_dnsServer.CachePrefetchSampleEligibilityHitsPerHour = bR.ReadInt32();
//blocking
_dnsServer.EnableBlocking = bR.ReadBoolean();
_dnsServer.AllowTxtBlockingReport = bR.ReadBoolean();
if (version >= 33)
_dnsServer.BlockingBypassList = AuthZoneInfo.ReadNetworkAddressesFrom(bR);
else
_dnsServer.BlockingBypassList = null;
_dnsServer.BlockingType = (DnsServerBlockingType)bR.ReadByte();
if (version >= 38)
_dnsServer.BlockingAnswerTtl = bR.ReadUInt32();
else
_dnsServer.BlockingAnswerTtl = 30;
{
//read custom blocking addresses
int count = bR.ReadByte();
if (count > 0)
{
List<DnsARecordData> dnsARecords = new List<DnsARecordData>();
List<DnsAAAARecordData> dnsAAAARecords = new List<DnsAAAARecordData>();
for (int i = 0; i < count; i++)
{
IPAddress customAddress = IPAddressExtensions.ReadFrom(bR);
switch (customAddress.AddressFamily)
{
case AddressFamily.InterNetwork:
dnsARecords.Add(new DnsARecordData(customAddress));
break;
case AddressFamily.InterNetworkV6:
dnsAAAARecords.Add(new DnsAAAARecordData(customAddress));
break;
}
}
_dnsServer.CustomBlockingARecords = dnsARecords;
_dnsServer.CustomBlockingAAAARecords = dnsAAAARecords;
}
else
{
_dnsServer.CustomBlockingARecords = null;
_dnsServer.CustomBlockingAAAARecords = null;
}
}
{
//read block list urls
int count = bR.ReadByte();
string[] blockListUrls = new string[count];
for (int i = 0; i < count; i++)
blockListUrls[i] = bR.ReadShortString();
_dnsServer.BlockListZoneManager.BlockListUrls = blockListUrls;
_dnsServer.BlockListZoneManager.BlockListUpdateIntervalHours = bR.ReadInt32();
_dnsServer.BlockListZoneManager.BlockListLastUpdatedOn = bR.ReadDateTime();
}
//proxy & forwarders
NetProxyType proxyType = (NetProxyType)bR.ReadByte();
if (proxyType != NetProxyType.None)
{
string address = bR.ReadShortString();
int port = bR.ReadInt32();
NetworkCredential credential = null;
if (bR.ReadBoolean()) //credential set
credential = new NetworkCredential(bR.ReadShortString(), bR.ReadShortString());
_dnsServer.Proxy = NetProxy.CreateProxy(proxyType, address, port, credential);
int count = bR.ReadByte();
List<NetProxyBypassItem> bypassList = new List<NetProxyBypassItem>(count);
for (int i = 0; i < count; i++)
bypassList.Add(new NetProxyBypassItem(bR.ReadShortString()));
_dnsServer.Proxy.BypassList = bypassList;
}
else
{
_dnsServer.Proxy = null;
}
{
int count = bR.ReadByte();
if (count > 0)
{
NameServerAddress[] forwarders = new NameServerAddress[count];
for (int i = 0; i < count; i++)
{
forwarders[i] = new NameServerAddress(bR);
if (forwarders[i].Protocol == DnsTransportProtocol.HttpsJson)
forwarders[i] = forwarders[i].Clone(DnsTransportProtocol.Https);
}
_dnsServer.Forwarders = forwarders;
}
else
{
_dnsServer.Forwarders = null;
}
}
if (version >= 37)
_dnsServer.ConcurrentForwarding = bR.ReadBoolean();
else
_dnsServer.ConcurrentForwarding = true;
_dnsServer.ForwarderRetries = bR.ReadInt32();
_dnsServer.ForwarderTimeout = bR.ReadInt32();
_dnsServer.ForwarderConcurrency = bR.ReadInt32();
//logging
if (version >= 33)
{
if (bR.ReadBoolean()) //ignore resolver logs
_dnsServer.ResolverLogManager = null;
else
_dnsServer.ResolverLogManager = _log;
}
else
{
_dnsServer.ResolverLogManager = _log;
}
if (bR.ReadBoolean()) //log all queries
_dnsServer.QueryLogManager = _log;
else
_dnsServer.QueryLogManager = null;
if (version >= 34)
_dnsServer.StatsManager.EnableInMemoryStats = bR.ReadBoolean();
else
_dnsServer.StatsManager.EnableInMemoryStats = false;
{
int maxStatFileDays = bR.ReadInt32();
if (maxStatFileDays < 0)
maxStatFileDays = 0;
_dnsServer.StatsManager.MaxStatFileDays = maxStatFileDays;
}
}
}
private void ReadConfigFromV27(BinaryReader bR, int version)
{
_dnsServer.ServerDomain = bR.ReadShortString();
_webServiceHttpPort = bR.ReadInt32();
if (version >= 13)
{
{
int count = bR.ReadByte();
if (count > 0)
{
IPAddress[] localAddresses = new IPAddress[count];
for (int i = 0; i < count; i++)
localAddresses[i] = IPAddressExtensions.ReadFrom(bR);
_webServiceLocalAddresses = localAddresses;
}
else
{
_webServiceLocalAddresses = new IPAddress[] { IPAddress.Any, IPAddress.IPv6Any };
}
}
_webServiceTlsPort = bR.ReadInt32();
_webServiceEnableTls = bR.ReadBoolean();
_webServiceHttpToTlsRedirect = bR.ReadBoolean();
_webServiceTlsCertificatePath = bR.ReadShortString();
_webServiceTlsCertificatePassword = bR.ReadShortString();
if (_webServiceTlsCertificatePath.Length == 0)
_webServiceTlsCertificatePath = null;
if (_webServiceTlsCertificatePath is null)
{
StopTlsCertificateUpdateTimer();
}
else
{
string webServiceTlsCertificatePath = ConvertToAbsolutePath(_webServiceTlsCertificatePath);
try
{
LoadWebServiceTlsCertificate(webServiceTlsCertificatePath, _webServiceTlsCertificatePassword);
}
catch (Exception ex)
{
_log.Write("DNS Server encountered an error while loading Web Service TLS certificate: " + webServiceTlsCertificatePath + "\r\n" + ex.ToString());
}
StartTlsCertificateUpdateTimer();
}
}
else
{
_webServiceLocalAddresses = new IPAddress[] { IPAddress.Any, IPAddress.IPv6Any };
_webServiceTlsPort = 53443;
_webServiceEnableTls = false;
_webServiceHttpToTlsRedirect = false;
_webServiceTlsCertificatePath = string.Empty;
_webServiceTlsCertificatePassword = string.Empty;
}
_dnsServer.PreferIPv6 = bR.ReadBoolean();
if (bR.ReadBoolean()) //logQueries
_dnsServer.QueryLogManager = _log;
if (version >= 14)
{
int maxStatFileDays = bR.ReadInt32();
if (maxStatFileDays < 0)
maxStatFileDays = 0;
_dnsServer.StatsManager.MaxStatFileDays = maxStatFileDays;
}
else
{
_dnsServer.StatsManager.MaxStatFileDays = 0;
}
if (version >= 17)
{
_dnsServer.Recursion = (DnsServerRecursion)bR.ReadByte();
NetworkAddress[] recursionDeniedNetworks;
{
int count = bR.ReadByte();
if (count > 0)
{
NetworkAddress[] networks = new NetworkAddress[count];
for (int i = 0; i < count; i++)
networks[i] = NetworkAddress.ReadFrom(bR);
recursionDeniedNetworks = networks;
}
else
{
recursionDeniedNetworks = null;
}
}
NetworkAddress[] recursionAllowedNetworks;
{
int count = bR.ReadByte();
if (count > 0)
{
NetworkAddress[] networks = new NetworkAddress[count];
for (int i = 0; i < count; i++)
networks[i] = NetworkAddress.ReadFrom(bR);
recursionAllowedNetworks = networks;
}
else
{
recursionAllowedNetworks = null;
}
}
_dnsServer.RecursionNetworkACL = AuthZoneInfo.ConvertDenyAllowToACL(recursionDeniedNetworks, recursionAllowedNetworks);
}
else
{
bool allowRecursion = bR.ReadBoolean();
bool allowRecursionOnlyForPrivateNetworks;
if (version >= 4)
allowRecursionOnlyForPrivateNetworks = bR.ReadBoolean();
else
allowRecursionOnlyForPrivateNetworks = true; //default true for security reasons
if (allowRecursion)
{
if (allowRecursionOnlyForPrivateNetworks)
_dnsServer.Recursion = DnsServerRecursion.AllowOnlyForPrivateNetworks;
else
_dnsServer.Recursion = DnsServerRecursion.Allow;
}
else
{
_dnsServer.Recursion = DnsServerRecursion.Deny;
}
}
if (version >= 12)
_dnsServer.RandomizeName = bR.ReadBoolean();
else
_dnsServer.RandomizeName = false; //default false to allow resolving from bad name servers
if (version >= 15)
_dnsServer.QnameMinimization = bR.ReadBoolean();
else
_dnsServer.QnameMinimization = true; //default true to enable privacy feature
if (version >= 20)
{
int qpmLimitRequests = bR.ReadInt32();
_ = bR.ReadInt32(); //obsolete qpmLimitErrors
int qpmLimitSampleMinutes = bR.ReadInt32();
int qpmLimitIPv4PrefixLength = bR.ReadInt32();
int qpmLimitIPv6PrefixLength = bR.ReadInt32();
_dnsServer.QpmPrefixLimitsIPv4 = new Dictionary<int, (int, int)>()
{
{ qpmLimitIPv4PrefixLength, (qpmLimitRequests, qpmLimitRequests) }
};
_dnsServer.QpmPrefixLimitsIPv6 = new Dictionary<int, (int, int)>()
{
{ qpmLimitIPv6PrefixLength, (qpmLimitRequests, qpmLimitRequests) }
};
_dnsServer.QpmLimitSampleMinutes = qpmLimitSampleMinutes;
_dnsServer.QpmLimitUdpTruncationPercentage = 0;
}
else if (version >= 17)
{
int qpmLimitRequests = bR.ReadInt32();
int qpmLimitSampleMinutes = bR.ReadInt32();
_ = bR.ReadInt32(); //read obsolete value _dnsServer.QpmLimitSamplingIntervalInMinutes
_dnsServer.QpmPrefixLimitsIPv4 = new Dictionary<int, (int, int)>()
{
{ 24, (qpmLimitRequests, qpmLimitRequests) }
};
_dnsServer.QpmPrefixLimitsIPv6 = new Dictionary<int, (int, int)>()
{
{ 56, (qpmLimitRequests, qpmLimitRequests) }
};
_dnsServer.QpmLimitSampleMinutes = qpmLimitSampleMinutes;
_dnsServer.QpmLimitUdpTruncationPercentage = 0;
}
else
{
_dnsServer.QpmPrefixLimitsIPv4 = new Dictionary<int, (int, int)>()
{
{ 32, (600, 600) },
{ 24, (6000, 6000) }
};
_dnsServer.QpmPrefixLimitsIPv6 = new Dictionary<int, (int, int)>()
{
{ 128, (600, 600) },
{ 64, (1200, 1200) },
{ 56, (6000, 6000) }
};
_dnsServer.QpmLimitSampleMinutes = 5;
_dnsServer.QpmLimitUdpTruncationPercentage = 50;
}
if (version >= 13)
{
_dnsServer.ServeStale = bR.ReadBoolean();
_dnsServer.CacheZoneManager.ServeStaleTtl = bR.ReadUInt32();
}
else
{
_dnsServer.ServeStale = true;
_dnsServer.CacheZoneManager.ServeStaleTtl = CacheZoneManager.SERVE_STALE_TTL;
}
if (version >= 9)
{
_dnsServer.CachePrefetchEligibility = bR.ReadInt32();
_dnsServer.CachePrefetchTrigger = bR.ReadInt32();
_dnsServer.CachePrefetchSampleIntervalMinutes = bR.ReadInt32();
_dnsServer.CachePrefetchSampleEligibilityHitsPerHour = bR.ReadInt32();
}
else
{
_dnsServer.CachePrefetchEligibility = 2;
_dnsServer.CachePrefetchTrigger = 9;
_dnsServer.CachePrefetchSampleIntervalMinutes = 5;
_dnsServer.CachePrefetchSampleEligibilityHitsPerHour = 30;
}
NetProxyType proxyType = (NetProxyType)bR.ReadByte();
if (proxyType != NetProxyType.None)
{
string address = bR.ReadShortString();
int port = bR.ReadInt32();
NetworkCredential credential = null;
if (bR.ReadBoolean()) //credential set
credential = new NetworkCredential(bR.ReadShortString(), bR.ReadShortString());
_dnsServer.Proxy = NetProxy.CreateProxy(proxyType, address, port, credential);
if (version >= 10)
{
int count = bR.ReadByte();
List<NetProxyBypassItem> bypassList = new List<NetProxyBypassItem>(count);
for (int i = 0; i < count; i++)
bypassList.Add(new NetProxyBypassItem(bR.ReadShortString()));
_dnsServer.Proxy.BypassList = bypassList;
}
else
{
_dnsServer.Proxy.BypassList = null;
}
}
else
{
_dnsServer.Proxy = null;
}
{
int count = bR.ReadByte();
if (count > 0)
{
NameServerAddress[] forwarders = new NameServerAddress[count];
for (int i = 0; i < count; i++)
{
forwarders[i] = new NameServerAddress(bR);
if (forwarders[i].Protocol == DnsTransportProtocol.HttpsJson)
forwarders[i] = forwarders[i].Clone(DnsTransportProtocol.Https);
}
_dnsServer.Forwarders = forwarders;
}
else
{
_dnsServer.Forwarders = null;
}
}
if (version <= 10)
{
DnsTransportProtocol forwarderProtocol = (DnsTransportProtocol)bR.ReadByte();
if (forwarderProtocol == DnsTransportProtocol.HttpsJson)
forwarderProtocol = DnsTransportProtocol.Https;
if (_dnsServer.Forwarders != null)
{
List<NameServerAddress> forwarders = new List<NameServerAddress>();
foreach (NameServerAddress forwarder in _dnsServer.Forwarders)
{
if (forwarder.Protocol == forwarderProtocol)
forwarders.Add(forwarder);
else
forwarders.Add(forwarder.Clone(forwarderProtocol));
}
_dnsServer.Forwarders = forwarders;
}
}
{
int count = bR.ReadByte();
if (count > 0)
{
if (version > 2)
{
for (int i = 0; i < count; i++)
{
string username = bR.ReadShortString();
string passwordHash = bR.ReadShortString();
if (username.Equals("admin", StringComparison.OrdinalIgnoreCase))
{
_authManager.LoadOldConfig(passwordHash, true);
break;
}
}
}
else
{
for (int i = 0; i < count; i++)
{
string username = bR.ReadShortString();
string password = bR.ReadShortString();
if (username.Equals("admin", StringComparison.OrdinalIgnoreCase))
{
_authManager.LoadOldConfig(password, false);
break;
}
}
}
}
}
if (version <= 6)
{
int count = bR.ReadInt32();
_configDisabledZones = new List<string>(count);
for (int i = 0; i < count; i++)
{
string domain = bR.ReadShortString();
_configDisabledZones.Add(domain);
}
}
if (version >= 18)
_dnsServer.EnableBlocking = bR.ReadBoolean();
else
_dnsServer.EnableBlocking = true;
if (version >= 18)
_dnsServer.BlockingType = (DnsServerBlockingType)bR.ReadByte();
else if (version >= 16)
_dnsServer.BlockingType = bR.ReadBoolean() ? DnsServerBlockingType.NxDomain : DnsServerBlockingType.AnyAddress;
else
_dnsServer.BlockingType = DnsServerBlockingType.AnyAddress;
if (version >= 18)
{
//read custom blocking addresses
int count = bR.ReadByte();
if (count > 0)
{
List<DnsARecordData> dnsARecords = new List<DnsARecordData>();
List<DnsAAAARecordData> dnsAAAARecords = new List<DnsAAAARecordData>();
for (int i = 0; i < count; i++)
{
IPAddress customAddress = IPAddressExtensions.ReadFrom(bR);
switch (customAddress.AddressFamily)
{
case AddressFamily.InterNetwork:
dnsARecords.Add(new DnsARecordData(customAddress));
break;
case AddressFamily.InterNetworkV6:
dnsAAAARecords.Add(new DnsAAAARecordData(customAddress));
break;
}
}
_dnsServer.CustomBlockingARecords = dnsARecords;
_dnsServer.CustomBlockingAAAARecords = dnsAAAARecords;
}
else
{
_dnsServer.CustomBlockingARecords = null;
_dnsServer.CustomBlockingAAAARecords = null;
}
}
else
{
_dnsServer.CustomBlockingARecords = null;
_dnsServer.CustomBlockingAAAARecords = null;
}
if (version > 4)
{
//read block list urls
int count = bR.ReadByte();
string[] blockListUrls = new string[count];
for (int i = 0; i < count; i++)
blockListUrls[i] = bR.ReadShortString();
_dnsServer.BlockListZoneManager.BlockListUrls = blockListUrls;
_dnsServer.BlockListZoneManager.BlockListLastUpdatedOn = bR.ReadDateTime();
if (version >= 13)
_dnsServer.BlockListZoneManager.BlockListUpdateIntervalHours = bR.ReadInt32();
}
else
{
_dnsServer.BlockListZoneManager.BlockListUrls = null;
_dnsServer.BlockListZoneManager.BlockListLastUpdatedOn = DateTime.MinValue;
_dnsServer.BlockListZoneManager.BlockListUpdateIntervalHours = 24;
}
if (version >= 11)
{
int count = bR.ReadByte();
if (count > 0)
{
List<IPEndPoint> localEndPoints = new List<IPEndPoint>(count);
for (int i = 0; i < count; i++)
{
IPEndPoint ep = EndPointExtensions.ReadFrom(bR) as IPEndPoint;
if (ep.Port == 853)
continue; //to avoid validation exception
localEndPoints.Add(ep);
}
_dnsServer.LocalEndPoints = localEndPoints;
}
else
{
_dnsServer.LocalEndPoints = new IPEndPoint[] { new IPEndPoint(IPAddress.Any, 53), new IPEndPoint(IPAddress.IPv6Any, 53) };
}
}
else if (version >= 6)
{
int count = bR.ReadByte();
if (count > 0)
{
List<IPEndPoint> localEndPoints = new List<IPEndPoint>(count);
for (int i = 0; i < count; i++)
{
IPEndPoint ep = EndPointExtensions.ReadFrom(bR) as IPEndPoint;
if (ep.Port == 853)
continue; //to avoid validation exception
localEndPoints.Add(ep);
}
_dnsServer.LocalEndPoints = localEndPoints;
}
else
{
_dnsServer.LocalEndPoints = new IPEndPoint[] { new IPEndPoint(IPAddress.Any, 53), new IPEndPoint(IPAddress.IPv6Any, 53) };
}
}
else
{
_dnsServer.LocalEndPoints = new IPEndPoint[] { new IPEndPoint(IPAddress.Any, 53), new IPEndPoint(IPAddress.IPv6Any, 53) };
}
if (version >= 8)
{
_dnsServer.EnableDnsOverHttp = bR.ReadBoolean();
_dnsServer.EnableDnsOverTls = bR.ReadBoolean();
_dnsServer.EnableDnsOverHttps = bR.ReadBoolean();
string dnsTlsCertificatePath = bR.ReadShortString();
string dnsTlsCertificatePassword = bR.ReadShortString();
if (dnsTlsCertificatePath.Length == 0)
dnsTlsCertificatePath = null;
if (dnsTlsCertificatePath is null)
_dnsServer.RemoveDnsTlsCertificate();
else
_dnsServer.SetDnsTlsCertificate(dnsTlsCertificatePath, dnsTlsCertificatePassword);
}
else
{
_dnsServer.EnableDnsOverHttp = false;
_dnsServer.EnableDnsOverTls = false;
_dnsServer.EnableDnsOverHttps = false;
_dnsServer.RemoveDnsTlsCertificate();
}
if (version >= 19)
{
_dnsServer.CacheZoneManager.MinimumRecordTtl = bR.ReadUInt32();
_dnsServer.CacheZoneManager.MaximumRecordTtl = bR.ReadUInt32();
_dnsServer.CacheZoneManager.NegativeRecordTtl = bR.ReadUInt32();
_dnsServer.CacheZoneManager.FailureRecordTtl = bR.ReadUInt32();
}
else
{
_dnsServer.CacheZoneManager.MinimumRecordTtl = CacheZoneManager.MINIMUM_RECORD_TTL;
_dnsServer.CacheZoneManager.MaximumRecordTtl = CacheZoneManager.MAXIMUM_RECORD_TTL;
_dnsServer.CacheZoneManager.NegativeRecordTtl = CacheZoneManager.NEGATIVE_RECORD_TTL;
_dnsServer.CacheZoneManager.FailureRecordTtl = CacheZoneManager.FAILURE_RECORD_TTL;
}
if (version >= 21)
{
int count = bR.ReadByte();
Dictionary<string, TsigKey> tsigKeys = new Dictionary<string, TsigKey>(count);
for (int i = 0; i < count; i++)
{
string keyName = bR.ReadShortString();
string sharedSecret = bR.ReadShortString();
TsigAlgorithm algorithm = (TsigAlgorithm)bR.ReadByte();
tsigKeys.Add(keyName, new TsigKey(keyName, sharedSecret, algorithm));
}
_dnsServer.TsigKeys = tsigKeys;
}
else if (version >= 20)
{
int count = bR.ReadByte();
Dictionary<string, TsigKey> tsigKeys = new Dictionary<string, TsigKey>(count);
for (int i = 0; i < count; i++)
{
string keyName = bR.ReadShortString();
string sharedSecret = bR.ReadShortString();
tsigKeys.Add(keyName, new TsigKey(keyName, sharedSecret, TsigAlgorithm.HMAC_SHA256));
}
_dnsServer.TsigKeys = tsigKeys;
}
else
{
_dnsServer.TsigKeys = null;
}
if (version >= 22)
_ = bR.ReadBoolean(); //removed NsRevalidation option
if (version >= 23)
{
_dnsServer.AllowTxtBlockingReport = bR.ReadBoolean();
_dnsServer.AuthZoneManager.DefaultRecordTtl = bR.ReadUInt32();
}
else
{
_dnsServer.AllowTxtBlockingReport = true;
_dnsServer.AuthZoneManager.DefaultRecordTtl = 3600;
}
if (version >= 24)
{
_webServiceUseSelfSignedTlsCertificate = bR.ReadBoolean();
CheckAndLoadSelfSignedCertificate(false, false);
}
else
{
_webServiceUseSelfSignedTlsCertificate = false;
}
if (version >= 25)
_dnsServer.UdpPayloadSize = bR.ReadUInt16();
else
_dnsServer.UdpPayloadSize = DnsDatagram.EDNS_DEFAULT_UDP_PAYLOAD_SIZE;
if (version >= 26)
{
_dnsServer.DnssecValidation = bR.ReadBoolean();
_dnsServer.ResolverRetries = bR.ReadInt32();
_dnsServer.ResolverTimeout = bR.ReadInt32();
_dnsServer.ResolverMaxStackCount = bR.ReadInt32();
_dnsServer.ForwarderRetries = bR.ReadInt32();
_dnsServer.ForwarderTimeout = bR.ReadInt32();
_dnsServer.ForwarderConcurrency = bR.ReadInt32();
_dnsServer.ClientTimeout = bR.ReadInt32();
if (_dnsServer.ClientTimeout == 4000)
_dnsServer.ClientTimeout = 2000;
_dnsServer.TcpSendTimeout = bR.ReadInt32();
_dnsServer.TcpReceiveTimeout = bR.ReadInt32();
}
else
{
_dnsServer.DnssecValidation = true;
CreateForwarderZoneToDisableDnssecForNTP();
_dnsServer.ResolverRetries = 2;
_dnsServer.ResolverTimeout = 1500;
_dnsServer.ResolverMaxStackCount = 16;
_dnsServer.ForwarderRetries = 3;
_dnsServer.ForwarderTimeout = 2000;
_dnsServer.ForwarderConcurrency = 2;
_dnsServer.ClientTimeout = 2000;
_dnsServer.TcpSendTimeout = 10000;
_dnsServer.TcpReceiveTimeout = 10000;
}
if (version >= 27)
_dnsServer.CacheZoneManager.MaximumEntries = bR.ReadInt32();
else
_dnsServer.CacheZoneManager.MaximumEntries = 10000;
}
#endregion
}
}