Merge branch 'develop'

This commit is contained in:
Shreyas Zare
2023-02-25 17:12:37 +05:30
28 changed files with 325 additions and 212 deletions

View File

@@ -494,8 +494,12 @@ RESPONSE:
"totalCached": 228,
"totalBlocked": 111,
"totalClients": 831,
"zones": 5,
"cachedEntries": 28,
"allowedZones": 6,
"blockedZones": 1136182
"blockedZones": 10,
"allowListZones": 0,
"blockListZones": 1136182
},
"mainChartData": {
"labelFormat": "HH:mm",

View File

@@ -3,7 +3,7 @@
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<Version>5.0</Version>
<Version>5.0.1</Version>
<Company>Technitium</Company>
<Product>Technitium DNS Server</Product>
<Authors>Shreyas Zare</Authors>

View File

@@ -1110,7 +1110,7 @@ namespace AdvancedBlocking
if (line.Length == 0)
continue; //skip empty line
if (line.StartsWith("#"))
if (line.StartsWith('#'))
continue; //skip comment line
firstWord = PopWord(ref line);
@@ -1123,7 +1123,7 @@ namespace AdvancedBlocking
{
secondWord = PopWord(ref line);
if (secondWord.Length == 0)
if ((secondWord.Length == 0) || secondWord.StartsWith('#'))
hostname = firstWord;
else
hostname = secondWord;
@@ -1239,7 +1239,7 @@ namespace AdvancedBlocking
if (line.Length == 0)
continue; //skip empty line
if (line.StartsWith("#"))
if (line.StartsWith('#'))
continue; //skip comment line
regices.Enqueue(line);
@@ -1338,7 +1338,7 @@ namespace AdvancedBlocking
if (line.Length == 0)
continue; //skip empty line
if (line.StartsWith("!"))
if (line.StartsWith('!'))
continue; //skip comment line
if (line.StartsWith("||"))
@@ -1349,7 +1349,7 @@ namespace AdvancedBlocking
string domain = line.Substring(2, i - 2);
string options = line.Substring(i + 1);
if (((options.Length == 0) || (options.StartsWith("$") && (options.Contains("doc") || options.Contains("all")))) && DnsClient.IsDomainNameValid(domain))
if (((options.Length == 0) || (options.StartsWith('$') && (options.Contains("doc") || options.Contains("all")))) && DnsClient.IsDomainNameValid(domain))
blockedDomains.Enqueue(domain);
}
else
@@ -1368,7 +1368,7 @@ namespace AdvancedBlocking
string domain = line.Substring(4, i - 4);
string options = line.Substring(i + 1);
if (((options.Length == 0) || (options.StartsWith("$") && (options.Contains("doc") || options.Contains("all")))) && DnsClient.IsDomainNameValid(domain))
if (((options.Length == 0) || (options.StartsWith('$') && (options.Contains("doc") || options.Contains("all")))) && DnsClient.IsDomainNameValid(domain))
allowedDomains.Enqueue(domain);
}
else

View File

@@ -3,7 +3,7 @@
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<Version>1.0</Version>
<Version>1.0.1</Version>
<Company>Technitium</Company>
<Product>Technitium DNS Server</Product>
<Authors>Shreyas Zare</Authors>

View File

