TechnitiumSoftware / DnsServer

Technitium DNS Server
https://technitium.com/dns/
GNU General Public License v3.0
4.48k stars 431 forks source link

Local UDP forwarders do not work #609

Closed ZzZombo closed 1 year ago

ZzZombo commented 1 year ago
[2023-04-15 13:45:49 Local] DNS Server failed to resolve the request with QNAME: dns.msftncsi.com; QTYPE: A; QCLASS: IN; Forwarders: 127.0.0.2;
System.Net.Sockets.SocketException (10061): Подключение не установлено, т.к. конечный компьютер отверг запрос на подключение.
   at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ThrowException(SocketError error, CancellationToken cancellationToken)
   at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.System.Threading.Tasks.Sources.IValueTaskSource.GetResult(Int16 token)
   at TechnitiumLibrary.Net.Proxy.NetProxy.GetTcpConnectionAsync(EndPoint ep, CancellationToken cancellationToken) in Z:\Technitium\Projects\TechnitiumLibrary\TechnitiumLibrary.Net\Proxy\NetProxy.cs:line 156
   at TechnitiumLibrary.Net.Proxy.NetProxy.ConnectAsync(EndPoint remoteEP, CancellationToken cancellationToken) in Z:\Technitium\Projects\TechnitiumLibrary\TechnitiumLibrary.Net\Proxy\NetProxy.cs:line 228
   at TechnitiumLibrary.Net.Dns.ClientConnection.TcpClientConnection.GetConnectionAsync(CancellationToken cancellationToken) in Z:\Technitium\Projects\TechnitiumLibrary\TechnitiumLibrary.Net\Dns\ClientConnection\TcpClientConnection.cs:line 157
   at TechnitiumLibrary.Net.Dns.ClientConnection.TcpClientConnection.SendDnsDatagramAsync(DnsDatagram request, Int32 timeout, Transaction transaction, CancellationToken cancellationToken) in Z:\Technitium\Projects\TechnitiumLibrary\TechnitiumLibrary.Net\Dns\ClientConnection\TcpClientConnection.cs:line 220
   at TechnitiumLibrary.Net.Dns.ClientConnection.TcpClientConnection.QueryAsync(DnsDatagram request, Int32 timeout, Int32 retries, CancellationToken cancellationToken) in Z:\Technitium\Projects\TechnitiumLibrary\TechnitiumLibrary.Net\Dns\ClientConnection\TcpClientConnection.cs:line 305
   at TechnitiumLibrary.Net.Dns.DnsClient.<>c__DisplayClass67_0.<<InternalResolveAsync>g__DoResolveAsync|1>d.MoveNext() in Z:\Technitium\Projects\TechnitiumLibrary\TechnitiumLibrary.Net\Dns\DnsClient.cs:line 4034
--- End of stack trace from previous location ---
   at TechnitiumLibrary.Net.Dns.DnsClient.<>c__DisplayClass67_0.<<InternalResolveAsync>g__DoResolveAsync|1>d.MoveNext() in Z:\Technitium\Projects\TechnitiumLibrary\TechnitiumLibrary.Net\Dns\DnsClient.cs:line 4212
--- End of stack trace from previous location ---
   at TechnitiumLibrary.Net.Dns.DnsClient.<>c__DisplayClass67_0.<<InternalResolveAsync>g__DoResolveAsync|1>d.MoveNext() in Z:\Technitium\Projects\TechnitiumLibrary\TechnitiumLibrary.Net\Dns\DnsClient.cs:line 3962
--- End of stack trace from previous location ---
   at TechnitiumLibrary.Net.Dns.DnsClient.InternalResolveAsync(DnsDatagram request, CancellationToken cancellationToken) in Z:\Technitium\Projects\TechnitiumLibrary\TechnitiumLibrary.Net\Dns\DnsClient.cs:line 4312
   at TechnitiumLibrary.Net.Dns.DnsClient.InternalDnssecResolveAsync(DnsQuestionRecord question, CancellationToken cancellationToken) in Z:\Technitium\Projects\TechnitiumLibrary\TechnitiumLibrary.Net\Dns\DnsClient.cs:line 4359
   at TechnitiumLibrary.Net.Dns.DnsClient.<>c__DisplayClass71_0.<<InternalCachedResolveQueryAsync>b__0>d.MoveNext() in Z:\Technitium\Projects\TechnitiumLibrary\TechnitiumLibrary.Net\Dns\DnsClient.cs:line 4471
