OpenSMTPD hardening profile
Introduction
This is a hardening profile to help securing OpenSMTPD by using systemd unit configuration.
Relevant FAQ: How to use systemctl edit to change a service?
Notes
This is the first version and currently under testing. Want to help get it to work, share feedback or issues, let it know!
Hardening profile
Important notes
- Test this profile first on a non-production system
- Reload and restart OpenSMTPD a few times after applying the new settings
- Confirm that all processes are running
Applying this profile
Open the unit file for OpenSMTPD with the built-in editor.
systemctl edit opensmtpd.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/opensmtpd/
# Profile version: 0.1 [2024-12-09]
################################################################################
# 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 our own binary
# Details: https://linux-audit.com/systemd/settings/units/noexecpaths/
NoExecPaths=/
# Details: https://linux-audit.com/systemd/settings/units/execpaths/
ExecPaths=/usr/sbin/smtpd /usr/lib
# Allow creation of files for storing messages
# Details: https://linux-audit.com/systemd/settings/units/readwritepaths/
ReadWritePaths=-/var/empty/smtpd /var/mail /var/run /var/spool/smtpd /var/spool/smtpd/incoming /var/spool/smtpd/offline /var/spool/smtpd/purge /var/spool/smtpd/temporary
# Allow read access to configuration files
ReadOnlyPaths=/etc/hosts -/etc/mailname /etc/resolv.conf /etc/smtpd.conf -/etc/ssl/certs/ca-certificates.crt
# ===============================
# Capabilities and system calls
# ===============================
# Only allow: bind to ports < 1024
# Details: https://linux-audit.com/systemd/settings/units/capabilityboundingset/
CapabilityBoundingSet=CAP_CHOWN CAP_DAC_READ_SEARCH 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
# Details: https://linux-audit.com/systemd/settings/units/systemcallfilter/
SystemCallFilter=@system-service
# 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
# Allow chroot syscall. This is enabled after @mount was disabled above.
SystemCallFilter=chroot
# ===============================
# 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
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, NETLINK for communication between user space and kernel, UNIX for local functions such as syslog
# Details: https://linux-audit.com/systemd/settings/units/restrictaddressfamilies/
RestrictAddressFamilies=AF_INET AF_INET6 AF_NETLINK 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 25 (SMTP)
# Details: https://linux-audit.com/systemd/settings/units/socketbindallow/
SocketBindAllow=tcp:25
# Allow port 465 (implicit TLS)
SocketBindAllow=tcp:465
# Allow port 587 (STARTTLS)
SocketBindAllow=tcp:587
# ===============================
# Umask
# ===============================
# Create new directories and files with 700/600 file permissions
# Details: https://linux-audit.com/systemd/settings/units/umask/
UMask=0077
Restart the opensmtpd service
systemctl restart opensmtpd.serviceAfter restarting the service, check the status.
systemctl status opensmtpd.serviceLast step is checking the service and its log files.
Everything working?
Perfect!
If it does (or not), share your feedback!