From 6629aff889a1a14899c16611bf7a845930a1d825 Mon Sep 17 00:00:00 2001 From: Mathieu Hofman <86499+mhofman@users.noreply.github.com> Date: Wed, 6 Feb 2019 02:02:30 -0800 Subject: [PATCH] Allow running pihole-FTL as non-root - Add a new container environment variable allowing to specify the user to run the pihole-FTL process as. Defaults to root. - Set inherited capabilities attributes on the pihole-FTL file to automatically grant runtime permitted capabilities when available in the bounding set. This allows dropping root before starting pihole-FTL without failing with a permission error if the capabilities are not available to the container (the process may still error out if performing an operation requiring the capability). - Add some information on capabilities to the Readme file. Signed-off-by: Mathieu Hofman <86499+mhofman@users.noreply.github.com> --- Dockerfile.template | 1 + Dockerfile_aarch64 | 1 + Dockerfile_amd64 | 1 + Dockerfile_armel | 1 + Dockerfile_armhf | 1 + README.md | 14 +++++++++++++- bash_functions.sh | 13 ++++++++++++- s6/debian-root/etc/services.d/pihole-FTL/run | 6 ++++-- start.sh | 1 + 9 files changed, 35 insertions(+), 4 deletions(-) diff --git a/Dockerfile.template b/Dockerfile.template index 43d39dc..fc273a0 100644 --- a/Dockerfile.template +++ b/Dockerfile.template @@ -31,6 +31,7 @@ ENV S6_LOGGING 0 ENV S6_KEEP_ENV 1 ENV S6_BEHAVIOUR_IF_STAGE2_FAILS 2 ENV FTL_CMD no-daemon +ENV DNSMASQ_USER root ENV VERSION {{ pihole.version }} ENV ARCH {{ pihole.arch }} diff --git a/Dockerfile_aarch64 b/Dockerfile_aarch64 index f8fcb8f..bd2a877 100644 --- a/Dockerfile_aarch64 +++ b/Dockerfile_aarch64 @@ -31,6 +31,7 @@ ENV S6_LOGGING 0 ENV S6_KEEP_ENV 1 ENV S6_BEHAVIOUR_IF_STAGE2_FAILS 2 ENV FTL_CMD no-daemon +ENV DNSMASQ_USER root ENV VERSION v4.2.1 ENV ARCH aarch64 diff --git a/Dockerfile_amd64 b/Dockerfile_amd64 index 39e5e40..092b63d 100644 --- a/Dockerfile_amd64 +++ b/Dockerfile_amd64 @@ -31,6 +31,7 @@ ENV S6_LOGGING 0 ENV S6_KEEP_ENV 1 ENV S6_BEHAVIOUR_IF_STAGE2_FAILS 2 ENV FTL_CMD no-daemon +ENV DNSMASQ_USER root ENV VERSION v4.2.1 ENV ARCH amd64 diff --git a/Dockerfile_armel b/Dockerfile_armel index 6ee9d66..b857e30 100644 --- a/Dockerfile_armel +++ b/Dockerfile_armel @@ -31,6 +31,7 @@ ENV S6_LOGGING 0 ENV S6_KEEP_ENV 1 ENV S6_BEHAVIOUR_IF_STAGE2_FAILS 2 ENV FTL_CMD no-daemon +ENV DNSMASQ_USER root ENV VERSION v4.2.1 ENV ARCH armel diff --git a/Dockerfile_armhf b/Dockerfile_armhf index 5cf6862..84adf48 100644 --- a/Dockerfile_armhf +++ b/Dockerfile_armhf @@ -31,6 +31,7 @@ ENV S6_LOGGING 0 ENV S6_KEEP_ENV 1 ENV S6_BEHAVIOUR_IF_STAGE2_FAILS 2 ENV FTL_CMD no-daemon +ENV DNSMASQ_USER root ENV VERSION v4.2.1 ENV ARCH armhf diff --git a/README.md b/README.md index 4e4bd72..a0af648 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,7 @@ There are other environment variables if you want to customize various things in | `-e INTERFACE=`
*Advanced/Optional* | The default works fine with our basic example docker run commands. If you're trying to use DHCP with `--net host` mode then you may have to customize this or DNSMASQ_LISTENING. | `-e DNSMASQ_LISTENING=`
*Advanced/Optional* | `local` listens on all local subnets, `all` permits listening on internet origin subnets in addition to local. | `-e WEB_PORT=`
*Advanced/Optional* | **This will break the 'webpage blocked' functionality of Pi-hole** however it may help advanced setups like those running synology or `--net=host` docker argument. This guide explains how to restore webpage blocked functionality using a linux router DNAT rule: [Alternative Synology installation method](https://discourse.pi-hole.net/t/alternative-synology-installation-method/5454?u=diginc) +| `-e DNSMASQ_USER=`
*Experimental Default: root* | Allows running FTLDNS as non-root. Here is a rundown of the other arguments passed into the example `docker run`: @@ -71,7 +72,7 @@ Here is a rundown of the other arguments passed into the example `docker run`: | `-v /dir/for/pihole:/etc/pihole`
**Recommended** | Volumes for your Pi-hole configs help persist changes across docker image updates | `-v /dir/for/dnsmasq.d:/etc/dnsmasq.d`
**Recommended** | Volumes for your dnsmasq configs help persist changes across docker image updates | `--net=host`
*Optional* | Alternative to `-p :` arguments (Cannot be used at same time as -p) if you don't run any other web application. DHCP runs best with --net=host, otherwise your router must support dhcp-relay settings. -| `--cap-add=NET_ADMIN`
*Required* | FTLDNS will fail to start without this setting +| `--cap-add=NET_ADMIN`
*Recommended* | FTLDNS may not work properly without this setting. See [Note on Capabilities](#note-on-capabilities) below. | `--dns=127.0.0.1`
*Recommended* | Sets your container's resolve settings to localhost so it can resolve DHCP hostnames from Pi-hole's DNSMasq | `--dns=1.1.1.1`
*Optional* | Sets a backup server of your choosing in case DNSMasq has problems starting | `--env-file .env`
*Optional* | File to store environment variables for docker. Here for convenience @@ -151,6 +152,17 @@ As long as your docker system service auto starts on boot and you run your conta NOTE: After initial run you may need to manually stop the docker container with "docker stop pihole" before the systemctl can start controlling the container. +## Note on Capabilities + +DNSMasq / [FTLDNS](https://docs.pi-hole.net/ftldns/in-depth/#linux-capabilities) expects to have the following capabilities available: +- `CAP_NET_BIND_SERVICE`: Allows FTLDNS binding to TCP/UDP sockets below 1024 (specifically DNS service on port 53) +- `CAP_NET_RAW`: use raw and packet sockets (needed for handling DHCPv6 requests, and verifying that an IP is not in use before leasing it) +- `CAP_NET_ADMIN`: modify routing tables and other network-related operations (in particular inserting an entry in the neighbor table to answer DHCP requests using unicast packets) + +This image automatically grants those capabilities, if available, to the FTLDNS process, even when run as non-root.\ +By default, docker does not include the `NET_ADMIN` capability for non-privileged containers, and it is recommended to explicitly add it to the container using `--cap-add=NET_ADMIN`.\ +However, if DHCP and IPv6 Router Advertisements are not in use, it should be safe to skip it. For the most paranoid, it should even be possible to explicitly drop the `NET_RAW` capability to prevent FTLDNS from automatically gaining it. + # User Feedback Please report issues on the [GitHub project](https://github.com/pi-hole/docker-pi-hole) when you suspect something docker related. Pi-hole or general docker questions are best answered on our [user forums](https://github.com/pi-hole/pi-hole/blob/master/README.md#get-help-or-connect-with-us-on-the-web). Ping me (@diginc) on the forums if it's a docker container and you're not sure if it's docker related. diff --git a/bash_functions.sh b/bash_functions.sh index ad15a20..b7afecd 100644 --- a/bash_functions.sh +++ b/bash_functions.sh @@ -25,6 +25,17 @@ docker_checks() { cat /etc/resolv.conf } +fix_capabilities() { + [ ! -f /.piholeFirstBoot ] && return + + setcap CAP_NET_BIND_SERVICE,CAP_NET_RAW,CAP_NET_ADMIN+ei $(which pihole-FTL) || ret=$? + + if [[ $ret -ne 0 && "${DNSMASQ_USER:-root}" != "root" ]]; then + echo "ERROR: Failed to set capabilities for pihole-FTL. Cannot run as non-root." + exit 1 + fi +} + prepare_configs() { # Done in /start.sh, don't do twice PH_TEST=true . $PIHOLE_INSTALL @@ -323,7 +334,7 @@ setup_ipv4_ipv6() { test_configs() { set -e echo -n '::: Testing pihole-FTL DNS: ' - pihole-FTL test || exit 1 + sudo -u ${DNSMASQ_USER:-root} pihole-FTL test || exit 1 echo -n '::: Testing lighttpd config: ' lighttpd -t -f /etc/lighttpd/lighttpd.conf || exit 1 set +e diff --git a/s6/debian-root/etc/services.d/pihole-FTL/run b/s6/debian-root/etc/services.d/pihole-FTL/run index cc72e5d..6c3277a 100644 --- a/s6/debian-root/etc/services.d/pihole-FTL/run +++ b/s6/debian-root/etc/services.d/pihole-FTL/run @@ -1,5 +1,7 @@ #!/usr/bin/with-contenv bash -s6-echo "Starting pihole-FTL ($FTL_CMD)" +DNSMASQ_USER=${DNSMASQ_USER:-root} + +s6-echo "Starting pihole-FTL ($FTL_CMD) as ${DNSMASQ_USER}" # /var/log/pihole*.log has this data - this duplicates it in docker logs unless you send to dev null -s6-setuidgid root pihole-FTL $FTL_CMD >/dev/null 2>&1 +s6-setuidgid ${DNSMASQ_USER} pihole-FTL $FTL_CMD >/dev/null 2>&1 diff --git a/start.sh b/start.sh index 8fa2939..8f5686f 100755 --- a/start.sh +++ b/start.sh @@ -27,6 +27,7 @@ PH_TEST=true . $PIHOLE_INSTALL echo " ::: Starting docker specific setup for docker pihole/pihole" docker_checks +fix_capabilities generate_password validate_env || exit 1 prepare_configs