# dnsmasq and privileged ports

## toralf

Today I realized at my server that a 

```
strace -p `pgrep dnsmasq` 2>&1 | grep -B 5 EACCE
```

spews a lot of findings like

```
bind(29, {sa_family=AF_INET, sin_port=htons(95), sin_addr=inet_addr("0.0.0.0")}, 16) = -1 EACCES (Permission denied)
```

 The author of dnsmasq gave me the hint to use 

```
--min-port=1024
```

Now I do wonder why the dnsmasq at the server can't use privileged ports. FWIW an 

```
 setcap 'CAP_NET_BIND_SERVICE=+eip' /usr/sbin/dnsmasq
```

doesn't helped.

----------

## Hu

What is the output of cat -n /proc/$(pgrep dnsmasq)/status?

----------

## toralf

 *Hu wrote:*   

> What is the output of cat -n /proc/$(pgrep dnsmasq)/status?

 

```
mr-fox ~ # cat -n /proc/$(pgrep dnsmasq)/status

     1  Name:   dnsmasq

     2  Umask:  0022

     3  State:  S (sleeping)

     4  Tgid:   19647

     5  Ngid:   0

     6  Pid:    19647

     7  PPid:   1

     8  TracerPid:      0

     9  Uid:    104     104     104     104

    10  Gid:    242     242     242     242

    11  FDSize: 128

    12  Groups:  

    13  NStgid: 19647

    14  NSpid:  19647

    15  NSpgid: 19646

    16  NSsid:  19646

    17  VmPeak:    26832 kB

    18  VmSize:    26832 kB

    19  VmLck:         0 kB

    20  VmPin:         0 kB

    21  VmHWM:      5048 kB

    22  VmRSS:      5048 kB

    23  RssAnon:            2668 kB

    24  RssFile:            2380 kB

    25  RssShmem:              0 kB

    26  VmData:     2828 kB                                                                                     

    27  VmStk:       132 kB                                                                                     

    28  VmExe:       328 kB                                                                                     

    29  VmLib:      3068 kB                                                                                     

    30  VmPTE:        68 kB                                                                                     

    31  VmPMD:        12 kB                                                                                     

    32  VmSwap:        0 kB

    33  Threads:        1

    34  SigQ:   0/255389

    35  SigPnd: 0000000000000000

    36  ShdPnd: 0000000000000000

    37  SigBlk: 0000000000000000

    38  SigIgn: 0000000000001000

    39  SigCgt: 0000000000016a01

    40  CapInh: 0000000000000000

    41  CapPrm: 0000000000003000

    42  CapEff: 0000000000003000

    43  CapBnd: 0000003fffffffff

    44  CapAmb: 0000000000000000

    45  NoNewPrivs:     0

    46  Seccomp:        0

    47  Cpus_allowed:   fff

    48  Cpus_allowed_list:      0-11

    49  voluntary_ctxt_switches:        4101625

    50  nonvoluntary_ctxt_switches:     56342

mr-
```

----------

## mike155

1) Please look at the lines following the bind request. Is the bind request part of an outgoing request to an DNS server? Below in an example of such a request:

```
bind(11, {sa_family=AF_INET, sin_port=htons(20189), sin_addr=inet_addr("0.0.0.0")}, 16) = 0

sendto(11, "\277l\1\0\0\1\0\0\0\0\0\0\3www\6google\2de\0\0\34\0\1", 31, 0, \

    {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("W.X.Y.Z")}, 16) = 31

...

recvfrom(11, "\277l\201\200\0\1\0\1\0\0\0\0\3www\6google\2de\0\0\34\0\1\300"..., 5131, 0, \

    {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("W.X.Y.Z")}, [16]) = 59

```

Or is it something else?

2) What is the output of "cat /proc/sys/net/ipv4/ip_local_port_range"?

----------

## toralf

 *mike155 wrote:*   

> 1) Please look at the lines following the bind request. Is the bind request part of an outgoing request to an DNS server? Below in an example of such a request:
> 
> ```
> bind(11, {sa_family=AF_INET, sin_port=htons(20189), sin_addr=inet_addr("0.0.0.0")}, 16) = 0
> 
> ...

 

```
bind(18, {sa_family=AF_INET6, sin6_port=htons(39368), inet_pton(AF_INET6, "::", &sin6_addr), sin6_flowinfo=htonl(0), sin6_scope_id=0}, 28) = 0

