Dovecot hardening profile
New to securing and tuning systemd services? Start with the how to harden a systemd service unit article to learn tuning step-by-step, including the usage of relevant tools.
Introduction
This is a hardening profile to help securing Dovecot, the POP3 and IMAP server by using a strict systemd unit configuration. The goal for this hardening profile is to sandbox the application while still allowing its tasks.
Relevant FAQ: How to use systemctl edit to change a service?
Notes
Hardening profile
Important notes
- Test this profile first on a non-production system
- Reload and restart Dovecot a few times after applying the new settings
- Confirm that Dovecot is working and serving pages
Excluded settings for this profile
Some settings were considered too strict, too specific, or not compatible for this service unit. For this reason they are not applied to the service.
Setting | Reason |
---|---|
DeviceAllow | PrivateDevices is already defined, therefore access to devices is very restricted |
PrivateNetwork | This service requires networking connectivity |
ReadOnlyPaths | ProtectSystem is used, which already marks most of the file system read-only |
Settings to consider
There are some settings that can be considered adding. These might not be added yet as they require additional testing. Want to help improving this profile? Test the setting and let it know!
Setting | Reason or description |
---|---|
PrivatePIDs | Define a new PID namespace for the process and its children |
KeyringMode | controls kernel session keyring and define what is available to the service |
PrivateMounts | provides a separated mount namespace to the service |
RuntimeDirectoryMode | set the default file permissions for runtime directory, which is defined as RuntimeDirectory |
DevicePolicy | define level of access to devices in /dev |
Applying this profile
Open the service unit for Dovecot with the editor function.
systemctl edit dovecot.serviceCopy the following block into the editor. As the profile can change over time, it is suggested to include the link and version. This way changes can easily be compared in the future. Also add your own customizations at the top to simplify the comparison.
################################################################################
# Source: https://linux-audit.com/systemd/hardening-profiles/dovecot/
# Profile version: 0.1alpha [2024-12-15]
################################################################################
# Customizations:
# - Insert here the changes you made to the profile
################################################################################
[Service]
# ===============================
# Paths
# ===============================
# Deny access to /dev/shm directory, suggested when using MemoryDenyWriteExecute=yes
# Details: https://linux-audit.com/systemd/settings/units/inaccessiblepaths/
InaccessiblePaths=/dev/shm
# Do not allow execution of files, except those needed for Dovecot itself
# Details: https://linux-audit.com/systemd/settings/units/noexecpaths/
NoExecPaths=/
# Related paths needed for Dovecot to work
# Details: https://linux-audit.com/systemd/settings/units/execpaths/
ExecPaths=/usr/bin/doveconf /usr/lib/dovecot/anvil /usr/lib/dovecot/config /usr/lib/dovecot/log /usr/sbin/dovecot
# ===============================
# Capabilities and system calls
# ===============================
# Define capabilities
# Details: https://linux-audit.com/systemd/settings/units/capabilityboundingset/
CapabilityBoundingSet=CAP_CHOWN CAP_DAC_OVERRIDE CAP_NET_BIND_SERVICE CAP_SETGID CAP_SETUID CAP_SYS_CHROOT
# Only allow the usage of system calls for own hardware platform. Advised when using RestrictAddressFamilies
# Details: https://linux-audit.com/systemd/settings/units/systemcallarchitectures/
SystemCallArchitectures=native
# Define an allow-list filter for system calls. Use the generic filter set @system-service and chroot() syscall
# Details: https://linux-audit.com/systemd/settings/units/systemcallfilter/
SystemCallFilter=@system-service chroot
# Explicit block memfd_create() due to using MemoryDenyWriteExecute=yes
SystemCallFilter=~memfd_create
# Block @mount, suggested as extension to PrivateTmp=, PrivateDevices=, ProtectSystem=, ProtectHome=, ProtectKernelTunables=, ProtectControlGroups=, ProtectKernelLogs=, ProtectClock=, ReadOnlyPaths=, InaccessiblePaths= and ReadWritePaths=.
SystemCallFilter=~@clock @mount @reboot
# ===============================
# Memory
# ===============================
# Do not allow memory segments to be writable+executable
# Details: https://linux-audit.com/systemd/settings/units/memorydenywriteexecute/
MemoryDenyWriteExecute=yes
# ===============================
# Privileges
# ===============================
# Do not gain new privileges
# Details: https://linux-audit.com/systemd/settings/units/nonewprivileges/
NoNewPrivileges=yes
# ===============================
# Personality
# ===============================
# Do not allow personality switch
# Details: https://linux-audit.com/systemd/settings/units/lockpersonality/
LockPersonality=yes
# ===============================
# Private
# ===============================
# Restrict access to devices in /dev, except for pseudo-devices like /dev/null, /dev/random, /dev/zero
# Details: https://linux-audit.com/systemd/settings/units/privatedevices/
PrivateDevices=yes
# Limit access to temporary directories such as /tmp and /var/tmp by creating a new namespace
# Details: https://linux-audit.com/systemd/settings/units/privatetmp/
PrivateTmp=yes
# ===============================
# Protect and Proc
# ===============================
# Do not allow changing the system clock
# Details: https://linux-audit.com/systemd/settings/units/protectclock/
ProtectClock=yes
# Details: https://linux-audit.com/systemd/settings/units/protectcontrolgroups/
ProtectControlGroups=yes
# No access to home directories
# Details: https://linux-audit.com/systemd/settings/units/protecthome/
ProtectHome=yes
# Do not allow changing the hostname
# Details: https://linux-audit.com/systemd/settings/units/protecthostname/
ProtectHostname=yes
# No access to kernel log ring buffer
# Details: https://linux-audit.com/systemd/settings/units/protectkernellogs/
ProtectKernelLogs=yes
# Do not allow loading kernel modules
# Details: https://linux-audit.com/systemd/settings/units/protectkernelmodules/
ProtectKernelModules=yes
# Don't allow changes to sysctl settings
# Details: https://linux-audit.com/systemd/settings/units/protectkerneltunables/
ProtectKernelTunables=yes
# No access to information about other users in /proc
# Details: https://linux-audit.com/systemd/settings/units/protectproc/
ProtectProc=invisible
# Most of the system paths will no longer be writable
# Details: https://linux-audit.com/systemd/settings/units/protectsystem/
ProtectSystem=strict
# Restricts information from /proc that not directly associated with process management and introspection
# Details: https://linux-audit.com/systemd/settings/units/procsubset/
ProcSubset=pid
# ===============================
# Restrictions
# ===============================
# Limit address families INET/INET6 for IPv4/IPv6, UNIX for local functions such as syslog
# Details: https://linux-audit.com/systemd/settings/units/restrictaddressfamilies/
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
# No access to Linux namespace functionality
# Details: https://linux-audit.com/systemd/settings/units/restrictnamespaces/
RestrictNamespaces=yes
# Realtime scheduling not allowed
# Details: https://linux-audit.com/systemd/settings/units/restrictrealtime/
RestrictRealtime=yes
# Do not allow setting set-user-ID and set-group-ID
# Details: https://linux-audit.com/systemd/settings/units/restrictsuidsgid/
RestrictSUIDSGID=yes
# ===============================
# Sockets
# ===============================
# Block socket bind as the default, then use SocketBindAllow to create allow-list
# Details: https://linux-audit.com/systemd/settings/units/socketbinddeny/
SocketBindDeny=any
# Allow port 143 (IMAP)
# Details: https://linux-audit.com/systemd/settings/units/socketbindallow/
SocketBindAllow=tcp:143
# Allow port 993 (IMAPS)
SocketBindAllow=tcp:993
# ===============================
# Umask
# ===============================
# Create new directories and files with 700/600 file permissions
# Details: https://linux-audit.com/systemd/settings/units/umask/
UMask=0077
Restart the dovecot service
systemctl restart dovecot.serviceAfter restarting the service, check the status.
systemctl status dovecot.serviceLast step is checking the service and its log files.
Troubleshooting
All is working? Perfect!
- A file mentioned in the hardening profile does not exist on your system
- Adjust the path
- Add a hyphen before optional paths)
- Process can't start as it requires additional paths
- Add the paths
- Make sure that paths that needs to be written to are defined in ReadWritePaths
- Process can't bind to a port
- Specify port with SocketBindAllow
See troubleshooting a failed systemd unit to learn how to do a more in-depth check of a failing systemd unit.
Did the hardening profile work right away or still some issues? Send a quick message!