/* 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 . */ 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 localEndPoints = new List(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 qpmPrefixLimitsIPv4 = new Dictionary(count); for (int i = 0; i < count; i++) qpmPrefixLimitsIPv4.Add(bR.ReadInt32(), (bR.ReadInt32(), bR.ReadInt32())); _dnsServer.QpmPrefixLimitsIPv4 = qpmPrefixLimitsIPv4; } { int count = bR.ReadByte(); Dictionary qpmPrefixLimitsIPv6 = new Dictionary(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() { { qpmLimitIPv4PrefixLength, (qpmLimitRequests, qpmLimitRequests) } }; _dnsServer.QpmPrefixLimitsIPv6 = new Dictionary() { { 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 tsigKeys = new Dictionary(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 dnsARecords = new List(); List dnsAAAARecords = new List(); 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 bypassList = new List(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() { { qpmLimitIPv4PrefixLength, (qpmLimitRequests, qpmLimitRequests) } }; _dnsServer.QpmPrefixLimitsIPv6 = new Dictionary() { { 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() { { 24, (qpmLimitRequests, qpmLimitRequests) } }; _dnsServer.QpmPrefixLimitsIPv6 = new Dictionary() { { 56, (qpmLimitRequests, qpmLimitRequests) } }; _dnsServer.QpmLimitSampleMinutes = qpmLimitSampleMinutes; _dnsServer.QpmLimitUdpTruncationPercentage = 0; } else { _dnsServer.QpmPrefixLimitsIPv4 = new Dictionary() { { 32, (600, 600) }, { 24, (6000, 6000) } }; _dnsServer.QpmPrefixLimitsIPv6 = new Dictionary() { { 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 bypassList = new List(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 forwarders = new List(); 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(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 dnsARecords = new List(); List dnsAAAARecords = new List(); 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 localEndPoints = new List(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 localEndPoints = new List(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 tsigKeys = new Dictionary(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 tsigKeys = new Dictionary(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 } }