Merge pull request #4705 from pi-hole/development

v5.10 Release
This commit is contained in:
Adam Warner 2022-04-20 19:41:17 +01:00 committed by GitHub
commit 853f6b7da2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 401 additions and 189 deletions

View file

@ -4,6 +4,9 @@ on:
pull_request: pull_request:
types: [opened, synchronize, reopened, ready_for_review] types: [opened, synchronize, reopened, ready_for_review]
permissions:
contents: read
jobs: jobs:
smoke-test: smoke-test:
if: github.event.pull_request.draft == false if: github.event.pull_request.draft == false
@ -37,7 +40,7 @@ jobs:
uses: actions/checkout@v2 uses: actions/checkout@v2
- -
name: Set up Python 3.8 name: Set up Python 3.8
uses: actions/setup-python@v2 uses: actions/setup-python@v3
with: with:
python-version: 3.8 python-version: 3.8
- -

View file

@ -161,4 +161,4 @@ Some notable features include:
There are several ways to [access the dashboard](https://discourse.pi-hole.net/t/how-do-i-access-pi-holes-dashboard-admin-interface/3168): There are several ways to [access the dashboard](https://discourse.pi-hole.net/t/how-do-i-access-pi-holes-dashboard-admin-interface/3168):
1. `http://pi.hole/admin/` (when using Pi-hole as your DNS server) 1. `http://pi.hole/admin/` (when using Pi-hole as your DNS server)
2. `http://<IP_ADDPRESS_OF_YOUR_PI_HOLE>/admin/` 2. `http://<IP_ADDRESS_OF_YOUR_PI_HOLE>/admin/`

View file

@ -1,5 +1,5 @@
# Determine if terminal is capable of showing colors # Determine if terminal is capable of showing colors
if [[ -t 1 ]] && [[ $(tput colors) -ge 8 ]]; then if ([[ -t 1 ]] && [[ $(tput colors) -ge 8 ]]) || [[ "${WEBCALL}" ]]; then
# Bold and underline may not show up on all clients # Bold and underline may not show up on all clients
# If something MUST be emphasized, use both # If something MUST be emphasized, use both
COL_BOLD='' COL_BOLD=''

View file

@ -906,9 +906,11 @@ dig_at() {
# Removes all interfaces which are not UP # Removes all interfaces which are not UP
# s/^[0-9]*: //g; # s/^[0-9]*: //g;
# Removes interface index # Removes interface index
# s/@.*//g;
# Removes everything after @ (if found)
# s/: <.*//g; # s/: <.*//g;
# Removes everything after the interface name # Removes everything after the interface name
interfaces="$(ip link show | sed "/ master /d;/UP/!d;s/^[0-9]*: //g;s/: <.*//g;")" interfaces="$(ip link show | sed "/ master /d;/UP/!d;s/^[0-9]*: //g;s/@.*//g;s/: <.*//g;")"
while IFS= read -r iface ; do while IFS= read -r iface ; do
# Get addresses of current interface # Get addresses of current interface
@ -1273,7 +1275,7 @@ show_clients() {
} }
show_messages() { show_messages() {
show_FTL_db_entries "Pi-hole diagnosis messages" "SELECT id,datetime(timestamp,'unixepoch','localtime') timestamp,type,message,blob1,blob2,blob3,blob4,blob5 FROM message;" "4 19 20 60 20 20 20 20 20" show_FTL_db_entries "Pi-hole diagnosis messages" "SELECT count (message) as count, datetime(max(timestamp),'unixepoch','localtime') as 'last timestamp', type, message, blob1, blob2, blob3, blob4, blob5 FROM message GROUP BY type, message, blob1, blob2, blob3, blob4, blob5;" "6 19 20 60 20 20 20 20 20"
} }
analyze_gravity_list() { analyze_gravity_list() {

View file

@ -63,7 +63,7 @@ else
fi fi
fi fi
# Delete most recent 24 hours from FTL's database, leave even older data intact (don't wipe out all history) # Delete most recent 24 hours from FTL's database, leave even older data intact (don't wipe out all history)
deleted=$(pihole-FTL sqlite3 "${DBFILE}" "DELETE FROM queries WHERE timestamp >= strftime('%s','now')-86400; select changes() from queries limit 1") deleted=$(pihole-FTL sqlite3 "${DBFILE}" "DELETE FROM query_storage WHERE timestamp >= strftime('%s','now')-86400; select changes() from query_storage limit 1")
# Restart pihole-FTL to force reloading history # Restart pihole-FTL to force reloading history
sudo pihole restartdns sudo pihole restartdns

View file

@ -64,8 +64,8 @@ Example: 'pihole -q -exact domain.com'
Query the adlists for a specified domain Query the adlists for a specified domain
Options: Options:
-exact Search the block lists for exact domain matches -exact Search the adlists for exact domain matches
-all Return all query matches within a block list -all Return all query matches within the adlists
-h, --help Show this help dialog" -h, --help Show this help dialog"
exit 0 exit 0
fi fi
@ -210,7 +210,7 @@ mapfile -t results <<< "$(scanDatabaseTable "${domainQuery}" "gravity")"
# Handle notices # Handle notices
if [[ -z "${wbMatch:-}" ]] && [[ -z "${wcMatch:-}" ]] && [[ -z "${results[*]}" ]]; then if [[ -z "${wbMatch:-}" ]] && [[ -z "${wcMatch:-}" ]] && [[ -z "${results[*]}" ]]; then
echo -e " ${INFO} No ${exact/t/t }results found for ${COL_BOLD}${domainQuery}${COL_NC} within the block lists" echo -e " ${INFO} No ${exact/t/t }results found for ${COL_BOLD}${domainQuery}${COL_NC} within the adlists"
exit 0 exit 0
elif [[ -z "${results[*]}" ]]; then elif [[ -z "${results[*]}" ]]; then
# Result found in WL/BL/Wildcards # Result found in WL/BL/Wildcards

View file

@ -1,4 +1,6 @@
#!/usr/bin/env bash #!/usr/bin/env sh
# shellcheck disable=SC3043 #https://github.com/koalaman/shellcheck/wiki/SC3043#exceptions
# Pi-hole: A black hole for Internet advertisements # Pi-hole: A black hole for Internet advertisements
# (c) 2017 Pi-hole, LLC (https://pi-hole.net) # (c) 2017 Pi-hole, LLC (https://pi-hole.net)
# Network-wide ad blocking via your own hardware. # Network-wide ad blocking via your own hardware.
@ -15,21 +17,82 @@
# - New functions must have a test added for them in test/test_any_utils.py # - New functions must have a test added for them in test/test_any_utils.py
####################### #######################
# Takes three arguments key, value, and file. # Takes Three arguments: file, key, and value.
#
# Checks the target file for the existence of the key # Checks the target file for the existence of the key
# - If it exists, it changes the value # - If it exists, it changes the value
# - If it does not exist, it adds the value # - If it does not exist, it adds the value
# #
# Example usage: # Example usage:
# addOrEditKeyValuePair "BLOCKING_ENABLED" "true" "/etc/pihole/setupVars.conf" # addOrEditKeyValPair "/etc/pihole/setupVars.conf" "BLOCKING_ENABLED" "true"
####################### #######################
addOrEditKeyValPair() { addOrEditKeyValPair() {
local key="${1}" local file="${1}"
local value="${2}" local key="${2}"
local file="${3}" local value="${3}"
if grep -q "^${key}=" "${file}"; then if grep -q "^${key}=" "${file}"; then
# Key already exists in file, modify the value
sed -i "/^${key}=/c\\${key}=${value}" "${file}" sed -i "/^${key}=/c\\${key}=${value}" "${file}"
else else
# Key does not already exist, add it and it's value
echo "${key}=${value}" >> "${file}" echo "${key}=${value}" >> "${file}"
fi fi
} }
#######################
# Takes two arguments: file, and key.
# Adds a key to target file
#
# Example usage:
# addKey "/etc/dnsmasq.d/01-pihole.conf" "log-queries"
#######################
addKey(){
local file="${1}"
local key="${2}"
if ! grep -q "^${key}" "${file}"; then
# Key does not exist, add it.
echo "${key}" >> "${file}"
fi
}
#######################
# Takes two arguments: file, and key.
# Deletes a key or key/value pair from target file
#
# Example usage:
# removeKey "/etc/pihole/setupVars.conf" "PIHOLE_DNS_1"
#######################
removeKey() {
local file="${1}"
local key="${2}"
sed -i "/^${key}/d" "${file}"
}
#######################
# returns FTL's current telnet API port
#######################
getFTLAPIPort(){
local FTLCONFFILE="/etc/pihole/pihole-FTL.conf"
local DEFAULT_PORT_FILE="/run/pihole-FTL.port"
local DEFAULT_FTL_PORT=4711
local PORTFILE
local ftl_api_port
if [ -f "$FTLCONFFILE" ]; then
# if PORTFILE is not set in pihole-FTL.conf, use the default path
PORTFILE="$( (grep "^PORTFILE=" $FTLCONFFILE || echo "$DEFAULT_PORT_FILE") | cut -d"=" -f2-)"
fi
if [ -s "$PORTFILE" ]; then
# -s: FILE exists and has a size greater than zero
ftl_api_port=$(cat "${PORTFILE}")
# Exploit prevention: unset the variable if there is malicious content
# Verify that the value read from the file is numeric
expr "$ftl_api_port" : "[^[:digit:]]" > /dev/null && unset ftl_api_port
fi
# echo the port found in the portfile or default to the default port
echo "${ftl_api_port:=$DEFAULT_FTL_PORT}"
}

View file

@ -1,5 +1,7 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# shellcheck disable=SC1090 # shellcheck disable=SC1090
# shellcheck disable=SC2154
# Pi-hole: A black hole for Internet advertisements # Pi-hole: A black hole for Internet advertisements
# (c) 2017 Pi-hole, LLC (https://pi-hole.net) # (c) 2017 Pi-hole, LLC (https://pi-hole.net)
@ -26,6 +28,9 @@ readonly PI_HOLE_FILES_DIR="/etc/.pihole"
PH_TEST="true" PH_TEST="true"
source "${PI_HOLE_FILES_DIR}/automated install/basic-install.sh" source "${PI_HOLE_FILES_DIR}/automated install/basic-install.sh"
utilsfile="/opt/pihole/utils.sh"
source "${utilsfile}"
coltable="/opt/pihole/COL_TABLE" coltable="/opt/pihole/COL_TABLE"
if [[ -f ${coltable} ]]; then if [[ -f ${coltable} ]]; then
source ${coltable} source ${coltable}
@ -51,45 +56,39 @@ Options:
} }
add_setting() { add_setting() {
echo "${1}=${2}" >> "${setupVars}" addOrEditKeyValPair "${setupVars}" "${1}" "${2}"
} }
delete_setting() { delete_setting() {
sed -i "/^${1}/d" "${setupVars}" removeKey "${setupVars}" "${1}"
} }
change_setting() { change_setting() {
delete_setting "${1}" addOrEditKeyValPair "${setupVars}" "${1}" "${2}"
add_setting "${1}" "${2}"
} }
addFTLsetting() { addFTLsetting() {
echo "${1}=${2}" >> "${FTLconf}" addOrEditKeyValPair "${FTLconf}" "${1}" "${2}"
} }
deleteFTLsetting() { deleteFTLsetting() {
sed -i "/^${1}/d" "${FTLconf}" removeKey "${FTLconf}" "${1}"
} }
changeFTLsetting() { changeFTLsetting() {
deleteFTLsetting "${1}" addOrEditKeyValPair "${FTLconf}" "${1}" "${2}"
addFTLsetting "${1}" "${2}"
} }
add_dnsmasq_setting() { add_dnsmasq_setting() {
if [[ "${2}" != "" ]]; then addOrEditKeyValPair "${dnsmasqconfig}" "${1}" "${2}"
echo "${1}=${2}" >> "${dnsmasqconfig}"
else
echo "${1}" >> "${dnsmasqconfig}"
fi
} }
delete_dnsmasq_setting() { delete_dnsmasq_setting() {
sed -i "/^${1}/d" "${dnsmasqconfig}" removeKey "${dnsmasqconfig}" "${1}"
} }
SetTemperatureUnit() { SetTemperatureUnit() {
change_setting "TEMPERATUREUNIT" "${unit}" addOrEditKeyValPair "${setupVars}" "TEMPERATUREUNIT" "${unit}"
echo -e " ${TICK} Set temperature unit to ${unit}" echo -e " ${TICK} Set temperature unit to ${unit}"
} }
@ -124,7 +123,7 @@ SetWebPassword() {
echo "" echo ""
if [ "${PASSWORD}" == "" ]; then if [ "${PASSWORD}" == "" ]; then
change_setting "WEBPASSWORD" "" addOrEditKeyValPair "${setupVars}" "WEBPASSWORD" ""
echo -e " ${TICK} Password Removed" echo -e " ${TICK} Password Removed"
exit 0 exit 0
fi fi
@ -137,7 +136,7 @@ SetWebPassword() {
# We do not wrap this in brackets, otherwise BASH will expand any appropriate syntax # We do not wrap this in brackets, otherwise BASH will expand any appropriate syntax
hash=$(HashPassword "$PASSWORD") hash=$(HashPassword "$PASSWORD")
# Save hash to file # Save hash to file
change_setting "WEBPASSWORD" "${hash}" addOrEditKeyValPair "${setupVars}" "WEBPASSWORD" "${hash}"
echo -e " ${TICK} New password set" echo -e " ${TICK} New password set"
else else
echo -e " ${CROSS} Passwords don't match. Your password has not been changed" echo -e " ${CROSS} Passwords don't match. Your password has not been changed"
@ -148,7 +147,7 @@ SetWebPassword() {
ProcessDNSSettings() { ProcessDNSSettings() {
source "${setupVars}" source "${setupVars}"
delete_dnsmasq_setting "server" removeKey "${dnsmasqconfig}" "server"
COUNTER=1 COUNTER=1
while true ; do while true ; do
@ -156,34 +155,34 @@ ProcessDNSSettings() {
if [ -z "${!var}" ]; then if [ -z "${!var}" ]; then
break; break;
fi fi
add_dnsmasq_setting "server" "${!var}" addKey "${dnsmasqconfig}" "server=${!var}"
(( COUNTER++ )) (( COUNTER++ ))
done done
# The option LOCAL_DNS_PORT is deprecated # The option LOCAL_DNS_PORT is deprecated
# We apply it once more, and then convert it into the current format # We apply it once more, and then convert it into the current format
if [ -n "${LOCAL_DNS_PORT}" ]; then if [ -n "${LOCAL_DNS_PORT}" ]; then
add_dnsmasq_setting "server" "127.0.0.1#${LOCAL_DNS_PORT}" addOrEditKeyValPair "${dnsmasqconfig}" "server" "127.0.0.1#${LOCAL_DNS_PORT}"
add_setting "PIHOLE_DNS_${COUNTER}" "127.0.0.1#${LOCAL_DNS_PORT}" addOrEditKeyValPair "${setupVars}" "PIHOLE_DNS_${COUNTER}" "127.0.0.1#${LOCAL_DNS_PORT}"
delete_setting "LOCAL_DNS_PORT" removeKey "${setupVars}" "LOCAL_DNS_PORT"
fi fi
delete_dnsmasq_setting "domain-needed" removeKey "${dnsmasqconfig}" "domain-needed"
delete_dnsmasq_setting "expand-hosts" removeKey "${dnsmasqconfig}" "expand-hosts"
if [[ "${DNS_FQDN_REQUIRED}" == true ]]; then if [[ "${DNS_FQDN_REQUIRED}" == true ]]; then
add_dnsmasq_setting "domain-needed" addKey "${dnsmasqconfig}" "domain-needed"
add_dnsmasq_setting "expand-hosts" addKey "${dnsmasqconfig}" "expand-hosts"
fi fi
delete_dnsmasq_setting "bogus-priv" removeKey "${dnsmasqconfig}" "bogus-priv"
if [[ "${DNS_BOGUS_PRIV}" == true ]]; then if [[ "${DNS_BOGUS_PRIV}" == true ]]; then
add_dnsmasq_setting "bogus-priv" addKey "${dnsmasqconfig}" "bogus-priv"
fi fi
delete_dnsmasq_setting "dnssec" removeKey "${dnsmasqconfig}" "dnssec"
delete_dnsmasq_setting "trust-anchor=" removeKey "${dnsmasqconfig}" "trust-anchor"
if [[ "${DNSSEC}" == true ]]; then if [[ "${DNSSEC}" == true ]]; then
echo "dnssec echo "dnssec
@ -191,24 +190,24 @@ trust-anchor=.,20326,8,2,E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC68345710423
" >> "${dnsmasqconfig}" " >> "${dnsmasqconfig}"
fi fi
delete_dnsmasq_setting "host-record" removeKey "${dnsmasqconfig}" "host-record"
if [ -n "${HOSTRECORD}" ]; then if [ -n "${HOSTRECORD}" ]; then
add_dnsmasq_setting "host-record" "${HOSTRECORD}" addOrEditKeyValPair "${dnsmasqconfig}" "host-record" "${HOSTRECORD}"
fi fi
# Setup interface listening behavior of dnsmasq # Setup interface listening behavior of dnsmasq
delete_dnsmasq_setting "interface" removeKey "${dnsmasqconfig}" "interface"
delete_dnsmasq_setting "local-service" removeKey "${dnsmasqconfig}" "local-service"
delete_dnsmasq_setting "except-interface" removeKey "${dnsmasqconfig}" "except-interface"
delete_dnsmasq_setting "bind-interfaces" removeKey "${dnsmasqconfig}" "bind-interfaces"
if [[ "${DNSMASQ_LISTENING}" == "all" ]]; then if [[ "${DNSMASQ_LISTENING}" == "all" ]]; then
# Listen on all interfaces, permit all origins # Listen on all interfaces, permit all origins
add_dnsmasq_setting "except-interface" "nonexisting" addOrEditKeyValPair "${dnsmasqconfig}" "except-interface" "nonexisting"
elif [[ "${DNSMASQ_LISTENING}" == "local" ]]; then elif [[ "${DNSMASQ_LISTENING}" == "local" ]]; then
# Listen only on all interfaces, but only local subnets # Listen only on all interfaces, but only local subnets
add_dnsmasq_setting "local-service" addKey "${dnsmasqconfig}" "local-service"
else else
# Options "bind" and "single" # Options "bind" and "single"
# Listen only on one interface # Listen only on one interface
@ -217,30 +216,30 @@ trust-anchor=.,20326,8,2,E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC68345710423
PIHOLE_INTERFACE="eth0" PIHOLE_INTERFACE="eth0"
fi fi
add_dnsmasq_setting "interface" "${PIHOLE_INTERFACE}" addOrEditKeyValPair "${dnsmasqconfig}" "interface" "${PIHOLE_INTERFACE}"
if [[ "${DNSMASQ_LISTENING}" == "bind" ]]; then if [[ "${DNSMASQ_LISTENING}" == "bind" ]]; then
# Really bind to interface # Really bind to interface
add_dnsmasq_setting "bind-interfaces" addKey "${dnsmasqconfig}" "bind-interfaces"
fi fi
fi fi
if [[ "${CONDITIONAL_FORWARDING}" == true ]]; then if [[ "${CONDITIONAL_FORWARDING}" == true ]]; then
# Convert legacy "conditional forwarding" to rev-server configuration # Convert legacy "conditional forwarding" to rev-server configuration
# Remove any existing REV_SERVER settings # Remove any existing REV_SERVER settings
delete_setting "REV_SERVER" removeKey "${setupVars}" "REV_SERVER"
delete_setting "REV_SERVER_DOMAIN" removeKey "${setupVars}" "REV_SERVER_DOMAIN"
delete_setting "REV_SERVER_TARGET" removeKey "${setupVars}" "REV_SERVER_TARGET"
delete_setting "REV_SERVER_CIDR" removeKey "${setupVars}" "REV_SERVER_CIDR"
REV_SERVER=true REV_SERVER=true
add_setting "REV_SERVER" "true" addOrEditKeyValPair "${setupVars}" "REV_SERVER" "true"
REV_SERVER_DOMAIN="${CONDITIONAL_FORWARDING_DOMAIN}" REV_SERVER_DOMAIN="${CONDITIONAL_FORWARDING_DOMAIN}"
add_setting "REV_SERVER_DOMAIN" "${REV_SERVER_DOMAIN}" addOrEditKeyValPair "${setupVars}" "REV_SERVER_DOMAIN" "${REV_SERVER_DOMAIN}"
REV_SERVER_TARGET="${CONDITIONAL_FORWARDING_IP}" REV_SERVER_TARGET="${CONDITIONAL_FORWARDING_IP}"
add_setting "REV_SERVER_TARGET" "${REV_SERVER_TARGET}" addOrEditKeyValPair "${setupVars}" "REV_SERVER_TARGET" "${REV_SERVER_TARGET}"
#Convert CONDITIONAL_FORWARDING_REVERSE if necessary e.g: #Convert CONDITIONAL_FORWARDING_REVERSE if necessary e.g:
# 1.1.168.192.in-addr.arpa to 192.168.1.1/32 # 1.1.168.192.in-addr.arpa to 192.168.1.1/32
@ -267,28 +266,28 @@ trust-anchor=.,20326,8,2,E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC68345710423
# shellcheck disable=2001 # shellcheck disable=2001
REV_SERVER_CIDR="$(sed "s+\\.[0-9]*$+\\.0/24+" <<< "${REV_SERVER_TARGET}")" REV_SERVER_CIDR="$(sed "s+\\.[0-9]*$+\\.0/24+" <<< "${REV_SERVER_TARGET}")"
fi fi
add_setting "REV_SERVER_CIDR" "${REV_SERVER_CIDR}" addOrEditKeyValPair "${setupVars}" "REV_SERVER_CIDR" "${REV_SERVER_CIDR}"
# Remove obsolete settings from setupVars.conf # Remove obsolete settings from setupVars.conf
delete_setting "CONDITIONAL_FORWARDING" removeKey "${setupVars}" "CONDITIONAL_FORWARDING"
delete_setting "CONDITIONAL_FORWARDING_REVERSE" removeKey "${setupVars}" "CONDITIONAL_FORWARDING_REVERSE"
delete_setting "CONDITIONAL_FORWARDING_DOMAIN" removeKey "${setupVars}" "CONDITIONAL_FORWARDING_DOMAIN"
delete_setting "CONDITIONAL_FORWARDING_IP" removeKey "${setupVars}" "CONDITIONAL_FORWARDING_IP"
fi fi
delete_dnsmasq_setting "rev-server" removeKey "${dnsmasqconfig}" "rev-server"
if [[ "${REV_SERVER}" == true ]]; then if [[ "${REV_SERVER}" == true ]]; then
add_dnsmasq_setting "rev-server=${REV_SERVER_CIDR},${REV_SERVER_TARGET}" addKey "${dnsmasqconfig}" "rev-server=${REV_SERVER_CIDR},${REV_SERVER_TARGET}"
if [ -n "${REV_SERVER_DOMAIN}" ]; then if [ -n "${REV_SERVER_DOMAIN}" ]; then
# Forward local domain names to the CF target, too # Forward local domain names to the CF target, too
add_dnsmasq_setting "server=/${REV_SERVER_DOMAIN}/${REV_SERVER_TARGET}" addKey "${dnsmasqconfig}" "server=/${REV_SERVER_DOMAIN}/${REV_SERVER_TARGET}"
fi fi
if [[ "${DNS_FQDN_REQUIRED}" != true ]]; then if [[ "${DNS_FQDN_REQUIRED}" != true ]]; then
# Forward unqualified names to the CF target only when the "never # Forward unqualified names to the CF target only when the "never
# forward non-FQDN" option is unticked # forward non-FQDN" option is unticked
add_dnsmasq_setting "server=//${REV_SERVER_TARGET}" addKey "${dnsmasqconfig}" "server=//${REV_SERVER_TARGET}"
fi fi
fi fi
@ -303,7 +302,7 @@ trust-anchor=.,20326,8,2,E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC68345710423
SetDNSServers() { SetDNSServers() {
# Save setting to file # Save setting to file
delete_setting "PIHOLE_DNS" removeKey "${setupVars}" "PIHOLE_DNS"
IFS=',' read -r -a array <<< "${args[2]}" IFS=',' read -r -a array <<< "${args[2]}"
for index in "${!array[@]}" for index in "${!array[@]}"
do do
@ -312,7 +311,7 @@ SetDNSServers() {
ip="${array[index]//\\#/#}" ip="${array[index]//\\#/#}"
if valid_ip "${ip}" || valid_ip6 "${ip}" ; then if valid_ip "${ip}" || valid_ip6 "${ip}" ; then
add_setting "PIHOLE_DNS_$((index+1))" "${ip}" addOrEditKeyValPair "${setupVars}" "PIHOLE_DNS_$((index+1))" "${ip}"
else else
echo -e " ${CROSS} Invalid IP has been passed" echo -e " ${CROSS} Invalid IP has been passed"
exit 1 exit 1
@ -320,30 +319,30 @@ SetDNSServers() {
done done
if [[ "${args[3]}" == "domain-needed" ]]; then if [[ "${args[3]}" == "domain-needed" ]]; then
change_setting "DNS_FQDN_REQUIRED" "true" addOrEditKeyValPair "${setupVars}" "DNS_FQDN_REQUIRED" "true"
else else
change_setting "DNS_FQDN_REQUIRED" "false" addOrEditKeyValPair "${setupVars}" "DNS_FQDN_REQUIRED" "false"
fi fi
if [[ "${args[4]}" == "bogus-priv" ]]; then if [[ "${args[4]}" == "bogus-priv" ]]; then
change_setting "DNS_BOGUS_PRIV" "true" addOrEditKeyValPair "${setupVars}" "DNS_BOGUS_PRIV" "true"
else else
change_setting "DNS_BOGUS_PRIV" "false" addOrEditKeyValPair "${setupVars}" "DNS_BOGUS_PRIV" "false"
fi fi
if [[ "${args[5]}" == "dnssec" ]]; then if [[ "${args[5]}" == "dnssec" ]]; then
change_setting "DNSSEC" "true" addOrEditKeyValPair "${setupVars}" "DNSSEC" "true"
else else
change_setting "DNSSEC" "false" addOrEditKeyValPair "${setupVars}" "DNSSEC" "false"
fi fi
if [[ "${args[6]}" == "rev-server" ]]; then if [[ "${args[6]}" == "rev-server" ]]; then
change_setting "REV_SERVER" "true" addOrEditKeyValPair "${setupVars}" "REV_SERVER" "true"
change_setting "REV_SERVER_CIDR" "${args[7]}" addOrEditKeyValPair "${setupVars}" "REV_SERVER_CIDR" "${args[7]}"
change_setting "REV_SERVER_TARGET" "${args[8]}" addOrEditKeyValPair "${setupVars}" "REV_SERVER_TARGET" "${args[8]}"
change_setting "REV_SERVER_DOMAIN" "${args[9]}" addOrEditKeyValPair "${setupVars}" "REV_SERVER_DOMAIN" "${args[9]}"
else else
change_setting "REV_SERVER" "false" addOrEditKeyValPair "${setupVars}" "REV_SERVER" "false"
fi fi
ProcessDNSSettings ProcessDNSSettings
@ -353,11 +352,11 @@ SetDNSServers() {
} }
SetExcludeDomains() { SetExcludeDomains() {
change_setting "API_EXCLUDE_DOMAINS" "${args[2]}" addOrEditKeyValPair "${setupVars}" "API_EXCLUDE_DOMAINS" "${args[2]}"
} }
SetExcludeClients() { SetExcludeClients() {
change_setting "API_EXCLUDE_CLIENTS" "${args[2]}" addOrEditKeyValPair "${setupVars}" "API_EXCLUDE_CLIENTS" "${args[2]}"
} }
Poweroff(){ Poweroff(){
@ -373,7 +372,7 @@ RestartDNS() {
} }
SetQueryLogOptions() { SetQueryLogOptions() {
change_setting "API_QUERY_LOG_SHOW" "${args[2]}" addOrEditKeyValPair "${setupVars}" "API_QUERY_LOG_SHOW" "${args[2]}"
} }
ProcessDHCPSettings() { ProcessDHCPSettings() {
@ -389,19 +388,19 @@ ProcessDHCPSettings() {
if [[ "${PIHOLE_DOMAIN}" == "" ]]; then if [[ "${PIHOLE_DOMAIN}" == "" ]]; then
PIHOLE_DOMAIN="lan" PIHOLE_DOMAIN="lan"
change_setting "PIHOLE_DOMAIN" "${PIHOLE_DOMAIN}" addOrEditKeyValPair "${setupVars}" "PIHOLE_DOMAIN" "${PIHOLE_DOMAIN}"
fi fi
if [[ "${DHCP_LEASETIME}" == "0" ]]; then if [[ "${DHCP_LEASETIME}" == "0" ]]; then
leasetime="infinite" leasetime="infinite"
elif [[ "${DHCP_LEASETIME}" == "" ]]; then elif [[ "${DHCP_LEASETIME}" == "" ]]; then
leasetime="24" leasetime="24"
change_setting "DHCP_LEASETIME" "${leasetime}" addOrEditKeyValPair "${setupVars}" "DHCP_LEASETIME" "${leasetime}"
elif [[ "${DHCP_LEASETIME}" == "24h" ]]; then elif [[ "${DHCP_LEASETIME}" == "24h" ]]; then
#Installation is affected by known bug, introduced in a previous version. #Installation is affected by known bug, introduced in a previous version.
#This will automatically clean up setupVars.conf and remove the unnecessary "h" #This will automatically clean up setupVars.conf and remove the unnecessary "h"
leasetime="24" leasetime="24"
change_setting "DHCP_LEASETIME" "${leasetime}" addOrEditKeyValPair "${setupVars}" "DHCP_LEASETIME" "${leasetime}"
else else
leasetime="${DHCP_LEASETIME}h" leasetime="${DHCP_LEASETIME}h"
fi fi
@ -454,24 +453,24 @@ ra-param=*,0,0
} }
EnableDHCP() { EnableDHCP() {
change_setting "DHCP_ACTIVE" "true" addOrEditKeyValPair "${setupVars}" "DHCP_ACTIVE" "true"
change_setting "DHCP_START" "${args[2]}" addOrEditKeyValPair "${setupVars}" "DHCP_START" "${args[2]}"
change_setting "DHCP_END" "${args[3]}" addOrEditKeyValPair "${setupVars}" "DHCP_END" "${args[3]}"
change_setting "DHCP_ROUTER" "${args[4]}" addOrEditKeyValPair "${setupVars}" "DHCP_ROUTER" "${args[4]}"
change_setting "DHCP_LEASETIME" "${args[5]}" addOrEditKeyValPair "${setupVars}" "DHCP_LEASETIME" "${args[5]}"
change_setting "PIHOLE_DOMAIN" "${args[6]}" addOrEditKeyValPair "${setupVars}" "PIHOLE_DOMAIN" "${args[6]}"
change_setting "DHCP_IPv6" "${args[7]}" addOrEditKeyValPair "${setupVars}" "DHCP_IPv6" "${args[7]}"
change_setting "DHCP_rapid_commit" "${args[8]}" addOrEditKeyValPair "${setupVars}" "DHCP_rapid_commit" "${args[8]}"
# Remove possible old setting from file # Remove possible old setting from file
delete_dnsmasq_setting "dhcp-" removeKey "${dnsmasqconfig}" "dhcp-"
delete_dnsmasq_setting "quiet-dhcp" removeKey "${dnsmasqconfig}" "quiet-dhcp"
# If a DHCP client claims that its name is "wpad", ignore that. # If a DHCP client claims that its name is "wpad", ignore that.
# This fixes a security hole. see CERT Vulnerability VU#598349 # This fixes a security hole. see CERT Vulnerability VU#598349
# We also ignore "localhost" as Windows behaves strangely if a # We also ignore "localhost" as Windows behaves strangely if a
# device claims this host name # device claims this host name
add_dnsmasq_setting "dhcp-name-match=set:hostname-ignore,wpad addKey "${dnsmasqconfig}" "dhcp-name-match=set:hostname-ignore,wpad
dhcp-name-match=set:hostname-ignore,localhost dhcp-name-match=set:hostname-ignore,localhost
dhcp-ignore-names=tag:hostname-ignore" dhcp-ignore-names=tag:hostname-ignore"
@ -481,11 +480,11 @@ dhcp-ignore-names=tag:hostname-ignore"
} }
DisableDHCP() { DisableDHCP() {
change_setting "DHCP_ACTIVE" "false" addOrEditKeyValPair "${setupVars}" "DHCP_ACTIVE" "false"
# Remove possible old setting from file # Remove possible old setting from file
delete_dnsmasq_setting "dhcp-" removeKey "${dnsmasqconfig}" "dhcp-"
delete_dnsmasq_setting "quiet-dhcp" removeKey "${dnsmasqconfig}" "quiet-dhcp"
ProcessDHCPSettings ProcessDHCPSettings
@ -493,11 +492,11 @@ DisableDHCP() {
} }
SetWebUILayout() { SetWebUILayout() {
change_setting "WEBUIBOXEDLAYOUT" "${args[2]}" addOrEditKeyValPair "${setupVars}" "WEBUIBOXEDLAYOUT" "${args[2]}"
} }
SetWebUITheme() { SetWebUITheme() {
change_setting "WEBTHEME" "${args[2]}" addOrEditKeyValPair "${setupVars}" "WEBTHEME" "${args[2]}"
} }
CheckUrl(){ CheckUrl(){
@ -592,10 +591,10 @@ Options:
exit 0 exit 0
fi fi
change_setting "ADMIN_EMAIL" "${args[2]}" addOrEditKeyValPair "${setupVars}" "ADMIN_EMAIL" "${args[2]}"
echo -e " ${TICK} Setting admin contact to ${args[2]}" echo -e " ${TICK} Setting admin contact to ${args[2]}"
else else
change_setting "ADMIN_EMAIL" "" addOrEditKeyValPair "${setupVars}" "ADMIN_EMAIL" ""
echo -e " ${TICK} Removing admin contact" echo -e " ${TICK} Removing admin contact"
fi fi
} }
@ -619,16 +618,16 @@ Interfaces:
if [[ "${args[2]}" == "all" ]]; then if [[ "${args[2]}" == "all" ]]; then
echo -e " ${INFO} Listening on all interfaces, permitting all origins. Please use a firewall!" echo -e " ${INFO} Listening on all interfaces, permitting all origins. Please use a firewall!"
change_setting "DNSMASQ_LISTENING" "all" addOrEditKeyValPair "${setupVars}" "DNSMASQ_LISTENING" "all"
elif [[ "${args[2]}" == "local" ]]; then elif [[ "${args[2]}" == "local" ]]; then
echo -e " ${INFO} Listening on all interfaces, permitting origins from one hop away (LAN)" echo -e " ${INFO} Listening on all interfaces, permitting origins from one hop away (LAN)"
change_setting "DNSMASQ_LISTENING" "local" addOrEditKeyValPair "${setupVars}" "DNSMASQ_LISTENING" "local"
elif [[ "${args[2]}" == "bind" ]]; then elif [[ "${args[2]}" == "bind" ]]; then
echo -e " ${INFO} Binding on interface ${PIHOLE_INTERFACE}" echo -e " ${INFO} Binding on interface ${PIHOLE_INTERFACE}"
change_setting "DNSMASQ_LISTENING" "bind" addOrEditKeyValPair "${setupVars}" "DNSMASQ_LISTENING" "bind"
else else
echo -e " ${INFO} Listening only on interface ${PIHOLE_INTERFACE}" echo -e " ${INFO} Listening only on interface ${PIHOLE_INTERFACE}"
change_setting "DNSMASQ_LISTENING" "single" addOrEditKeyValPair "${setupVars}" "DNSMASQ_LISTENING" "single"
fi fi
# Don't restart DNS server yet because other settings # Don't restart DNS server yet because other settings
@ -698,7 +697,7 @@ clearAudit()
SetPrivacyLevel() { SetPrivacyLevel() {
# Set privacy level. Minimum is 0, maximum is 3 # Set privacy level. Minimum is 0, maximum is 3
if [ "${args[2]}" -ge 0 ] && [ "${args[2]}" -le 3 ]; then if [ "${args[2]}" -ge 0 ] && [ "${args[2]}" -le 3 ]; then
changeFTLsetting "PRIVACYLEVEL" "${args[2]}" addOrEditKeyValPair "${FTLconf}" "PRIVACYLEVEL" "${args[2]}"
pihole restartdns reload-lists pihole restartdns reload-lists
fi fi
} }
@ -808,6 +807,23 @@ RemoveCustomCNAMERecord() {
fi fi
} }
SetRateLimit() {
local rate_limit_count rate_limit_interval reload
rate_limit_count="${args[2]}"
rate_limit_interval="${args[3]}"
reload="${args[4]}"
# Set rate-limit setting inf valid
if [ "${rate_limit_count}" -ge 0 ] && [ "${rate_limit_interval}" -ge 0 ]; then
addOrEditKeyValPair "${FTLconf}" "RATE_LIMIT" "${rate_limit_count}/${rate_limit_interval}"
fi
# Restart FTL to update rate-limit settings only if $reload not false
if [[ ! $reload == "false" ]]; then
RestartDNS
fi
}
main() { main() {
args=("$@") args=("$@")
@ -841,6 +857,7 @@ main() {
"removecustomdns" ) RemoveCustomDNSAddress;; "removecustomdns" ) RemoveCustomDNSAddress;;
"addcustomcname" ) AddCustomCNAMERecord;; "addcustomcname" ) AddCustomCNAMERecord;;
"removecustomcname" ) RemoveCustomCNAMERecord;; "removecustomcname" ) RemoveCustomCNAMERecord;;
"ratelimit" ) SetRateLimit;;
* ) helpFunc;; * ) helpFunc;;
esac esac

View file

@ -164,13 +164,35 @@ ini_set("default_socket_timeout", 3);
function queryAds($serverName) { function queryAds($serverName) {
// Determine the time it takes while querying adlists // Determine the time it takes while querying adlists
$preQueryTime = microtime(true)-$_SERVER["REQUEST_TIME_FLOAT"]; $preQueryTime = microtime(true)-$_SERVER["REQUEST_TIME_FLOAT"];
// Determine which protocol should be used
$protocol = "http";
if ((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on') ||
(isset($_SERVER['REQUEST_SCHEME']) && $_SERVER['REQUEST_SCHEME'] === 'https') ||
(isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https')
) {
$protocol = "https";
}
// Format the URL
$queryAdsURL = sprintf( $queryAdsURL = sprintf(
"http://127.0.0.1:%s/admin/scripts/pi-hole/php/queryads.php?domain=%s&bp", "%s://127.0.0.1:%s/admin/scripts/pi-hole/php/queryads.php?domain=%s&bp",
$protocol,
$_SERVER["SERVER_PORT"], $_SERVER["SERVER_PORT"],
$serverName $serverName
); );
$queryAds = file($queryAdsURL, FILE_IGNORE_NEW_LINES);
$queryAds = array_values(array_filter(preg_replace("/data:\s+/", "", $queryAds))); // Request the file and receive the response
$queryAdsFile = file($queryAdsURL, FILE_IGNORE_NEW_LINES);
// $queryAdsFile must be an array (to avoid PHP 8.0+ error)
if (is_array($queryAdsFile)) {
$queryAds = array_values(array_filter(preg_replace("/data:\s+/", "", $queryAdsFile)));
} else {
// if not an array, return an error message
return array("0" => "error", "1" => "<br>(".gettype($queryAdsFile).")<br>".print_r($queryAdsFile, true));
}
$queryTime = sprintf("%.0f", (microtime(true)-$_SERVER["REQUEST_TIME_FLOAT"]) - $preQueryTime); $queryTime = sprintf("%.0f", (microtime(true)-$_SERVER["REQUEST_TIME_FLOAT"]) - $preQueryTime);
// Exception Handling // Exception Handling

View file

@ -36,6 +36,11 @@ server.port = 80
accesslog.filename = "/var/log/lighttpd/access.log" accesslog.filename = "/var/log/lighttpd/access.log"
accesslog.format = "%{%s}t|%V|%r|%s|%b" accesslog.format = "%{%s}t|%V|%r|%s|%b"
# Allow streaming response
# reference: https://redmine.lighttpd.net/projects/lighttpd/wiki/Server_stream-response-bodyDetails
server.stream-response-body = 1
#ssl.read-ahead = "disable"
index-file.names = ( "index.php", "index.html", "index.lighttpd.html" ) index-file.names = ( "index.php", "index.html", "index.lighttpd.html" )
url.access-deny = ( "~", ".inc", ".md", ".yml", ".ini" ) url.access-deny = ( "~", ".inc", ".md", ".yml", ".ini" )
static-file.exclude-extensions = ( ".php", ".pl", ".fcgi" ) static-file.exclude-extensions = ( ".php", ".pl", ".fcgi" )

View file

@ -37,6 +37,11 @@ server.port = 80
accesslog.filename = "/var/log/lighttpd/access.log" accesslog.filename = "/var/log/lighttpd/access.log"
accesslog.format = "%{%s}t|%V|%r|%s|%b" accesslog.format = "%{%s}t|%V|%r|%s|%b"
# Allow streaming response
# reference: https://redmine.lighttpd.net/projects/lighttpd/wiki/Server_stream-response-bodyDetails
server.stream-response-body = 1
#ssl.read-ahead = "disable"
index-file.names = ( "index.php", "index.html", "index.lighttpd.html" ) index-file.names = ( "index.php", "index.html", "index.lighttpd.html" )
url.access-deny = ( "~", ".inc", ".md", ".yml", ".ini" ) url.access-deny = ( "~", ".inc", ".md", ".yml", ".ini" )
static-file.exclude-extensions = ( ".php", ".pl", ".fcgi" ) static-file.exclude-extensions = ( ".php", ".pl", ".fcgi" )

View file

@ -239,10 +239,10 @@ os_check() {
printf " If you wish to attempt to continue anyway, you can try one of the following commands to skip this check:\\n" printf " If you wish to attempt to continue anyway, you can try one of the following commands to skip this check:\\n"
printf "\\n" printf "\\n"
printf " e.g: If you are seeing this message on a fresh install, you can run:\\n" printf " e.g: If you are seeing this message on a fresh install, you can run:\\n"
printf " %bcurl -sSL https://install.pi-hole.net | PIHOLE_SKIP_OS_CHECK=true sudo -E bash%b\\n" "${COL_LIGHT_GREEN}" "${COL_NC}" printf " %bcurl -sSL https://install.pi-hole.net | sudo PIHOLE_SKIP_OS_CHECK=true bash%b\\n" "${COL_LIGHT_GREEN}" "${COL_NC}"
printf "\\n" printf "\\n"
printf " If you are seeing this message after having run pihole -up:\\n" printf " If you are seeing this message after having run pihole -up:\\n"
printf " %bPIHOLE_SKIP_OS_CHECK=true sudo -E pihole -r%b\\n" "${COL_LIGHT_GREEN}" "${COL_NC}" printf " %bsudo PIHOLE_SKIP_OS_CHECK=true pihole -r%b\\n" "${COL_LIGHT_GREEN}" "${COL_NC}"
printf " (In this case, your previous run of pihole -up will have already updated the local repository)\\n" printf " (In this case, your previous run of pihole -up will have already updated the local repository)\\n"
printf "\\n" printf "\\n"
printf " It is possible that the installation will still fail at this stage due to an unsupported configuration.\\n" printf " It is possible that the installation will still fail at this stage due to an unsupported configuration.\\n"
@ -259,6 +259,29 @@ os_check() {
fi fi
} }
# This function waits for dpkg to unlock, which signals that the previous apt-get command has finished.
test_dpkg_lock() {
i=0
printf " %b Waiting for package manager to finish (up to 30 seconds)\\n" "${INFO}"
# fuser is a program to show which processes use the named files, sockets, or filesystems
# So while the lock is held,
while fuser /var/lib/dpkg/lock >/dev/null 2>&1
do
# we wait half a second,
sleep 0.5
# increase the iterator,
((i=i+1))
# exit if waiting for more then 30 seconds
if [[ $i -gt 60 ]]; then
printf " %b %bError: Could not verify package manager finished and released lock. %b\\n" "${CROSS}" "${COL_LIGHT_RED}" "${COL_NC}"
printf " Attempt to install packages manually and retry.\\n"
exit 1;
fi
done
# and then report success once dpkg is unlocked.
return 0
}
# Compatibility # Compatibility
package_manager_detect() { package_manager_detect() {
# First check to see if apt-get is installed. # First check to see if apt-get is installed.
@ -287,7 +310,7 @@ package_manager_detect() {
# Packages required to run this install script (stored as an array) # Packages required to run this install script (stored as an array)
INSTALLER_DEPS=(git iproute2 whiptail ca-certificates) INSTALLER_DEPS=(git iproute2 whiptail ca-certificates)
# Packages required to run Pi-hole (stored as an array) # Packages required to run Pi-hole (stored as an array)
PIHOLE_DEPS=(cron curl iputils-ping psmisc sudo unzip idn2 libcap2-bin dns-root-data libcap2 netcat-openbsd) PIHOLE_DEPS=(cron curl iputils-ping psmisc sudo unzip idn2 libcap2-bin dns-root-data libcap2 netcat-openbsd procps)
# Packages required for the Web admin interface (stored as an array) # Packages required for the Web admin interface (stored as an array)
# It's useful to separate this from Pi-hole, since the two repos are also setup separately # It's useful to separate this from Pi-hole, since the two repos are also setup separately
PIHOLE_WEB_DEPS=(lighttpd "${phpVer}-common" "${phpVer}-cgi" "${phpVer}-sqlite3" "${phpVer}-xml" "${phpVer}-intl") PIHOLE_WEB_DEPS=(lighttpd "${phpVer}-common" "${phpVer}-cgi" "${phpVer}-sqlite3" "${phpVer}-xml" "${phpVer}-intl")
@ -302,22 +325,6 @@ package_manager_detect() {
# and config file # and config file
LIGHTTPD_CFG="lighttpd.conf.debian" LIGHTTPD_CFG="lighttpd.conf.debian"
# This function waits for dpkg to unlock, which signals that the previous apt-get command has finished.
test_dpkg_lock() {
i=0
# fuser is a program to show which processes use the named files, sockets, or filesystems
# So while the lock is held,
while fuser /var/lib/dpkg/lock >/dev/null 2>&1
do
# we wait half a second,
sleep 0.5
# increase the iterator,
((i=i+1))
done
# and then report success once dpkg is unlocked.
return 0
}
# If apt-get is not found, check for rpm. # If apt-get is not found, check for rpm.
elif is_command rpm ; then elif is_command rpm ; then
# Then check if dnf or yum is the package manager # Then check if dnf or yum is the package manager
@ -2209,7 +2216,7 @@ get_binary_name() {
local rev local rev
rev=$(uname -m | sed "s/[^0-9]//g;") rev=$(uname -m | sed "s/[^0-9]//g;")
local lib local lib
lib=$(ldd /bin/ls | grep -E '^\s*/lib' | awk '{ print $1 }') lib=$(ldd "$(which sh)" | grep -E '^\s*/lib' | awk '{ print $1 }')
if [[ "${lib}" == "/lib/ld-linux-aarch64.so.1" ]]; then if [[ "${lib}" == "/lib/ld-linux-aarch64.so.1" ]]; then
printf "%b %b Detected AArch64 (64 Bit ARM) processor\\n" "${OVER}" "${TICK}" printf "%b %b Detected AArch64 (64 Bit ARM) processor\\n" "${OVER}" "${TICK}"
# set the binary to be used # set the binary to be used

View file

@ -11,10 +11,9 @@
source "/opt/pihole/COL_TABLE" source "/opt/pihole/COL_TABLE"
while true; do while true; do
read -rp " ${QST} Are you sure you would like to remove ${COL_WHITE}Pi-hole${COL_NC}? [y/N] " yn read -rp " ${QST} Are you sure you would like to remove ${COL_WHITE}Pi-hole${COL_NC}? [y/N] " answer
case ${yn} in case ${answer} in
[Yy]* ) break;; [Yy]* ) break;;
[Nn]* ) echo -e "${OVER} ${COL_LIGHT_GREEN}Uninstall has been canceled${COL_NC}"; exit 0;;
* ) echo -e "${OVER} ${COL_LIGHT_GREEN}Uninstall has been canceled${COL_NC}"; exit 0;; * ) echo -e "${OVER} ${COL_LIGHT_GREEN}Uninstall has been canceled${COL_NC}"; exit 0;;
esac esac
done done
@ -76,8 +75,8 @@ removeAndPurge() {
for i in "${DEPS[@]}"; do for i in "${DEPS[@]}"; do
if package_check "${i}" > /dev/null; then if package_check "${i}" > /dev/null; then
while true; do while true; do
read -rp " ${QST} Do you wish to remove ${COL_WHITE}${i}${COL_NC} from your system? [Y/N] " yn read -rp " ${QST} Do you wish to remove ${COL_WHITE}${i}${COL_NC} from your system? [Y/N] " answer
case ${yn} in case ${answer} in
[Yy]* ) [Yy]* )
echo -ne " ${INFO} Removing ${i}..."; echo -ne " ${INFO} Removing ${i}...";
${SUDO} "${PKG_REMOVE[@]}" "${i}" &> /dev/null; ${SUDO} "${PKG_REMOVE[@]}" "${i}" &> /dev/null;
@ -215,8 +214,8 @@ while true; do
echo -n "${i} " echo -n "${i} "
done done
echo "${COL_NC}" echo "${COL_NC}"
read -rp " ${QST} Do you wish to go through each dependency for removal? (Choosing No will leave all dependencies installed) [Y/n] " yn read -rp " ${QST} Do you wish to go through each dependency for removal? (Choosing No will leave all dependencies installed) [Y/n] " answer
case ${yn} in case ${answer} in
[Yy]* ) removeAndPurge; break;; [Yy]* ) removeAndPurge; break;;
[Nn]* ) removeNoPurge; break;; [Nn]* ) removeNoPurge; break;;
* ) removeAndPurge; break;; * ) removeAndPurge; break;;

View file

@ -527,8 +527,9 @@ parseList() {
# This sed does the following things: # This sed does the following things:
# 1. Remove all domains containing invalid characters. Valid are: a-z, A-Z, 0-9, dot (.), minus (-), underscore (_) # 1. Remove all domains containing invalid characters. Valid are: a-z, A-Z, 0-9, dot (.), minus (-), underscore (_)
# 2. Append ,adlistID to every line # 2. Append ,adlistID to every line
# 3. Ensures there is a newline on the last line # 3. Remove trailing period (see https://github.com/pi-hole/pi-hole/issues/4701)
sed -e "/[^a-zA-Z0-9.\_-]/d;s/$/,${adlistID}/;/.$/a\\" "${src}" >> "${target}" # 4. Ensures there is a newline on the last line
sed -e "/[^a-zA-Z0-9.\_-]/d;s/\.$//;s/$/,${adlistID}/;/.$/a\\" "${src}" >> "${target}"
# Find (up to) five domains containing invalid characters (see above) # Find (up to) five domains containing invalid characters (see above)
incorrect_lines="$(sed -e "/[^a-zA-Z0-9.\_-]/!d" "${src}" | head -n 5)" incorrect_lines="$(sed -e "/[^a-zA-Z0-9.\_-]/!d" "${src}" | head -n 5)"

61
pihole
View file

@ -21,7 +21,7 @@ readonly FTL_PID_FILE="/run/pihole-FTL.pid"
readonly colfile="${PI_HOLE_SCRIPT_DIR}/COL_TABLE" readonly colfile="${PI_HOLE_SCRIPT_DIR}/COL_TABLE"
source "${colfile}" source "${colfile}"
readonly utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh"
source "${utilsfile}" source "${utilsfile}"
webpageFunc() { webpageFunc() {
@ -226,7 +226,7 @@ Time:
fi fi
local str="Pi-hole Disabled" local str="Pi-hole Disabled"
addOrEditKeyValPair "BLOCKING_ENABLED" "false" "${setupVars}" addOrEditKeyValPair "${setupVars}" "BLOCKING_ENABLED" "false"
fi fi
else else
# Enable Pi-hole # Enable Pi-hole
@ -238,7 +238,7 @@ Time:
echo -e " ${INFO} Enabling blocking" echo -e " ${INFO} Enabling blocking"
local str="Pi-hole Enabled" local str="Pi-hole Enabled"
addOrEditKeyValPair "BLOCKING_ENABLED" "true" "${setupVars}" addOrEditKeyValPair "${setupVars}" "BLOCKING_ENABLED" "true"
fi fi
restartDNS reload-lists restartDNS reload-lists
@ -260,8 +260,8 @@ Options:
exit 0 exit 0
elif [[ "${1}" == "off" ]]; then elif [[ "${1}" == "off" ]]; then
# Disable logging # Disable logging
sed -i 's/^log-queries/#log-queries/' /etc/dnsmasq.d/01-pihole.conf removeKey /etc/dnsmasq.d/01-pihole.conf "log-queries"
addOrEditKeyValPair "QUERY_LOGGING" "false" "${setupVars}" addOrEditKeyValPair "${setupVars}" "QUERY_LOGGING" "false"
if [[ "${2}" != "noflush" ]]; then if [[ "${2}" != "noflush" ]]; then
# Flush logs # Flush logs
"${PI_HOLE_BIN_DIR}"/pihole -f "${PI_HOLE_BIN_DIR}"/pihole -f
@ -270,8 +270,8 @@ Options:
local str="Logging has been disabled!" local str="Logging has been disabled!"
elif [[ "${1}" == "on" ]]; then elif [[ "${1}" == "on" ]]; then
# Enable logging # Enable logging
sed -i 's/^#log-queries/log-queries/' /etc/dnsmasq.d/01-pihole.conf addKey /etc/dnsmasq.d/01-pihole.conf "log-queries"
addOrEditKeyValPair "QUERY_LOGGING" "true" "${setupVars}" addOrEditKeyValPair "${setupVars}" "QUERY_LOGGING" "true"
echo -e " ${INFO} Enabling logging..." echo -e " ${INFO} Enabling logging..."
local str="Logging has been enabled!" local str="Logging has been enabled!"
else else
@ -316,9 +316,10 @@ analyze_ports() {
statusFunc() { statusFunc() {
# Determine if there is pihole-FTL service is listening # Determine if there is pihole-FTL service is listening
local listening pid port local pid port ftl_api_port
pid="$(getFTLPID)" pid="$(getFTLPID)"
ftl_api_port="$(getFTLAPIPort)"
if [[ "$pid" -eq "-1" ]]; then if [[ "$pid" -eq "-1" ]]; then
case "${1}" in case "${1}" in
"web") echo "-1";; "web") echo "-1";;
@ -326,8 +327,8 @@ statusFunc() {
esac esac
return 0 return 0
else else
#get the port pihole-FTL is listening on by using FTL's telnet API #get the DNS port pihole-FTL is listening on by using FTL's telnet API
port="$(echo ">dns-port >quit" | nc 127.0.0.1 4711)" port="$(echo ">dns-port >quit" | nc 127.0.0.1 "$ftl_api_port")"
if [[ "${port}" == "0" ]]; then if [[ "${port}" == "0" ]]; then
case "${1}" in case "${1}" in
"web") echo "-1";; "web") echo "-1";;
@ -364,7 +365,7 @@ statusFunc() {
# Enable blocking # Enable blocking
"${PI_HOLE_BIN_DIR}"/pihole enable "${PI_HOLE_BIN_DIR}"/pihole enable
fi fi
exit 0
} }
tailFunc() { tailFunc() {
@ -495,8 +496,38 @@ if [[ $# = 0 ]]; then
helpFunc helpFunc
fi fi
# functions that do not require sudo power
case "${1}" in case "${1}" in
"-h" | "help" | "--help" ) helpFunc;; "-h" | "help" | "--help" ) helpFunc;;
"-v" | "version" ) versionFunc "$@";;
"-c" | "chronometer" ) chronometerFunc "$@";;
"-q" | "query" ) queryFunc "$@";;
"status" ) statusFunc "$2";;
"-t" | "tail" ) tailFunc "$2";;
"tricorder" ) tricorderFunc;;
# we need to add all arguments that require sudo power to not trigger the * argument
"-w" | "whitelist" ) ;;
"-b" | "blacklist" ) ;;
"--wild" | "wildcard" ) ;;
"--regex" | "regex" ) ;;
"--white-regex" | "white-regex" ) ;;
"--white-wild" | "white-wild" ) ;;
"-f" | "flush" ) ;;
"-up" | "updatePihole" ) ;;
"-r" | "reconfigure" ) ;;
"-g" | "updateGravity" ) ;;
"-l" | "logging" ) ;;
"uninstall" ) ;;
"enable" ) ;;
"disable" ) ;;
"-d" | "debug" ) ;;
"restartdns" ) ;;
"-a" | "admin" ) ;;
"checkout" ) ;;
"updatechecker" ) ;;
"arpflush" ) ;;
* ) helpFunc;;
esac esac
# Must be root to use this tool # Must be root to use this tool
@ -523,21 +554,13 @@ case "${1}" in
"-up" | "updatePihole" ) updatePiholeFunc "$@";; "-up" | "updatePihole" ) updatePiholeFunc "$@";;
"-r" | "reconfigure" ) reconfigurePiholeFunc;; "-r" | "reconfigure" ) reconfigurePiholeFunc;;
"-g" | "updateGravity" ) updateGravityFunc "$@";; "-g" | "updateGravity" ) updateGravityFunc "$@";;
"-c" | "chronometer" ) chronometerFunc "$@";;
"-h" | "help" ) helpFunc;;
"-v" | "version" ) versionFunc "$@";;
"-q" | "query" ) queryFunc "$@";;
"-l" | "logging" ) piholeLogging "$@";; "-l" | "logging" ) piholeLogging "$@";;
"uninstall" ) uninstallFunc;; "uninstall" ) uninstallFunc;;
"enable" ) piholeEnable 1;; "enable" ) piholeEnable 1;;
"disable" ) piholeEnable 0 "$2";; "disable" ) piholeEnable 0 "$2";;
"status" ) statusFunc "$2";;
"restartdns" ) restartDNS "$2";; "restartdns" ) restartDNS "$2";;
"-a" | "admin" ) webpageFunc "$@";; "-a" | "admin" ) webpageFunc "$@";;
"-t" | "tail" ) tailFunc "$2";;
"checkout" ) piholeCheckoutFunc "$@";; "checkout" ) piholeCheckoutFunc "$@";;
"tricorder" ) tricorderFunc;;
"updatechecker" ) updateCheckFunc "$@";; "updatechecker" ) updateCheckFunc "$@";;
"arpflush" ) arpFunc "$@";; "arpflush" ) arpFunc "$@";;
* ) helpFunc;;
esac esac

