more realistic structure

nixos-config-re
Alexander Tomokhov 2023-06-22 06:43:05 +04:00
parent 72758cbfab
commit 2b55461d8a
1 changed files with 58 additions and 41 deletions

View File

@ -6,26 +6,54 @@ When it comes to security, we care about limiting access of each entity of a sys
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.
Systemd is the standard software suite for organizing and running services/daemons in a modern GNU/Linux distribution, including NixOS. Systemd provides means to secure services. And in many ways, the isolation level of a systemd service can be similar to that of containers (by the means of namespaces, cgroups, etc; interestingly, [systemd even allows running](https://www.stevenrombauts.be/2019/01/run-multiple-instances-of-the-same-systemd-unit/) [multiple instances of the same service](https://opensource.com/article/20/12/multiple-service-instances-systemctl)). However, systemd hardening defaults are quite loose (perhaps, not to disturb the operation of newly written services and their administrators in any way).
Systemd is the standard software suite for organizing and running services/daemons in a modern GNU/Linux distribution, including NixOS. Systemd provides means to secure services. And in many ways, the isolation level of a systemd service can be similar to that of containers (by the means of sandboxing, namespaces, cgroups, etc; interestingly, [systemd even allows running](https://www.stevenrombauts.be/2019/01/run-multiple-instances-of-the-same-systemd-unit/) [multiple instances of the same service](https://opensource.com/article/20/12/multiple-service-instances-systemctl)). However, systemd hardening defaults are quite loose (perhaps, not to disturb the operation of newly written services and their administrators in any way).
What NixOS does - it generates systemd configuration files in accordance to NixOS configuration given, written in Nix language. To some extent, Nix acts as a macro language and NixOS configuration module system acts as a unified control center, so that you don't bother about location of systemd files, their syntax and common stuff, which NixOS generates for you. Also, NixOS manages runtime switching between systemd configurations, conducting services restarts when required and whole system rollbacks from GRUB/systemd-boot/extlinux.
## overview of systemd integration within NixOS
## overview of systemd services integration within NixOS configuration
NixOS features lots of systemd services, which are ready to use (without even knowing what systemd is) just by setting appropriate options in `configuration.nix`. For example, `services.netdata.enable = true`. Documentation for all related options can be found on the [website](https://search.nixos.org/options?channel=unstable&from=0&size=50&sort=relevance&type=packages&query=services.) or in `man configuration.nix` (also in `man home-configuration.nix` for [managing desktop](https://github.com/nix-community/home-manager) user services).
NixOS features lots of systemd services, which are ready to use (without even knowing what systemd is) just by setting appropriate options in `configuration.nix`. For example, write `services.netdata.enable = true;` to enable [Netdata](https://www.netdata.cloud/) monitoring service. Documentation for all related options can be found on the [website](https://search.nixos.org/options?channel=unstable&from=0&size=50&sort=relevance&type=packages&query=services.) or in `man configuration.nix` (also in `man home-configuration.nix` for [managing desktop](https://github.com/nix-community/home-manager) user services). Often many useful high-level tunables are available as `services.<name>.*` options.
- configuring systemd service units in NixOS step by step (edit, rebuild (maybe in VM), `systemd status`, `systemd restart`, `systemd cat`, `htop` tree)
When services, provided by NixOS, are insufficient or additional tuning is demanded, `systemd.services.<name>.*` set of options comes into play. They allow to define custom systemd services or modify existing ones. Regardless of the origin of a systemd service (provided by NixOS or written by yourself), `systemd` native options for sections such as `[Unit]` and `[Service]` can be specified accordingly in the following [nix attribute sets](https://nixos.org/manual/nix/stable/language/values.html#attribute-set): `systemd.services.<name>.unitConfig` and `systemd.services.<name>.serviceConfig`. `[Install]` section options such as `Alias`, `WantedBy` and `RequiredBy` can be specified as [nix lists](https://learnxinyminutes.com/docs/nix/) in `systemd.services.<name>.aliases`, `systemd.services.<name>.wantedBy`, `systemd.services.<name>.requiredBy`. You can find more information about such options [online](https://search.nixos.org/options?channel=unstable&from=0&size=50&sort=relevance&type=packages&query=systemd.services.) or in `man configuration.nix` as usual.
## resources limits strategy
In a nutshell, configuring systemd options for services on NixOS typically boils down to these steps:
## existing practices and solutions within NixOS
- https://github.com/fort-nix/nix-bitcoin#security
- some explanation that there is no universal way: https://github.com/NixOS/nixpkgs/pull/87661#issuecomment-698945283
1. edit `systemd.services.*` options in `configuration.nix` or in other imported nix files;
2. run `sudo nixos-rebuild test` to apply new configuration just for now or `sudo nixos-rebuild switch` to apply changes permanently;
3. evaluate `systemd` service operation (we will elaborate on this further);
4. return to step 1 or finish.
## list of systemd options and their implications
Alternatively, new configurations can be tested inside a QEMU VM clone of your system without affecting your running system configuration. `nixos-build build-vm` leaves a symlink `./result` in the current directory that contains the built VM. To run it, use `result/bin/run-<hostname>-vm`.
Keep in mind that mutable operations like `systemd SERVICE enable` are useless, because they would deviate the system from declarative reproducible configuration and NixOS won't let or will stubbornly resist you doing so at the design level. And there is no need, since each permanent setting is in the hands of NixOS.
## hardening
### resources limits strategy
NixOS already provides more or less isolation for many services, which are available as `services.<name>.*` options.
## cgroups
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/).
### blocking outgoing internet connections
The idea is to keep responding to incoming requests to some 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:
```nix
networking.firewall = {
extraCommands = ''
iptables -t filter -I OUTPUT 1 -m owner --uid-owner ${user} -m state --state NEW -j REJECT
'';
extraStopCommands = ''
iptables -t filter -D OUTPUT 1 -m owner --uid-owner ${user} -m state --state NEW
'';
};
```
### cgroups
[`cgroup`](https://en.wikipedia.org/wiki/Cgroups) - control group.
_Docker's isolation implementation is also based on cgroups._
@ -38,11 +66,18 @@ DefaultBlockIOAccounting=yes
DefaultIPAccounting=yes
```
## hardening in available services provided by NixOS upstream
### list of systemd options and their implications
NixOS already provides more or less isolation for many services, which are available as `services.NAME_OF_SERVICE` options.
## hardening in your own systemd services
## testing
### basic systemd commands for diagnostics
- `systemd status`, `systemd restart`, `systemd cat`, `htop` tree
`systemd-analyze`'s words "`SAFE`", "`EXPOSED`" and "`UNSAFE`" do not mean the factual situation, rather whether various systemd hardedning features are in use or not.
### when trying systemd options alone
You can manually test various systemd options without writing service files using `systemd-run`, for example:
@ -69,46 +104,27 @@ IO bytes read: 0B
IO bytes written: 0B
```
## blocking outgoing internet connections
### using tmux shell via socket inside a systemd unit
The idea is to keep responding to incoming requests to some service, but forbid any outgoing connections, initiated by itself.
With the help of [`tmux`](https://github.com/tmux/tmux/wiki/Getting-Started) you can [run a shell inside a hardened systemd unit](https://nixos.wiki/wiki/Systemd_Hardening#Dropping_a_shell_inside_a_systemd_service) in order to test our isolation in practice. Here is [example-systemd-service.nix](example-systemd-service.nix) nix file, the path to which you can add to the `imports` list in `configuration.nix` and then execute `nixos-rebuild switch` or `nixos-rebuild test` _(if you don't want new configuration to be permanent; however, it leaves `./result` symbolic link in current directory)_.
When it comes to a more sophisticated firewall, unfortunatelly systemd is not capable of such granular control. So, `iptables` configuration will be:
```nix
networking.firewall = {
extraCommands = ''
iptables -t filter -I OUTPUT 1 -m owner --uid-owner ${user} -m state --state NEW -j REJECT
'';
extraStopCommands = ''
iptables -t filter -D OUTPUT 1 -m owner --uid-owner ${user} -m state --state NEW
'';
};
```console
# nix-shell -p tmux --run "tmux -S /run/example-service/tmux.socket attach"
```
### testing
## existing practices and solutions within NixOS
[example-systemd-service.nix](example-systemd-service.nix) features a way to run a shell inside a systemd service in order to test our isolation in practice. You can just add path to the file to the `imports` list in `configuration.nix` and execute `nixos-rebuild switch` or `nixos-rebuild test` _(if you don't want new configuration to be permanent; however, it creates `./result` symbolic link in current directory)_.
There is [no universal way](https://github.com/NixOS/nixpkgs/pull/87661#issuecomment-698945283) in configuring systemd services options sandboxing/hardening for all services.
## unsolved problems
`confinement.enable` is not compatible with systemd's `ProtectSystem`.
`confinement.enable` NixOS option is not compatible with systemd's `ProtectSystem`.
## final notes
###security principles and strategy
#1. define desired security requirements
#2. apply systemd hardening options, suggested by `systemd-analyze` (until they harm service functionality)
#3. vulnerability scanning, penetration testing, and security audits
#4. monitor and respond
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.
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. 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 rescue plan to mitigate the impact of incidents. This might include restoring system from backups, keys and passwords reset.
Business continuity plan.
In order for the actions (measures?) taken not to be ad-hoc, but rather systematic.
#In order for the actions (measures?) taken not to be ad-hoc, but rather systematic.
## related resources
@ -118,3 +134,4 @@ In order for the actions (measures?) taken not to be ad-hoc, but rather systemat
- [NixOS systemd hardening wiki page](https://nixos.wiki/wiki/Systemd_Hardening)
- [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)