refactor(networking): harden networkmanager systemd services

This commit is contained in:
Mohammad Rafiq 2025-04-02 16:16:10 +08:00
parent f450885e01
commit 76381b19c5
No known key found for this signature in database
2 changed files with 70 additions and 11 deletions

View file

@ -1,16 +1,23 @@
> "This is fucking brilliant. Nobody needs this, nobody has a real use for this and this definitely does not attract girls. Still, I'll try this and probably love it. -Tim Goeree" > "This is fucking brilliant. Nobody needs this, nobody has a real use for this
> and this definitely does not attract girls. Still, I'll try this and probably
> love it. -Tim Goeree"
# As Yet Unreproducible # As Yet Unreproducible
- [x] ~User passwords~ -> _Managed with sops-nix_ - [x] ~~User passwords~~ -> _Managed with sops-nix_
- [ ] Spotify login - [ ] Spotify login
- [ ] Firefox login - [ ] Firefox login
# Adding Secrets with sops-nix # Adding Secrets with sops-nix
Secrets are stored in configs/secrets/secrets.yaml. You can edit these secrets with `sops secrets.yaml` given you have an age private key stored at `~/.config/sops/age/keys.txt`. Secrets are stored in configs/secrets/secrets.yaml. You can edit these secrets
with `sops secrets.yaml` given you have an age private key stored at
`~/.config/sops/age/keys.txt`.
To decrypt these secrets with sops-nix during a rebuild, you must add your host public key to the `.sops.yaml` file. Generate it with `cat /etc/ssh/ssh_host_ed25519_key.pub | ssh-to-age`, add it to the file, then run `sops updatekeys secrets.yaml`. To decrypt these secrets with sops-nix during a rebuild, you must add your host
public key to the `.sops.yaml` file. Generate it with
`cat /etc/ssh/ssh_host_ed25519_key.pub | ssh-to-age`, add it to the file, then
run `sops updatekeys secrets.yaml`.
# Provisioning A New Machine # Provisioning A New Machine
@ -33,7 +40,8 @@ wpa_cli
ip addr ip addr
``` ```
On the host machine, run the following command to build the new system configuration and copy it over SSH along with the sops age key and ssh keys. On the host machine, run the following command to build the new system
configuration and copy it over SSH along with the sops age key and ssh keys.
```bash ```bash
# WARNING: You must use the IP address of the machine. # WARNING: You must use the IP address of the machine.
@ -41,7 +49,8 @@ On the host machine, run the following command to build the new system configura
deploy --flake .#<hostname> --target-host <username>@<ip_address> deploy --flake .#<hostname> --target-host <username>@<ip_address>
``` ```
Complete the setup by running the following on the target system once it is booted into the new install. Complete the setup by running the following on the target system once it is
booted into the new install.
```bash ```bash
# On the target machine: # On the target machine:
@ -52,12 +61,34 @@ cat /etc/ssh/ssh_host_ed25519_key.pub | ssh-to-age
# On the host machine: # On the host machine:
# Add the host age public key to .sops.yaml # Add the host age public key to .sops.yaml
sops updatekeys secrets.yaml sops updatekeys secrets.yaml
``` ```
# Hardening
[!NOTE] Thanks to
https://blog.notashelf.dev/posts/2025-03-03-insecurities-remedies-i.html for
this section!
Systemd services where appropriate are hardened using
`systemd.services.<servicename>.serviceConfig`:
- Protected from modifying the system clock
- Protected from modifying kernel parameters, modules or logs
- Whitelists syscalls
- Restricts namespaces the service is allowed to use, or changing its user or
group
- Restricts realtime access
- Restricts setting memory as writable and executable
# Acknowledgements # Acknowledgements
- https://www.youtube.com/watch?v=CwfKlX3rA6E for piquing my interest in this OS in the first place - https://www.youtube.com/watch?v=CwfKlX3rA6E for piquing my interest in this OS
- https://nixos-and-flakes.thiscute.world/ for teaching me about nix, nixos, flakes, and home-manager in an extremely easy to follow and well-documented fashion in the first place
- https://blog.notashelf.dev/posts/2025-02-24-ssh-signing-commits.html for teaching me how to trivially sign my commits - https://nixos-and-flakes.thiscute.world/ for teaching me about nix, nixos,
- https://www.reddit.com/r/NixOS/comments/fsummx/comment/fm3jbcm/ for an easy way to list all installed packages (`nix-store --query --requisites /run/current-system | cut -d- -f2- | sort | uniq`) flakes, and home-manager in an extremely easy to follow and well-documented
fashion
- https://blog.notashelf.dev/posts/2025-02-24-ssh-signing-commits.html for
teaching me how to trivially sign my commits
- https://www.reddit.com/r/NixOS/comments/fsummx/comment/fm3jbcm/ for an easy
way to list all installed packages
(`nix-store --query --requisites /run/current-system | cut -d- -f2- | sort | uniq`)

View file

@ -5,6 +5,34 @@
... ...
}: }:
{ {
systemd.services.NetworkManager-dispatcher.serviceConfig = {
ProtectClock = true; # Prevents the service from changing the system time or timezone.
ProtectKernelTunables = true; # Restricts the service's ability to modify kernel parameters via sysctl.
ProtectKernelModules = true; # Prevents the service from loading or unloading kernel modules.
ProtectKernelLogs = true; # Prevents the service from reading kernel logs directly.
SystemCallFilter = "~@clock @cpu-emulation @debug @obsolete @module @mount @raw-io @reboot @swap"; # Whitelists system calls, blocking all others based on specified groups.
ProtectControlGroups = true; # Prevents the service from joining or modifying control groups other than its own.
RestrictNamespaces = true; # Enforces stricter namespace isolation, preventing user namespace creation/joining.
LockPersonality = true; # Disables the `personality()` system call, preventing execution domain changes.
MemoryDenyWriteExecute = true; # Prevents the service from mapping memory pages as both writable and executable (W^X).
RestrictRealtime = true; # Prevents the service from using real-time scheduling policies.
RestrictSUIDSGID = true; # Prevents the service from utilizing setuid/setgid functionality.
};
systemd.services.NetworkManager.serviceConfig = {
ProtectClock = true; # Prevents the service from changing the system time or timezone.
ProtectKernelTunables = true; # Restricts the service's ability to modify kernel parameters via sysctl.
ProtectKernelModules = true; # Prevents the service from loading or unloading kernel modules.
ProtectKernelLogs = true; # Prevents the service from reading kernel logs directly.
SystemCallFilter = "~@clock @cpu-emulation @debug @obsolete @module @mount @raw-io @reboot @swap"; # Whitelists system calls, blocking all others based on specified groups.
ProtectControlGroups = true; # Prevents the service from joining or modifying control groups other than its own.
RestrictNamespaces = true; # Enforces stricter namespace isolation, preventing user namespace creation/joining.
LockPersonality = true; # Disables the `personality()` system call, preventing execution domain changes.
MemoryDenyWriteExecute = true; # Prevents the service from mapping memory pages as both writable and executable (W^X).
RestrictRealtime = true; # Prevents the service from using real-time scheduling policies.
RestrictSUIDSGID = true; # Prevents the service from utilizing setuid/setgid functionality.
};
networking = { networking = {
hostName = hostname; hostName = hostname;
useDHCP = lib.mkDefault true; useDHCP = lib.mkDefault true;