View file

@ -1,4 +1,4 @@
FROM buildpack-deps:hirsute-scm FROM buildpack-deps:impish-scm
ENV GITDIR /etc/.pihole ENV GITDIR /etc/.pihole
ENV SCRIPTDIR /opt/pihole ENV SCRIPTDIR /opt/pihole

View file

@ -675,17 +675,10 @@ def test_FTL_detect_aarch64_no_errors(host):
''' '''
# mock uname to return aarch64 platform # mock uname to return aarch64 platform
mock_command('uname', {'-m': ('aarch64', '0')}, host) mock_command('uname', {'-m': ('aarch64', '0')}, host)
# mock `which sh` to return `/bin/sh`
mock_command('which', {'sh': ('/bin/sh', '0')}, host)
# mock ldd to respond with aarch64 shared library # mock ldd to respond with aarch64 shared library
mock_command( mock_command('ldd', {'/bin/sh': ('/lib/ld-linux-aarch64.so.1', '0')}, host)
'ldd',
{
'/bin/ls': (
'/lib/ld-linux-aarch64.so.1',
'0'
)
},
host
)
detectPlatform = host.run(''' detectPlatform = host.run('''
source /opt/pihole/basic-install.sh source /opt/pihole/basic-install.sh
create_pihole_user create_pihole_user
@ -708,8 +701,10 @@ def test_FTL_detect_armv4t_no_errors(host):
''' '''
# mock uname to return armv4t platform # mock uname to return armv4t platform
mock_command('uname', {'-m': ('armv4t', '0')}, host) mock_command('uname', {'-m': ('armv4t', '0')}, host)
# mock ldd to respond with ld-linux shared library # mock `which sh` to return `/bin/sh`
mock_command('ldd', {'/bin/ls': ('/lib/ld-linux.so.3', '0')}, host) mock_command('which', {'sh': ('/bin/sh', '0')}, host)
# mock ldd to respond with armv4t shared library
mock_command('ldd', {'/bin/sh': ('/lib/ld-linux.so.3', '0')}, host)
detectPlatform = host.run(''' detectPlatform = host.run('''
source /opt/pihole/basic-install.sh source /opt/pihole/basic-install.sh
create_pihole_user create_pihole_user
@ -732,8 +727,10 @@ def test_FTL_detect_armv5te_no_errors(host):
''' '''
# mock uname to return armv5te platform # mock uname to return armv5te platform
mock_command('uname', {'-m': ('armv5te', '0')}, host) mock_command('uname', {'-m': ('armv5te', '0')}, host)
# mock `which sh` to return `/bin/sh`
mock_command('which', {'sh': ('/bin/sh', '0')}, host)
# mock ldd to respond with ld-linux shared library # mock ldd to respond with ld-linux shared library
mock_command('ldd', {'/bin/ls': ('/lib/ld-linux.so.3', '0')}, host) mock_command('ldd', {'/bin/sh': ('/lib/ld-linux.so.3', '0')}, host)
detectPlatform = host.run(''' detectPlatform = host.run('''
source /opt/pihole/basic-install.sh source /opt/pihole/basic-install.sh
create_pihole_user create_pihole_user
@ -757,7 +754,9 @@ def test_FTL_detect_armv6l_no_errors(host):
# mock uname to return armv6l platform # mock uname to return armv6l platform
mock_command('uname', {'-m': ('armv6l', '0')}, host) mock_command('uname', {'-m': ('armv6l', '0')}, host)
# mock ldd to respond with ld-linux-armhf shared library # mock ldd to respond with ld-linux-armhf shared library
mock_command('ldd', {'/bin/ls': ('/lib/ld-linux-armhf.so.3', '0')}, host) # mock `which sh` to return `/bin/sh`
mock_command('which', {'sh': ('/bin/sh', '0')}, host)
mock_command('ldd', {'/bin/sh': ('/lib/ld-linux-armhf.so.3', '0')}, host)
detectPlatform = host.run(''' detectPlatform = host.run('''
source /opt/pihole/basic-install.sh source /opt/pihole/basic-install.sh
create_pihole_user create_pihole_user
@ -782,7 +781,9 @@ def test_FTL_detect_armv7l_no_errors(host):
# mock uname to return armv7l platform # mock uname to return armv7l platform
mock_command('uname', {'-m': ('armv7l', '0')}, host) mock_command('uname', {'-m': ('armv7l', '0')}, host)
# mock ldd to respond with ld-linux-armhf shared library # mock ldd to respond with ld-linux-armhf shared library
mock_command('ldd', {'/bin/ls': ('/lib/ld-linux-armhf.so.3', '0')}, host) # mock `which sh` to return `/bin/sh`
mock_command('which', {'sh': ('/bin/sh', '0')}, host)
mock_command('ldd', {'/bin/sh': ('/lib/ld-linux-armhf.so.3', '0')}, host)
detectPlatform = host.run(''' detectPlatform = host.run('''
source /opt/pihole/basic-install.sh source /opt/pihole/basic-install.sh
create_pihole_user create_pihole_user
@ -806,8 +807,10 @@ def test_FTL_detect_armv8a_no_errors(host):
''' '''
# mock uname to return armv8a platform # mock uname to return armv8a platform
mock_command('uname', {'-m': ('armv8a', '0')}, host) mock_command('uname', {'-m': ('armv8a', '0')}, host)
# mock `which sh` to return `/bin/sh`
mock_command('which', {'sh': ('/bin/sh', '0')}, host)
# mock ldd to respond with ld-linux-armhf shared library # mock ldd to respond with ld-linux-armhf shared library
mock_command('ldd', {'/bin/ls': ('/lib/ld-linux-armhf.so.3', '0')}, host) mock_command('ldd', {'/bin/sh': ('/lib/ld-linux-armhf.so.3', '0')}, host)
detectPlatform = host.run(''' detectPlatform = host.run('''
source /opt/pihole/basic-install.sh source /opt/pihole/basic-install.sh
create_pihole_user create_pihole_user
@ -828,6 +831,8 @@ def test_FTL_detect_x86_64_no_errors(host):
''' '''
confirms only x86_64 package is downloaded for FTL engine confirms only x86_64 package is downloaded for FTL engine
''' '''
# mock `which sh` to return `/bin/sh`
mock_command('which', {'sh': ('/bin/sh', '0')}, host)
detectPlatform = host.run(''' detectPlatform = host.run('''
source /opt/pihole/basic-install.sh source /opt/pihole/basic-install.sh
create_pihole_user create_pihole_user
@ -848,6 +853,8 @@ def test_FTL_detect_unknown_no_errors(host):
''' confirms only generic package is downloaded for FTL engine ''' ''' confirms only generic package is downloaded for FTL engine '''
# mock uname to return generic platform # mock uname to return generic platform
mock_command('uname', {'-m': ('mips', '0')}, host) mock_command('uname', {'-m': ('mips', '0')}, host)
# mock `which sh` to return `/bin/sh`
mock_command('which', {'sh': ('/bin/sh', '0')}, host)
detectPlatform = host.run(''' detectPlatform = host.run('''
source /opt/pihole/basic-install.sh source /opt/pihole/basic-install.sh
create_pihole_user create_pihole_user

View file

@ -1,16 +1,74 @@
def test_key_val_replacement_works(host): def test_key_val_replacement_works(host):
''' Confirms addOrEditKeyValPair provides the expected output ''' ''' Confirms addOrEditKeyValPair either adds or replaces a key value pair in a given file '''
host.run(''' host.run('''
setupvars=./testoutput
source /opt/pihole/utils.sh source /opt/pihole/utils.sh
addOrEditKeyValPair "KEY_ONE" "value1" "./testoutput" addOrEditKeyValPair "./testoutput" "KEY_ONE" "value1"
addOrEditKeyValPair "KEY_TWO" "value2" "./testoutput" addOrEditKeyValPair "./testoutput" "KEY_TWO" "value2"
addOrEditKeyValPair "KEY_ONE" "value3" "./testoutput" addOrEditKeyValPair "./testoutput" "KEY_ONE" "value3"
addOrEditKeyValPair "KEY_FOUR" "value4" "./testoutput" addOrEditKeyValPair "./testoutput" "KEY_FOUR" "value4"
cat ./testoutput
''') ''')
output = host.run(''' output = host.run('''
cat ./testoutput cat ./testoutput
''') ''')
expected_stdout = 'KEY_ONE=value3\nKEY_TWO=value2\nKEY_FOUR=value4\n' expected_stdout = 'KEY_ONE=value3\nKEY_TWO=value2\nKEY_FOUR=value4\n'
assert expected_stdout == output.stdout assert expected_stdout == output.stdout
def test_key_addition_works(host):
''' Confirms addKey adds a key (no value) to a file without duplicating it '''
host.run('''
source /opt/pihole/utils.sh
addKey "./testoutput" "KEY_ONE"
addKey "./testoutput" "KEY_ONE"
addKey "./testoutput" "KEY_TWO"
addKey "./testoutput" "KEY_TWO"
addKey "./testoutput" "KEY_THREE"
addKey "./testoutput" "KEY_THREE"
''')
output = host.run('''
cat ./testoutput
''')
expected_stdout = 'KEY_ONE\nKEY_TWO\nKEY_THREE\n'
assert expected_stdout == output.stdout
def test_key_removal_works(host):
''' Confirms removeKey removes a key or key/value pair '''
host.run('''
source /opt/pihole/utils.sh
addOrEditKeyValPair "./testoutput" "KEY_ONE" "value1"
addOrEditKeyValPair "./testoutput" "KEY_TWO" "value2"
addOrEditKeyValPair "./testoutput" "KEY_THREE" "value3"
addKey "./testoutput" "KEY_FOUR"
removeKey "./testoutput" "KEY_TWO"
removeKey "./testoutput" "KEY_FOUR"
''')
output = host.run('''
cat ./testoutput
''')
expected_stdout = 'KEY_ONE=value1\nKEY_THREE=value3\n'
assert expected_stdout == output.stdout
def test_getFTLAPIPort_default(host):
''' Confirms getFTLAPIPort returns the default API port '''
output = host.run('''
source /opt/pihole/utils.sh
getFTLAPIPort
''')
expected_stdout = '4711\n'
assert expected_stdout == output.stdout
def test_getFTLAPIPort_custom(host):
''' Confirms getFTLAPIPort returns a custom API port in a custom PORTFILE location '''
host.run('''
echo "PORTFILE=/tmp/port.file" > /etc/pihole/pihole-FTL.conf
echo "1234" > /tmp/port.file
''')
output = host.run('''
source /opt/pihole/utils.sh
getFTLAPIPort
''')
expected_stdout = '1234\n'
assert expected_stdout == output.stdout