@@ -444,6 +444,28 @@ namespace AdvancedForwarding
return false;
}
public static bool IsForwarderDomain(string domain, IReadOnlyList<Forwarding> forwardings)
{
foreach (Forwarding forwarding in forwardings)
{
if (IsForwarderDomain(domain, forwarding._forwarderRecords))
return true;
}
return false;
}
public static bool IsForwarderDomain(string domain, IReadOnlyList<DnsForwarderRecordData> forwarderRecords)
{
foreach (DnsForwarderRecordData forwarderRecord in forwarderRecords)
{
if (domain.Equals(forwarderRecord.NameServer.Host, StringComparison.OrdinalIgnoreCase))
return true;
}
return false;
}
#endregion
#region private
@@ -554,7 +576,12 @@ namespace AdvancedForwarding
{
DateTime configFileLastModified = File.GetLastWriteTimeUtc(_configFile);
if (configFileLastModified > _configFileLastModified)
{
ReloadUpstreamsFile();
//force GC collection to remove old cache data from memory quickly
GC.Collect();
}
}
catch (Exception ex)
{
@@ -611,10 +638,10 @@ namespace AdvancedForwarding
if (line.Length == 0)
continue; //skip empty line
if (line.StartsWith("#"))
if (line.StartsWith('#'))
continue; //skip comment line
if (line.StartsWith("["))
if (line.StartsWith('['))
{
int i = line.LastIndexOf(']');
if (i < 0)
@@ -689,11 +716,26 @@ namespace AdvancedForwarding
public bool TryGetForwarderRecords(string domain, out IReadOnlyList<DnsForwarderRecordData> forwarderRecords)
{
if ((_forwardings.Count > 0) && Forwarding.TryGetForwarderRecords(domain, _forwardings, out forwarderRecords))
return true;
if (_defaultForwarderRecords.Count > 0)
if ((_forwardings is not null) && (_forwardings.Count > 0))
{
if (Forwarding.IsForwarderDomain(domain, _forwardings))
{
forwarderRecords = null;
return false;
}
if (Forwarding.TryGetForwarderRecords(domain, _forwardings, out forwarderRecords))
return true;
}
if ((_defaultForwarderRecords is not null) && (_defaultForwarderRecords.Count > 0))
{
if (Forwarding.IsForwarderDomain(domain, _defaultForwarderRecords))
{
forwarderRecords = null;
return false;
}
forwarderRecords = _defaultForwarderRecords;
return true;
}

View File

@@ -2,6 +2,8 @@
"enableBlocking": true,
"allowTxtBlockingReport": true,
"blocked": [
"use-application-dns.net"
"use-application-dns.net",
"mask.icloud.com",
"mask-h2.icloud.com"
]
}

View File

@@ -1,6 +1,6 @@
{
"enableLogging": true,
"maxLogDays": 0,
"maxLogDays": 7,
"sqliteDbPath": "querylogs.db",
"connectionString": "Data Source='{sqliteDbPath}'; Cache=Shared;"
}

View File

@@ -1,5 +1,19 @@
# Technitium DNS Server Change Log
## Version 11.0.1
Release Date: 25 February 2023
- Changed allow list implementation to handle them separately and show allow list count on Dashboard.
- Fixed bug in conditional forwarder zone for root zone that caused the DNS server to return RCODE=ServerFailure.
- Fixed issues with DNS server's App request query handling sequence to fix issues with Advanced Forwarding app.
- Fixed issues with block list parser to detect in-line comments.
- Fixed issue of "URI too long" in save DHCP scope action.
- Updated Linux install script to use new install path in `/opt` and new config path `/etc/dns` for new installations.
- Updated Docker container to use new volume path `/etc/dns` for config.
- Updated Docker container to correctly handle container stop event to gracefully shutdown the DNS server.
- Updated Docker container to include `libmsquic` to allow QUIC support.
- Multiple other minor bug fixes and improvements.
## Version 11.0
Release Date: 18 February 2023

View File

@@ -6,7 +6,7 @@
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ApplicationIcon>logo2.ico</ApplicationIcon>
<Version>11.0</Version>
<Version>11.0.1</Version>
<Company>Technitium</Company>
<Product>Technitium DNS Server</Product>
<Authors>Shreyas Zare</Authors>

View File

@@ -1,8 +1,15 @@
#!/bin/sh
dotnetDir="/opt/dotnet"
dnsDir="/etc/dns"
dnsTar="/etc/dns/DnsServerPortable.tar.gz"
if [ -d "/etc/dns/config" ]
then
dnsDir="/etc/dns"
else
dnsDir="/opt/technitium/dns"
fi
dnsTar="$dnsDir/DnsServerPortable.tar.gz"
dnsUrl="https://download.technitium.com/dns/DnsServerPortable.tar.gz"
mkdir -p $dnsDir

View File

@@ -2,8 +2,8 @@
Description=Technitium DNS Server
[Service]
WorkingDirectory=/etc/dns
ExecStart=/usr/bin/dotnet /etc/dns/DnsServerApp.dll
WorkingDirectory=/opt/technitium/dns
ExecStart=/usr/bin/dotnet /opt/technitium/dns/DnsServerApp.dll /etc/dns
Restart=always
# Restart service after 10 seconds if the dotnet service crashes:
RestartSec=10

View File

@@ -1,7 +1,13 @@
#!/bin/sh
dotnetDir="/opt/dotnet"
dnsDir="/etc/dns"
if [ -d "/etc/dns/config" ]
then
dnsDir="/etc/dns"
else
dnsDir="/opt/technitium/dns"
fi
echo ""
echo "================================="

View File

@@ -619,6 +619,10 @@ namespace DnsServerCore.Dns
_queryLog?.Write(remoteEP, protocol, request, response);
_stats.QueueUpdate(request, remoteEP, protocol, response);
}
catch (ObjectDisposedException)
{
//ignore
}
catch (IOException)
{
//ignore IO exceptions
@@ -1839,38 +1843,9 @@ namespace DnsServerCore.Dns
private async Task<DnsDatagram> ProcessAuthoritativeQueryAsync(DnsDatagram request, IPEndPoint remoteEP, DnsTransportProtocol protocol, bool isRecursionAllowed, bool skipDnsAppAuthoritativeRequestHandlers)
{
DnsDatagram response = null;
if (!skipDnsAppAuthoritativeRequestHandlers)
{
foreach (IDnsAuthoritativeRequestHandler requestHandler in _dnsApplicationManager.DnsAuthoritativeRequestHandlers)
{
try
{
response = await requestHandler.ProcessRequestAsync(request, remoteEP, protocol, isRecursionAllowed);
if (response is not null)
{
if (response.Tag is null)
response.Tag = DnsServerResponseType.Authoritative;
break;
}
}
catch (Exception ex)
{
_log?.Write(remoteEP, protocol, ex);
}
}
}
DnsDatagram response = await AuthoritativeQueryAsync(request, remoteEP, protocol, isRecursionAllowed, skipDnsAppAuthoritativeRequestHandlers);
if (response is null)
{
response = _authZoneManager.Query(request);
if (response is null)
return null;
response.Tag = DnsServerResponseType.Authoritative;
}
return null;
bool reprocessResponse;
do
@@ -1911,16 +1886,8 @@ namespace DnsServerCore.Dns
break;
case DnsResourceRecordType.FWD:
if ((response.Authority.Count == 1) && (firstAuthority.RDATA is DnsForwarderRecordData fwd) && fwd.Forwarder.Equals("this-server", StringComparison.OrdinalIgnoreCase))
{
//do conditional forwarding via "this-server"
return await ProcessRecursiveQueryAsync(request, remoteEP, protocol, null, fwd.DnssecValidation, false, skipDnsAppAuthoritativeRequestHandlers);
}
else
{
//do conditional forwarding
return await ProcessRecursiveQueryAsync(request, remoteEP, protocol, response.Authority, _dnssecValidation, false, skipDnsAppAuthoritativeRequestHandlers);
}
//do conditional forwarding
return await ProcessRecursiveQueryAsync(request, remoteEP, protocol, response.Authority, _dnssecValidation, false, skipDnsAppAuthoritativeRequestHandlers);
case DnsResourceRecordType.APP:
response = await ProcessAPPAsync(request, remoteEP, response, isRecursionAllowed, protocol);
@@ -1935,6 +1902,41 @@ namespace DnsServerCore.Dns
return response;
}
private async Task<DnsDatagram> AuthoritativeQueryAsync(DnsDatagram request, IPEndPoint remoteEP, DnsTransportProtocol protocol, bool isRecursionAllowed, bool skipDnsAppAuthoritativeRequestHandlers)
{
if (!skipDnsAppAuthoritativeRequestHandlers)
{
foreach (IDnsAuthoritativeRequestHandler requestHandler in _dnsApplicationManager.DnsAuthoritativeRequestHandlers)
{
try
{
DnsDatagram appResponse = await requestHandler.ProcessRequestAsync(request, remoteEP, protocol, isRecursionAllowed);
if (appResponse is not null)
{
if (appResponse.Tag is null)
appResponse.Tag = DnsServerResponseType.Authoritative;
return appResponse;
}
}
catch (Exception ex)
{
_log?.Write(remoteEP, protocol, ex);
}
}
}
DnsDatagram response = _authZoneManager.Query(request);
if (response is not null)
{
response.Tag = DnsServerResponseType.Authoritative;
return response;
}
return null;
}
private async Task<DnsDatagram> ProcessAPPAsync(DnsDatagram request, IPEndPoint remoteEP, DnsDatagram response, bool isRecursionAllowed, DnsTransportProtocol protocol)
{
DnsResourceRecord appResourceRecord = response.Authority[0];
@@ -2059,7 +2061,7 @@ namespace DnsServerCore.Dns
DnsDatagram newRequest = new DnsDatagram(0, false, DnsOpcode.StandardQuery, false, false, request.RecursionDesired, false, false, false, DnsResponseCode.NoError, new DnsQuestionRecord[] { new DnsQuestionRecord(cnameDomain, request.Question[0].Type, request.Question[0].Class) }, null, null, null, _udpPayloadSize, request.DnssecOk ? EDnsHeaderFlags.DNSSEC_OK : EDnsHeaderFlags.None, eDnsClientSubnetOption);
//query authoritative zone first
newResponse = _authZoneManager.Query(newRequest);
newResponse = await AuthoritativeQueryAsync(newRequest, remoteEP, protocol, isRecursionAllowed, skipDnsAppAuthoritativeRequestHandlers);
if (newResponse is null)
{
//not found in auth zone
@@ -2096,19 +2098,9 @@ namespace DnsServerCore.Dns
break;
case DnsResourceRecordType.FWD:
if ((newResponse.Authority.Count == 1) && (firstAuthority.RDATA is DnsForwarderRecordData fwd) && fwd.Forwarder.Equals("this-server", StringComparison.OrdinalIgnoreCase))
{
//do conditional forwarding via "this-server"
newResponse = await RecursiveResolveAsync(newRequest, remoteEP, null, fwd.DnssecValidation, false, false, skipDnsAppAuthoritativeRequestHandlers);
isAuthoritativeAnswer = false;
}
else
{
//do conditional forwarding
newResponse = await RecursiveResolveAsync(newRequest, remoteEP, newResponse.Authority, _dnssecValidation, false, false, skipDnsAppAuthoritativeRequestHandlers);
isAuthoritativeAnswer = false;
}
//do conditional forwarding
newResponse = await RecursiveResolveAsync(newRequest, remoteEP, newResponse.Authority, _dnssecValidation, false, false, skipDnsAppAuthoritativeRequestHandlers);
isAuthoritativeAnswer = false;
break;
case DnsResourceRecordType.APP:
@@ -2216,7 +2208,7 @@ namespace DnsServerCore.Dns
DnsDatagram newRequest = new DnsDatagram(0, false, DnsOpcode.StandardQuery, false, false, request.RecursionDesired, false, false, false, DnsResponseCode.NoError, new DnsQuestionRecord[] { new DnsQuestionRecord(lastDomain, request.Question[0].Type, request.Question[0].Class) }, null, null, null, _udpPayloadSize, request.DnssecOk ? EDnsHeaderFlags.DNSSEC_OK : EDnsHeaderFlags.None, eDnsClientSubnetOption);
//query authoritative zone first
DnsDatagram newResponse = _authZoneManager.Query(newRequest);
DnsDatagram newResponse = await AuthoritativeQueryAsync(newRequest, remoteEP, protocol, isRecursionAllowed, skipDnsAppAuthoritativeRequestHandlers);
if (newResponse is null)
{
//not found in auth zone; do recursion
@@ -2234,17 +2226,8 @@ namespace DnsServerCore.Dns
break;
case DnsResourceRecordType.FWD:
if ((newResponse.Authority.Count == 1) && (firstAuthority.RDATA is DnsForwarderRecordData fwd) && fwd.Forwarder.Equals("this-server", StringComparison.OrdinalIgnoreCase))
{
//do conditional forwarding via "this-server"
newResponse = await RecursiveResolveAsync(newRequest, remoteEP, null, fwd.DnssecValidation, false, false, skipDnsAppAuthoritativeRequestHandlers);
}
else
{
//do conditional forwarding
newResponse = await RecursiveResolveAsync(newRequest, remoteEP, newResponse.Authority, _dnssecValidation, false, false, skipDnsAppAuthoritativeRequestHandlers);
}
//do conditional forwarding
newResponse = await RecursiveResolveAsync(newRequest, remoteEP, newResponse.Authority, _dnssecValidation, false, false, skipDnsAppAuthoritativeRequestHandlers);
break;
case DnsResourceRecordType.APP:
@@ -2366,27 +2349,17 @@ namespace DnsServerCore.Dns
private DnsDatagram ProcessBlockedQuery(DnsDatagram request)
{
DnsDatagram response = null;
if (_blockedZoneManager.TotalZonesBlocked > 0)
response = _blockedZoneManager.Query(request);
DnsDatagram response = _blockedZoneManager.Query(request);
if (response is null)
{
//domain not blocked in blocked zone
if (_blockListZoneManager.TotalZonesBlocked > 0)
{
response = _blockListZoneManager.Query(request); //check in block list zone
if (response is not null)
{
//domain is blocked in block list zone
response.Tag = DnsServerResponseType.Blocked;
return response;
}
}
response = _blockListZoneManager.Query(request); //check in block list zone
if (response is null)
return null; //domain not blocked in block list zone
//domain not blocked in block list zone
return null;
//domain is blocked in block list zone
response.Tag = DnsServerResponseType.Blocked;
return response;
}
else
{
@@ -2505,7 +2478,7 @@ namespace DnsServerCore.Dns
}
else
{
inAllowedZone = (_allowedZoneManager.TotalZonesAllowed > 0) && (_allowedZoneManager.Query(request) is not null);
inAllowedZone = _allowedZoneManager.IsAllowed(request) || _blockListZoneManager.IsAllowed(request);
if (!inAllowedZone)
{
//check in blocked zone and block list zone
@@ -2538,7 +2511,7 @@ 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) });
//check allowed zone
inAllowedZone = (_allowedZoneManager.TotalZonesAllowed > 0) && (_allowedZoneManager.Query(newRequest) is not null);
inAllowedZone = _allowedZoneManager.IsAllowed(newRequest) || _blockListZoneManager.IsAllowed(newRequest);
if (inAllowedZone)
break; //CNAME is in allowed zone
@@ -2743,6 +2716,14 @@ namespace DnsServerCore.Dns
else
dnsCache = _dnsCache;
//check for this-server
if ((conditionalForwarders is not null) && (conditionalForwarders.Count == 1) && (conditionalForwarders[0].RDATA is DnsForwarderRecordData fwd) && fwd.Forwarder.Equals("this-server", StringComparison.OrdinalIgnoreCase))
{
//resolve directly with DNSSEC validation preference
conditionalForwarders = null;
dnssecValidation = fwd.DnssecValidation;
}
DnsDatagram response;
if ((conditionalForwarders is not null) && (conditionalForwarders.Count > 0))
@@ -3414,7 +3395,7 @@ namespace DnsServerCore.Dns
return false; //no need to refresh for this query
}
private void CachePrefetchSamplingTimerCallback(object state)
private async void CachePrefetchSamplingTimerCallback(object state)
{
try
{
@@ -3439,7 +3420,8 @@ namespace DnsServerCore.Dns
{
reQueryAuthZone = false;
DnsDatagram response = _authZoneManager.Query(new DnsDatagram(0, false, DnsOpcode.StandardQuery, false, false, false, false, false, false, DnsResponseCode.NoError, new DnsQuestionRecord[] { eligibleQuerySample }));
DnsDatagram request = new DnsDatagram(0, false, DnsOpcode.StandardQuery, false, false, false, false, false, false, DnsResponseCode.NoError, new DnsQuestionRecord[] { eligibleQuerySample });
DnsDatagram response = await AuthoritativeQueryAsync(request, IPENDPOINT_ANY_0, DnsTransportProtocol.Tcp, true, false);
if (response is null)
{
//zone not hosted; do refresh
@@ -3469,16 +3451,7 @@ namespace DnsServerCore.Dns
case DnsResourceRecordType.FWD: //zone is conditional forwarder
refreshQuery = GetCacheRefreshNeededQuery(eligibleQuerySample, cacheRefreshTrigger);
if ((response.Authority.Count == 1) && (firstAuthority.RDATA as DnsForwarderRecordData).Forwarder.Equals("this-server", StringComparison.OrdinalIgnoreCase))
{
//do conditional forwarding via "this-server"
}
else
{
//do conditional forwarding
conditionalForwarders = response.Authority;
}
conditionalForwarders = response.Authority; //do conditional forwarding
break;
}
}
@@ -3951,8 +3924,8 @@ namespace DnsServerCore.Dns
#endregion
udpListener.ReceiveBufferSize = 64 * 1024;
udpListener.SendBufferSize = 64 * 1024;
udpListener.ReceiveBufferSize = 512 * 1024;
udpListener.SendBufferSize = 512 * 1024;
udpListener.Bind(localEP);

View File

@@ -176,9 +176,12 @@ namespace DnsServerCore.Dns.ZoneManagers
log.Write("DNS Server allowed zone file was saved: " + allowedZoneFile);
}
public DnsDatagram Query(DnsDatagram request)
public bool IsAllowed(DnsDatagram request)
{
return _zoneManager.Query(request);
if (_zoneManager.TotalZones < 1)
return false;
return _zoneManager.Query(request) is not null;
}
#endregion

View File

@@ -43,6 +43,8 @@ namespace DnsServerCore.Dns.ZoneManagers
readonly List<Uri> _allowListUrls = new List<Uri>();
readonly List<Uri> _blockListUrls = new List<Uri>();
IReadOnlyDictionary<string, object> _allowListZone = new Dictionary<string, object>();
IReadOnlyDictionary<string, List<Uri>> _blockListZone = new Dictionary<string, List<Uri>>();
DnsSOARecordData _soaRecord;
@@ -109,9 +111,10 @@ namespace DnsServerCore.Dns.ZoneManagers
return word;
}
private Queue<string> ReadListFile(Uri listUrl, bool isAllowList, Dictionary<string, object> allowedDomains)
private Queue<string> ReadListFile(Uri listUrl, bool isAllowList, out Queue<string> exceptionDomains)
{
Queue<string> domains = new Queue<string>();
exceptionDomains = new Queue<string>();
try
{
@@ -141,7 +144,7 @@ namespace DnsServerCore.Dns.ZoneManagers
if (line.Length == 0)
continue; //skip empty line
if (line.StartsWith("#") || line.StartsWith("!"))
if (line.StartsWith('#') || line.StartsWith("!"))
continue; //skip comment line
if (line.StartsWith("||"))
@@ -153,38 +156,35 @@ namespace DnsServerCore.Dns.ZoneManagers
domain = line.Substring(2, i - 2);
options = line.Substring(i + 1);
if (((options.Length == 0) || (options.StartsWith("$") && (options.Contains("doc") || options.Contains("all")))) && DnsClient.IsDomainNameValid(domain))
domains.Enqueue(domain);
if (((options.Length == 0) || (options.StartsWith('$') && (options.Contains("doc") || options.Contains("all")))) && DnsClient.IsDomainNameValid(domain))
domains.Enqueue(domain.ToLower());
}
else
{
domain = line.Substring(2);
if (DnsClient.IsDomainNameValid(domain))
domains.Enqueue(domain);
domains.Enqueue(domain.ToLower());
}
}
else if (line.StartsWith("@@||"))
{
//adblock format
if (!isAllowList)
//adblock format - exception syntax
i = line.IndexOf('^');
if (i > -1)
{
i = line.IndexOf('^');
if (i > -1)
{
domain = line.Substring(4, i - 4);
options = line.Substring(i + 1);
domain = line.Substring(4, i - 4);
options = line.Substring(i + 1);
if (((options.Length == 0) || (options.StartsWith("$") && (options.Contains("doc") || options.Contains("all")))) && DnsClient.IsDomainNameValid(domain))
allowedDomains.TryAdd(domain, null);
}
else
{
domain = line.Substring(4);
if (((options.Length == 0) || (options.StartsWith('$') && (options.Contains("doc") || options.Contains("all")))) && DnsClient.IsDomainNameValid(domain))
exceptionDomains.Enqueue(domain.ToLower());
}
else
{
domain = line.Substring(4);
if (DnsClient.IsDomainNameValid(domain))
allowedDomains.TryAdd(domain, null);
}
if (DnsClient.IsDomainNameValid(domain))
exceptionDomains.Enqueue(domain.ToLower());
}
}
else
@@ -200,7 +200,7 @@ namespace DnsServerCore.Dns.ZoneManagers
{
secondWord = PopWord(ref line);
if (secondWord.Length == 0)
if ((secondWord.Length == 0) || secondWord.StartsWith('#'))
hostname = firstWord;
else
hostname = secondWord;
@@ -267,11 +267,13 @@ namespace DnsServerCore.Dns.ZoneManagers
return null;
}
private static bool IsZoneAllowed(Dictionary<string, object> allowedDomains, string domain)
private bool IsZoneAllowed(string domain)
{
domain = domain.ToLower();
do
{
if (allowedDomains.TryGetValue(domain, out _))
if (_allowListZone.TryGetValue(domain, out _))
return true;
domain = AuthZoneManager.GetParentZone(domain);
@@ -287,37 +289,57 @@ namespace DnsServerCore.Dns.ZoneManagers
public void LoadBlockLists()
{
//read all allowed domains in dictionary
Dictionary<string, object> allowedDomains = new Dictionary<string, object>();
Dictionary<Uri, Queue<string>> allowListQueues = new Dictionary<Uri, Queue<string>>(_allowListUrls.Count);
Dictionary<Uri, Queue<string>> blockListQueues = new Dictionary<Uri, Queue<string>>(_blockListUrls.Count);
int totalAllowedDomains = 0;
int totalBlockedDomains = 0;
//read all allow lists in a queue
foreach (Uri allowListUrl in _allowListUrls)
{
Queue<string> queue = ReadListFile(allowListUrl, true, null);
if (!allowListQueues.ContainsKey(allowListUrl))
{
Queue<string> allowListQueue = ReadListFile(allowListUrl, true, out Queue<string> blockListQueue);
totalAllowedDomains += allowListQueue.Count;
allowListQueues.Add(allowListUrl, allowListQueue);
totalBlockedDomains += blockListQueue.Count;
blockListQueues.Add(allowListUrl, blockListQueue);
}
}
//read all block lists in a queue
foreach (Uri blockListUrl in _blockListUrls)
{
if (!blockListQueues.ContainsKey(blockListUrl))
{
Queue<string> blockListQueue = ReadListFile(blockListUrl, false, out Queue<string> allowListQueue);
totalBlockedDomains += blockListQueue.Count;
blockListQueues.Add(blockListUrl, blockListQueue);
totalAllowedDomains += allowListQueue.Count;
allowListQueues.Add(blockListUrl, allowListQueue);
}
}
//load block list zone
Dictionary<string, object> allowListZone = new Dictionary<string, object>(totalAllowedDomains);
foreach (KeyValuePair<Uri, Queue<string>> allowListQueue in allowListQueues)
{
Queue<string> queue = allowListQueue.Value;
while (queue.Count > 0)
{
string domain = queue.Dequeue();
allowedDomains.TryAdd(domain, null);
allowListZone.TryAdd(domain, null);
}
}
//read all block lists in a queue
Dictionary<Uri, Queue<string>> blockListQueues = new Dictionary<Uri, Queue<string>>(_blockListUrls.Count);
int totalDomains = 0;
foreach (Uri blockListUrl in _blockListUrls)
{
if (!blockListQueues.ContainsKey(blockListUrl))
{
Queue<string> blockListQueue = ReadListFile(blockListUrl, false, allowedDomains);
totalDomains += blockListQueue.Count;
blockListQueues.Add(blockListUrl, blockListQueue);
}
}
//load block list zone
Dictionary<string, List<Uri>> blockListZone = new Dictionary<string, List<Uri>>(totalDomains);
Dictionary<string, List<Uri>> blockListZone = new Dictionary<string, List<Uri>>(totalBlockedDomains);
foreach (KeyValuePair<Uri, Queue<string>> blockListQueue in blockListQueues)
{
@@ -327,9 +349,6 @@ namespace DnsServerCore.Dns.ZoneManagers
{
string domain = queue.Dequeue();
if (IsZoneAllowed(allowedDomains, domain))
continue; //domain is in allowed list so skip adding it to block list zone
if (!blockListZone.TryGetValue(domain, out List<Uri> blockLists))
{
blockLists = new List<Uri>(2);
@@ -340,16 +359,16 @@ namespace DnsServerCore.Dns.ZoneManagers
}
}
//set new blocked zone
//set new allowed and blocked zones
_allowListZone = allowListZone;
_blockListZone = blockListZone;
LogManager log = _dnsServer.LogManager;
if (log != null)
log.Write("DNS Server block list zone was loaded successfully.");
_dnsServer.LogManager?.Write("DNS Server block list zone was loaded successfully.");
}
public void Flush()
{
_allowListZone = new Dictionary<string, object>();
_blockListZone = new Dictionary<string, List<Uri>>();
}
@@ -451,8 +470,19 @@ namespace DnsServerCore.Dns.ZoneManagers
return downloaded || notModified;
}
public bool IsAllowed(DnsDatagram request)
{
if (_allowListZone.Count < 1)
return false;
return IsZoneAllowed(request.Question[0].Name);
}
public DnsDatagram Query(DnsDatagram request)
{
if (_blockListZone.Count < 1)
return null;
DnsQuestionRecord question = request.Question[0];
List<Uri> blockLists = IsZoneBlocked(question.Name, out string blockedDomain);
@@ -572,6 +602,9 @@ namespace DnsServerCore.Dns.ZoneManagers
public List<Uri> BlockListUrls
{ get { return _blockListUrls; } }
public int TotalZonesAllowed
{ get { return _allowListZone.Count; } }
public int TotalZonesBlocked
{ get { return _blockListZone.Count; } }

View File

@@ -196,6 +196,9 @@ namespace DnsServerCore.Dns.ZoneManagers
public DnsDatagram Query(DnsDatagram request)
{
if (_zoneManager.TotalZones < 1)
return null;
return _zoneManager.Query(request);
}

View File

@@ -12,7 +12,7 @@
<RepositoryType></RepositoryType>
<Description></Description>
<PackageId>DnsServer</PackageId>
<Version>11.0</Version>
<Version>11.0.1</Version>
</PropertyGroup>
<ItemGroup>

View File

@@ -203,7 +203,7 @@ namespace DnsServerCore
try
{
_webServiceLocalAddresses = DnsServer.GetValidKestralLocalAddresses(_webServiceLocalAddresses);
await StartWebServiceAsync();
await StartWebServiceAsync(false);
}
catch (Exception ex)
{
@@ -213,7 +213,7 @@ namespace DnsServerCore
try
{
_webServiceLocalAddresses = new IPAddress[] { IPAddress.Any };
await StartWebServiceAsync();
await StartWebServiceAsync(false);
}
catch (Exception ex2)
{
@@ -221,12 +221,12 @@ namespace DnsServerCore
_log.Write("Attempting to start Web Service on loopback (127.0.0.1) fallback address...");
_webServiceLocalAddresses = new IPAddress[] { IPAddress.Loopback };
await StartWebServiceAsync();
await StartWebServiceAsync(true);
}
}
}
private async Task StartWebServiceAsync()
private async Task StartWebServiceAsync(bool safeMode)
{
WebApplicationBuilder builder = WebApplication.CreateBuilder();
@@ -249,7 +249,7 @@ namespace DnsServerCore
serverOptions.Listen(webServiceLocalAddress, _webServiceHttpPort);
//https
if (_webServiceEnableTls && (_webServiceTlsCertificate is not null))
if (!safeMode && _webServiceEnableTls && (_webServiceTlsCertificate is not null))
{
serverOptions.ConfigureHttpsDefaults(delegate (HttpsConnectionAdapterOptions configureOptions)
{
@@ -277,7 +277,7 @@ namespace DnsServerCore
_webService = builder.Build();
if (_webServiceHttpToTlsRedirect)
if (_webServiceHttpToTlsRedirect && !safeMode && _webServiceEnableTls && (_webServiceTlsCertificate is not null))
_webService.UseHttpsRedirection();
_webService.UseDefaultFiles();
@@ -300,7 +300,7 @@ namespace DnsServerCore
{
_log?.Write(new IPEndPoint(webServiceLocalAddress, _webServiceHttpPort), "Http", "Web Service was bound successfully.");
if (_webServiceEnableTls && (_webServiceTlsCertificate is not null))
if (!safeMode && _webServiceEnableTls && (_webServiceTlsCertificate is not null))
_log?.Write(new IPEndPoint(webServiceLocalAddress, _webServiceHttpPort), "Https", "Web Service was bound successfully.");
}
}
@@ -312,7 +312,7 @@ namespace DnsServerCore
{
_log?.Write(new IPEndPoint(webServiceLocalAddress, _webServiceHttpPort), "Http", "Web Service failed to bind.");
if (_webServiceEnableTls && (_webServiceTlsCertificate is not null))
if (!safeMode && _webServiceEnableTls && (_webServiceTlsCertificate is not null))
_log?.Write(new IPEndPoint(webServiceLocalAddress, _webServiceHttpPort), "Https", "Web Service failed to bind.");
}
@@ -832,7 +832,7 @@ namespace DnsServerCore
foreach (string strBlockListUrl in strBlockListUrlList)
{
if (strBlockListUrl.StartsWith("!"))
if (strBlockListUrl.StartsWith('!'))
{
Uri allowListUrl = new Uri(strBlockListUrl.Substring(1));
@@ -1288,7 +1288,7 @@ namespace DnsServerCore
{
string listUrl = bR.ReadShortString();
if (listUrl.StartsWith("!"))
if (listUrl.StartsWith('!'))
_dnsServer.BlockListZoneManager.AllowListUrls.Add(new Uri(listUrl.Substring(1)));
else
_dnsServer.BlockListZoneManager.BlockListUrls.Add(new Uri(listUrl));
@@ -1710,7 +1710,7 @@ namespace DnsServerCore
{
string listUrl = bR.ReadShortString();
if (listUrl.StartsWith("!"))
if (listUrl.StartsWith('!'))
_dnsServer.BlockListZoneManager.AllowListUrls.Add(new Uri(listUrl.Substring(1)));
else
_dnsServer.BlockListZoneManager.BlockListUrls.Add(new Uri(listUrl));

View File

@@ -237,6 +237,7 @@ namespace DnsServerCore
jsonWriter.WriteNumber("cachedEntries", _dnsWebService.DnsServer.CacheZoneManager.TotalEntries);
jsonWriter.WriteNumber("allowedZones", _dnsWebService.DnsServer.AllowedZoneManager.TotalZonesAllowed);
jsonWriter.WriteNumber("blockedZones", _dnsWebService.DnsServer.BlockedZoneManager.TotalZonesBlocked);
jsonWriter.WriteNumber("allowListZones", _dnsWebService.DnsServer.BlockListZoneManager.TotalZonesAllowed);
jsonWriter.WriteNumber("blockListZones", _dnsWebService.DnsServer.BlockListZoneManager.TotalZonesBlocked);
jsonWriter.WriteEndObject();

View File

@@ -1033,7 +1033,7 @@ namespace DnsServerCore
{
foreach (string strBlockListUrl in blockListUrlList)
{
if (strBlockListUrl.StartsWith("!"))
if (strBlockListUrl.StartsWith('!'))
{
string strAllowListUrl = strBlockListUrl.Substring(1);
@@ -1062,7 +1062,7 @@ namespace DnsServerCore
foreach (string strBlockListUrl in blockListUrlList)
{
if (strBlockListUrl.StartsWith("!"))
if (strBlockListUrl.StartsWith('!'))
{
Uri allowListUrl = new Uri(strBlockListUrl.Substring(1));

View File

@@ -289,16 +289,16 @@ th a {
}
.zone-stats-panel .stats-item {
width: 19.25%;
width: 16%;
float: left;
padding: 6px 4px;
margin-right: 0.75%;
margin-right: 0.65%;
background-color: rgba(51, 122, 183, 0.7);
color: #ffffff;
}
.zone-stats-panel .stats-item .number {
font-size: 15px;
font-size: 14px;
font-weight: bold;
padding: 6px 0;
}

View File

@@ -223,27 +223,32 @@
<div class="zone-stats-panel">
<div class="stats-item">
<div class="number" id="divDashboardStatsZones">10</div>
<div class="title">Hosted Zones</div>
<div class="title">Zones</div>
</div>
<div class="stats-item">
<div class="number" id="divDashboardStatsCachedEntries">10</div>
<div class="title">Cached Entries</div>
<div class="title">Cache</div>
</div>
<div class="stats-item">
<div class="number" id="divDashboardStatsAllowedZones">10</div>
<div class="title">Allowed Zones</div>
<div class="title">Allowed</div>
</div>
<div class="stats-item">
<div class="number" id="divDashboardStatsBlockedZones">10</div>
<div class="title">Blocked Zones</div>
<div class="title">Blocked</div>
</div>
<div class="stats-item">
<div class="number" id="divDashboardStatsAllowListZones">10</div>
<div class="title">Allow List</div>
</div>
<div class="stats-item">
<div class="number" id="divDashboardStatsBlockListZones">10</div>
<div class="title">Block List Zones</div>
<div class="title">Block List</div>
</div>
</div>
@@ -935,7 +940,7 @@
<div class="col-sm-8">
<div class="checkbox">
<label>
<input id="chkDnssecValidation" type="checkbox"> Enable DNSSEC Validation
<input id="chkDnssecValidation" type="checkbox" checked> Enable DNSSEC Validation
</label>
</div>
<div style="padding-top: 5px; padding-left: 20px;">DNS Server will validate all responses from name servers or forwarders when this option is enabled.</div>
@@ -1167,6 +1172,8 @@
<p>Use the following openssl command to convert your TLS certificate that is in PEM format to PKCS #12 certificate (.pfx) format:</p>
<pre>openssl pkcs12 -export -out "example.com.pfx" -inkey "privkey.pem" -in "cert.pem" -certfile "chain.pem"</pre>
</div>
<div style="margin-top: 10px;"><a href="https://blog.technitium.com/2023/02/configuring-dns-over-quic-and-https3.html" target="_blank">Help: Configuring DNS-over-QUIC and HTTPS/3 For Technitium DNS Server</a></div>
</div>
</div>
@@ -1260,7 +1267,7 @@
<div>
<p>Note! These optional DNS server protocol changes will be automatically applied and so you do not need to manually restart the main service. The DNS-over-TLS, DNS-over-QUIC, and DNS-over-HTTPS protocols will be enabled only when a TLS certificate is configured.</p>
<p>These optional DNS server protocols are used to host these as a service. You do not need to enable these optional protocols to use them with Forwarders or Conditional Forwarder Zones.</p>
<p>For DNS-over-HTTP, use <code>http://<span id="lblDoHHost">localhost:8053</span>/dns-query</code> with a TLS terminating reverse proxy like nginx. For DNS-over-TLS, use <code id="lblDoTHost">tls-certificate-domain:853</code>, for DNS-over-QUIC, use <code id="lblDoQHost">tls-certificate-domain:853</code>, and for DNS-over-HTTPS use <code>https://tls-certificate-domain/dns-query</code> to configure supported DNS clients.</p>
<p>For DNS-over-HTTP, use <code>http://<span id="lblDoHHost">localhost:8053</span>/dns-query</code> with a TLS terminating reverse proxy like nginx. For DNS-over-TLS, use <code id="lblDoTHost">tls-certificate-domain:853</code>, for DNS-over-QUIC, use <code id="lblDoQHost">tls-certificate-domain:853</code>, and for DNS-over-HTTPS use <code>https://<span id="lblDoHsHost">tls-certificate-domain</span>/dns-query</code> to configure supported DNS clients.</p>
<p>When using a reverse proxy with the DNS-over-HTTP service, you need to add <code>X-Real-IP</code> header to the proxy request with the IP address of the client to allow the DNS server to know the real IP address of the client originating the request. For example, if you are using nginx as the reverse proxy, you can add <code>proxy_set_header X-Real-IP $remote_addr;</code> to make it work.</p>
<p>DNS-over-QUIC protocol support is not available on all platforms. On Windows, it is available only on Windows 11 (build 22000 or later) and Windows Server 2022. On Linux, it requires <code>libmsquic</code> and <code>openssl v1.1.1</code> to be installed.</p>
<p>Use the following openssl command to convert your TLS certificate that is in PEM format to PKCS #12 certificate (.pfx) format:</p>
@@ -1268,6 +1275,7 @@
</div>
<div style="margin-top: 10px;"><a href="https://blog.technitium.com/2020/07/how-to-host-your-own-dns-over-https-and.html" target="_blank">Help: How To Host Your Own DNS-over-HTTPS And DNS-over-TLS Services</a></div>
<div style="margin-top: 10px;"><a href="https://blog.technitium.com/2023/02/configuring-dns-over-quic-and-https3.html" target="_blank">Help: Configuring DNS-over-QUIC and HTTPS/3 For Technitium DNS Server</a></div>
</div>
</div>
@@ -1446,7 +1454,7 @@
<input type="number" class="form-control" id="txtCacheMaximumEntries" placeholder="entries" style="width: 125px; display: inline;">
<span>(default 10000; set 0 to disable)</span>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The maximum number of entries that the cache can store. A relevant value should be configured by monitoring the Cached Entries value on Dashboard and the server's memory usage to limit the amount of RAM used by the DNS server. A cache entry is a complete Resource Record Set (RR Set) which is a group of records with the same type for a given domain name. When a value is configured, the DNS server will trigger a clean up operation every few minutes and remove least recently used entries to maintain the maximum allowed entries in cache.</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The maximum number of entries that the cache can store. A relevant value should be configured by monitoring the Cache entries value on Dashboard and the server's memory usage to limit the amount of RAM used by the DNS server. A cache entry is a complete Resource Record Set (RR Set) which is a group of records with the same type for a given domain name. When a value is configured, the DNS server will trigger a clean up operation every few minutes and remove least recently used entries to maintain the maximum allowed entries in cache.</div>
</div>
<div class="form-group">
@@ -1630,7 +1638,7 @@
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">
<p>Enter block list URL one below another in the above text field or use the Quick Add list to add known block list URLs.</p>
<p>Add <code>!</code> character at the start of an URL to make it an allow list URL. Domain names in such an allow list URL are prevented from being added to the block list zone.</p>
<p>Add <code>!</code> character at the start of an URL to make it an allow list URL. This option must not be used with allow lists that use <code>Adblock plus</code> format.</p>
</div>
</div>
@@ -1847,6 +1855,7 @@
<div style="margin-top: 10px;">Forwarders are DNS servers which this DNS Server should use to resolve recursive queries. If no forwarders are configured then this DNS server will use preconfigured ROOT SERVERS to perform recursive resolution.</div>
<div style="margin-top: 10px;"><a href="https://blog.technitium.com/2018/06/configuring-dns-server-for-privacy.html" target="_blank">Help: Configuring DNS Server For Privacy & Security</a></div>
<div style="margin-top: 10px;"><a href="https://blog.technitium.com/2023/02/configuring-dns-over-quic-and-https3.html" target="_blank">Help: Configuring DNS-over-QUIC and HTTPS/3 For Technitium DNS Server</a></div>
</div>
<div class="well well-sm form-horizontal">

View File

@@ -1,6 +1,6 @@
/*
Technitium DNS Server
Copyright (C) 2022 Shreyas Zare (shreyas@technitium.com)
Copyright (C) 2023 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
@@ -516,11 +516,14 @@ function saveDhcpScope() {
var btn = $("#btnSaveDhcpScope").button('loading');
HTTPRequest({
url: "/api/dhcp/scopes/set?token=" + sessionData.token + "&name=" + encodeURIComponent(name) + (newName == null ? "" : "&newName=" + encodeURIComponent(newName)) + "&startingAddress=" + encodeURIComponent(startingAddress) + "&endingAddress=" + encodeURIComponent(endingAddress) + "&subnetMask=" + encodeURIComponent(subnetMask) +
url: "/api/dhcp/scopes/set",
method: "POST",
data: "token=" + sessionData.token + "&name=" + encodeURIComponent(name) + (newName == null ? "" : "&newName=" + encodeURIComponent(newName)) + "&startingAddress=" + encodeURIComponent(startingAddress) + "&endingAddress=" + encodeURIComponent(endingAddress) + "&subnetMask=" + encodeURIComponent(subnetMask) +
"&leaseTimeDays=" + leaseTimeDays + "&leaseTimeHours=" + leaseTimeHours + "&leaseTimeMinutes=" + leaseTimeMinutes + "&offerDelayTime=" + offerDelayTime + "&pingCheckEnabled=" + pingCheckEnabled + "&pingCheckTimeout=" + pingCheckTimeout + "&pingCheckRetries=" + pingCheckRetries +
"&domainName=" + encodeURIComponent(domainName) + "&domainSearchList=" + encodeURIComponent(domainSearchList) + "&dnsUpdates=" + dnsUpdates + "&dnsTtl=" + dnsTtl + "&serverAddress=" + encodeURIComponent(serverAddress) + "&serverHostName=" + encodeURIComponent(serverHostName) + "&bootFileName=" + encodeURIComponent(bootFileName) +
"&routerAddress=" + encodeURIComponent(routerAddress) + "&useThisDnsServer=" + useThisDnsServer + (useThisDnsServer ? "" : "&dnsServers=" + encodeURIComponent(dnsServers)) + "&winsServers=" + encodeURIComponent(winsServers) + "&ntpServers=" + encodeURIComponent(ntpServers) + "&ntpServerDomainNames=" + encodeURIComponent(ntpServerDomainNames) +
"&staticRoutes=" + encodeURIComponent(staticRoutes) + "&vendorInfo=" + encodeURIComponent(vendorInfo) + "&capwapAcIpAddresses=" + encodeURIComponent(capwapAcIpAddresses) + "&tftpServerAddresses=" + encodeURIComponent(tftpServerAddresses) + "&genericOptions=" + encodeURIComponent(genericOptions) + "&exclusions=" + encodeURIComponent(exclusions) + "&reservedLeases=" + encodeURIComponent(reservedLeases) + "&allowOnlyReservedLeases=" + allowOnlyReservedLeases + "&blockLocallyAdministeredMacAddresses=" + blockLocallyAdministeredMacAddresses,
processData: false,
success: function (responseJSON) {
refreshDhcpScopes();
btn.button('reset');

View File

@@ -942,9 +942,10 @@ function loadDnsSettings() {
else
$("#txtDnsTlsCertificatePassword").val(responseJSON.response.dnsTlsCertificatePassword);
$("#lblDoHHost").text(window.location.hostname + ":" + responseJSON.response.dnsOverHttpPort);
$("#lblDoHHost").text(window.location.hostname + (responseJSON.response.dnsOverHttpPort == 80 ? "" : ":" + responseJSON.response.dnsOverHttpPort));
$("#lblDoTHost").text("tls-certificate-domain:" + responseJSON.response.dnsOverTlsPort);
$("#lblDoQHost").text("tls-certificate-domain:" + responseJSON.response.dnsOverQuicPort);
$("#lblDoHsHost").text("tls-certificate-domain" + (responseJSON.response.dnsOverHttpsPort == 443 ? "" : ":" + responseJSON.response.dnsOverHttpsPort));
//tsig
$("#tableTsigKeys").html("");
@@ -1651,9 +1652,10 @@ function saveDnsSettings() {
$("#txtWebServiceTlsCertificatePassword").prop("disabled", !responseJSON.response.webServiceEnableTls);
//optional protocols
$("#lblDoHHost").text(window.location.hostname + ":" + responseJSON.response.dnsOverHttpPort);
$("#lblDoHHost").text(window.location.hostname + (responseJSON.response.dnsOverHttpPort == 80 ? "" : ":" + responseJSON.response.dnsOverHttpPort));
$("#lblDoTHost").text("tls-certificate-domain:" + responseJSON.response.dnsOverTlsPort);
$("#lblDoQHost").text("tls-certificate-domain:" + responseJSON.response.dnsOverQuicPort);
$("#lblDoHsHost").text("tls-certificate-domain" + (responseJSON.response.dnsOverHttpsPort == 443 ? "" : ":" + responseJSON.response.dnsOverHttpsPort));
//reload tsig keys
$("#tableTsigKeys").html("");
@@ -1992,6 +1994,7 @@ function refreshDashboard(hideLoader) {
$("#divDashboardStatsCachedEntries").text(responseJSON.response.stats.cachedEntries.toLocaleString());
$("#divDashboardStatsAllowedZones").text(responseJSON.response.stats.allowedZones.toLocaleString());
$("#divDashboardStatsBlockedZones").text(responseJSON.response.stats.blockedZones.toLocaleString());
$("#divDashboardStatsAllowListZones").text(responseJSON.response.stats.allowListZones.toLocaleString());
$("#divDashboardStatsBlockListZones").text(responseJSON.response.stats.blockListZones.toLocaleString());
if (responseJSON.response.stats.totalQueries > 0) {

View File

@@ -8,7 +8,7 @@
<RootNamespace>DnsServerWindowsService</RootNamespace>
<AssemblyName>DnsService</AssemblyName>
<ApplicationIcon>logo2.ico</ApplicationIcon>
<Version>11.0</Version>
<Version>11.0.1</Version>
<Authors>Shreyas Zare</Authors>
<Company>Technitium</Company>
<Product>Technitium DNS Server</Product>

View File

@@ -2,7 +2,7 @@
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
#define MyAppName "Technitium DNS Server"
#define MyAppVersion "11.0"
#define MyAppVersion "11.0.1"
#define MyAppPublisher "Technitium"
#define MyAppURL "https://technitium.com/dns/"
#define MyAppExeName "DnsServerSystemTrayApp.exe"

View File

@@ -5,7 +5,14 @@ LABEL email="support@technitium.com"
LABEL project_url="https://technitium.com/dns/"
LABEL github_url="https://github.com/TechnitiumSoftware/DnsServer"
WORKDIR /etc/dns/
WORKDIR /opt/technitium/dns/
RUN apt update; apt install curl -y; \
curl https://packages.microsoft.com/config/debian/11/packages-microsoft-prod.deb --output packages-microsoft-prod.deb; \
dpkg -i packages-microsoft-prod.deb; \
rm packages-microsoft-prod.deb
RUN apt update; apt install libmsquic -y; apt clean -y;
COPY ./DnsServerApp/bin/Release/publish/ .
@@ -21,6 +28,9 @@ EXPOSE 80/tcp
EXPOSE 8053/tcp
EXPOSE 67/udp
VOLUME ["/etc/dns/config"]
VOLUME ["/etc/dns"]
CMD ["/usr/bin/dotnet", "/etc/dns/DnsServerApp.dll"]
STOPSIGNAL SIGINT
ENTRYPOINT ["/usr/bin/dotnet", "/opt/technitium/dns/DnsServerApp.dll"]
CMD ["/etc/dns"]

View File

@@ -34,7 +34,7 @@ services:
# - DNS_SERVER_FORWARDER_PROTOCOL=Tcp #Forwarder protocol options: Udp, Tcp, Tls, Https, HttpsJson.
# - DNS_SERVER_LOG_USING_LOCAL_TIME=true #Enable this option to use local time instead of UTC for logging.
volumes:
- config:/etc/dns/config
- config:/etc/dns
restart: unless-stopped
sysctls:
- net.ipv4.ip_local_port_range=1024 65000