2

When i go to my local port range on Debian 7, i can see that my ephemeral port range is:

cat /proc/sys/net/ipv4/ip_local_port_range
32768   61000

My /etc/sysctl.conf is empty.

Normally that would mean that all requests coming out from this nameserver resolver should use ports in that range. However, using tcpdump, when i look at a DNS request & answer created with dig, I can see that the request can use a sending port as low as 1500.

For instance, in the following tcpdump example (tcpdump udp and port 53 and host server.domain), the request came from port 15591. It is way below the server lowest port limit for ephemeral ports that we saw before: 32768. In other words, using dig, DNS requests are out of the local port range.

11:57:33.704090 IP baremetal.15591 > M.ROOT-SERVERS.NET.domain: 41939% [1au] A? r.arin.net. (39)
11:57:33.704400 IP baremetal.41573 > M.ROOT-SERVERS.NET.domain: 40945% [1au] A? t.arin.net. (39)
11:57:33.704541 IP baremetal.22658 > M.ROOT-SERVERS.NET.domain: 44090% [1au] AAAA? t.arin.net. (39)
11:57:33.705295 IP baremetal.13277 > M.ROOT-SERVERS.NET.domain: 42356% [1au] A? v.arin.net. (39)
11:57:33.705499 IP baremetal.48755 > M.ROOT-SERVERS.NET.domain: 32253% [1au] A? w.arin.net. (39)
11:57:33.705639 IP baremetal.55309 > M.ROOT-SERVERS.NET.domain: 64660% [1au] AAAA? w.arin.net. (39)
11:57:33.705812 IP baremetal.56652 > M.ROOT-SERVERS.NET.domain: 43023% [1au] A? y.arin.net. (39)
11:57:33.706012 IP baremetal.26383 > M.ROOT-SERVERS.NET.domain: 42377% [1au] AAAA? y.arin.net. (39)
11:57:33.706172 IP baremetal.12895 > M.ROOT-SERVERS.NET.domain: 13206% [1au] AAAA? z.arin.net. (39)

I wonder what could have change the port range of ephemeral ports on my Debian 7 & 8. Only thing that is perhaps worth to mention. I have used on one of them ifenslave & one uses ifenslave to bond two ethernet ports.

The resolver is the server itself and

#cat /etc/resolv.conf
nameserver ::1

but it does exactly the same with nameserver 127.0.0.1 because ipv4 & ipv6 shares /proc/sys/net/ipv4/ip_local_port_range (reference) & also I have tried it.

To avoid confusion with IPv6, I have decided to use Ipv4 only. I have only added nameserver 127.0.0.1 to /etc/resolv.conf.

Results below are with nameserver 127.0.0.1 in /etc/resolv.conf only.

Then, I issued rndc flush to flush the DNS cache from resolver and dig google.com

I opened a second terminal window and typed tcpdump udp and port 53:

Lots of records but I noticed, whatever the request (A,PTR...) & receiving host, DNS requests CAN be issued from port lower than 32768

>strace -f dig www.google.com 2>&1 | egrep 'sendmsg|recvmsg|connect|bind'
open("/usr/lib/libbind9.so.80", O_RDONLY) = 3
[pid 10651] bind(20, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("0.0.0.0")}, 16) = 0
[pid 10651] recvmsg(20, 0x7f5dd95cab60, 0) = -1 EAGAIN (Resource temporarily unavailable)
[pid 10651] sendmsg(20, {msg_name(16)={sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("127.0.0.1")}, msg_iov(1)=[{"\251\261\1\0\0\1\0\0\0\0\0\0\3www\6google\3com\0\0\1\0\1", 32}], msg_controllen=0, msg_flags=0}, 0 <unfinished ...>
[pid 10651] <... sendmsg resumed> )     = 32
[pid 10651] recvmsg(20, {msg_name(16)={sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("127.0.0.1")}, msg_iov(1)=[{"\251\261\201\200\0\1\0\1\0\4\0\4\3www\6google\3com\0\0\1\0\1"..., 65535}], msg_controllen=32, {cmsg_len=32, cmsg_level=SOL_SOCKET, cmsg_type=0x1d /* SCM_??? */, ...}, msg_flags=0}, 0) = 184

This issue is related to my firewall. Since ephemeral ports can be issued from (my own guess) 1024 to 65000, it means that I can't block input traffic coming from ports higher than 1024 just like in the old days. If I do this I will slow down or block DNS resolution.

UPDATE: thank you, I understand that if I want to use a server as a DNS resolver it means that I have to consider that UDP port range 1024:65535 is the ephemeral port range.

  • 2
    That's interesting. I just tried this on a Ubuntu 14.04 LTS box in Amazon EC2, and it does not exhibit the behaviour in question. 1. What specific distro of Linux is this? 2. What version of dig? 3. Where are you running tcpdump - is it on the same box that's running dig? – Per von Zweigbergk Oct 11 '15 at 5:50
  • Hi, you are right, there is something strange here. I had this result with debian 7. With debian 8, requests are in the range. I will further investigate. – Nicolas Guérinet Oct 11 '15 at 7:46
  • Are you running tcpdump on the same box as you're running dig, or are you looking somewhere else in the network path? – Per von Zweigbergk Oct 11 '15 at 7:52
  • On the Debian 7. I use 2 servers. One nameserver and one server sending dig. For the one that sends dig i opened another terminal window and catch the packet using tcpdump. It looks like something has modified ip_local_port_range. – Nicolas Guérinet Oct 11 '15 at 7:58
  • 2
    Can you post the output of this: strace -f dig www.google.com 2>&1 | egrep 'sendmsg|recvmsg|connect|bind' - Specifically interesting would be the sin_port argument to bind. – Per von Zweigbergk Oct 11 '15 at 8:10
3

I don't think there is anything wrong with your ip_local_port_range setting or that it wouldn't normally be applicable to this type of scenario, I rather believe this is directly related to making spoofing DNS replies harder.

We see in your strace output that you have dig sending a datagram to 127.0.0.1 (some resolver server running there) but the tcpdump output seems to be relating to the traffic from that resolver server, not dig itself.


Plain old DNS (without DNSSEC) relies on only the transaction id (16 bits) and the data in the question section to match up the response received over UDP with the query that was sent earlier.

With UDP datagrams easy to spoof and with only 16 bits of randomness that need to be guessed if you have a specific name as the target, this makes it quite possible to guess the right transaction id (32k guesses on average) before the real answer arrives.

Therefore, all modern resolver servers will go out of their way to randomize a source port to increase the number of random bits that need to be guessed.

You really wants as large a span of ports as is possible so presumably it will randomize in the whole range of ports >1024, which will add a significant number of bits of randomness compared to what your OS's default handling would give you.


Ie, I think it's simply considered "best practice" to ignore the normal OS handling of local ports for sockets.

  • This is probably what's going on! But dig is not the one doing this (as you can see from the strace output, it's just binding with sin_port=htons(0), it's rather the local DNS server that he ommitted to mention that he's running on the box that's doing it. :-) That would also be why it was not observable when I was testing it, since the box I was running on didn't have a local DNS server. – Per von Zweigbergk Oct 11 '15 at 9:49
  • @PervonZweigbergk Ah, that's quite possible. Looking at the `strace´ output that seems to fit better as well. If they confirm I'll adjust the answer based on this. – Håkan Lindqvist Oct 11 '15 at 9:55
  • Note how the strace output connects to 127.0.0.1, and he's been sniffing on the outside interface, that's definitely what's going on here. – Per von Zweigbergk Oct 11 '15 at 9:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.