[GH-ISSUE #2014] dnscrypt-proxy and systemd's DynamicUser concept #1356

Closed
opened 2026-05-05 07:55:16 -06:00 by gitea-mirror · 5 comments
Owner

Originally created by @ghost on GitHub (Jun 27, 2018).
Original GitHub issue: https://github.com/netblue30/firejail/issues/2014

Hi, I'm having some issues/questions about firejail's dnscrypt-proxy profile and the way to integrate firejail in systemd service files for that program. Let me start with providing some context. If the following sounds confusing, be advised: it's because of my limited experience with systemd's DynamicUser concept, let alone in combination with firejail.

In the beginning... there was only DNSCrypt v1. This is still the default version served by Ubuntu in its official repositories (1.6.1 for 16.04 LTS up until 1.9.5 for 18.04 LTS). Firejail's dnscrypt-proxy.profile works fine with v1. In fact, I've been succesfully using a custom dnscrypt-proxy.local to tighten-up things further via 'netfilter', 'nodbus', 'nogroups', 'nou2f' and 'protocol inet,inet6'.

Example of a working dnscrypt-proxy v1 systemd unit file with integrated firejail sandboxing:

[Unit]
Description=DNSCrypt proxy client [v1]
Documentation=man:dnscrypt-proxy(8)
After=network-online.target
Before=nss-lookup.target

[Service]
Type=simple
ExecStart=/usr/bin/firejail --name=dnscrypt-proxy-1 dnscrypt-proxy /etc/dnscrypt/dnscrypt-proxy-1.conf
ExecStop=/usr/bin/firejail --shutdown=dnscrypt-proxy-1
# firejail
SuccessExitStatus=15

[Install]
WantedBy=multi-user.target

Beginnings only last for so long, also in the case of DNSCrypt. For a while now v1 has been superseded by DNSCrypt v2. This is the default version on Arch, currently at 2.0.15. As far as firejail is concerned there's still the same executable /usr/bin/dnscrypt-proxy to be sandboxed, no changes there (at least not in the way the binary is named, exactly like in v1 packages). Behind the scenes though this is a different beast alltogether (see https://github.com/jedisct1/dnscrypt-proxy/wiki/Differences-to-v1 for a comparison).

On Arch, dnscrypt-proxy comes with a systemd unit file that uses the DynamicUser concept:

[Unit]
Description=DNSCrypt-proxy client [v2]
Documentation=https://github.com/jedisct1/dnscrypt-proxy/wiki
Wants=network-online.target nss-lookup.target
Before=nss-lookup.target

[Service]
NonBlocking=true
#ExecStart=/usr/bin/dnscrypt-proxy --config /etc/dnscrypt-proxy/dnscrypt-proxy.toml
ExecStart=/usr/bin/firejail --name=dnscrypt-proxy-v2 dnscrypt-proxy /etc/dnscrypt-proxy/dnscrypt-proxy.toml
ExecStop=/usr/bin/firejail --shutdown=dnscrypt-proxy-1
# firejail
SuccessExitStatus=15
ProtectHome=yes
ProtectControlGroups=yes
ProtectKernelModules=yes
DynamicUser=yes
CacheDirectory=dnscrypt-proxy
LogsDirectory=dnscrypt-proxy
RuntimeDirectory=dnscrypt-proxy
AmbientCapabilities=CAP_NET_BIND_SERVICE

[Install]
WantedBy=multi-user.target

In this form, starting the unit file throws an error:
Jun 27 13:02:36 systemd[1]: Started DNSCrypt proxy client [v2].
Jun 27 13:02:36 systemd[1]: Reached target Host and Network Name Lookups.
Jun 27 13:02:36 firejail[21411]: Error: cannot create /run/firejail/profile/21411
Jun 27 13:02:36 systemd[1]: dnscrypt-proxy.service: Main process exited, code=exited, status=1/FAILURE
Jun 27 13:02:36 systemd[1]: dnscrypt-proxy.service: Failed with result 'exit-code'.

For users on Arch ( and I assume this is the same on any distro using v2) the current dnscrypt-proxy.profile looks broken. I'm not getting anywhere when experimenting with
* whitelisting dirs under /var/cache/, /var/log/, /var/run incl. their /var/*/private counterparts
* declaring the above dirs read-write
* adding writable-var

Has anyone been looking into this recently?

Originally created by @ghost on GitHub (Jun 27, 2018). Original GitHub issue: https://github.com/netblue30/firejail/issues/2014 Hi, I'm having some issues/questions about firejail's `dnscrypt-proxy` profile and the way to integrate firejail in systemd service files for that program. Let me start with providing some context. If the following sounds confusing, be advised: it's because of my limited experience with systemd's `DynamicUser` concept, let alone in combination with firejail. In the beginning... there was only [DNSCrypt v1](https://github.com/dyne/dnscrypt-proxy). This is still the default version served by Ubuntu in its official repositories (1.6.1 for 16.04 LTS up until 1.9.5 for 18.04 LTS). Firejail's dnscrypt-proxy.profile works fine with v1. In fact, I've been succesfully using a custom dnscrypt-proxy.local to tighten-up things further via 'netfilter', 'nodbus', 'nogroups', 'nou2f' and 'protocol inet,inet6'. Example of a *working* dnscrypt-proxy v1 systemd unit file with integrated firejail sandboxing: ``` [Unit] Description=DNSCrypt proxy client [v1] Documentation=man:dnscrypt-proxy(8) After=network-online.target Before=nss-lookup.target [Service] Type=simple ExecStart=/usr/bin/firejail --name=dnscrypt-proxy-1 dnscrypt-proxy /etc/dnscrypt/dnscrypt-proxy-1.conf ExecStop=/usr/bin/firejail --shutdown=dnscrypt-proxy-1 # firejail SuccessExitStatus=15 [Install] WantedBy=multi-user.target ``` Beginnings only last for so long, also in the case of DNSCrypt. For a while now v1 has been superseded by [DNSCrypt v2](https://github.com/jedisct1/dnscrypt-proxy). This is the default version on Arch, currently at 2.0.15. As far as firejail is concerned there's still the same executable `/usr/bin/dnscrypt-proxy` to be sandboxed, no changes there (at least not in the way the binary is named, exactly like in v1 packages). Behind the scenes though this is a different beast alltogether (see https://github.com/jedisct1/dnscrypt-proxy/wiki/Differences-to-v1 for a comparison). On Arch, dnscrypt-proxy comes with a [systemd unit file](https://git.archlinux.org/svntogit/community.git/tree/trunk/dnscrypt-proxy.service?h=packages/dnscrypt-proxy) that uses the [DynamicUser](http://0pointer.net/blog/dynamic-users-with-systemd.html) concept: ``` [Unit] Description=DNSCrypt-proxy client [v2] Documentation=https://github.com/jedisct1/dnscrypt-proxy/wiki Wants=network-online.target nss-lookup.target Before=nss-lookup.target [Service] NonBlocking=true #ExecStart=/usr/bin/dnscrypt-proxy --config /etc/dnscrypt-proxy/dnscrypt-proxy.toml ExecStart=/usr/bin/firejail --name=dnscrypt-proxy-v2 dnscrypt-proxy /etc/dnscrypt-proxy/dnscrypt-proxy.toml ExecStop=/usr/bin/firejail --shutdown=dnscrypt-proxy-1 # firejail SuccessExitStatus=15 ProtectHome=yes ProtectControlGroups=yes ProtectKernelModules=yes DynamicUser=yes CacheDirectory=dnscrypt-proxy LogsDirectory=dnscrypt-proxy RuntimeDirectory=dnscrypt-proxy AmbientCapabilities=CAP_NET_BIND_SERVICE [Install] WantedBy=multi-user.target ``` In this form, starting the unit file throws an error: Jun 27 13:02:36 systemd[1]: Started DNSCrypt proxy client [v2]. Jun 27 13:02:36 systemd[1]: Reached target Host and Network Name Lookups. Jun 27 13:02:36 firejail[21411]: Error: cannot create /run/firejail/profile/21411 Jun 27 13:02:36 systemd[1]: dnscrypt-proxy.service: Main process exited, code=exited, status=1/FAILURE Jun 27 13:02:36 systemd[1]: dnscrypt-proxy.service: Failed with result 'exit-code'. For users on Arch ( and I assume this is the same on any distro using v2) the current `dnscrypt-proxy.profile` looks broken. I'm not getting anywhere when experimenting with * `whitelisting` dirs under /var/cache/, /var/log/, /var/run incl. their /var/*/private counterparts * declaring the above dirs `read-write` * adding `writable-var` Has anyone been looking into this recently?
gitea-mirror 2026-05-05 07:55:16 -06:00
Author
Owner

@Vincent43 commented on GitHub (Jun 28, 2018):

Don't use two sandboxing tools at the same time. I would leave that one to systemd. It's pretty much hardened by default, if you want to do more look at https://github.com/jedisct1/dnscrypt-proxy/issues/289#issuecomment-377522739

<!-- gh-comment-id:400869126 --> @Vincent43 commented on GitHub (Jun 28, 2018): Don't use two sandboxing tools at the same time. I would leave that one to systemd. It's pretty much hardened by default, if you want to do more look at https://github.com/jedisct1/dnscrypt-proxy/issues/289#issuecomment-377522739
Author
Owner

@ghost commented on GitHub (Jun 28, 2018):

@Vincent43 Indeed, that's exactly what I'm doing in the case of dnscrypt-proxy, at least on Arch, where the default systemd unit looks already tightened-up. Cheers.

<!-- gh-comment-id:400869874 --> @ghost commented on GitHub (Jun 28, 2018): @Vincent43 Indeed, that's exactly what I'm doing in the case of dnscrypt-proxy, at least on Arch, where the default systemd unit looks already tightened-up. Cheers.
Author
Owner

@ghost commented on GitHub (Jun 28, 2018):

Did some more testing, and for users who would like to harden the sandboxing in Arch's systemd unit for dnscrypt-proxy, these extras have been tested to work:

KeyringMode=private
MemoryDenyWriteExecute=true
NoNewPrivileges=true
PrivateDevices=true
ProtectKernelTunables=yes
ProtectSystem=strict
ReadWritePaths=/var/cache/dnscrypt-proxy /var/log/dnscrypt-proxy /var/run/dnscrypt-proxy
RemoveIPC=true
RestrictRealtime=true
<!-- gh-comment-id:400878590 --> @ghost commented on GitHub (Jun 28, 2018): Did some more testing, and for users who would like to harden the sandboxing in Arch's systemd unit for dnscrypt-proxy, these extras have been tested to work: ``` KeyringMode=private MemoryDenyWriteExecute=true NoNewPrivileges=true PrivateDevices=true ProtectKernelTunables=yes ProtectSystem=strict ReadWritePaths=/var/cache/dnscrypt-proxy /var/log/dnscrypt-proxy /var/run/dnscrypt-proxy RemoveIPC=true RestrictRealtime=true ```
Author
Owner

@curiosity-seeker commented on GitHub (Jun 28, 2018):

FWIW, I'm using those setting, too, on Fedora 28. Additionally:

CapabilityBoundingSet=CAP_NET_BIND_SERVICE
AmbientCapabilities=CAP_NET_BIND_SERVICE

following this advice, and:

# SystemCallFilter=~@aio @chown @clock @cpu-emulation @ipc @keyring @memlock @module @mount @obsolete @privileged @raw-io @reboot @setuid @swap @resources @sync @timer
# @privileged includes @chown @clock @module @raw-io @reboot @swap
SystemCallFilter=~@aio @cpu-emulation @ipc @keyring @memlock @mount @obsolete @privileged @setuid @resources @sync @timer
SystemCallFilter=fchownat
SystemCallArchitectures=native

I think those syscall filters harden the sandbox considerably.

<!-- gh-comment-id:401026429 --> @curiosity-seeker commented on GitHub (Jun 28, 2018): FWIW, I'm using those setting, too, on Fedora 28. Additionally: ``` CapabilityBoundingSet=CAP_NET_BIND_SERVICE AmbientCapabilities=CAP_NET_BIND_SERVICE ``` following [this](https://github.com/jedisct1/dnscrypt-proxy/issues/480#issuecomment-395734793) advice, and: ``` # SystemCallFilter=~@aio @chown @clock @cpu-emulation @ipc @keyring @memlock @module @mount @obsolete @privileged @raw-io @reboot @setuid @swap @resources @sync @timer # @privileged includes @chown @clock @module @raw-io @reboot @swap SystemCallFilter=~@aio @cpu-emulation @ipc @keyring @memlock @mount @obsolete @privileged @setuid @resources @sync @timer SystemCallFilter=fchownat SystemCallArchitectures=native ``` I think those syscall filters harden the sandbox considerably.
Author
Owner

@ghost commented on GitHub (Jun 29, 2018):

@curiosity-seeker Thanks for sharing your insights on this and providing that link. All good now :-)

<!-- gh-comment-id:401274941 --> @ghost commented on GitHub (Jun 29, 2018): @curiosity-seeker Thanks for sharing your insights on this and providing that link. All good now :-)
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: github-starred/firejail#1356
No description provided.