sendto(18, "Bq\1\0\0\1\0\0\0\0\0\1\23ARcherYBraNDApPareL"..., 52, 0, {sa_family=AF_INET6, sin6_port=htons(53), inet_pton(AF_INET6, "2a01:4f8:0:a0a1::add:1010", &sin6_addr), sin6_flowinfo=htonl(0), sin6_scope_id=0}, 28) = 52

recvfrom(18, "Bq\201\200\0\1\0\0\0\6\0\1\23ARcherYBraNDApPareL"..., 5131, 0, {sa_family=AF_INET6, sin6_port=htons(53), inet_pton(AF_INET6, "2a01:4f8:0:a0a1::add:1010", &sin6_addr), sin6_flowinfo=htonl(0), sin6_scope_id=0}, [28]) = 773

recvfrom(26, "\273\307\201\200\0\1\0\0\0\1\0\1\23ARcHErybraNdaPpAreL"..., 5131, 0, {sa_family=AF_INET6, sin6_port=htons(53), inet_pton(AF_INET6, "2a01:4f8:0:a0a1::add:1010", &sin6_addr), sin6_flowinfo=htonl(0), sin6_scope_id=0}, [28]) = 114

recvmsg(4, {msg_name={sa_family=AF_INET, sin_port=htons(60281), sin_addr=inet_addr("127.0.0.1")}, msg_namelen=28->16, msg_iov=[{iov_base="\0\250\1\0\0\1\0\0\0\0\0\0\7andRoId\nGOoglEaPiS\3"..., iov_len=4096}], msg_iovlen=1, msg_control=[{cmsg_len=28, cmsg_level=SOL_IP, cmsg_type=IP_PKTINFO, cmsg_data={ipi_ifindex=if_nametoindex("lo"), ipi_spec_dst=inet_addr("127.0.0.1"), ipi_addr=inet_addr("127.0.0.1")}}], msg_controllen=32, msg_flags=0}, 0) = 40

bind(18, {sa_family=AF_INET6, sin6_port=htons(64690), inet_pton(AF_INET6, "::", &sin6_addr), sin6_flowinfo=htonl(0), sin6_scope_id=0}, 28) = 0

sendto(18, ";@\1\0\0\1\0\0\0\0\0\1\7andRoId\nGOoglEaPiS\3"..., 51, 0, {sa_family=AF_INET6, sin6_port=htons(53), inet_pton(AF_INET6, "2a01:4f8:0:a0a1::add:1010", &sin6_addr), sin6_flowinfo=htonl(0), sin6_scope_id=0}, 28) = 51

recvmsg(4, {msg_name={sa_family=AF_INET, sin_port=htons(60281), sin_addr=inet_addr("127.0.0.1")}, msg_namelen=28->16, msg_iov=[{iov_base="yI\1\0\0\1\0\0\0\0\0\0\7aNDRoID\ngOOgLeAPiS\3"..., iov_len=4096}], msg_iovlen=1, msg_control=[{cmsg_len=28, cmsg_level=SOL_IP, cmsg_type=IP_PKTINFO, cmsg_data={ipi_ifindex=if_nametoindex("lo"), ipi_spec_dst=inet_addr("127.0.0.1"), ipi_addr=inet_addr("127.0.0.1")}}], msg_controllen=32, msg_flags=0}, 0) = 40

bind(24, {sa_family=AF_INET6, sin6_port=htons(56974), inet_pton(AF_INET6, "::", &sin6_addr), sin6_flowinfo=htonl(0), sin6_scope_id=0}, 28) = 0

sendto(24, "\213\377\1\0\0\1\0\0\0\0\0\1\7aNDRoID\ngOOgLeAPiS\3"..., 51, 0, {sa_family=AF_INET6, sin6_port=htons(53), inet_pton(AF_INET6, "2a01:4f8:0:a0a1::add:1010", &sin6_addr), sin6_flowinfo=htonl(0), sin6_scope_id=0}, 28) = 51

