Persistent tcp-upstream

Hello,

I'm using unbound with a TCP upstream [1]:

    server:
      tcp-upstream: yes
      do-not-query-localhost: no
    forward-zone:
      name: "."
      forward-addr: 192.0.2.53

However one problem I find when using "tcp-upstream: yes" is that it
seems to only open one connection per DNS request [2]:

    $ for a in $(seq 0 300) ; do dig test$a.ldn-fai.net ; done &> /dev/null
    $ netstat -tnp | grep 192.0.2.53:53 | grep TIME_WAIT | wc -l
    300

This is quite suboptimal, especially when the connection is
encapsulated over TLS [1], and leads to many TIME_WAIT
connections. In order to overcome this problem, I wrote a prototypical
daemon which aggregates DNS requests over a single persistent TCP
connection [3]:

    [DNS]<->[DNS ]<->[DNS ]<---------------------->[DNS]
    [UDP]<->[UDP|TCP]<->[TCP ]<---------------------->[TCP]
    [IP ]<->[IP ]<->[IP ]<---------------------->[IP ]
    Client Aggregator Forwarder Internet Recursive
             (dnsfwd) (unbound)

However, having to use (and compile) a dedicated tool is not very user
friendly.

Is this behaviour expected or am I missing some configuration option
in order to reuse TCP connections for multiple requests?

Thanks,

[1] http://www.gabriel.urdhr.fr/2015/02/14/recursive-dns-over-tls-over-tcp-443/

[2] http://www.gabriel.urdhr.fr/2015/12/09/dns-aggregator-tls/

[3] https://github.com/randomstuff/dnsfwd

This is cool :slight_smile:

A couple of questions:

I can't see where you are handling truncated responses. Since your
upstream queries are over TCP, the responses can be too big to return
to a UDP client - you need to strip them down and set the TC bit.

I think, if I understand service::add_request() and client::add_request()
correctly, you only have one outstanding query on the upstream connection
at a time. You can reduce latency by pipelining queries over TCP. Make
sure to allow for out-of-order responses!

Tony.