mirror of
https://github.com/fergalmoran/DnsServer.git
synced 2026-01-07 17:24:02 +00:00
Merge branch 'develop'
This commit is contained in:
@@ -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",
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
"enableBlocking": true,
|
||||
"allowTxtBlockingReport": true,
|
||||
"blocked": [
|
||||
"use-application-dns.net"
|
||||
"use-application-dns.net",
|
||||
"mask.icloud.com",
|
||||
"mask-h2.icloud.com"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"enableLogging": true,
|
||||
"maxLogDays": 0,
|
||||
"maxLogDays": 7,
|
||||
"sqliteDbPath": "querylogs.db",
|
||||
"connectionString": "Data Source='{sqliteDbPath}'; Cache=Shared;"
|
||||
}
|
||||
|
||||
14
CHANGELOG.md
14
CHANGELOG.md
@@ -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
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 "================================="
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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; } }
|
||||
|
||||
|
||||
@@ -196,6 +196,9 @@ namespace DnsServerCore.Dns.ZoneManagers
|
||||
|
||||
public DnsDatagram Query(DnsDatagram request)
|
||||
{
|
||||
if (_zoneManager.TotalZones < 1)
|
||||
return null;
|
||||
|
||||
return _zoneManager.Query(request);
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<RepositoryType></RepositoryType>
|
||||
<Description></Description>
|
||||
<PackageId>DnsServer</PackageId>
|
||||
<Version>11.0</Version>
|
||||
<Version>11.0.1</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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));
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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"
|
||||
|
||||
16
Dockerfile
16
Dockerfile
@@ -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"]
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user