[RFC] Hardening tinc systemd service

Oleksandr Natalenko oleksandr at natalenko.name
Tue Apr 6 21:09:13 CEST 2021


(resending after ml approval)

Hello.

I'm currently working on hardening the tinc's systemd service file.

Here are the principles I'm following:

1. employing all the hardening knobs possible as per
    `systemd-analyze security tinc@` output for the latest systemd stable
    release available
2. running tincd on behalf of dynamic non-root user so that no static
    user creation is needed; a user per network is used
3. making the current host keys, both public and private, a part of
    state, not a configuration; in systemd's terms it means that the keys
    of the current host should move under /var/lib, while /etc stays
    immutable

This is what I came up with at the moment:

```
[Unit]
Description=Tinc net %i
Documentation=info:tinc
Documentation=man:tinc(8) man:tinc.conf(5)
Documentation=http://tinc-vpn.org/docs/
PartOf=tinc.service
ReloadPropagatedFrom=tinc.service

[Service]
DynamicUser=true
User=tinc-%i
Group=tinc-%i
AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RAW
CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RAW
RestrictAddressFamilies=AF_INET AF_INET6
RestrictNamespaces=true
DeviceAllow=/dev/net/tun rw
NoNewPrivileges=true
PrivateTmp=true
ProtectClock=true
ProtectControlGroups=true
ProtectHome=true
ProtectKernelLogs=true
ProtectKernelModules=true
ProtectKernelTunables=yes
ProtectProc=invisible
ProcSubset=pid
ProtectSystem=strict
RestrictSUIDSGID=true
SystemCallArchitectures=native
RestrictRealtime=true
LockPersonality=true
MemoryDenyWriteExecute=true
RemoveIPC=true
ProtectHostname=true
SystemCallFilter=@system-service
SystemCallFilter=~@resources @privileged
WorkingDirectory=/var/lib/tinc/%i
ConfigurationDirectory=tinc/%i
RuntimeDirectory=tinc/%i
StateDirectory=tinc/%i
ExecStart=/usr/bin/tincd -D -c ${CONFIGURATION_DIRECTORY} 
--pidfile=${RUNTIME_DIRECTORY}/pid
PIDFile=${RUNTIME_DIRECTORY}/pid
ExecReload=/usr/bin/tincd -kHUP -c ${CONFIGURATION_DIRECTORY} 
--pidfile=${RUNTIME_DIRECTORY}/pid

[Install]
WantedBy=tinc.service
```

Current concerns:

1. initial key placement is a bit tricky; first, a service should be
    started so that /var/lib/private/tinc/NETNAME folder with proper
    ownership is created, and only then the user can move and chown
    a key there
2. key generation can totally be automated via (currently imaginary)
    tinc-genkey@ service, but this requires:
    a) for private key, keygen to actually use PrivateKeyFile value
       (currently it just relies on confbase)
    b) for public key, introduction of PublicKeyFile instead of looking
       up current host's public key under "hosts" folder.

Once 2. is implemented, tinc-genkey@ can be implemented in a way it
never touches /etc and places both public and private key under
/var/lib/private/tinc/NETNAME with proper permissions and ownership.
This way, the workload for deploying a new network would look like this:

1. user creates tinc.conf under /etc/tinc/NETNAME
2. tinc.conf has, among others:
    a) PrivateKeyFile = /var/lib/tinc/NETNAME/rsa_key.priv
    b) PublicKeyFile = /var/lib/tinc/NETNAME/rsa_key.pub
3. user places all the peers under /etc/tinc/hosts
4. at this moment /etc is sealed, and no further modification to it is
    needed
5. user starts tinc-genkey@ which creates private and public keys under
    /var/lib/tinc/NETNAME
6. user starts tinc@
7. that's it

What do you think?

Thanks.

-- 
   Oleksandr Natalenko (post-factum)


More information about the tinc-devel mailing list