all common systemd hardening options

nixos-config-re
Alexander Tomokhov 2023-06-30 04:27:17 +04:00
parent 6e6e164c11
commit 069f98ce34
1 changed files with 79 additions and 8 deletions

View File

@ -2,7 +2,7 @@
## introduction
When it comes to security, we care about limiting access of each entity of a system to as few other entities as possible. Network input, executables and users must be able to reach only those resources, which are necessary to perform the defined server tasks.
When it comes to security, we care about limiting access of each entity of a system to as few other entities as possible. Network input, executables and users must be able to reach only those resources, which are necessary to perform the defined server tasks. Principle of least priviledge.
Generally, it's better to implement as many layers of security as possible. Although, there is no way to make a server 100% bullet proof - it's a huge endless topic, this article covers some feasible essential `systemd` tunables that give us a layer of protection.
@ -55,11 +55,79 @@ There are, however, services like `services.dovecot2`, `services.postfix` and `s
_Btw, if your systemd service code gets large and you want to wrap it into something more esthetic, you [can](https://nixos.wiki/wiki/Extend_NixOS) [write your own NixOS service module](https://scvalex.net/posts/58/)._
### some important systemd options and their implications
### common hardening options (execution environment configuration)
TODO
Note, that many of these may cause your service malfunction or even crash. So, always test after applying them.
### resources control (limits) for a systemd service
```nix
# (refer to [capabilities man page](https://www.man7.org/linux/man-pages/man7/capabilities.7.html))
AmbientCapabilities = [ "" ];
# this can be enough for some web services
CapabilityBoundingSet = [ "CAP_NET_BIND_SERVICE" ];
DynamicUser = true;
LockPersonality = true;
MemoryDenyWriteExecute = true;
NoNewPrivileges = true;
PrivateDevices = true;
PrivateTmp = true;
# set PrivateIPC in case IPC is used, but not between services
# PrivateIPC = true;
PrivateUsers = true;
ProcSubset = "pid";
ProtectClock = true;
ProtectControlGroups = true;
ProtectHome = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
# some services need `ProtectProc = "invisible"` instead; this option implies `MountAPIVFS`
ProtectProc = "invisible";
ProtectSystem = "strict";
# you need to exclude "AF_UNIX" if unix sockets are not used
RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" ];
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
SystemCallArchitectures = "native";
# contrary to intuition this does not forbid IPC, but removes IPC objects after unit is stopped
RemoveIPC = true;
# allow general system service operations, except ~@ sets
# (see full list of predefined system call sets with `systemd-analyze syscall-filter`)
SystemCallFilter = [ "@system-service" "~@cpu-emulation" "~@debug" "~@keyring" "~@memlock" "~@obsolete" "~@privileged" "~@setuid" "~@resources" ];
# this disables IPC (some services require IPC, so be careful)
SystemCallFilter = [ "~@ipc" ];
```
#### very specific hardening options (resource control unit settings)
When `PrivateDevices` is `true`, all non-pseudo /dev devices are not accessible. You may want to whitelist some. Note, this is not related to filesystems.
```nix
# allow pseudo devices
DevicePolicy = "closed";
# explicit list of accessible devices
DeviceAllow = [ "" ];
```
The following are self-explanatory:
```nix
SocketBindAllow = "tcp:80";
SocketBindDeny = "any";
```
#### resources control (limits) for a systemd service
Systemd resource control directives allow you to limit resources provided to a service. For example, if `MemoryMax` limit is exceeded, OOM killer gets invoked.
@ -81,7 +149,7 @@ systemd.service = {
Refer to [official documentation](https://www.freedesktop.org/software/systemd/man/systemd.resource-control.html#Options) for many other options.
### blocking any network connections except localhost
#### blocking any network connections except localhost
This is appropriate, for example, if a service communicates with outside world via proxy (like `nginx`). And can be configured also with the help of systemd resource control directives, partially mentioned above.
@ -92,7 +160,7 @@ systemd.services.netdata.serviceConfig = {
};
```
### blocking outgoing internet connections
#### blocking outgoing internet connections
The idea here is to keep responding to incoming requests for a service, but forbid any outgoing connections, initiated by itself. When it comes to a more sophisticated firewall, unfortunatelly systemd is not capable of such granular control. So, `iptables` configuration will be aimed at a specific user, which runs the service:
@ -171,11 +239,11 @@ With the help of [`tmux`](https://github.com/tmux/tmux/wiki/Getting-Started) you
## unsolved problems
`systemd.services.<name>.confinement.enable` NixOS option is not compatible with systemd's `ProtectSystem`.
As of 2023-06-29 [`systemd.services.<name>.confinement.enable` NixOS option is not compatible with systemd's `ProtectSystem`](https://discourse.nixos.org/t/nixos-policy-regarding-systemd-confinement/18976).
## final notes
Systemd hardening is just a part of measures to be taken to narrow the potential threat landscape and risks for a server. Ideally, vulnerabilities scanning, penetration testing, unauthorized access prevention and security audits should be involved. Take advantage of monitoring tools and respond quickly, according to a rescue plan to mitigate the impact of incidents. This might include restoring system from backups, keys and passwords reset, etc. Keep running software up to date and respond to CVEs ([deploying software with patches is easy in NixOS](https://nixos.wiki/wiki/Overlays#Adding_patches) in case it hasn't been already patched). Have a business continuity plan. Many measures must not be ad-hoc, but rather systematic to stay vigilant against emerging threats.
Systemd hardening is just a part of measures to be taken to narrow the potential threat landscape and risks for a server. Ideally, vulnerabilities scanning, penetration testing, unauthorized access prevention and security audits should be involved. Take advantage of monitoring tools and respond quickly, according to a rescue plan to mitigate the impact of intrusion incidents. This might include restoring system from backups, keys and passwords reset, etc. Keep running software up to date and respond to CVEs ([deploying software with patches is easy in NixOS](https://nixos.wiki/wiki/Overlays#Adding_patches) in case it hasn't been already patched). Have a business continuity plan. Many measures must not be ad-hoc, but rather systematic to stay vigilant against emerging threats.
As for NixOS, it also features `security.apparmor`, `security.audit` and even `programs.firejail` options which might help in building a more secure system.
@ -188,3 +256,6 @@ As for NixOS, it also features `security.apparmor`, `security.audit` and even `p
- [security in NixOS overview wiki page](https://nixos.wiki/wiki/Security)
- [utility for validating nix store for packages affected by vulnerabilities](https://github.com/nix-community/vulnix)
- [example of the complex security hardening in NixOS](https://github.com/fort-nix/nix-bitcoin#security)
- [Limit the impact of a security intrusion with systemd directives article](https://www.ctrl.blog/entry/systemd-opensmtpd-hardening.html)
- [Hardening Applications with systemd](https://blog.sergeantbiggs.net/posts/hardening-applications-with-systemd/)
- [Systemd Hardening options explained](https://docs.arbitrary.ch/security/systemd.html)