From e0de65670521a70490811db6dff3442d64dc6885 Mon Sep 17 00:00:00 2001 From: Damob Date: Thu, 25 Aug 2022 11:02:59 +0900 Subject: [PATCH 1/4] Add DNS over HTTPS --- DNS/Client/DnsClient.cs | 3 + .../RequestResolver/HttpsRequestResolver.cs | 59 +++++++++++++++++++ DNS/Server/DnsServer.cs | 7 +++ 3 files changed, 69 insertions(+) create mode 100644 DNS/Client/RequestResolver/HttpsRequestResolver.cs diff --git a/DNS/Client/DnsClient.cs b/DNS/Client/DnsClient.cs index 2a7a7a9..82f6eeb 100644 --- a/DNS/Client/DnsClient.cs +++ b/DNS/Client/DnsClient.cs @@ -26,6 +26,9 @@ public DnsClient(string ip, int port = DEFAULT_PORT) : public DnsClient(IRequestResolver resolver) { this.resolver = resolver; } + public DnsClient(Uri uri) : + this(new HttpsRequestResolver(uri)) + { } public ClientRequest FromArray(byte[] message) { Request request = Request.FromArray(message); diff --git a/DNS/Client/RequestResolver/HttpsRequestResolver.cs b/DNS/Client/RequestResolver/HttpsRequestResolver.cs new file mode 100644 index 0000000..22a3255 --- /dev/null +++ b/DNS/Client/RequestResolver/HttpsRequestResolver.cs @@ -0,0 +1,59 @@ +using System; +using System.Net; +using System.Net.Sockets; +using System.Threading; +using System.Threading.Tasks; +using System.IO; +using System.Net.Http; +using System.Net.Http.Headers; +using DNS.Protocol; +using DNS.Protocol.Utils; + +namespace DNS.Client.RequestResolver { + public class HttpsRequestResolver : IRequestResolver { + private int timeout; + private IRequestResolver fallback; + private IPEndPoint dns; + private HttpClient httpClient; + private void SetUpClient(Uri uri) + { + httpClient = new HttpClient() + { + BaseAddress = uri, + Timeout = TimeSpan.FromMilliseconds(timeout) + //DefaultRequestVersion = new Version(2, 0), + }; + httpClient.DefaultRequestHeaders.Add("Accept", "application/dns-message"); + + } + public HttpsRequestResolver(Uri uri, IRequestResolver fallback, int timeout = 5000) { + this.fallback = fallback; + this.timeout = timeout; + SetUpClient(uri); + } + + public HttpsRequestResolver(Uri uri, int timeout = 5000) { + this.fallback = new NullRequestResolver(); + this.timeout = timeout; + SetUpClient(uri); + } + + public async Task Resolve(IRequest request, CancellationToken cancellationToken = default(CancellationToken)) { + var httpRequest = new HttpRequestMessage(HttpMethod.Post, "") + { + Content = new ByteArrayContent(request.ToArray(), 0, request.Size) + }; + httpRequest.Content.Headers.ContentType = new MediaTypeHeaderValue("application/dns-message"); + var httpResponse = await httpClient.SendAsync(httpRequest).WithCancellationTimeout(TimeSpan.FromMilliseconds(timeout), cancellationToken).ConfigureAwait(false); + Byte[] buffer = await httpResponse.Content.ReadAsByteArrayAsync(); + Response response = Response.FromArray(buffer); + + if (response.Truncated) + { + return await fallback.Resolve(request, cancellationToken).ConfigureAwait(false); + } + + return new ClientResponse(request, response, buffer); + } + } +} diff --git a/DNS/Server/DnsServer.cs b/DNS/Server/DnsServer.cs index efd997b..172fa63 100644 --- a/DNS/Server/DnsServer.cs +++ b/DNS/Server/DnsServer.cs @@ -35,6 +35,10 @@ public DnsServer(IRequestResolver resolver, IPAddress endServer, int port = DEFA public DnsServer(IRequestResolver resolver, string endServer, int port = DEFAULT_PORT) : this(resolver, IPAddress.Parse(endServer), port) {} + public DnsServer(IRequestResolver resolver, Uri uri) : + this(new FallbackRequestResolver(resolver, new HttpsRequestResolver(uri))) + { } + public DnsServer(IPEndPoint endServer) : this(new UdpRequestResolver(endServer)) {} @@ -47,6 +51,9 @@ public DnsServer(string endServer, int port = DEFAULT_PORT) : public DnsServer(IRequestResolver resolver) { this.resolver = resolver; } + public DnsServer(Uri uri) : + this(new HttpsRequestResolver(uri)) + { } public Task Listen(int port = DEFAULT_PORT, IPAddress ip = null) { return Listen(new IPEndPoint(ip ?? IPAddress.Any, port)); From 154954883ca15fc735384c27bd3d3ddf6bb88427 Mon Sep 17 00:00:00 2001 From: Damob Date: Thu, 25 Aug 2022 13:27:35 +0900 Subject: [PATCH 2/4] Add Dns Over https Example --- Examples/ClientServer/ClientServerExample.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Examples/ClientServer/ClientServerExample.cs b/Examples/ClientServer/ClientServerExample.cs index 65840c8..0d85d94 100644 --- a/Examples/ClientServer/ClientServerExample.cs +++ b/Examples/ClientServer/ClientServerExample.cs @@ -13,7 +13,8 @@ public static void Main(string[] args) { public async static Task MainAsync() { MasterFile masterFile = new MasterFile(); - DnsServer server = new DnsServer(masterFile, "8.8.8.8"); + //Dns Proxy to Dns over https + DnsServer server = new DnsServer(masterFile, new Uri("https://1.1.1.1/dns-query")); masterFile.AddIPAddressResourceRecord("google.com", "127.0.0.1"); From 18215ea8ff0f8f399c1095ba5538aa353feac684 Mon Sep 17 00:00:00 2001 From: Damob Date: Thu, 25 Aug 2022 13:38:17 +0900 Subject: [PATCH 3/4] Add Dns over Https description in readme --- README.md | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 5a93fa6..878cd40 100644 --- a/README.md +++ b/README.md @@ -99,7 +99,7 @@ It's also possible to modify the `request` instance in the `server.Requested` ca ### Request Resolver -The `DnsServer`, `DnsClient` and `ClientRequest` classes also accept an instance implementing the `IRequestResolver` interface, which they internally use to resolve DNS requests. Some of the default implementations are `UdpRequestResolver`, `TcpRequestResolver` and `MasterFile` classes. But it's also possible to provide a custom request resolver. +The `DnsServer`, `DnsClient` and `ClientRequest` classes also accept an instance implementing the `IRequestResolver` interface, which they internally use to resolve DNS requests. Some of the default implementations are `UdpRequestResolver`, `TcpRequestResolver`, `HttpsRequestResolver` and `MasterFile` classes. But it's also possible to provide a custom request resolver. ```C# // A request resolver that resolves all dns queries to localhost @@ -124,3 +124,17 @@ DnsServer server = new DnsServer(new LocalRequestResolver()); await server.Listen(); ``` + +### Support Dns Over Https + +DNS over HTTPS (DoH), DNS queries and responses are encrypted and sent via the HTTP or HTTP/2 protocols. DoH ensures that attackers cannot forge or alter DNS traffic. DoH uses port 443, which is the standard HTTPS traffic port, to wrap the DNS query in an HTTPS request. DNS queries and responses are camouflaged within other HTTPS traffic, since it all comes and goes from the same port. + +[https://developers.cloudflare.com/1.1.1.1/encryption/dns-over-https/](https://developers.cloudflare.com/1.1.1.1/encryption/dns-over-https/) + +```C# +// DoH Proxy Server +MasterFile masterFile = new MasterFile(); +DnsServer server = new DnsServer(masterFile, new Uri("https://1.1.1.1/dns-query")); +// DoH Client +DnsClient client = new DnsClient(new Uri("https://1.1.1.1/dns-query")) +``` From 0fbda2db356e94dad9123914fa1c43de476d30c1 Mon Sep 17 00:00:00 2001 From: Damob Date: Wed, 12 Oct 2022 14:39:33 +0900 Subject: [PATCH 4/4] Delete unused imports --- DNS/Client/RequestResolver/HttpsRequestResolver.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/DNS/Client/RequestResolver/HttpsRequestResolver.cs b/DNS/Client/RequestResolver/HttpsRequestResolver.cs index 22a3255..282ea57 100644 --- a/DNS/Client/RequestResolver/HttpsRequestResolver.cs +++ b/DNS/Client/RequestResolver/HttpsRequestResolver.cs @@ -1,9 +1,6 @@ using System; -using System.Net; -using System.Net.Sockets; using System.Threading; using System.Threading.Tasks; -using System.IO; using System.Net.Http; using System.Net.Http.Headers; using DNS.Protocol; @@ -13,7 +10,6 @@ namespace DNS.Client.RequestResolver { public class HttpsRequestResolver : IRequestResolver { private int timeout; private IRequestResolver fallback; - private IPEndPoint dns; private HttpClient httpClient; private void SetUpClient(Uri uri) { @@ -24,7 +20,6 @@ private void SetUpClient(Uri uri) //DefaultRequestVersion = new Version(2, 0), }; httpClient.DefaultRequestHeaders.Add("Accept", "application/dns-message"); - } public HttpsRequestResolver(Uri uri, IRequestResolver fallback, int timeout = 5000) { this.fallback = fallback; @@ -43,6 +38,7 @@ public HttpsRequestResolver(Uri uri, int timeout = 5000) { { Content = new ByteArrayContent(request.ToArray(), 0, request.Size) }; + httpRequest.Content.Headers.ContentType = new MediaTypeHeaderValue("application/dns-message"); var httpResponse = await httpClient.SendAsync(httpRequest).WithCancellationTimeout(TimeSpan.FromMilliseconds(timeout), cancellationToken).ConfigureAwait(false); Byte[] buffer = await httpResponse.Content.ReadAsByteArrayAsync();