diff --git a/Apps/BlockPageApp/App.cs b/Apps/BlockPageApp/App.cs index 1fe460ace..a1caf5aff 100644 --- a/Apps/BlockPageApp/App.cs +++ b/Apps/BlockPageApp/App.cs @@ -473,7 +473,8 @@ private async Task ServeDefaultPageAsync(HttpContext context, RequestDelegate ne if (host is not null) { DnsDatagram dnsRequest = new DnsDatagram(0, false, DnsOpcode.StandardQuery, false, false, true, false, false, false, DnsResponseCode.NoError, [new DnsQuestionRecord(host, DnsResourceRecordType.A, DnsClass.IN)], udpPayloadSize: DnsDatagram.EDNS_DEFAULT_UDP_PAYLOAD_SIZE); - DnsDatagram dnsResponse = await _dnsServer.DirectQueryAsync(dnsRequest, 500); + System.Net.IPEndPoint clientEndPoint = context.Connection.RemoteIpAddress is null ? new System.Net.IPEndPoint(System.Net.IPAddress.Any, 0) : new System.Net.IPEndPoint(context.Connection.RemoteIpAddress, context.Connection.RemotePort); + DnsDatagram dnsResponse = await _dnsServer.DirectQueryAsync(dnsRequest, clientEndPoint, 500); List options = new List(); diff --git a/DnsServerCore.ApplicationCommon/IDnsServer.cs b/DnsServerCore.ApplicationCommon/IDnsServer.cs index fd9b3a9ef..485c5172d 100644 --- a/DnsServerCore.ApplicationCommon/IDnsServer.cs +++ b/DnsServerCore.ApplicationCommon/IDnsServer.cs @@ -18,6 +18,7 @@ You should have received a copy of the GNU General Public License */ using System; +using System.Net; using System.Net.Mail; using System.Threading; using System.Threading.Tasks; @@ -51,6 +52,17 @@ public interface IDnsServer : IDnsClient /// When request times out. Task DirectQueryAsync(DnsDatagram request, int timeout = 4000, CancellationToken cancellationToken = default); + /// + /// Allows querying the DNS server core directly on behalf of a specific client endpoint. This overload passes the supplied through the full query pipeline, allowing DNS Apps that perform client-based group mapping (such as the Advanced Blocking App) to apply the correct policy for the originating client rather than treating the query as originating from 0.0.0.0. The request wont be routed to any of the installed DNS Apps except for processing APP records. The request and its response are not counted in any stats or logged. + /// + /// The DNS request to query. + /// The client endpoint to present to the query pipeline. + /// The timeout value in milliseconds to wait for response. + /// The cancellation token to cancel the operation. + /// The DNS response for the DNS query. + /// When request times out. + Task DirectQueryAsync(DnsDatagram request, IPEndPoint remoteEndPoint, int timeout = 4000, CancellationToken cancellationToken = default); + /// /// Writes a log entry to the DNS server log file. /// diff --git a/DnsServerCore/Dns/Applications/InternalDnsServer.cs b/DnsServerCore/Dns/Applications/InternalDnsServer.cs index 9b2d14e47..0e23b6f56 100644 --- a/DnsServerCore/Dns/Applications/InternalDnsServer.cs +++ b/DnsServerCore/Dns/Applications/InternalDnsServer.cs @@ -19,6 +19,7 @@ You should have received a copy of the GNU General Public License using DnsServerCore.ApplicationCommon; using System; +using System.Net; using System.Net.Mail; using System.Threading; using System.Threading.Tasks; @@ -62,6 +63,11 @@ public Task DirectQueryAsync(DnsDatagram request, int timeout = 400 return _dnsServer.DirectQueryAsync(request, timeout, true, cancellationToken); } + public Task DirectQueryAsync(DnsDatagram request, IPEndPoint remoteEndPoint, int timeout = 4000, CancellationToken cancellationToken = default) + { + return _dnsServer.DirectQueryAsync(request, remoteEndPoint, timeout, true, cancellationToken); + } + public Task ResolveAsync(DnsQuestionRecord question, CancellationToken cancellationToken = default) { return DirectQueryAsync(question, cancellationToken: cancellationToken); diff --git a/DnsServerCore/Dns/DnsServer.cs b/DnsServerCore/Dns/DnsServer.cs index 2f0734092..12605ed4d 100644 --- a/DnsServerCore/Dns/DnsServer.cs +++ b/DnsServerCore/Dns/DnsServer.cs @@ -6954,6 +6954,14 @@ public Task DirectQueryAsync(DnsDatagram request, int timeout = 400 }, timeout, cancellationToken); } + public Task DirectQueryAsync(DnsDatagram request, IPEndPoint remoteEndPoint, int timeout = 4000, bool skipDnsAppAuthoritativeRequestHandlers = false, CancellationToken cancellationToken = default) + { + return TechnitiumLibrary.TaskExtensions.TimeoutAsync(delegate (CancellationToken cancellationToken1) + { + return ProcessQueryAsync(request, remoteEndPoint, DnsTransportProtocol.Tcp, true, skipDnsAppAuthoritativeRequestHandlers, timeout, null); + }, timeout, cancellationToken); + } + Task IDnsClient.ResolveAsync(DnsQuestionRecord question, CancellationToken cancellationToken) { return DirectQueryAsync(question, cancellationToken: cancellationToken);