recvfrom(18, ";@\201\200\0\1\0\21\0\0\0\1\7andRoId\nGOoglEaPiS\3"..., 5131, 0, {sa_family=AF_INET6, sin6_port=htons(53), inet_pton(AF_INET6, "2a01:4f8:0:a0a1::add:1010", &sin6_addr), sin6_flowinfo=htonl(0), sin6_scope_id=0}, [28]) = 341

recvfrom(24, "\213\377\201\200\0\1\0\2\0\0\0\1\7aNDRoID\ngOOgLeAPiS\3"..., 5131, 0, {sa_family=AF_INET6, sin6_port=htons(53), inet_pton(AF_INET6, "2a01:4f8:0:a0a1::add:1010", &sin6_addr), sin6_flowinfo=htonl(0), sin6_scope_id=0}, [28]) = 113
```

 *mike155 wrote:*   

> 2) What is the output of "cat /proc/sys/net/ipv4/ip_local_port_range"?

 

```
t44 ~ # cat /proc/sys/net/ipv4/ip_local_port_range

32768   60999

```

----------

## mike155

Toralf, I'm confused now. The strace output you showed in your first post was IPv4. The output you showed in your last post is IPv6.

1) outgoing DNS requests seem to use IPv6 and they are OK. They use source ports in the range 32768 - 60999. They don't generate errors and they seem to work.

2) ...which brings me back to your first post. I guess that the IPv4 request you showed is not part of an outgoing DNS request. So what can it be? Port 95 (supdup) is highly unusual. Is it really 95? Or is it 953? Please post the lines following such an IPv4 request.

----------

## toralf

I do have ipv4 and ipv6 at that server acticated. The dnsmasq is :

```
tinderbox@mr-fox ~ $ grep -v -e '^$' -e '#' /etc/dnsmasq.conf 

domain-needed

conf-file=/usr/share/dnsmasq/trust-anchors.conf

dnssec

dnssec-check-unsigned

no-resolv

server=213.133.98.98

server=213.133.99.99

server=213.133.100.100

server=2a01:4f8:0:a0a1::add:1010

server=2a01:4f8:0:a102::add:9999

server=2a01:4f8:0:a111::add:9898

cache-size=10000

```

and

```
tinderbox@mr-fox ~ $ cat /etc/conf.d/dnsmasq 

# /etc/conf.d/dnsmasq: config file for /etc/init.d/dnsmasq

# See the dnsmasq(8) man page for possible options to put here.

DNSMASQ_OPTS="--user=dnsmasq --group=dnsmasq --min-port=1024"

#DNSMASQ_OPTS="--user=dnsmasq --group=dnsmasq"

```

The strace is derived via 

```
strace -p `pgrep dnsmasq` 2>&1 | grep -e ^bind  -e ^sendto -e ^rec
```

.

It is a fast Tor exit relay having >10,000 connecitons open and >100new per seconds or so.

The question is just how to let dnsmasq to use lower ports.

----------

## mike155

 *Quote:*   

> The question is just how to let dnsmasq to use lower ports.

 

There are two ways to go on:

1) One way is, as you suggest, to allow dnsmasq to use source ports < 1024. I doubt it will help you.

2) The other way is to try to find out why dnsmasq wants to open a source port < 1024 at all. 

EDIT: the next paragraph is wrong (sorry!) - please ignore it

# You wrote that your computer has more than 10.000 open connections. But your local port range is only 32768 - 60999. 

# So maybe (!) dnsmasq (or your # kernel) decides that there are no more free source ports and then uses source ports < 1024. 

# In that is true, something is going wrong and it wouldn't help # you to allow ports < 1024. Note: this is only a guess! 

# 

# 1) You could increase the range of local source ports to 1024 - 65536? 

# See: https://www.cyberciti.biz/tips/linux-increase-outgoing-network-sockets-range.html. 

# But make sure that this doesn't have negative effects on other services running on your computer like Tor. 

#

# 2) Another solution could be to use a second IP address (if you have one) and configure dnsmasq to use the second 

# IP address for outgoing DNS requests. This would give you a new set of epheremal ports.

I looked at /var/tmp/portage/net-dns/dnsmasq-2.78/work/dnsmasq-2.78/src/network.c, function: int random_sock(int family)

1) dnsmasq doesn't use values defined in proc/sys/net/ipv4/ip_local_port_range. For that reason, it doesn't make sense to change these values. A possible reason can be found here (see first answer).

2) dnsmasq uses its own port range. The default is 0 - 65535. The default range can be modified with options --min-port and --max-port.

3) EDIT: this topic is probably not true - I think I saw this bug this afternoon, but I can't reproduce it: There seems to be a bug in dnsmasq's option parser. It doesn't process the last parameter. For that reason, DNSMASQ_OPTS="--user=dnsmasq --group=dnsmasq --min-port=1024" doesn't change the port range.  :Sad:  Solution: add another parameter after --min-port. You could use '--max-port=65000' - but this parameter will be ignored.

4) If dnsmasq wants to send an outgoing DNS request, it randomly selects a port number from the port range and tries to bind to a socket with this source port. If it gets an error, it will randomly select another port and retry. It will retry up to 100 times. 

```
bind(29, {sa_family=AF_INET, sin_port=htons(95), sin_addr=inet_addr("0.0.0.0")}, 16) = -1 EACCES (Permission denied)

