Skip to content

Instantly share code, notes, and snippets.

@lucaswerkmeister
Last active October 22, 2017 14:28
Show Gist options
  • Save lucaswerkmeister/26c5aefbb69438a16901aef714c3fee6 to your computer and use it in GitHub Desktop.
Save lucaswerkmeister/26c5aefbb69438a16901aef714c3fee6 to your computer and use it in GitHub Desktop.
systemd sandbox for Dovecot on Debian Stretch
[Service]
# change user for worker processes
CapabilityBoundingSet=CAP_SETUID CAP_SETGID
# bind to ports 143 and 993
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
# fchown() /var/run/dovecot/login
CapabilityBoundingSet=CAP_CHOWN
# bind to /var/spool/postfix/private/dovecot{-auth}
CapabilityBoundingSet=CAP_DAC_OVERRIDE
# chroot to /var/run/dovecot/empty
CapabilityBoundingSet=CAP_SYS_CHROOT
# kill services
CapabilityBoundingSet=CAP_KILL
PrivateTmp=yes
PrivateDevices=yes
ProtectSystem=strict
ProtectHome=yes
ProtectKernelTunables=yes
ProtectControlGroups=yes
MountFlags=slave
NoNewPrivileges=yes
# note: @mount is needed by the anvil service
SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @obsolete @raw-io
SystemCallArchitectures=native
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
RestrictNamespaces=yes
ProtectKernelModules=yes
MemoryDenyWriteExecute=yes
RestrictRealtime=yes
RuntimeDirectory=dovecot
# partially undo ProtectSystem=strict
ReadWritePaths=/var/mail/vmail
ReadWritePaths=/var/spool/postfix
ReadWritePaths=/var/lib/dovecot
ReadWritePaths=/run/dovecot
# partially mitigate CAP_DAC_OVERRIDE
InaccessiblePaths=/etc/ssh /etc/opendkim /etc/shadow /etc/gshadow /var/lib/sudo /var/lib/tor
@lucaswerkmeister
Copy link
Author

Usage: drop it in /etc/systemd/system/dovecot.service.d/, systemctl daemon-reload, systemctl restart dovecot. Then check systemctl status dovecot and see if there are any error messages – if yes, our systems differ by a bit, and you’ll need to tweak the sandbox. (For instance, your setup might use a different path than /var/spool/postfix for communication sockets.)

@lucaswerkmeister
Copy link
Author

# note: @mount is needed by the anvil service

I just realized that the service can’t actually do any mounting, because it doesn’t have the required capability (not part of the CapabilityBoundingSet), so not including it in the SystemCallFilter only means that the process will get an error delivered instead of instantly dying with an uncatchable SIGSYS.

Now, since we have MountFlags=slave, I actually would be fine with even permitting the service to mount stuff within its mount namespace, but unfortunately the mount syscalls are under CAP_SYS_ADMIN, which is way too broad to grant the service :(

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment