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>
This commit is contained in:
Mathieu Hofman 2019-02-06 02:02:30 -08:00
parent 68d6c343a5
commit 6629aff889
9 changed files with 35 additions and 4 deletions

View File

@ -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 }}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -61,6 +61,7 @@ There are other environment variables if you want to customize various things in
| `-e INTERFACE=<NIC>`<br/> *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=<local\|all\|NIC>`<br/> *Advanced/Optional* | `local` listens on all local subnets, `all` permits listening on internet origin subnets in addition to local.
| `-e WEB_PORT=<PORT>`<br/> *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=<pihole\|root>`<br/> *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`<br/> **Recommended** | Volumes for your Pi-hole configs help persist changes across docker image updates
| `-v /dir/for/dnsmasq.d:/etc/dnsmasq.d`<br/> **Recommended** | Volumes for your dnsmasq configs help persist changes across docker image updates
| `--net=host`<br/> *Optional* | Alternative to `-p <port>:<port>` 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`<br/> *Required* | FTLDNS will fail to start without this setting
| `--cap-add=NET_ADMIN`<br/> *Recommended* | FTLDNS may not work properly without this setting. See [Note on Capabilities](#note-on-capabilities) below.
| `--dns=127.0.0.1`<br/> *Recommended* | Sets your container's resolve settings to localhost so it can resolve DHCP hostnames from Pi-hole's DNSMasq <!-- also fixes common resolution errors on container restart -->
| `--dns=1.1.1.1`<br/> *Optional* | Sets a backup server of your choosing in case DNSMasq has problems starting
| `--env-file .env` <br/> *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.

View File

@ -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

View File

@ -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

View File

@ -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