Use netcat to Convert UDP DNS Queries to TCP DNS Queries

0

I'm running Debian 9 on an isolated network and need DNS services to resolve external hostnames.

(I'm sure some will wonder why I need to be able to resolve external hostnames if I'm on an insolated network, but that's more detail than I need to go into here to pose my question. Suffice it to say, this need does exist.)

On the isolated host from which I need to be able to resolve external host names, I've set up this SSH tunnel:

ssh -N -L localhost:53:192.168.13.14:53 myUserId@jumpServer

Here, 192.168.13.14 is a DNS server that can resolve all names, globally. This SSH tunnel forwards anything heard on local TCP port 53 to TCP port 53 on 192.168.13.14.

I can use dig to resolve a hostname by specifying that the query should be made using TCP port 53, rather than the usual UDP port 53:

root@isolatedHost:~# dig @localhost +vc example.com

; <<>> DiG 9.10.3-P4-Debian <<>> @localhost +vc example.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 53054
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;example.com.                   IN      A

;; ANSWER SECTION:
example.com.            3600    IN      A       93.184.216.34

;; Query time: 133 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Wed Dec 20 15:21:01 MST 2017
;; MSG SIZE  rcvd: 56

The key to making this example work is that:

  1. dig has the "+vc+" ("virtual circuit") flag that allows you to tell it to use TCP rather than the usual UDP
  2. Our nameserver (the one at 192.168.13.14) is configured to accept normal recursive queries on TCP as well as the usual UDP

Of course, dig is special. It can be told to use TCP rather than UDP. In the generic case of a random application calling into the local resolver library, the query will always be done via the usual UDP.

The problem with my SSH tunnel is that SSH can only forward TCP ports. It cannot forward UDP ports. So, I need a way to convert all DNS queries from the usual UDP to TCP. They can then get out of our isolated network via the SSH tunnel and make their way to the nameserver.

The first thing that comes to mind is netcat:

nc -u -l -p 53 | nc localhost 53

This, unfortunately, does not work, and I am not yet sure why.

Does anybody have a solution to forwarding UDP DNS queries out if an isolated network, using netcat in conjunction with an SSH tunnel or otherwise?

Dave

Posted 2017-12-20T22:46:36.957

Reputation: 597

You can't simply convert a UDP datagram to a TCP segment. UDP is connectionless, but TCP requires a connection between the hosts. The DNS query must be made with TCP from the start because TCP must first establish a connection between the requester and respondent. A proper DNS implementation is required to support TCP, per RFC 7766: "This document therefore updates the core DNS protocol specifications such that support for TCP is henceforth a REQUIRED part of a full DNS protocol implementation." Your application and OS must support TCP for DNS.

– Ron Maupin – 2017-12-20T22:56:17.220

XY problem. How to configure Linux to use TCP for DNS queries?

– Kamil Maciorowski – 2017-12-20T22:58:26.897

Yes, the intent was that for every UDP packet that comes in (and the stack does hand off complete fragments to the app, not fragments), a TCP connection would be established, the UDP payload sent over the TCP connection, and the TCP connection closed. My first-try netcat command was too simplistic.

Thanks to both Ron and Kamil!

I will look at the link "How to configure Linux to use TCP for DNS Queries". This sounds perfect, except that I do not have a guarantee that any arbitrary application that comes along will use the system resolver. – Dave – 2017-12-21T01:10:06.000

Want to correct my last comment, but cannot edit it for some reason...

"(and the stack does hand off complete packets (not fragments) to the app, not fragments...") – Dave – 2017-12-21T01:42:25.663

@Dave comment edit time is limited to 3 minutes (so far as I know). After that, you just have to copy/paste/correct and post as a new comment (likely deleting the old one, assuming it isn't correct/relevant). – Anaksunaman – 2017-12-21T04:26:05.160

No answers