From dafc9983f56177b4c831d193ceaf8dcf13fadd5b Mon Sep 17 00:00:00 2001 From: Glenn Strauss Date: Fri, 7 Aug 2020 23:53:14 -0400 Subject: [PATCH 1/4] lighttpd include external.conf using file glob lighttpd 1.4.40 and later support 'include' using file glob (The prior code for compatibility was presumably for Debian Jessie and earlier, now obsolete. Debian Stretch -- currently oldstable -- ships with lighttpd 1.4.45) Signed-off-by: Glenn Strauss --- advanced/lighttpd.conf.debian | 5 ++--- advanced/lighttpd.conf.fedora | 5 ++--- automated install/basic-install.sh | 4 ---- 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/advanced/lighttpd.conf.debian b/advanced/lighttpd.conf.debian index 74761303..f57bad2d 100644 --- a/advanced/lighttpd.conf.debian +++ b/advanced/lighttpd.conf.debian @@ -67,9 +67,8 @@ mimetype.assign = ( ".woff2" => "font/woff2" ) -# Add user chosen options held in external file -# This uses include_shell instead of an include wildcard for compatibility -include_shell "cat external.conf 2>/dev/null" +# Add user chosen options held in (optional) external file +include "external*.conf" # default listening port for IPv6 falls back to the IPv4 port include_shell "/usr/share/lighttpd/use-ipv6.pl " + server.port diff --git a/advanced/lighttpd.conf.fedora b/advanced/lighttpd.conf.fedora index 7a6a39c5..34056672 100644 --- a/advanced/lighttpd.conf.fedora +++ b/advanced/lighttpd.conf.fedora @@ -68,9 +68,8 @@ mimetype.assign = ( ".woff2" => "font/woff2" ) -# Add user chosen options held in external file -# This uses include_shell instead of an include wildcard for compatibility -include_shell "cat external.conf 2>/dev/null" +# Add user chosen options held in (optional) external file +include "external*.conf" # default listening port for IPv6 falls back to the IPv4 port #include_shell "/usr/share/lighttpd/use-ipv6.pl " + server.port diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index 50ce584d..7462e2f0 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -1412,10 +1412,6 @@ installConfigs() { fi # and copy in the config file Pi-hole needs install -D -m 644 -T ${PI_HOLE_LOCAL_REPO}/advanced/${LIGHTTPD_CFG} "${lighttpdConfig}" - # Make sure the external.conf file exists, as lighttpd v1.4.50 crashes without it - if [ ! -f /etc/lighttpd/external.conf ]; then - install -m 644 /dev/null /etc/lighttpd/external.conf - fi # If there is a custom block page in the html/pihole directory, replace 404 handler in lighttpd config if [[ -f "${PI_HOLE_404_DIR}/custom.php" ]]; then sed -i 's/^\(server\.error-handler-404\s*=\s*\).*$/\1"\/pihole\/custom\.php"/' "${lighttpdConfig}" From 62bf9957dc39f6bfbb1fb4d493c657889793cdf1 Mon Sep 17 00:00:00 2001 From: Glenn Strauss Date: Fri, 7 Aug 2020 23:57:20 -0400 Subject: [PATCH 2/4] lighttpd conf: collect ^/admin/ conditions move a sub-condition to be a nested condition under ^/admin/ Signed-off-by: Glenn Strauss --- advanced/lighttpd.conf.debian | 18 +++++++++--------- advanced/lighttpd.conf.fedora | 18 +++++++++--------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/advanced/lighttpd.conf.debian b/advanced/lighttpd.conf.debian index f57bad2d..cb52cf38 100644 --- a/advanced/lighttpd.conf.debian +++ b/advanced/lighttpd.conf.debian @@ -95,17 +95,17 @@ $HTTP["url"] =~ "^/admin/" { "X-Permitted-Cross-Domain-Policies" => "none", "Referrer-Policy" => "same-origin" ) -} -# Block . files from being served, such as .git, .github, .gitignore -$HTTP["url"] =~ "^/admin/\.(.*)" { - url.access-deny = ("") -} + # Block . files from being served, such as .git, .github, .gitignore + $HTTP["url"] =~ "^/admin/\." { + url.access-deny = ("") + } -# allow teleporter and API qr code iframe on settings page -$HTTP["url"] =~ "/(teleporter|api_token)\.php$" { - $HTTP["referer"] =~ "/admin/settings\.php" { - setenv.add-response-header = ( "X-Frame-Options" => "SAMEORIGIN" ) + # allow teleporter and API qr code iframe on settings page + $HTTP["url"] =~ "/(teleporter|api_token)\.php$" { + $HTTP["referer"] =~ "/admin/settings\.php" { + setenv.add-response-header = ( "X-Frame-Options" => "SAMEORIGIN" ) + } } } diff --git a/advanced/lighttpd.conf.fedora b/advanced/lighttpd.conf.fedora index 34056672..39c665f5 100644 --- a/advanced/lighttpd.conf.fedora +++ b/advanced/lighttpd.conf.fedora @@ -103,17 +103,17 @@ $HTTP["url"] =~ "^/admin/" { "X-Permitted-Cross-Domain-Policies" => "none", "Referrer-Policy" => "same-origin" ) -} -# Block . files from being served, such as .git, .github, .gitignore -$HTTP["url"] =~ "^/admin/\.(.*)" { - url.access-deny = ("") -} + # Block . files from being served, such as .git, .github, .gitignore + $HTTP["url"] =~ "^/admin/\." { + url.access-deny = ("") + } -# allow teleporter and API qr code iframe on settings page -$HTTP["url"] =~ "/(teleporter|api_token)\.php$" { - $HTTP["referer"] =~ "/admin/settings\.php" { - setenv.add-response-header = ( "X-Frame-Options" => "SAMEORIGIN" ) + # allow teleporter and API qr code iframe on settings page + $HTTP["url"] =~ "/(teleporter|api_token)\.php$" { + $HTTP["referer"] =~ "/admin/settings\.php" { + setenv.add-response-header = ( "X-Frame-Options" => "SAMEORIGIN" ) + } } } From 08c7691d1eef900feeda8a8fa2353a8aef5280a6 Mon Sep 17 00:00:00 2001 From: Glenn Strauss Date: Wed, 14 Dec 2022 21:18:04 -0500 Subject: [PATCH 3/4] lighttpd pihole-admin.conf for admin interface Signed-off-by: Glenn Strauss --- advanced/lighttpd.conf.debian | 35 -------------- advanced/lighttpd.conf.fedora | 35 +------------- advanced/pihole-admin.conf | 75 ++++++++++++++++++++++++++++++ automated install/basic-install.sh | 14 ++++++ automated install/uninstall.sh | 13 ++++++ 5 files changed, 103 insertions(+), 69 deletions(-) create mode 100644 advanced/pihole-admin.conf diff --git a/advanced/lighttpd.conf.debian b/advanced/lighttpd.conf.debian index cb52cf38..706b00a8 100644 --- a/advanced/lighttpd.conf.debian +++ b/advanced/lighttpd.conf.debian @@ -76,38 +76,3 @@ include_shell "/usr/share/lighttpd/use-ipv6.pl " + server.port # Prevent Lighttpd from enabling Let's Encrypt SSL for every blocked domain #include_shell "/usr/share/lighttpd/include-conf-enabled.pl" include_shell "find /etc/lighttpd/conf-enabled -name '*.conf' -a ! -name 'letsencrypt.conf' -printf 'include \"%p\"\n' 2>/dev/null" - -# If the URL starts with /admin, it is the Web interface -$HTTP["url"] =~ "^/admin/" { - # X-Pi-hole is a response header for debugging using curl -I - # X-Frame-Options prevents clickjacking attacks and helps ensure your content is not embedded into other sites via < frame >, < iframe > or < object >. - # X-XSS-Protection sets the configuration for the cross-site scripting filters built into most browsers. This is important because it tells the browser to block the response if a malicious script has been inserted from a user input. - # X-Content-Type-Options stops a browser from trying to MIME-sniff the content type and forces it to stick with the declared content-type. This is important because the browser will only load external resources if their content-type matches what is expected, and not malicious hidden code. - # Content-Security-Policy tells the browser where resources are allowed to be loaded and if it’s allowed to parse/run inline styles or Javascript. This is important because it prevents content injection attacks, such as Cross Site Scripting (XSS). - # X-Permitted-Cross-Domain-Policies is an XML document that grants a web client, such as Adobe Flash Player or Adobe Acrobat (though not necessarily limited to these), permission to handle data across domains. - # Referrer-Policy allows control/restriction of the amount of information present in the referral header for links away from your page—the URL path or even if the header is sent at all. - setenv.add-response-header = ( - "X-Pi-hole" => "The Pi-hole Web interface is working!", - "X-Frame-Options" => "DENY", - "X-XSS-Protection" => "0", - "X-Content-Type-Options" => "nosniff", - "Content-Security-Policy" => "default-src 'self' 'unsafe-inline';", - "X-Permitted-Cross-Domain-Policies" => "none", - "Referrer-Policy" => "same-origin" - ) - - # Block . files from being served, such as .git, .github, .gitignore - $HTTP["url"] =~ "^/admin/\." { - url.access-deny = ("") - } - - # allow teleporter and API qr code iframe on settings page - $HTTP["url"] =~ "/(teleporter|api_token)\.php$" { - $HTTP["referer"] =~ "/admin/settings\.php" { - setenv.add-response-header = ( "X-Frame-Options" => "SAMEORIGIN" ) - } - } -} - -# Default expire header -expire.url = ( "" => "access plus 0 seconds" ) diff --git a/advanced/lighttpd.conf.fedora b/advanced/lighttpd.conf.fedora index 39c665f5..05dfc7ec 100644 --- a/advanced/lighttpd.conf.fedora +++ b/advanced/lighttpd.conf.fedora @@ -85,37 +85,4 @@ fastcgi.server = ( ) ) -# If the URL starts with /admin, it is the Web interface -$HTTP["url"] =~ "^/admin/" { - # X-Pi-hole is a response header for debugging using curl -I - # X-Frame-Options prevents clickjacking attacks and helps ensure your content is not embedded into other sites via < frame >, < iframe > or < object >. - # X-XSS-Protection sets the configuration for the cross-site scripting filters built into most browsers. This is important because it tells the browser to block the response if a malicious script has been inserted from a user input. - # X-Content-Type-Options stops a browser from trying to MIME-sniff the content type and forces it to stick with the declared content-type. This is important because the browser will only load external resources if their content-type matches what is expected, and not malicious hidden code. - # Content-Security-Policy tells the browser where resources are allowed to be loaded and if it’s allowed to parse/run inline styles or Javascript. This is important because it prevents content injection attacks, such as Cross Site Scripting (XSS). - # X-Permitted-Cross-Domain-Policies is an XML document that grants a web client, such as Adobe Flash Player or Adobe Acrobat (though not necessarily limited to these), permission to handle data across domains. - # Referrer-Policy allows control/restriction of the amount of information present in the referral header for links away from your page—the URL path or even if the header is sent at all. - setenv.add-response-header = ( - "X-Pi-hole" => "The Pi-hole Web interface is working!", - "X-Frame-Options" => "DENY", - "X-XSS-Protection" => "0", - "X-Content-Type-Options" => "nosniff", - "Content-Security-Policy" => "default-src 'self' 'unsafe-inline';", - "X-Permitted-Cross-Domain-Policies" => "none", - "Referrer-Policy" => "same-origin" - ) - - # Block . files from being served, such as .git, .github, .gitignore - $HTTP["url"] =~ "^/admin/\." { - url.access-deny = ("") - } - - # allow teleporter and API qr code iframe on settings page - $HTTP["url"] =~ "/(teleporter|api_token)\.php$" { - $HTTP["referer"] =~ "/admin/settings\.php" { - setenv.add-response-header = ( "X-Frame-Options" => "SAMEORIGIN" ) - } - } -} - -# Default expire header -expire.url = ( "" => "access plus 0 seconds" ) +include "/etc/lighttpd/conf.d/pihole-admin.conf" diff --git a/advanced/pihole-admin.conf b/advanced/pihole-admin.conf new file mode 100644 index 00000000..7d321831 --- /dev/null +++ b/advanced/pihole-admin.conf @@ -0,0 +1,75 @@ +# Pi-hole: A black hole for Internet advertisements +# (c) 2017 Pi-hole, LLC (https://pi-hole.net) +# Network-wide ad blocking via your own hardware. +# +# Lighttpd config for Pi-hole +# +# This file is copyright under the latest version of the EUPL. +# Please see LICENSE file for your rights under this license. + +############################################################################### +# FILE AUTOMATICALLY OVERWRITTEN BY PI-HOLE INSTALL/UPDATE PROCEDURE. # +# ANY CHANGES MADE TO THIS FILE AFTER INSTALL WILL BE LOST ON THE NEXT UPDATE # +############################################################################### + +$HTTP["url"] =~ "^/admin/" { + server.document-root = "/var/www/html" + server.stream-response-body = 1 + fastcgi.server = ( + ".php" => ( + "localhost" => ( + "socket" => "/tmp/pihole-php-fastcgi.socket", + "bin-path" => "/usr/bin/php-cgi", + "min-procs" => 0, + "max-procs" => 1, + ) + ) + ) + + # X-Pi-hole is a response header for debugging using curl -I + # X-Frame-Options prevents clickjacking attacks and helps ensure your content is not embedded into other sites via < frame >, < iframe > or < object >. + # X-XSS-Protection sets the configuration for the cross-site scripting filters built into most browsers. This is important because it tells the browser to block the response if a malicious script has been inserted from a user input. (deprecated; disabled) + # X-Content-Type-Options stops a browser from trying to MIME-sniff the content type and forces it to stick with the declared content-type. This is important because the browser will only load external resources if their content-type matches what is expected, and not malicious hidden code. + # Content-Security-Policy tells the browser where resources are allowed to be loaded and if it’s allowed to parse/run inline styles or Javascript. This is important because it prevents content injection attacks, such as Cross Site Scripting (XSS). + # X-Permitted-Cross-Domain-Policies is an XML document that grants a web client, such as Adobe Flash Player or Adobe Acrobat (though not necessarily limited to these), permission to handle data across domains. + # Referrer-Policy allows control/restriction of the amount of information present in the referral header for links away from your page—the URL path or even if the header is sent at all. + setenv.add-response-header = ( + "X-Pi-hole" => "The Pi-hole Web interface is working!", + "X-Frame-Options" => "DENY", + "X-XSS-Protection" => "0", + "X-Content-Type-Options" => "nosniff", + "Content-Security-Policy" => "default-src 'self' 'unsafe-inline';", + "X-Permitted-Cross-Domain-Policies" => "none", + "Referrer-Policy" => "same-origin" + ) + + # Block . files from being served, such as .git, .github, .gitignore + $HTTP["url"] =~ "^/admin/\." { + url.access-deny = ("") + } + + # allow teleporter and API qr code iframe on settings page + $HTTP["url"] =~ "/(teleporter|api_token)\.php$" { + $HTTP["referer"] =~ "/admin/settings\.php" { + setenv.set-response-header = ( "X-Frame-Options" => "SAMEORIGIN" ) + } + } +} +else $HTTP["url"] == "/admin" { + url.redirect = ("" => "/admin/") +} + +$HTTP["host"] == "pi.hole" { + $HTTP["url"] == "/" { + url.redirect = ("" => "/admin/") + } +} + +# (safe to enable after pihole ceases to support Debian 10 (Buster)) +# (For lighttpd 1.4.56+ which ignores duplicated server.modules entries) +#server.modules += ( +# "mod_access", +# "mod_redirect", +# "mod_fastcgi", +# "mod_setenv", +#) diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index 7462e2f0..39d7ced4 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -1416,6 +1416,20 @@ installConfigs() { if [[ -f "${PI_HOLE_404_DIR}/custom.php" ]]; then sed -i 's/^\(server\.error-handler-404\s*=\s*\).*$/\1"\/pihole\/custom\.php"/' "${lighttpdConfig}" fi + # Copy the config file to include for pihole admin interface + if [[ -d "/etc/lighttpd/conf.d" ]]; then + install -D -m 644 -T ${PI_HOLE_LOCAL_REPO}/advanced/pihole-admin.conf /etc/lighttpd/conf.d/pihole-admin.conf + elif [[ -d "/etc/lighttpd/conf-available" ]]; then + conf=/etc/lighttpd/conf-available/15-pihole-admin.conf + install -D -m 644 -T ${PI_HOLE_LOCAL_REPO}/advanced/pihole-admin.conf $conf + if is_command lighty-enable-mod ; then + lighty-enable-mod pihole-admin > /dev/null || true + fi + else + # lighttpd config include dir not found + printf " %b Warning: lighttpd config include dir not found\\n" "${INFO}" + printf " Please manually install pihole-admin.conf\\n" + fi # Make the directories if they do not exist and set the owners mkdir -p /run/lighttpd chown ${LIGHTTPD_USER}:${LIGHTTPD_GROUP} /run/lighttpd diff --git a/automated install/uninstall.sh b/automated install/uninstall.sh index 0b516d0f..541c0a76 100755 --- a/automated install/uninstall.sh +++ b/automated install/uninstall.sh @@ -139,6 +139,19 @@ removeNoPurge() { ${SUDO} rm /etc/lighttpd/external.conf fi + # Fedora-based + if [[ -f /etc/lighttpd/conf.d/pihole-admin.conf ]]; then + ${SUDO} rm /etc/lighttpd/conf.d/pihole-admin.conf + fi + + # Debian-based + if [[ -f /etc/lighttpd/conf-available/pihole-admin.conf ]]; then + if is_command lighty-disable-mod ; then + ${SUDO} lighty-disable-mod pihole-admin > /dev/null || true + fi + ${SUDO} rm /etc/lighttpd/conf-available/15-pihole-admin.conf + fi + echo -e " ${TICK} Removed lighttpd configs" fi From 78f9e3842536d14f04acc093540c54b83fbcbd1e Mon Sep 17 00:00:00 2001 From: Glenn Strauss Date: Sun, 18 Dec 2022 00:58:08 -0500 Subject: [PATCH 4/4] lighttpd: test for /etc/lighttpd/conf*/pihole-admin.conf Signed-off-by: Glenn Strauss --- test/test_any_automated_install.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/test_any_automated_install.py b/test/test_any_automated_install.py index 2ea619f7..0b039593 100644 --- a/test/test_any_automated_install.py +++ b/test/test_any_automated_install.py @@ -289,6 +289,24 @@ def test_installPihole_fresh_install_readableFiles(host): check_lighttpd = test_cmd.format("r", "/etc/lighttpd/lighttpd.conf", piholeuser) actual_rc = host.run(check_lighttpd).rc assert exit_status_success == actual_rc + # check readable /etc/lighttpd/conf*/pihole-admin.conf + check_lighttpd = test_cmd.format("r", "/etc/lighttpd/conf.d", piholeuser) + if host.run(check_lighttpd).rc == exit_status_success: + check_lighttpd = test_cmd.format( + "r", "/etc/lighttpd/conf.d/pihole-admin.conf", piholeuser + ) + actual_rc = host.run(check_lighttpd).rc + assert exit_status_success == actual_rc + else: + check_lighttpd = test_cmd.format( + "r", "/etc/lighttpd/conf-available", piholeuser + ) + if host.run(check_lighttpd).rc == exit_status_success: + check_lighttpd = test_cmd.format( + "r", "/etc/lighttpd/conf-available/15-pihole-admin.conf", piholeuser + ) + actual_rc = host.run(check_lighttpd).rc + assert exit_status_success == actual_rc # check readable and executable manpages if maninstalled is True: check_man = test_cmd.format("x", "/usr/local/share/man", piholeuser)