- Auditing Service Security with systemd-analyze
- Applying Security Directives to systemd Service Units
- Limiting Capabilities and System Calls
- Restricting File System Access
- Running Services as Non-Root Users
- Using DynamicUser for Ephemeral User Accounts
- Automating Directory Creation
- Monitoring and Troubleshooting
Systemd manages the startup and operation of services on most modern Linux systems, offering a powerful set of security options to restrict and isolate services. Applying these security options reduces the risk of service compromise by limiting access to system resources, capabilities, and files.
Using systemd’s built-in tools and directives, you can audit your services’ current security posture, then incrementally apply restrictions to reduce their attack surface while ensuring they continue to function correctly.
Auditing Service Security with systemd-analyze
Before modifying any service, it is crucial to understand its current security exposure. The systemd-analyze security
command generates a report for each service, scoring its security exposure on a scale from 0 (secure) to 10 (highly exposed). This score reflects the use of systemd's security features, not the inherent security of the application itself.
Step 1: Run the following command to review all services:
systemd-analyze security
This outputs a list of services with their exposure scores and a summary of which security features are enabled or missing.
Step 2: For a focused view on a specific service, such as Apache HTTP Server (httpd.service
), run:
systemd-analyze security httpd.service
Review the output to identify which security directives are not currently applied and which contribute most to the service’s exposure score.
Applying Security Directives to systemd Service Units
Systemd allows you to override or extend service unit configurations without modifying the original unit files by creating drop-in override files. This approach preserves your changes across package updates.
Step 1: Create or edit an override file for the target service:
sudo systemctl edit httpd.service
This opens a text editor where you can add security-related directives under the [Service]
section.
Key Security Directives to Lower Exposure
- PrivateTmp=yes: Provides the service a private /tmp directory, isolating its temporary files from other services.
- NoNewPrivileges=true: Prevents the service and its child processes from gaining new privileges, closing privilege escalation paths.
- ProtectSystem=strict: Mounts critical system directories such as /usr, /boot, and /etc as read-only, preventing unauthorized modifications.
- CapabilityBoundingSet=...: Restricts Linux capabilities to only those required by the service, minimizing the privileges it holds.
- RestrictNamespaces=...: Limits the use of Linux namespaces to reduce resource isolation capabilities.
- ProtectKernelTunables=yes: Blocks changes to kernel tunables via /proc/sys and similar interfaces.
- ProtectKernelModules=yes: Prevents loading or unloading kernel modules.
- ProtectControlGroups=yes: Restricts modification of control groups.
- PrivateDevices=yes: Denies access to physical devices, allowing only pseudo devices.
- RestrictSUIDSGID=true: Disallows creation of SUID/SGID files.
- IPAddressAllow=...: Restricts network access to specified IP ranges, if applicable.
Step 2: Add these directives to the override file as needed. For example:
[Service]
PrivateTmp=yes
NoNewPrivileges=true
ProtectSystem=strict
CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_DAC_READ_SEARCH
RestrictNamespaces=uts ipc pid user cgroup
ProtectKernelTunables=yes
ProtectKernelModules=yes
ProtectControlGroups=yes
PrivateDevices=yes
RestrictSUIDSGID=true
IPAddressAllow=192.168.1.0/24
Step 3: Save the file, then reload systemd and restart the service to apply changes:
sudo systemctl daemon-reload
sudo systemctl restart httpd.service
Re-run systemd-analyze security httpd.service
to observe the reduced exposure score.
Limiting Capabilities and System Calls
Linux capabilities divide root privileges into fine-grained units. Systemd allows restricting the capabilities a service can use, reducing the risk if the service is compromised.
Step 1: Determine which capabilities your service requires. Common capabilities include:
CAP_NET_BIND_SERVICE
: Bind to privileged ports below 1024.CAP_CHOWN
: Change file ownership.CAP_DAC_OVERRIDE
: Bypass file permission checks.CAP_SETUID
andCAP_SETGID
: Change user and group IDs.
Step 2: Restrict capabilities in the override file:
[Service]
CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_SETUID CAP_SETGID
AmbientCapabilities=CAP_NET_BIND_SERVICE
The AmbientCapabilities
directive is necessary if the service drops privileges but still needs specific capabilities.
Step 3: To further restrict system calls, use SystemCallFilter=
to whitelist only allowed syscalls. Identifying required syscalls can be done using tools like strace
or systemd’s SystemCallLog=
directive.
Example:
[Service]
SystemCallFilter=@system-service chroot
Restricting File System Access
Systemd can limit file system access by mounting parts of the file system as read-only or inaccessible, isolating services from sensitive data.
- ProtectHome=yes: Makes /home, /root, and /run/user inaccessible.
- InaccessiblePaths=: Denies access to specific paths.
- ReadOnlyPaths= and ReadWritePaths=: Control access to specific directories.
- PrivateDevices=yes: Limits device access.
- UMask=: Sets default permission mask for files created by the service.
Step: Add these directives to the override file to restrict file system access appropriately for your service.
Running Services as Non-Root Users
Running services as root unnecessarily increases risk. Systemd allows specifying the user and group under which a service runs.
Step: Add the following to the override file to run the service as a less privileged user:
[Service]
User=apache
Group=apache
Ensure the service has the necessary permissions on files and directories it needs to access.
Using DynamicUser for Ephemeral User Accounts
DynamicUser creates a temporary user account for the service that exists only while the service runs, improving isolation without requiring manual user management.
Step: Add this directive to the override file:
[Service]
DynamicUser=yes
This is ideal for services that do not require persistent user identities or access to user data.
Automating Directory Creation
Systemd can automatically create and manage directories for cache, state, logs, and runtime data tied to the service’s lifecycle.
Step: Add these directives to the override file to automate directory management:
[Service]
CacheDirectory=myservice
StateDirectory=myservice
LogsDirectory=myservice
RuntimeDirectory=myservice
Replace myservice
with a name matching your service. These directories are created with appropriate ownership and cleaned up on service stop.
Monitoring and Troubleshooting
After applying security settings, monitor service logs and behavior to ensure functionality is intact. Use journalctl -u servicename
to view logs.
If the service fails to start or behaves unexpectedly, review the applied security directives and adjust as necessary, possibly relaxing some restrictions.
Tools like strace
can help identify missing permissions or syscalls by tracing system calls during service execution.
Applying systemd security options systematically strengthens your Linux services by reducing privilege levels and isolating them from critical system components. Regularly auditing and tuning these settings ensures your services run securely without sacrificing functionality.
Member discussion
0 comments