```

This algorithm and the default port range (0-65536) could explain the bind request with source port 95.

Conclusion (so far):

The default value for min-port is 0. It should be 1024. So everybody should add "--min-port=1024" to DNSMASQ_OPTS. I sent a bug report to the developers of dnsmasq. I don't know why this didn't work for Toralf - maybe he also suffered from topic 3) - I saw it, but I can't reproduce it.

----------

## Hu

 *toralf wrote:*   

> 
> 
> ```
>     41  CapPrm: 0000000000003000
> 
> ...

 That at least makes sense.  It has CAP_NET_ADMIN and CAP_NET_RAW, but privileged ports are provided via CAP_NET_BIND_SERVICE.  So I think it is expected that requesting a low port fails in this case.  Whether it should be requesting a low port, and whether it should be retaining a capability that allows it to request a low port, are both good questions that I cannot address.

If you want it to use low ports (why?), then you need it to retain CAP_NET_BIND_SERVICE.

----------

## toralf

 *Hu wrote:*   

>  *toralf wrote:*   
> 
> ```
>     41  CapPrm: 0000000000003000
> 
> ...

 I run 

```
setcap 'CAP_NET_BIND_SERVICE=+eip' /usr/sbin/dnsmasq
```

changed back /etc/conf.d/dnsmasq to 

```
DNSMASQ_OPTS="--user=dnsmasq --group=dnsmasq"
```

restarted dnsmasq and verified the caps :

```
mr-fox ~ # cat -n /proc/$(pgrep dnsmasq)/status | grep -i cap

    40  CapInh: 0000000000000000

    41  CapPrm: 0000000000003000

    42  CapEff: 0000000000003000

    43  CapBnd: 0000003fffffffff

    44  CapAmb: 0000000000000000

```

but 

```
strace -p `pgrep dnsmasq` 2>&1 | grep EACCE
```

still shows the EACCES error

----------

## Hu

CAP_NET_BIND_SERVICE is defined as 10 (here), so you should expect 1 << 10 = 400 to be enabled if that change worked.  Looking at the source, it seems dnsmasq includes code to drop unwanted capabilities.  Based on your output, that if test yielded false, so dnsmasq decided to drop CAP_NET_BIND_SERVICE.

```
     /* On linux, we keep CAP_NETADMIN (for ARP-injection) and

        CAP_NET_RAW (for icmp) if we're doing dhcp. If we have yet to bind 

        ports because of DAD, or we're doing it dynamically,

        we need CAP_NET_BIND_SERVICE too. */

     if (is_dad_listeners() || option_bool(OPT_CLEVERBIND))

       data->effective = data->permitted = data->inheritable =

         (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) | 

         (1 << CAP_SETUID) | (1 << CAP_NET_BIND_SERVICE);

     else

       data->effective = data->permitted = data->inheritable =

         (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) | (1 << CAP_SETUID);
```

Does it help if you explicitly enable option OPT_CLEVERBLIND?  I think that you would pass --bind-dynamic to do this.

----------

## mike155

Simon Kelley (one of the developers of dnsmasq) just checked in a patch that sets the default value of min-port to 1024.

----------

