Systemd/Hardening: Difference between revisions
No edit summary |
Marked this version for translation |
||
Line 2: | Line 2: | ||
<translate> | <translate> | ||
<!--T:1--> | |||
Systemd's service options are quite lax by default, and so it is often desirable to look at ways to harden systemd services. | Systemd's service options are quite lax by default, and so it is often desirable to look at ways to harden systemd services. | ||
</translate> | </translate> | ||
<translate> | <translate> | ||
<!--T:2--> | |||
A good way to get started on a given service is to look at the output of the command <code>systemd-analyze security myService</code>. From there, you can look at the documentation for the options you see in the output, often in <code>man systemd.exec</code> or <code>man systemd.resource-control</code>, and set the appropriate options for your service. | A good way to get started on a given service is to look at the output of the command <code>systemd-analyze security myService</code>. From there, you can look at the documentation for the options you see in the output, often in <code>man systemd.exec</code> or <code>man systemd.resource-control</code>, and set the appropriate options for your service. | ||
</translate> | </translate> | ||
<translate> | <translate> | ||
== Accessing the network with a different RootDirectory == | == Accessing the network with a different RootDirectory == <!--T:3--> | ||
</translate> | </translate> | ||
<translate> | <translate> | ||
<!--T:4--> | |||
To be able to access the network while having a RootDirectory specified, you need to give access to <code>/etc/ssl</code>, <code>/etc/static/ssl</code> and <code>/etc/resolv.conf</code>. The simplest way of doing this is by simply putting <code>/etc</code> in the <code>BindReadOnlyPaths</code> option. | To be able to access the network while having a RootDirectory specified, you need to give access to <code>/etc/ssl</code>, <code>/etc/static/ssl</code> and <code>/etc/resolv.conf</code>. The simplest way of doing this is by simply putting <code>/etc</code> in the <code>BindReadOnlyPaths</code> option. | ||
</translate> | </translate> | ||
<translate> | <translate> | ||
<!--T:5--> | |||
A more granular way, would be to put these 3 paths into <code>BindReadOnlyPaths</code>, and wait for the creation of <code>/etc/resolv.conf</code> through a <code>systemd.path</code> unit. | A more granular way, would be to put these 3 paths into <code>BindReadOnlyPaths</code>, and wait for the creation of <code>/etc/resolv.conf</code> through a <code>systemd.path</code> unit. | ||
</translate> | </translate> | ||
<translate> | <translate> | ||
== Dropping a shell inside a systemd service == | == Dropping a shell inside a systemd service == <!--T:6--> | ||
</translate> | </translate> | ||
<translate> | <translate> | ||
<!--T:7--> | |||
While hardening a service, it often happens that you want a shell inside a hardened systemd unit, for exemple to check access to files, or check the network connectivity. One way to do this is to use tmux to create a session inside the service, and attaching to it outside of the service. | While hardening a service, it often happens that you want a shell inside a hardened systemd unit, for exemple to check access to files, or check the network connectivity. One way to do this is to use tmux to create a session inside the service, and attaching to it outside of the service. | ||
</translate> | </translate> | ||
<translate> | <translate> | ||
<!--T:8--> | |||
Simple example: | Simple example: | ||
</translate> | </translate> | ||
Line 41: | Line 47: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<translate> | <translate> | ||
<!--T:9--> | |||
Example with a <code>RootDirectory</code> specified: | Example with a <code>RootDirectory</code> specified: | ||
</translate> | </translate> | ||
<translate> | <translate> | ||
<!--T:10--> | |||
<syntaxhighlight lang="nix"> | <syntaxhighlight lang="nix"> | ||
{ pkgs }: | { pkgs }: | ||
Line 53: | Line 61: | ||
Type = "forking"; | Type = "forking"; | ||
# Used as root directory | <!--T:11--> | ||
# Used as root directory | |||
RuntimeDirectory = "myService"; | RuntimeDirectory = "myService"; | ||
RootDirectory = "/run/myService"; | RootDirectory = "/run/myService"; | ||
BindReadOnlyPaths = [ | <!--T:12--> | ||
BindReadOnlyPaths = [ | |||
"/nix/store" | "/nix/store" | ||
# So tmux uses /bin/sh as shell | <!--T:13--> | ||
# So tmux uses /bin/sh as shell | |||
"/bin" | "/bin" | ||
]; | ]; | ||
# This sets up a private /dev/tty | <!--T:14--> | ||
# This sets up a private /dev/tty | |||
# The tmux server would crash without this | # The tmux server would crash without this | ||
# since there would be nothing in /dev | # since there would be nothing in /dev | ||
Line 74: | Line 86: | ||
</translate> | </translate> | ||
<translate> | <translate> | ||
<!--T:15--> | |||
To attach to the shell, simply execute <code>tmux -S /path/to/tmux.socket attach</code>. | To attach to the shell, simply execute <code>tmux -S /path/to/tmux.socket attach</code>. | ||
</translate> | </translate> | ||
<translate> | <translate> | ||
== Hardening examples == | == Hardening examples == <!--T:16--> | ||
</translate> | </translate> | ||
<translate> | <translate> | ||
<!--T:17--> | |||
This list contains proposed hardening options that are not yet upstreamed. Please use with caution, and please notify the author of the change if something breaks: | This list contains proposed hardening options that are not yet upstreamed. Please use with caution, and please notify the author of the change if something breaks: | ||
</translate> | </translate> | ||
<translate> | <translate> | ||
<!--T:18--> | |||
* Chrony: https://github.com/NixOS/nixpkgs/pull/104944/files | * Chrony: https://github.com/NixOS/nixpkgs/pull/104944/files | ||
* Isso: https://github.com/NixOS/nixpkgs/pull/140840/files | * Isso: https://github.com/NixOS/nixpkgs/pull/140840/files | ||
Line 90: | Line 105: | ||
</translate> | </translate> | ||
<translate> | <translate> | ||
== Related links == | == Related links == <!--T:19--> | ||
</translate> | </translate> | ||
<translate> | <translate> | ||
<!--T:20--> | |||
* SHH, systemd hardening helper: [https://www.synacktiv.com/en/publications/systemd-hardening-made-easy-with-shh systemd hardening made easy with SHH] | * SHH, systemd hardening helper: [https://www.synacktiv.com/en/publications/systemd-hardening-made-easy-with-shh systemd hardening made easy with SHH] | ||
</translate> | </translate> |
Latest revision as of 08:36, 8 August 2024
Systemd's service options are quite lax by default, and so it is often desirable to look at ways to harden systemd services.
A good way to get started on a given service is to look at the output of the command systemd-analyze security myService
. From there, you can look at the documentation for the options you see in the output, often in man systemd.exec
or man systemd.resource-control
, and set the appropriate options for your service.
Accessing the network with a different RootDirectory
To be able to access the network while having a RootDirectory specified, you need to give access to /etc/ssl
, /etc/static/ssl
and /etc/resolv.conf
. The simplest way of doing this is by simply putting /etc
in the BindReadOnlyPaths
option.
A more granular way, would be to put these 3 paths into BindReadOnlyPaths
, and wait for the creation of /etc/resolv.conf
through a systemd.path
unit.
Dropping a shell inside a systemd service
While hardening a service, it often happens that you want a shell inside a hardened systemd unit, for exemple to check access to files, or check the network connectivity. One way to do this is to use tmux to create a session inside the service, and attaching to it outside of the service. Simple example:
{ pkgs, ... }:
{
systemd.services.myService = {
serviceConfig = {
ExecStart = "${pkgs.tmux}/bin/tmux -S /tmp/tmux.socket new-session -s my-session -d";
ExecStop = "${pkgs.tmux}/bin/tmux -S /tmp/tmux.socket kill-session -t my-session";
Type = "forking";
# ...
};
};
}
Example with a RootDirectory
specified:
{ pkgs }:
{
systemd.services.myService = {
serviceConfig = {
ExecStart = "${pkgs.tmux}/bin/tmux -S /run/myService/tmux.socket new-session -s my-session -d";
ExecStop = "${pkgs.tmux}/bin/tmux -S /run/myService/tmux.socket kill-session -t my-session";
Type = "forking";
# Used as root directory
RuntimeDirectory = "myService";
RootDirectory = "/run/myService";
BindReadOnlyPaths = [
"/nix/store"
# So tmux uses /bin/sh as shell
"/bin"
];
# This sets up a private /dev/tty
# The tmux server would crash without this
# since there would be nothing in /dev
PrivateDevices = true;
};
};
}
To attach to the shell, simply execute tmux -S /path/to/tmux.socket attach
.
Hardening examples
This list contains proposed hardening options that are not yet upstreamed. Please use with caution, and please notify the author of the change if something breaks:
- Chrony: https://github.com/NixOS/nixpkgs/pull/104944/files
- Isso: https://github.com/NixOS/nixpkgs/pull/140840/files
- Mautrix-based bridge: https://github.com/mautrix/docs/pull/18/files
- Postfix: https://github.com/NixOS/nixpkgs/pull/93305/files
- TheLounge: https://github.com/thelounge/thelounge-deb/pull/78
Related links
- SHH, systemd hardening helper: systemd hardening made easy with SHH