ISC BIND, DoH and SE Linux

What's in This Post

If you're using a recent development version of ISC BIND you'll be able to configure DNS over HTTPS (DoH). However if you have selinux enabled, which of course you do because security is always important, then you may notice the following entry in your named log (/var/log/named/named.log):

1network: info: listening on IPv4 interface ens18,
2network: error: creating HTTPS socket: permission denied

I use centos with very few changes to the default selinux policies, but for some reason no entry was logged to the audit log (/var/log/audit/audit.log). If you know why a dontaudit rule has been applied to named accessing the http port then please leave a comment below.

Enable all SE Linux audit entries

If sealert -l returns an entry for named, you can skip this step.

1# Temporarily enable all selinux entries. This will result in a lot of entries, so don't leave it enabled
2semodule -DB

Why named can't access port 443

With auditing enabled I can now see what selinux did and why.

 1$ sealert -l "*"
 3SELinux is preventing /opt/isc/isc-bind/root/usr/sbin/named from name_bind access on the tcp_socket port 443.
 5*****  Plugin catchall_boolean (89.3 confidence) suggests   ******************
 7If you want to allow named to tcp bind http port
 8Then you must tell SELinux about this by enabling the 'named_tcp_bind_http_port' boolean.
11setsebool -P named_tcp_bind_http_port 1
13*****  Plugin catchall (11.6 confidence) suggests   **************************
15If you believe that named should be allowed name_bind access on the port 443 tcp_socket by default.
16Then you should report this as a bug.
17You can generate a local policy module to allow this access.
19allow this access for now by executing:
20# ausearch -c 'isc-net-0000' --raw | audit2allow -M my-iscnet0000
21# semodule -X 300 -i my-iscnet0000.pp
25Raw Audit Messages
26type=AVC msg=audit(1636540447.98:3800): avc:  denied  { name_bind } for  pid=99769 comm="isc-net-0000" src=443 scontext=system_u:system_
27r:named_t:s0 tcontext=system_u:object_r:http_port_t:s0 tclass=tcp_socket permissive=1
29type=SYSCALL msg=audit(1636540447.98:3800): arch=x86_64 syscall=bind success=yes exit=0 a0=25 a1=7f866583c078 a2=10 a3=7f8668be5d64 item
30s=0 ppid=99766 pid=99769 auid=4294967295 uid=994 gid=991 euid=994 suid=994 fsuid=994 egid=991 sgid=991 fsgid=991 tty=(none) ses=42949672
3195 comm=isc-net-0000 exe=/opt/isc/isc-bind/root/usr/sbin/named subj=system_u:system_r:named_t:s0 key=(null)
33Hash: isc-net-0000,named_t,http_port_t,tcp_socket,name_bind

It's a lot of output, but the first few lines tell us exactly what happened and what to do about it. Specifically setsebool -P named_tcp_bind_http_port 1 should solve our problem. The entry then goes on to provide a method for allowing bind to access the https port by default, which I wouldn't recommend. As a general rule of thumb, you should strongly prefer the first suggestion selinux gives you to solve a problem. In my case I can quickly check the selinux boolean to see if it is enabled or not:

1$ getsebool -a | grep named_tcp_bind
2named_tcp_bind_http_port --> off

Let named access port 443

We can see that there's an selinux boolean that allows named to access http ports and it's currently off. That's simple to fix:

1$ setsebool -P named_tcp_bind_http_port on
2$ getsebool -a | grep named_tcp_bind
3named_tcp_bind_http_port --> on

Because I don't like managing configuration at the command line, here's an Ansible stanza, which does the same thing.

1  - name: SE Linux configuration for DoH
2    seboolean:
3      name: named_tcp_bind_http_port
4      state: yes
5      persistent: yes

That's it. BIND should now be able to access the port you configured in named.conf to listen for incoming DoH queries.

Turn off the selinux noise

If you had to enable logging of all selinux events, like I did, then don't forget to turn it off again.

1$ semodule -B