Securing BIND 9 with SELinux workshop

1 SELinux DNS workshop

The virtual machines have a domain name in the form selinuxNNN.dnslab.org.

Please login to the machines with a modern web browser under the URL https://selinuxNNN.dnslab.org:9090 with the username user and the password DNSandBIND. You can also login with SSH and the same username and password.

The virtual machines run the cockpit tool (https://cockpit-project.org) to provide a terminal in the web browser.

Then select the terminal (last menue option on the left) and start the tutorial.

1.1 Virtual machines

Every participant has a VM number. Please replace the NNN in the instructions with your participant number from the table below:

VM Number Name

1.2 Basic Installation

  • The DNS authoritative DNS Server runs a BIND 9.11.20 ESV (RockyLinux 8)
  • The BIND 9 configuration file can be found in /etc/named.conf
  • For the sessions you need to become the user root with the sudo command, for example with sudo -s
  • A command line promt starting with % indicates a root shell
  • Check that BIND 9 is running and is under SELinux control
% ps -auxZ | grep named

2 Session 1 - Making a primary zone dynamic

  • Create a new zone in the file /var/named/example.org
$ttl 3600
@      IN SOA selinuxNNN.dnslab.org.  .  1001  2h 1h 40d 1h
       IN NS  selinuxNNN.dnslab.org.
       IN A   1.2.3.4
  • Check the SElinux context label on the new zone-file
% ls -Z /var/named/example.org
unconfined_u:object_r:named_zone_t:s0 /var/named/example.org
  • Create a new zone definition in the file /etc/named.conf
zone "example.org" {
     type master;
     file "example.org";
     };
  • Check the configuration and load the new zone file into the running BIND 9 server
% named-checkconf -z
% rndc reconfig
% rndc zonestatus example.org
  • Edit the BIND 9 configuration file /etc/named.conf and make the zone example.org a dynamic zone
zone "example.org" {
     type master;
     file "example.org";
     update-policy local;
     };
  • Check the configuration with named-checkconf -z, reload the configuration and check the dynamic status of the zone with rndc zonestatus. It should now be listed as a dynamic zone.
% nsupdate -l
> ttl 3600
> add example.org in aaaa 2001:db8::1
> send
> quit
  • The dynamic update will fail. Why?
  • Check the BIND 9 log
% journalctl -eu named
  • Check the Audit log:
% ausearch -m avc -x /usr/sbin/named -i
  • How to solve this issue?

2.1 Solution 1

  • Move the zone file into /var/named/dynamic and adjust the SELinux file context label (and the Unix permission/owner)
% mv example.org dynamic/
% chown named: dynamic/example.org
% restorecon -vr dynamic/
Relabeled /var/named/dynamic/example.org from unconfined_u:object_r:named_zone_t:s0 to unconfined_u:object_r:named_cache_t:s0
  • Adjust the file label and the named.conf configuration.
zone "example.org" {
     type master;
     file "dynamic/example.org";
     update-policy local;
     };

2.2 Solution 2

  • Set the SELinux Boolean named_write_master_zones to on
% setsebool named_write_master_zones=on

3 Session 2 - Zonefile at an unusual location

  • In this example, for operational purposes, the BIND 9 zonefiles must be stored under the /srv/ filesystem path
  • Create the directory /srv/bind/zones/primary/
% mkdir -p /srv/bind/zones/primary
  • Create a zonefile for the zone example.net in the new directory
$ttl 3600
@      IN SOA selinuxNNN.dnslab.org.  .  1001  2h 1h 40d 1h
       IN NS  selinuxNNN.dnslab.org.
       IN A   1.2.3.4
  • Create a zone block for the new primary zone in the BIND 9 configuration file /etc/named.conf
zone "example.net" {
  type master;
  file "/srv/bind/zones/primary/example.net";
};
  • Check the configuration, reconfig the BIND 9 server, check the zone-status on the zone example.net
  • The zone is not loaded
  • Check with journalctl and ausearch for the reasons
% journalctl -eu named
% ausearch -m avc -x /usr/sbin/named -i
  • How to solve this issue?

3.1 Solution

  • Change the SELinux Policy to include the new directory as a path for BIND 9 zonefiles
% semanage fcontext -a -t named_zone_t --ftype f "/srv/bind/zones(/.*)?"
% semanage fcontext -a -t named_zone_t --ftype d "/srv/bind/zones(/.*)?"
  • Relabel the file with the new SELinux security context label
% restorecon -rv /srv/bind/zones/
Relabeled /srv/bind/zones from unconfined_u:object_r:var_t:s0 to unconfined_u:object_r:named_zone_t:s0
Relabeled /srv/bind/zones/primary from unconfined_u:object_r:var_t:s0 to unconfined_u:object_r:named_zone_t:s0
Relabeled /srv/bind/zones/primary/example.net from unconfined_u:object_r:var_t:s0 to unconfined_u:object_r:named_zone_t:s0

4 Session 3 - RNDC on Port 65053

  • In this example, for operational reasons the BIND 9 "remote name daemon control" socket cannot listen on its default port 953, but should listen on port 65083
  • Configure BIND 9 to listen on the rndc port 65053. Add to the file /etc/named.conf
include "/etc/rndc.key";

controls {
       inet 127.0.0.1 port 65053
               allow { 127.0.0.1; } keys { "rndc-key"; };
 };
  • Check the configuration, restart the BIND 9 name server
% systemctl restart named
  • Text the new rndc configuration
% rndc -p 65053 status
  • What is causing this issue? Troubleshoot with journalctl and ausearch
  • How to solve this issue?
  • Hint:
% semanage port  -l | grep 953

4.1 Solution

  • Add port 65053 to the SELinux definition of the type rndc_port_t
% semanage port -a -t rndc_port_t -p tcp 65053
  • Restart BIND 9
% systemctl restart named
  • Test rndc
% rndc -p 65053 status
version: BIND 9.11.26-RedHat-9.11.26-4.el8_4 (Extended Support Version) <id:3ff8620>
running on selinux-test: Linux x86_64 4.18.0-305.3.1.el8_4.x86_64 #1 SMP Thu Jun 17 07:52:48 UTC 2021
boot time: Sun, 19 Sep 2021 19:26:35 GMT
last configured: Sun, 19 Sep 2021 19:26:35 GMT
configuration file: /etc/named.conf
CPUs found: 1
worker threads: 1
UDP listeners per interface: 1
number of zones: 105 (97 automatic)
debug level: 0
xfers running: 0
xfers deferred: 0
soa queries in progress: 0
query logging is OFF
recursive clients: 0/900/1000
tcp clients: 2/150
TCP high-water: 2
server is up and running