Skip to content

Add systemd hardening options

Hardening Options Applied:

  • ProtectSystem=strict: Limits write access to the entire filesystem, allowing only specific directories.
  • ProtectHome=tmpfs: Isolates user home directories with a temporary filesystem.
  • PrivateTmp=true: Provides an isolated /tmp directory for the service.
  • PrivateDevices=true: Restricts access to device files in /dev.
  • ProtectKernelTunables=true: Prevents access to kernel tunable files, reducing risk of kernel settings modification.
  • ProtectKernelModules=true: Disallows loading/unloading of kernel modules.
  • ProtectKernelLogs=true: Blocks access to kernel logs, protecting sensitive system data.
  • ProtectControlGroups=true: Restricts control group (cgroup) manipulation.
  • ProtectProc=ptraceable: Limits access to process information, allowing only self-inspection (ptrace).
  • MemoryDenyWriteExecute=true: Blocks writable memory from being executable, enhancing memory safety.
  • LockPersonality=true: Locks process personality to prevent modification of binary execution domain.
  • RestrictRealtime=true: Prevents real-time scheduling, mitigating potential CPU abuse.
  • SystemCallFilter=~[...]: Denies potentially risky system calls, enhancing syscall-level security:
    • @memlock, @module, @mount, @cpu-emulation, @debug, @keyring, @chown, @obsolete, @reboot, @sandbox, @setuid, @swap, @sync, @timer: Denied with EPERM, restricting access to privileged or deprecated operations.

This change was tested by running curl http://localhost:9100/metrics before and after the changes and ensuring all metrics were still reported.

  1. Run curl http://localhost:9100/metrics > before_hardening.txt
  2. Apply hardening changes
  3. Run curl http://localhost:9100/metrics > after_hardening.txt
  4. python3 verify.py

The source code to verify.py is

import re

def extract_metric_names(file_path):
    metric_names = set()
    with open(file_path, 'r') as f:
        for line in f:
            # Match lines that define a TYPE or have a metric name before a space
            match = re.match(r"# TYPE (\w+)", line) or re.match(r"^(\w+)", line)
            if match:
                metric_names.add(match.group(1))
    return metric_names

# Load metric names from both "before" and "after" files
before_metrics = extract_metric_names('before_hardening.txt')
after_metrics = extract_metric_names('after_hardening.txt')

# Check for missing or extra metrics
missing_in_after = before_metrics - after_metrics
extra_in_after = after_metrics - before_metrics

if missing_in_after:
    print("Metrics missing in after_metrics.txt:")
    for metric in missing_in_after:
        print(f"  - {metric}")

if extra_in_after:
    print("Extra metrics in after_metrics.txt:")
    for metric in extra_in_after:
        print(f"  - {metric}")

if not missing_in_after and not extra_in_after:
    print("All metrics are present in both files.")

Merge request reports

Loading