From 4f066d050aba9a2d66df9e52da2cb8e81e57caf1 Mon Sep 17 00:00:00 2001 From: "J. Dekker" Date: Mon, 18 Mar 2024 17:42:03 +0100 Subject: [PATCH] systemd: tight sandboxing (#103) wireproxy needs very little permissions, we can restrict it to basically nothing. DynamicUser means the system will generate a UID on demand for service, also CAP_NET_BIND_SERVICE can be used to allow this user to bind to a port < 1024 if desired. Also LoadCredential lets us read a file with tight permissions i.e. root:root 0400 and pass it to only wireproxy in an ephemeral and constrained manner. Signed-off-by: J. Dekker --- systemd/README.md | 20 ++++---------------- systemd/wireproxy.service | 40 +++++++++++++++++++++++++++++++++------ 2 files changed, 38 insertions(+), 22 deletions(-) diff --git a/systemd/README.md b/systemd/README.md index d0a2a56..33e8d00 100644 --- a/systemd/README.md +++ b/systemd/README.md @@ -13,24 +13,12 @@ The provided systemd unit assumes you have the wireproxy executable installed on 2. If necessary, customize the unit. - Edit the parts with `ExecStartPre=` and `ExecStart=` to point to the executable and the configuration file. For example, if wireproxy is installed on `/usr/bin` and the configuration file is located in `/opt/myfiles/wireproxy.conf` do the following change: + Edit the parts with `LoadCredential`, `ExecStartPre=` and `ExecStart=` to point to the executable and the configuration file. For example, if wireproxy is installed on `/usr/bin` and the configuration file is located in `/opt/myfiles/wireproxy.conf` do the following change: ```service - ExecStartPre=/usr/bin/wireproxy -n -c /opt/myfiles/wireproxy.conf - ExecStart=/usr/bin/wireproxy -c /opt/myfiles/wireproxy.conf + LoadCredential=conf:/opt/myfiles/wireproxy.conf + ExecStartPre=/usr/bin/wireproxy -n -c ${CREDENTIALS_DIRECTORY}/conf + ExecStart=/usr/bin/wireproxy -c ${CREDENTIALS_DIRECTORY}/conf ``` - #### 2.2 Drop root privileges (optional, but recommended) - Without any modifications, this Wireproxy service will run as root. You might want to drop those privileges. One way to do this is to simply create a system account for Wireproxy (or just use your own user account to run it instead). - ```bash - sudo useradd --comment "Wireproxy tunnel" --system wireproxy - ``` - Then uncomment these lines from the wireproxy.service: - ```service - #User=wireproxy - #Group=wireproxy - ``` - Caveats: - 1) Make sure `wireproxy` user can read the wireproxy configuration file. - 2) Also note that unprivileged user cannot bind to ports below 1024 by default. 4. Reload systemd and enable the unit. ```bash diff --git a/systemd/wireproxy.service b/systemd/wireproxy.service index ee0fae5..832f813 100644 --- a/systemd/wireproxy.service +++ b/systemd/wireproxy.service @@ -4,15 +4,43 @@ Wants=network-online.target After=network-online.target [Service] -#Uncomment and/or change these if you don't want to run Wireproxy as root -#User=wireproxy -#Group=wireproxy +User=wireproxy +Group=wireproxy +SyslogIdentifier=wireproxy Type=simple Restart=on-failure RestartSec=30s -ExecStartPre=/opt/wireproxy/wireproxy -n -c /etc/wireproxy.conf -ExecStart=/opt/wireproxy/wireproxy -c /etc/wireproxy.conf -SyslogIdentifier=wireproxy + +DynamicUser=yes +LoadCredential=conf:/etc/wireproxy.conf +ExecStartPre=/opt/wireproxy/wireproxy -n -c ${CREDENTIALS_DIRECTORY}/conf +ExecStart=/opt/wireproxy/wireproxy -c ${CREDENTIALS_DIRECTORY}/conf + +# Required if <1024 port +#AmbientCapabilities=CAP_NET_BIND_SERVICE +#CapabilityBoundingSet=CAP_NET_BIND_SERVICE +LimitNPROC=64 +LockPersonality=true +MemoryDenyWriteExecute=true +NoNewPrivileges=true +PrivateDevices=true +PrivateTmp=true +PrivateUsers=true +ProcSubset=pid +ProtectClock=true +ProtectControlGroups=true +ProtectHome=true +ProtectHostname=true +ProtectKernelLogs=true +ProtectKernelModules=true +ProtectKernelTunables=true +ProtectProc=invisible +ProtectSystem=strict +RestrictAddressFamilies=AF_INET AF_INET6 AF_NETLINK +RestrictNamespaces=true +RestrictRealtime=true +SystemCallArchitectures=native +SystemCallFilter=@system-service [Install] WantedBy=multi-user.target