--- End of stack trace from previous location ---
   at TechnitiumLibrary.Net.Dns.DnsClient.ResolveQueryAsync(DnsQuestionRecord question, Func`2 resolveAsync) in Z:\Technitium\Projects\TechnitiumLibrary\TechnitiumLibrary.Net\Dns\DnsClient.cs:line 3891
   at TechnitiumLibrary.Net.Dns.DnsClient.InternalCachedResolveQueryAsync(DnsQuestionRecord question, CancellationToken cancellationToken) in Z:\Technitium\Projects\TechnitiumLibrary\TechnitiumLibrary.Net\Dns\DnsClient.cs:line 4472
   at DnsServerCore.Dns.DnsServer.RecursiveResolveAsync(DnsQuestionRecord question, NetworkAddress eDnsClientSubnet, IReadOnlyList`1 conditionalForwarders, Boolean dnssecValidation, Boolean cachePrefetchOperation, Boolean cacheRefreshOperation, Boolean skipDnsAppAuthoritativeRequestHandlers, TaskCompletionSource`1 taskCompletionSource) in Z:\Technitium\Projects\DnsServer\DnsServerCore\Dns\DnsServer.cs:line 2894

Yet nslookup.exe googl.com 127.0.0.2 and similar tools all have no issues working with the specified resolver. As both the resolver and the software run on the same machine there are absolutely no firewall restrictions. In fact, my machine is expressly set to allow all IN/OUT connections in the private network and the same resolver is also available from my Android phone.

ShreyasZare commented 1 year ago

Thanks for the post. From the error its clear that you have configured either HTTP or SOCKS5 proxy in Technitium DNS Server's settings and that proxy server is not running which is why there is this error System.Net.Sockets.SocketException (10061): The connection was not established because the destination computer denied the connection request logged.

Which is why its not working for local forwarders. Other tools like nslookup will work since they sending request directly. Remove the proxy from settings and it will work as expected.

ZzZombo commented 1 year ago

The proxy is still up. I did want to switch from DoH to UDP for the dnscrypt-proxy forwarder for a long time actually as you've suggested in #608, but this issue stopped me every time. So the only change on my system was to change the forwarder from DoH https://localhost:2000 to UDP localhost:530, the proxy was not touched at all. Are you implying that for some reason TDNS would still try to use a HTTP proxy when talking to a UDP resolver, regardless of the proxy being running or not?

ZzZombo commented 1 year ago

Followed my hunch and indeed disabling the HTTP proxy does fix this issue. So the bug is that the software tries to use incompatible proxies.

ShreyasZare commented 1 year ago

When you configure a HTTP proxy, which supports only TCP connections, the DNS server will use DNS-over-TCP instead of using UDP. So, your forwarder must then support TCP too to receive a connection.

Secondly, if you are connecting to a forwarder on your local network then why do you even want to configure a HTTP proxy in first place? You do not need DoH too for local forwarder.

Just remove the HTTP proxy from settings and use UDP with forwarder.

ZzZombo commented 1 year ago

This is going to be awkward, but for completeness' sake I tried the following: DNS-over-TCP (yes, the forwarder supports this) with the old proxy in use. The end result is still the same. So something doesn't work as expected still. The proxy logs do not show any incoming traffic from TDNS.

ShreyasZare commented 1 year ago

This is going to be awkward, but for completeness' sake I tried the following: DNS-over-TCP (yes, the forwarder supports this) with the old proxy in use. The end result is still the same. So something doesn't work as expected still. The proxy logs do not show any incoming traffic from TDNS.

The proxy logs do not show anything since the DNS server is unable to connect to it. The error you posted says that the DNS server is failing to connect to the proxy server and that the proxy server is refusing connection which indicates that the proxy service is not running on the TCP port that you have configured in the DNS server settings.

I am also failing to understand why you need to use a HTTP proxy for forwarding DNS requests to a locally running dnscrypt-proxy upstream.

ZzZombo commented 1 year ago

I do not need it anymore, it was needed only because previously I couldn't manage to make dnscrypt-proxy use my self-signed certificate, due to my mistake as it turned out, the proxy was easier to get going. Now, for me at least, this issue holds only academic interest.

The thing about the proxy it does listen on the specified interface, protocol and port, I've double and triple checked that I'm sure.

ShreyasZare commented 1 year ago

I do not need it anymore, it was needed only because previously I couldn't manage to make dnscrypt-proxy use my self-signed certificate, due to my mistake as it turned out, the proxy was easier to get going. Now, for me at least, this issue holds only academic interest.

Using HTTP proxy will not fix self signed cert issue. HTTP proxy server just provides a TCP tunnel and does not help with any kind of SSL/TLS security bypass.

The thing about the proxy it does listen on the specified interface, protocol and port, I've double and triple checked that I'm sure.

Try to use something like telnet <proxy-server-IP-address> <port-number> command from the shell of the server that runs the DNS server and see if telnet is able to connect to that IP and port. Make sure that you have same proxy config in the DNS server too.