Running unbound in chroot

Updated -

For systems with SELinux enabled and in enforcing mode, SELinux provides significant protection and limits what the unbound service can access.

Running unbound in chroot jail increases security in the following cases:

  • You want to run DNS cache unbound.
  • You cannot configure SELinux in enforcing mode and you want some protection.

NOTE: The chroot utility changes the root directory for a process, so that the process can not see or access files outside the designated directory tree. Using the chroot utility for jailing unbound into a limited chroot environment in combination with SELinux does not result in any additional security. Therefore, use chroot only on systems where SELinux does not run in enforcing mode.

If you want to run unbound under chroot, you must change the default configuration of unbound. By default, unbound uses files located in the /etc/unbound and /var/lib/unbound directories. Running unbound under chroot requires all unbound paths to start with the chroot directory.

Environment

  • Red Hat Enterprise Linux 7
  • Red Hat Enterprise Linux 8
  • Red Hat Enterprise Linux 9

Prerequisites

  • Root privileges

Configuring unbound to run inside chroot

  • Edit the /etc/unbound/unbound.conf file:

    • In the server: section find the chroot: parameter and change its value from empty (“”) to “/etc/unbound”.
    • Change the auto-trust-anchor-file: parameter value by replacing the default value /var/lib/unbound/root.key with /etc/unbound/var/root.key.
  • Create a directory for running unbound with chroot:

# mkdir /etc/unbound/var
  • Create the unbound-chroot.service file for setting up chroot:
#  touch /etc/systemd/system/unbound-chroot.service
  • Add the following text to the service file to prepare a bind mount using a systemd unit:
# systemctl edit --full unbound-chroot.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/mount --bind /var/lib/unbound /etc/unbound/var
ExecStop=/bin/umount /etc/unbound/var

NOTE: Because unbound-anchor.service modifies root.key as well as unbound.service, it is recommended to use the bind mount from its original location.

  • Add the following text to the service file of unbound service to allow the unbound-chroot.service to start before unbound.service:
# systemctl edit unbound.service
[Unit]
After=unbound-chroot.service
Requires=unbound-chroot.service
  • Start the unbound service:
# systemctl start unbound.service

NOTE: Before running the unbound service, ensure full paths to files under chroot directory are used in /etc/unbound/unbound.conf file.

Verification Steps

  • Display the systemd unit definitions of the unbound.service to ensure your changes to systemd services worked:
# systemctl cat unbound.service

The output has following structure:

# /usr/lib/systemd/system/unbound.service
[Unit]
Description=Unbound recursive Domain Name Server
After=syslog.target network.target
After=unbound-keygen.service
Wants=unbound-keygen.service
Wants=unbound-anchor.timer
Before=nss-lookup.target
Wants=nss-lookup.target

[Service]
Type=simple
EnvironmentFile=-/etc/sysconfig/unbound
ExecStartPre=/usr/sbin/unbound-checkconf
ExecStartPre=-/usr/sbin/unbound-anchor -a /var/lib/unbound/root.key -c /etc/unbound/icannbundle.pem
ExecStart=/usr/sbin/unbound -d $UNBOUND_OPTIONS

[Install]
WantedBy=multi-user.target

# /etc/systemd/system/unbound.service.d/override.conf
[Unit]
After=unbound-chroot.service
Requires=unbound-chroot.service

NOTE: The output consists of two parts:

  • the original service distributed with RHEL ( /usr/lib/systemd/system/unbound.service)
  • your customization (/etc/systemd/system/unbound.service.d/override.conf)

If you display the systemd unit information for the unbound-chroot.service, you see only the customization:

# systemctl cat unbound-chroot.service
# /etc/systemd/system/unbound-chroot.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/mount --bind /var/lib/unbound /etc/unbound/var
ExecStop=/bin/umount /etc/unbound/var
  • Restart the unbound.service:
# systemctl restart unbound.service

Ensure the unbound.service is running:

# systemctl status unbound.service
  • Verify the root property of the unbound process to check that unbound is running with a modified root:
# ls -l /proc/$(PID_of_unbound)/root
lrwxrwxrwx. 1 root root 0 Oct  5 10:18 /proc/19725/root -> /etc/unbound

The verification is successful if the unbound process is jailed into /etc/unbound and cannot reach outside of it.

Comments