From d6f614758423b0df6b173058b52e8568eefc0840 Mon Sep 17 00:00:00 2001 From: arevindh <arevindh@gmail.com> Date: Sun, 19 May 2019 16:07:28 +0530 Subject: [PATCH] v4.3 update --- README.md | 13 +- advanced/Scripts/chronometer.sh | 31 ++- advanced/Scripts/piholeCheckout.sh | 4 +- advanced/Scripts/piholeDebug.sh | 41 ++-- advanced/Scripts/query.sh | 2 +- advanced/Scripts/update.sh | 14 ++ advanced/Scripts/updatecheck.sh | 2 +- advanced/Scripts/webpage.sh | 2 +- advanced/index.php | 13 +- automated install/basic-install.sh | 293 ++++++++++++++++------------- automated install/uninstall.sh | 3 +- gravity.sh | 2 +- requirements.txt | 12 +- 13 files changed, 233 insertions(+), 199 deletions(-) diff --git a/README.md b/README.md index c0f413ca..fb2179eb 100644 --- a/README.md +++ b/README.md @@ -17,9 +17,9 @@ The Pi-hole[®](https://pi-hole.net/trademark-rules-and-brand-guidelines/) is a - **Free**: open source software which helps ensure _you_ are the sole person in control of your privacy ----- -<a href="https://www.codacy.com/app/Pi-hole/pi-hole?utm_source=github.com&utm_medium=referral&utm_content=pi-hole/pi-hole&utm_campaign=Badge_Grade"><img src="https://api.codacy.com/project/badge/Grade/c558a0f8d7124c99b02b84f0f5564238" alt="Codacy Grade"/></a> -<a href="https://travis-ci.org/pi-hole/pi-hole"><img src="https://travis-ci.org/pi-hole/pi-hole.svg?branch=development" alt="Travis Build Status"/></a> -<a href="https://www.bountysource.com/trackers/3011939-pi-hole-pi-hole?utm_source=3011939&utm_medium=shield&utm_campaign=TRACKER_BADGE"><img src="https://www.bountysource.com/badge/tracker?tracker_id=3011939" alt="BountySource"/></a> +[](https://www.codacy.com/app/Pi-hole/pi-hole?utm_source=github.com&utm_medium=referral&utm_content=pi-hole/pi-hole&utm_campaign=Badge_Grade) +[](https://travis-ci.org/pi-hole/pi-hole) +[](https://www.bountysource.com/trackers/3011939-pi-hole-pi-hole?utm_source=3011939&utm_medium=shield&utm_campaign=TRACKER_BADGE) ## One-Step Automated Install Those who want to get started quickly and conveniently may install Pi-hole using the following command: @@ -61,16 +61,13 @@ Make no mistake: **your support is absolutely vital to help keep us innovating!* Sending a donation using our links below is **extremely helpful** in offsetting a portion of our monthly expenses: - <img src="https://pi-hole.github.io/graphics/Badges/paypal-badge-black.svg" width="24" height="24" alt="PP"/> <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=3J2L3Z4DHW9UY">Donate via PayPal</a><br/> -- <img src="https://pi-hole.github.io/graphics/Badges/bitcoin-badge-black.svg" width="24" height="24" alt="BTC"/> [Bitcoin](https://commerce.coinbase.com/checkout/fb7facaf-bebd-46be-bb77-b358f4546763): <code> -3MDPzjXu2hjw5sGLJvKUi1uXbvQPzVrbpF</code></br> -- <img src="https://pi-hole.github.io/graphics/Badges/bitcoin-badge-black.svg" width="24" height="24" alt="BTC"/> [Bitcoin Cash](https://commerce.coinbase.com/checkout/fb7facaf-bebd-46be-bb77-b358f4546763): <code>qzqsz4aju2eecc6uhs7tus4vlwhhela24sdruf4qp5</code></br> -- <img src="https://pi-hole.github.io/graphics/Badges/ethereum-badge-black.svg" width="24" height="24" alt="BTC"/> [Ethereum](https://commerce.coinbase.com/checkout/fb7facaf-bebd-46be-bb77-b358f4546763): <code>0x79d4e90A4a0C732819526c93e21A3F1356A2FAe1</code> +- <img src="https://pi-hole.github.io/graphics/Badges/bitcoin-badge-black.svg" width="24" height="24" alt="BTC"/> [Bitcoin, Bitcoin Cash, Ethereum, Litecoin](https://commerce.coinbase.com/checkout/dd304d04-f324-4a77-931b-0db61c77a41b) ### Alternative support If you'd rather not [donate](https://pi-hole.net/donate/) (_which is okay!_), there are other ways you can help support us: - [Patreon](https://patreon.com/pihole) _Become a patron for rewards_ - [Digital Ocean](http://www.digitalocean.com/?refcode=344d234950e1) _affiliate link_ -- [Stickermule](https://www.stickermule.com/unlock?ref_id=6055890701&utm_medium=link&utm_source=invite) _earn a $10 credit after your first purchase_ +- [Stickermule](https://www.stickermule.com/unlock?ref_id=9127301701&utm_medium=link&utm_source=invite) _earn a $10 credit after your first purchase_ - [Pi-hole Swag Store](https://pi-hole.net/shop/) _affiliate link_ - [Amazon](http://www.amazon.com/exec/obidos/redirect-home/pihole09-20) _affiliate link_ - [DNS Made Easy](https://cp.dnsmadeeasy.com/u/133706) _affiliate link_ diff --git a/advanced/Scripts/chronometer.sh b/advanced/Scripts/chronometer.sh index 7c2d8b52..1a4ce993 100755 --- a/advanced/Scripts/chronometer.sh +++ b/advanced/Scripts/chronometer.sh @@ -444,6 +444,9 @@ get_strings() { } chronoFunc() { + local extra_arg="$1" + local extra_value="$2" + get_init_stats for (( ; ; )); do @@ -461,10 +464,8 @@ chronoFunc() { fi # Get refresh number - if [[ "$*" == *"-r"* ]]; then - num="$*" - num="${num/*-r /}" - num="${num/ */}" + if [[ "${extra_arg}" = "refresh" ]]; then + num="${extra_value}" num_str="Refresh set for every $num seconds" else num_str="" @@ -473,7 +474,7 @@ chronoFunc() { clear # Remove exit message heading on third refresh - if [[ "$count" -le 2 ]] && [[ "$*" != *"-e"* ]]; then + if [[ "$count" -le 2 ]] && [[ "${extra_arg}" != "exit" ]]; then echo -e " ${COL_LIGHT_GREEN}Pi-hole Chronometer${COL_NC} $num_str ${COL_LIGHT_RED}Press Ctrl-C to exit${COL_NC} @@ -521,10 +522,10 @@ chronoFunc() { fi # Handle exit/refresh options - if [[ "$*" == *"-e"* ]]; then + if [[ "${extra_arg}" == "exit" ]]; then exit 0 else - if [[ "$*" == *"-r"* ]]; then + if [[ "${extra_arg}" == "refresh" ]]; then sleep "$num" else sleep 5 @@ -561,12 +562,10 @@ if [[ $# = 0 ]]; then chronoFunc fi -for var in "$@"; do - case "$var" in - "-j" | "--json" ) jsonFunc;; - "-h" | "--help" ) helpFunc;; - "-r" | "--refresh" ) chronoFunc "$@";; - "-e" | "--exit" ) chronoFunc "$@";; - * ) helpFunc "?";; - esac -done +case "$1" in + "-j" | "--json" ) jsonFunc;; + "-h" | "--help" ) helpFunc;; + "-r" | "--refresh" ) chronoFunc refresh "$2";; + "-e" | "--exit" ) chronoFunc exit;; + * ) helpFunc "?";; +esac diff --git a/advanced/Scripts/piholeCheckout.sh b/advanced/Scripts/piholeCheckout.sh index 1bfe5e21..c4b07a98 100644 --- a/advanced/Scripts/piholeCheckout.sh +++ b/advanced/Scripts/piholeCheckout.sh @@ -115,7 +115,7 @@ checkout() { if [[ "${corebranches[*]}" == *"master"* ]]; then echo -e "${OVER} ${TICK} $str" - echo -e "${INFO} ${#corebranches[@]} branches available for Pi-hole Core" + echo -e " ${INFO} ${#corebranches[@]} branches available for Pi-hole Core" else # Print STDERR output from get_available_branches echo -e "${OVER} ${CROSS} $str\\n\\n${corebranches[*]}" @@ -142,7 +142,7 @@ checkout() { if [[ "${webbranches[*]}" == *"master"* ]]; then echo -e "${OVER} ${TICK} $str" - echo -e "${INFO} ${#webbranches[@]} branches available for Web Admin" + echo -e " ${INFO} ${#webbranches[@]} branches available for Web Admin" else # Print STDERR output from get_available_branches echo -e "${OVER} ${CROSS} $str\\n\\n${webbranches[*]}" diff --git a/advanced/Scripts/piholeDebug.sh b/advanced/Scripts/piholeDebug.sh index c840ed04..1010f26c 100755 --- a/advanced/Scripts/piholeDebug.sh +++ b/advanced/Scripts/piholeDebug.sh @@ -109,7 +109,6 @@ FTL_PORT="${RUN_DIRECTORY}/pihole-FTL.port" PIHOLE_LOG="${LOG_DIRECTORY}/pihole.log" PIHOLE_LOG_GZIPS="${LOG_DIRECTORY}/pihole.log.[0-9].*" PIHOLE_DEBUG_LOG="${LOG_DIRECTORY}/pihole_debug.log" -PIHOLE_DEBUG_LOG_SANITIZED="${LOG_DIRECTORY}/pihole_debug-sanitized.log" PIHOLE_FTL_LOG="${LOG_DIRECTORY}/pihole-FTL.log" PIHOLE_WEB_SERVER_ACCESS_LOG_FILE="${WEB_SERVER_LOG_DIRECTORY}/access.log" @@ -209,11 +208,6 @@ log_write() { copy_to_debug_log() { # Copy the contents of file descriptor 3 into the debug log cat /proc/$$/fd/3 > "${PIHOLE_DEBUG_LOG}" - # Since we use color codes such as '\e[1;33m', they should be removed before being - # uploaded to our server, since it can't properly display in color - # This is accomplished by use sed to remove characters matching that patter - # The entire file is then copied over to a sanitized version of the log - sed 's/\[[0-9;]\{1,5\}m//g' > "${PIHOLE_DEBUG_LOG_SANITIZED}" <<< cat "${PIHOLE_DEBUG_LOG}" } initialize_debug() { @@ -269,6 +263,9 @@ compare_local_version_to_git_version() { # The commit they are on local remote_commit remote_commit=$(git describe --long --dirty --tags --always) + # Status of the repo + local local_status + local_status=$(git status -s) # echo this information out to the user in a nice format # If the current version matches what pihole -v produces, the user is up-to-date if [[ "${remote_version}" == "$(pihole -v | awk '/${search_term}/ {print $6}' | cut -d ')' -f1)" ]]; then @@ -291,6 +288,16 @@ compare_local_version_to_git_version() { fi # echo the current commit log_write "${INFO} Commit: ${remote_commit}" + # if `local_status` is non-null, then the repo is not clean, display details here + if [[ ${local_status} ]]; then + #Replace new lines in the status with 12 spaces to make the output cleaner + log_write "${INFO} Status: ${local_status//$'\n'/'\n '}" + local local_diff + local_diff=$(git diff) + if [[ ${local_diff} ]]; then + log_write "${INFO} Diff: ${local_diff//$'\n'/'\n '}" + fi + fi # If git status failed, else # Return an error message @@ -1134,20 +1141,20 @@ analyze_pihole_log() { IFS="$OLD_IFS" } -tricorder_use_nc_or_ssl() { - # Users can submit their debug logs using nc (unencrypted) or openssl (enrypted) if available - # Check for openssl first since encryption is a good thing - if command -v openssl &> /dev/null; then +tricorder_use_nc_or_curl() { + # Users can submit their debug logs using nc (unencrypted) or curl (encrypted) if available + # Check for curl first since encryption is a good thing + if command -v curl &> /dev/null; then # If the command exists, - log_write " * Using ${COL_GREEN}openssl${COL_NC} for transmission." - # encrypt and transmit the log and store the token returned in a variable - tricorder_token=$(< ${PIHOLE_DEBUG_LOG_SANITIZED} openssl s_client -quiet -connect tricorder.pi-hole.net:${TRICORDER_SSL_PORT_NUMBER} 2> /dev/null) + log_write " * Using ${COL_GREEN}curl${COL_NC} for transmission." + # transmit he log via TLS and store the token returned in a variable + tricorder_token=$(curl --silent --upload-file ${PIHOLE_DEBUG_LOG} https://tricorder.pi-hole.net:${TRICORDER_SSL_PORT_NUMBER}) # Otherwise, else # use net cat log_write "${INFO} Using ${COL_YELLOW}netcat${COL_NC} for transmission." # Save the token returned by our server in a variable - tricorder_token=$(< ${PIHOLE_DEBUG_LOG_SANITIZED} nc tricorder.pi-hole.net ${TRICORDER_NC_PORT_NUMBER}) + tricorder_token=$(< ${PIHOLE_DEBUG_LOG} nc tricorder.pi-hole.net ${TRICORDER_NC_PORT_NUMBER}) fi } @@ -1173,7 +1180,7 @@ upload_to_tricorder() { # let the user know log_write "${INFO} Debug script running in automated mode" # and then decide again which tool to use to submit it - tricorder_use_nc_or_ssl + tricorder_use_nc_or_curl # If we're not running in automated mode, else echo "" @@ -1182,7 +1189,7 @@ upload_to_tricorder() { read -r -p "[?] Would you like to upload the log? [y/N] " response case ${response} in # If they say yes, run our function for uploading the log - [yY][eE][sS]|[yY]) tricorder_use_nc_or_ssl;; + [yY][eE][sS]|[yY]) tricorder_use_nc_or_curl;; # If they choose no, just exit out of the script *) log_write " * Log will ${COL_GREEN}NOT${COL_NC} be uploaded to tricorder.";exit; esac @@ -1209,7 +1216,7 @@ upload_to_tricorder() { log_write " * Please try again or contact the Pi-hole team for assistance." fi # Finally, show where the log file is no matter the outcome of the function so users can look at it - log_write " * A local copy of the debug log can be found at: ${COL_CYAN}${PIHOLE_DEBUG_LOG_SANITIZED}${COL_NC}\\n" + log_write " * A local copy of the debug log can be found at: ${COL_CYAN}${PIHOLE_DEBUG_LOG}${COL_NC}\\n" } # Run through all the functions we made diff --git a/advanced/Scripts/query.sh b/advanced/Scripts/query.sh index b599aa6b..69a3c7a4 100644 --- a/advanced/Scripts/query.sh +++ b/advanced/Scripts/query.sh @@ -54,7 +54,7 @@ scanList(){ # /dev/null forces filename to be printed when only one list has been generated # shellcheck disable=SC2086 case "${type}" in - "exact" ) grep -i -E -l "(^|\\s)${domain}($|\\s|#)" ${lists} /dev/null 2>/dev/null;; + "exact" ) grep -i -E -l "(^|(?<!#)\\s)${domain}($|\\s|#)" ${lists} /dev/null 2>/dev/null;; "wc" ) grep -i -o -m 1 "/${domain}/" ${lists} 2>/dev/null;; * ) grep -i "${domain}" ${lists} /dev/null 2>/dev/null;; esac diff --git a/advanced/Scripts/update.sh b/advanced/Scripts/update.sh index 59212a94..4d352777 100755 --- a/advanced/Scripts/update.sh +++ b/advanced/Scripts/update.sh @@ -146,6 +146,20 @@ main() { FTL_update=false fi + # Determine FTL branch + local ftlBranch + if [[ -f "/etc/pihole/ftlbranch" ]]; then + ftlBranch=$(</etc/pihole/ftlbranch) + else + ftlBranch="master" + fi + + if [[ ! "${ftlBranch}" == "master" && ! "${ftlBranch}" == "development" ]]; then + # Notify user that they are on a custom branch which might mean they they are lost + # behind if a branch was merged to development and got abandoned + printf " %b %bWarning:%b You are using FTL from a custom branch (%s) and might be missing future releases.\\n" "${INFO}" "${COL_LIGHT_RED}" "${COL_NC}" "${ftlBranch}" + fi + if [[ "${core_update}" == false && "${web_update}" == false && "${FTL_update}" == false ]]; then echo "" echo -e " ${TICK} Everything is up to date!" diff --git a/advanced/Scripts/updatecheck.sh b/advanced/Scripts/updatecheck.sh index 257c1929..26dc2ac2 100755 --- a/advanced/Scripts/updatecheck.sh +++ b/advanced/Scripts/updatecheck.sh @@ -34,7 +34,7 @@ function get_local_branch() { function get_local_version() { # Return active branch cd "${1}" 2> /dev/null || return 1 - git describe --long --dirty --tags || return 1 + git describe --long --dirty --tags 2> /dev/null || return 1 } # Source the setupvars config file diff --git a/advanced/Scripts/webpage.sh b/advanced/Scripts/webpage.sh index bb75701f..50aeb382 100755 --- a/advanced/Scripts/webpage.sh +++ b/advanced/Scripts/webpage.sh @@ -618,7 +618,7 @@ Interfaces: Teleporter() { local datetimestamp=$(date "+%Y-%m-%d_%H-%M-%S") - php /var/www/html/admin/scripts/pi-hole/php/teleporter.php > "pi-hole-teleporter_${datetimestamp}.zip" + php /var/www/html/admin/scripts/pi-hole/php/teleporter.php > "pi-hole-teleporter_${datetimestamp}.tar.gz" } addAudit() diff --git a/advanced/index.php b/advanced/index.php index 49eb0f45..78135e1a 100644 --- a/advanced/index.php +++ b/advanced/index.php @@ -40,13 +40,6 @@ $validExtTypes = array("asp", "htm", "html", "php", "rss", "xml", ""); // Get extension of current URL $currentUrlExt = pathinfo($_SERVER["REQUEST_URI"], PATHINFO_EXTENSION); -// Check if this is served over HTTP or HTTPS -if(isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == "on") { - $proto = "https"; -} else { - $proto = "http"; -} - // Set mobile friendly viewport $viewPort = '<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>'; @@ -229,10 +222,10 @@ setHeader(); <?=$viewPort ?> <meta name="robots" content="noindex,nofollow"/> <meta http-equiv="x-dns-prefetch-control" content="off"> - <link rel="shortcut icon" href="<?=$proto ?>://pi.hole/admin/img/favicon.png" type="image/x-icon"/> - <link rel="stylesheet" href="<?=$proto ?>://pi.hole/pihole/blockingpage.css" type="text/css"/> + <link rel="shortcut icon" href="//pi.hole/admin/img/favicon.png" type="image/x-icon"/> + <link rel="stylesheet" href="//pi.hole/pihole/blockingpage.css" type="text/css"/> <title>● <?=$serverName ?></title> - <script src="<?=$proto ?>://pi.hole/admin/scripts/vendor/jquery.min.js"></script> + <script src="//pi.hole/admin/scripts/vendor/jquery.min.js"></script> <script> window.onload = function () { <?php diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index c6244bd1..4705b8a0 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -28,6 +28,20 @@ set -e # Local variables will be in lowercase and will exist only within functions # It's still a work in progress, so you may see some variance in this guideline until it is complete +# List of supported DNS servers +DNS_SERVERS=$(cat << EOM +Google (ECS);8.8.8.8;8.8.4.4;2001:4860:4860:0:0:0:0:8888;2001:4860:4860:0:0:0:0:8844 +OpenDNS (ECS);208.67.222.222;208.67.220.220;2620:0:ccc::2;2620:0:ccd::2 +Level3;4.2.2.1;4.2.2.2;; +Comodo;8.26.56.26;8.20.247.20;; +DNS.WATCH;84.200.69.80;84.200.70.40;2001:1608:10:25:0:0:1c04:b12f;2001:1608:10:25:0:0:9249:d69b +Quad9 (filtered, DNSSEC);9.9.9.9;149.112.112.112;2620:fe::fe;2620:fe::9 +Quad9 (unfiltered, no DNSSEC);9.9.9.10;149.112.112.10;2620:fe::10;2620:fe::fe:10 +Quad9 (filtered + ECS);9.9.9.11;149.112.112.11;2620:fe::11; +Cloudflare;1.1.1.1;1.0.0.1;2606:4700:4700::1111;2606:4700:4700::1001 +EOM +) + # Location for final installation log storage installLogLoc=/etc/pihole/install.log # This is an important file as it contains information specific to the machine it's being installed on @@ -38,9 +52,12 @@ lighttpdConfig=/etc/lighttpd/lighttpd.conf # This is a file used for the colorized output coltable=/opt/pihole/COL_TABLE +# Root of the web server +webroot="/var/www/html" + # We store several other directories and -webInterfaceGitUrl="https://github.com/pi-hole/AdminLTE.git" -webInterfaceDir="/var/www/html/admin" +webInterfaceGitUrl="https://github.com/arevindh/AdminLTE.git" +webInterfaceDir="${webroot}/admin" piholeGitUrl="https://github.com/arevindh/pi-hole.git" PI_HOLE_LOCAL_REPO="/etc/.pihole" # These are the names of pi-holes files, stored in an array @@ -48,6 +65,7 @@ PI_HOLE_FILES=(chronometer list piholeDebug piholeLogFlush setupLCD update versi # This directory is where the Pi-hole scripts will be installed PI_HOLE_INSTALL_DIR="/opt/pihole" PI_HOLE_CONFIG_DIR="/etc/pihole" +PI_HOLE_BLOCKPAGE_DIR="${webroot}/pihole" useUpdateVars=false adlistFile="/etc/pihole/adlists.list" @@ -395,7 +413,7 @@ make_repo() { rm -rf "${directory}" fi # Clone the repo and return the return code from this command - git clone -q --depth 1 "${remoteRepo}" "${directory}" &> /dev/null || return $? + git clone -q --depth 20 "${remoteRepo}" "${directory}" &> /dev/null || return $? # Show a colored message showing it's status printf "%b %b %s\\n" "${OVER}" "${TICK}" "${str}" # Always return 0? Not sure this is correct @@ -507,7 +525,7 @@ find_IPv4_information() { fi # Append the CIDR notation to the IP address, if valid_ip fails this should return 127.0.0.1/8 - IPV4_ADDRESS=$(ip -oneline -family inet address show | grep "${IPv4bare}" | awk '{print $4}' | awk 'END {print}') + IPV4_ADDRESS=$(ip -oneline -family inet address show | grep "${IPv4bare}/" | awk '{print $4}' | awk 'END {print}') } # Get available interfaces that are UP @@ -862,6 +880,13 @@ setStaticIPv4() { # Local, named variables local IFCFG_FILE local CONNECTION_NAME + + # If a static interface is already configured, we are done. + if [[ -r "/etc/sysconfig/network/ifcfg-${PIHOLE_INTERFACE}" ]]; then + if grep -q '^BOOTPROTO=.static.' "/etc/sysconfig/network/ifcfg-${PIHOLE_INTERFACE}"; then + return 0 + fi + fi # For the Debian family, if dhcpcd.conf exists, if [[ -f "/etc/dhcpcd.conf" ]]; then # configure networking via dhcpcd @@ -922,15 +947,26 @@ setDNS() { local DNSSettingsCorrect # In an array, list the available upstream providers - DNSChooseOptions=(Google "" - OpenDNS "" - Level3 "" - Comodo "" - DNSWatch "" - Quad9 "" - FamilyShield "" - Cloudflare "" - Custom "") + DNSChooseOptions=() + local DNSServerCount=0 + # Save the old Internal Field Separator in a variable + OIFS=$IFS + # and set the new one to newline + IFS=$'\n' + # Put the DNS Servers into an array + for DNSServer in ${DNS_SERVERS} + do + DNSName="$(cut -d';' -f1 <<< "${DNSServer}")" + DNSChooseOptions[DNSServerCount]="${DNSName}" + (( DNSServerCount=DNSServerCount+1 )) + DNSChooseOptions[DNSServerCount]="" + (( DNSServerCount=DNSServerCount+1 )) + done + DNSChooseOptions[DNSServerCount]="Custom" + (( DNSServerCount=DNSServerCount+1 )) + DNSChooseOptions[DNSServerCount]="" + # Restore the IFS to what it was + IFS=${OIFS} # In a whiptail dialog, show the options DNSchoices=$(whiptail --separate-output --menu "Select Upstream DNS Provider. To use your own, select Custom." ${r} ${c} 7 \ "${DNSChooseOptions[@]}" 2>&1 >/dev/tty) || \ @@ -940,113 +976,90 @@ setDNS() { # Display the selection printf " %b Using " "${INFO}" # Depending on the user's choice, set the GLOBAl variables to the IP of the respective provider - case ${DNSchoices} in - Google) - printf "Google DNS servers\\n" - PIHOLE_DNS_1="8.8.8.8" - PIHOLE_DNS_2="8.8.4.4" - ;; - OpenDNS) - printf "OpenDNS servers\\n" - PIHOLE_DNS_1="208.67.222.222" - PIHOLE_DNS_2="208.67.220.220" - ;; - Level3) - printf "Level3 servers\\n" - PIHOLE_DNS_1="4.2.2.1" - PIHOLE_DNS_2="4.2.2.2" - ;; - Comodo) - printf "Comodo Secure servers\\n" - PIHOLE_DNS_1="8.26.56.26" - PIHOLE_DNS_2="8.20.247.20" - ;; - DNSWatch) - printf "DNS.WATCH servers\\n" - PIHOLE_DNS_1="84.200.69.80" - PIHOLE_DNS_2="84.200.70.40" - ;; - Quad9) - printf "Quad9 servers\\n" - PIHOLE_DNS_1="9.9.9.9" - PIHOLE_DNS_2="149.112.112.112" - ;; - FamilyShield) - printf "FamilyShield servers\\n" - PIHOLE_DNS_1="208.67.222.123" - PIHOLE_DNS_2="208.67.220.123" - ;; - Cloudflare) - printf "Cloudflare servers\\n" - PIHOLE_DNS_1="1.1.1.1" - PIHOLE_DNS_2="1.0.0.1" - ;; - Custom) - # Until the DNS settings are selected, - until [[ "${DNSSettingsCorrect}" = True ]]; do - # - strInvalid="Invalid" - # If the first - if [[ ! "${PIHOLE_DNS_1}" ]]; then - # and second upstream servers do not exist - if [[ ! "${PIHOLE_DNS_2}" ]]; then - prePopulate="" - # Otherwise, - else - prePopulate=", ${PIHOLE_DNS_2}" - fi - elif [[ "${PIHOLE_DNS_1}" ]] && [[ ! "${PIHOLE_DNS_2}" ]]; then - prePopulate="${PIHOLE_DNS_1}" - elif [[ "${PIHOLE_DNS_1}" ]] && [[ "${PIHOLE_DNS_2}" ]]; then - prePopulate="${PIHOLE_DNS_1}, ${PIHOLE_DNS_2}" - fi - - # Dialog for the user to enter custom upstream servers - piholeDNS=$(whiptail --backtitle "Specify Upstream DNS Provider(s)" --inputbox "Enter your desired upstream DNS provider(s), separated by a comma.\\n\\nFor example '8.8.8.8, 8.8.4.4'" ${r} ${c} "${prePopulate}" 3>&1 1>&2 2>&3) || \ - { printf " %bCancel was selected, exiting installer%b\\n" "${COL_LIGHT_RED}" "${COL_NC}"; exit 1; } - # Clean user input and replace whitespace with comma. - piholeDNS=$(sed 's/[, \t]\+/,/g' <<< "${piholeDNS}") - - printf -v PIHOLE_DNS_1 "%s" "${piholeDNS%%,*}" - printf -v PIHOLE_DNS_2 "%s" "${piholeDNS##*,}" - - # If the IP is valid, - if ! valid_ip "${PIHOLE_DNS_1}" || [[ ! "${PIHOLE_DNS_1}" ]]; then - # store it in the variable so we can use it - PIHOLE_DNS_1=${strInvalid} - fi - # Do the same for the secondary server - if ! valid_ip "${PIHOLE_DNS_2}" && [[ "${PIHOLE_DNS_2}" ]]; then - PIHOLE_DNS_2=${strInvalid} - fi - # If either of the DNS servers are invalid, - if [[ "${PIHOLE_DNS_1}" == "${strInvalid}" ]] || [[ "${PIHOLE_DNS_2}" == "${strInvalid}" ]]; then - # explain this to the user - whiptail --msgbox --backtitle "Invalid IP" --title "Invalid IP" "One or both entered IP addresses were invalid. Please try again.\\n\\n DNS Server 1: $PIHOLE_DNS_1\\n DNS Server 2: ${PIHOLE_DNS_2}" ${r} ${c} - # and set the variables back to nothing - if [[ "${PIHOLE_DNS_1}" == "${strInvalid}" ]]; then - PIHOLE_DNS_1="" - fi - if [[ "${PIHOLE_DNS_2}" == "${strInvalid}" ]]; then - PIHOLE_DNS_2="" - fi - # Since the settings will not work, stay in the loop - DNSSettingsCorrect=False + if [[ "${DNSchoices}" == "Custom" ]] + then + # Until the DNS settings are selected, + until [[ "${DNSSettingsCorrect}" = True ]]; do + # + strInvalid="Invalid" + # If the first + if [[ ! "${PIHOLE_DNS_1}" ]]; then + # and second upstream servers do not exist + if [[ ! "${PIHOLE_DNS_2}" ]]; then + prePopulate="" # Otherwise, else - # Show the settings - if (whiptail --backtitle "Specify Upstream DNS Provider(s)" --title "Upstream DNS Provider(s)" --yesno "Are these settings correct?\\n DNS Server 1: $PIHOLE_DNS_1\\n DNS Server 2: ${PIHOLE_DNS_2}" ${r} ${c}); then - # and break from the loop since the servers are valid - DNSSettingsCorrect=True - # Otherwise, - else - # If the settings are wrong, the loop continues - DNSSettingsCorrect=False - fi + prePopulate=", ${PIHOLE_DNS_2}" fi - done - ;; - esac + elif [[ "${PIHOLE_DNS_1}" ]] && [[ ! "${PIHOLE_DNS_2}" ]]; then + prePopulate="${PIHOLE_DNS_1}" + elif [[ "${PIHOLE_DNS_1}" ]] && [[ "${PIHOLE_DNS_2}" ]]; then + prePopulate="${PIHOLE_DNS_1}, ${PIHOLE_DNS_2}" + fi + + # Dialog for the user to enter custom upstream servers + piholeDNS=$(whiptail --backtitle "Specify Upstream DNS Provider(s)" --inputbox "Enter your desired upstream DNS provider(s), separated by a comma.\\n\\nFor example '8.8.8.8, 8.8.4.4'" ${r} ${c} "${prePopulate}" 3>&1 1>&2 2>&3) || \ + { printf " %bCancel was selected, exiting installer%b\\n" "${COL_LIGHT_RED}" "${COL_NC}"; exit 1; } + # Clean user input and replace whitespace with comma. + piholeDNS=$(sed 's/[, \t]\+/,/g' <<< "${piholeDNS}") + + printf -v PIHOLE_DNS_1 "%s" "${piholeDNS%%,*}" + printf -v PIHOLE_DNS_2 "%s" "${piholeDNS##*,}" + + # If the IP is valid, + if ! valid_ip "${PIHOLE_DNS_1}" || [[ ! "${PIHOLE_DNS_1}" ]]; then + # store it in the variable so we can use it + PIHOLE_DNS_1=${strInvalid} + fi + # Do the same for the secondary server + if ! valid_ip "${PIHOLE_DNS_2}" && [[ "${PIHOLE_DNS_2}" ]]; then + PIHOLE_DNS_2=${strInvalid} + fi + # If either of the DNS servers are invalid, + if [[ "${PIHOLE_DNS_1}" == "${strInvalid}" ]] || [[ "${PIHOLE_DNS_2}" == "${strInvalid}" ]]; then + # explain this to the user + whiptail --msgbox --backtitle "Invalid IP" --title "Invalid IP" "One or both entered IP addresses were invalid. Please try again.\\n\\n DNS Server 1: $PIHOLE_DNS_1\\n DNS Server 2: ${PIHOLE_DNS_2}" ${r} ${c} + # and set the variables back to nothing + if [[ "${PIHOLE_DNS_1}" == "${strInvalid}" ]]; then + PIHOLE_DNS_1="" + fi + if [[ "${PIHOLE_DNS_2}" == "${strInvalid}" ]]; then + PIHOLE_DNS_2="" + fi + # Since the settings will not work, stay in the loop + DNSSettingsCorrect=False + # Otherwise, + else + # Show the settings + if (whiptail --backtitle "Specify Upstream DNS Provider(s)" --title "Upstream DNS Provider(s)" --yesno "Are these settings correct?\\n DNS Server 1: $PIHOLE_DNS_1\\n DNS Server 2: ${PIHOLE_DNS_2}" ${r} ${c}); then + # and break from the loop since the servers are valid + DNSSettingsCorrect=True + # Otherwise, + else + # If the settings are wrong, the loop continues + DNSSettingsCorrect=False + fi + fi + done + else + # Save the old Internal Field Separator in a variable + OIFS=$IFS + # and set the new one to newline + IFS=$'\n' + for DNSServer in ${DNS_SERVERS} + do + DNSName="$(cut -d';' -f1 <<< "${DNSServer}")" + if [[ "${DNSchoices}" == "${DNSName}" ]] + then + printf "%s\\n" "${DNSName}" + PIHOLE_DNS_1="$(cut -d';' -f2 <<< "${DNSServer}")" + PIHOLE_DNS_2="$(cut -d';' -f3 <<< "${DNSServer}")" + break + fi + done + # Restore the IFS to what it was + IFS=${OIFS} + fi } # Allow the user to enable/disable logging @@ -1084,7 +1097,7 @@ setPrivacyLevel() { local LevelCommand local LevelOptions - LevelCommand=(whiptail --separate-output --radiolist "Select a privacy mode for FTL." "${r}" "${c}" 6) + LevelCommand=(whiptail --separate-output --radiolist "Select a privacy mode for FTL. https://docs.pi-hole.net/ftldns/privacylevels/" "${r}" "${c}" 6) # The default selection is level 0 LevelOptions=( @@ -1345,9 +1358,16 @@ installConfigs() { printf "\\n %b Installing configs from %s...\\n" "${INFO}" "${PI_HOLE_LOCAL_REPO}" # Make sure Pi-hole's config files are in place version_check_dnsmasq + + # Install list of DNS servers + # Format: Name;Primary IPv4;Secondary IPv4;Primary IPv6;Secondary IPv6 + # Some values may be empty (for example: DNS servers without IPv6 support) + echo "${DNS_SERVERS}" > "${PI_HOLE_CONFIG_DIR}/dns-servers.conf" + # Install empty file if it does not exist - if [[ ! -f "${PI_HOLE_CONFIG_DIR}/pihole-FTL.conf" ]]; then - if ! install -o pihole -g pihole -m 664 /dev/null "${PI_HOLE_CONFIG_DIR}/pihole-FTL.conf" &>/dev/null; then + if [[ ! -r "${PI_HOLE_CONFIG_DIR}/pihole-FTL.conf" ]]; then + install -d -m 0755 ${PI_HOLE_CONFIG_DIR} + if ! install -o pihole -m 664 /dev/null "${PI_HOLE_CONFIG_DIR}/pihole-FTL.conf" &>/dev/null; then printf " %bError: Unable to initialize configuration file %s/pihole-FTL.conf\\n" "${COL_LIGHT_RED}" "${PI_HOLE_CONFIG_DIR}" return 1 fi @@ -1375,7 +1395,7 @@ installConfigs() { # Make sure the external.conf file exists, as lighttpd v1.4.50 crashes without it touch /etc/lighttpd/external.conf # if there is a custom block page in the html/pihole directory, replace 404 handler in lighttpd config - if [[ -f "/var/www/html/pihole/custom.php" ]]; then + if [[ -f "${PI_HOLE_BLOCKPAGE_DIR}/custom.php" ]]; then sed -i 's/^\(server\.error-handler-404\s*=\s*\).*$/\1"pihole\/custom\.php"/' /etc/lighttpd/lighttpd.conf fi # Make the directories if they do not exist and set the owners @@ -1543,7 +1563,7 @@ update_package_cache() { else # show an error and exit printf "%b %b %s\\n" "${OVER}" "${CROSS}" "${str}" - printf " %bError: Unable to update package cache. Please try \"%s\"%b" "${COL_LIGHT_RED}" "${COL_LIGHT_RED}" "${COL_NC}" + printf " %bError: Unable to update package cache. Please try \"%s\"%b" "${COL_LIGHT_RED}" "${UPDATE_PKG_CACHE}" "${COL_NC}" return 1 fi } @@ -1641,13 +1661,13 @@ installPiholeWeb() { local str="Creating directory for blocking page, and copying files" printf " %b %s..." "${INFO}" "${str}" # Install the directory - install -d /var/www/html/pihole + install -d -m 0755 ${PI_HOLE_BLOCKPAGE_DIR} # and the blockpage - install -D ${PI_HOLE_LOCAL_REPO}/advanced/{index,blockingpage}.* /var/www/html/pihole/ + install -D ${PI_HOLE_LOCAL_REPO}/advanced/{index,blockingpage}.* ${PI_HOLE_BLOCKPAGE_DIR}/ # Remove superseded file - if [[ -e "/var/www/html/pihole/index.js" ]]; then - rm "/var/www/html/pihole/index.js" + if [[ -e "${PI_HOLE_BLOCKPAGE_DIR}/index.js" ]]; then + rm "${PI_HOLE_BLOCKPAGE_DIR}/index.js" fi printf "%b %b %s\\n" "${OVER}" "${TICK}" "${str}" @@ -1655,9 +1675,9 @@ installPiholeWeb() { local str="Backing up index.lighttpd.html" printf " %b %s..." "${INFO}" "${str}" # If the default index file exists, - if [[ -f "/var/www/html/index.lighttpd.html" ]]; then + if [[ -f "${webroot}/index.lighttpd.html" ]]; then # back it up - mv /var/www/html/index.lighttpd.html /var/www/html/index.lighttpd.orig + mv ${webroot}/index.lighttpd.html ${webroot}/index.lighttpd.orig printf "%b %b %s\\n" "${OVER}" "${TICK}" "${str}" # Otherwise, else @@ -1672,7 +1692,7 @@ installPiholeWeb() { # Make the .d directory if it doesn't exist mkdir -p /etc/sudoers.d/ # and copy in the pihole sudoers file - cp ${PI_HOLE_LOCAL_REPO}/advanced/Templates/pihole.sudo /etc/sudoers.d/pihole + install -m 0640 ${PI_HOLE_LOCAL_REPO}/advanced/Templates/pihole.sudo /etc/sudoers.d/pihole # Add lighttpd user (OS dependent) to sudoers file echo "${LIGHTTPD_USER} ALL=NOPASSWD: /usr/local/bin/pihole" >> /etc/sudoers.d/pihole @@ -1867,15 +1887,15 @@ installPihole() { # If the user wants to install the Web interface, if [[ "${INSTALL_WEB_INTERFACE}" == true ]]; then - if [[ ! -d "/var/www/html" ]]; then + if [[ ! -d "${webroot}" ]]; then # make the Web directory if necessary - mkdir -p /var/www/html + install -d -m 0755 ${webroot} fi if [[ "${INSTALL_WEB_SERVER}" == true ]]; then # Set the owner and permissions - chown ${LIGHTTPD_USER}:${LIGHTTPD_GROUP} /var/www/html - chmod 775 /var/www/html + chown ${LIGHTTPD_USER}:${LIGHTTPD_GROUP} ${webroot} + chmod 0775 ${webroot} # Give pihole access to the Web server group usermod -a -G ${LIGHTTPD_GROUP} pihole # If the lighttpd command is executable, @@ -2181,6 +2201,9 @@ FTLinstall() { if sha1sum --status --quiet -c "${binary}".sha1; then printf "transferred... " + # Before stopping FTL, we download the macvendor database + curl -sSL "https://ftl.pi-hole.net/macvendor.db" -o "${PI_HOLE_CONFIG_DIR}/macvendor.db" || true + # Stop pihole-FTL service if available stop_service pihole-FTL &> /dev/null @@ -2274,10 +2297,12 @@ get_binary_name() { elif [[ "${machine}" == "x86_64" ]]; then # This gives the architecture of packages dpkg installs (for example, "i386") local dpkgarch - dpkgarch=$(dpkg --print-architecture 2> /dev/null) + dpkgarch=$(dpkg --print-architecture 2> /dev/null || true) # Special case: This is a 32 bit OS, installed on a 64 bit machine # -> change machine architecture to download the 32 bit executable + # We only check this for Debian-based systems as this has been an issue + # in the past (see https://github.com/pi-hole/pi-hole/pull/2004) if [[ "${dpkgarch}" == "i386" ]]; then printf "%b %b Detected 32bit (i686) architecture\\n" "${OVER}" "${TICK}" binary="pihole-FTL-linux-x86_32" diff --git a/automated install/uninstall.sh b/automated install/uninstall.sh index 52760cfb..d0a6dcf0 100755 --- a/automated install/uninstall.sh +++ b/automated install/uninstall.sh @@ -131,8 +131,7 @@ removeNoPurge() { echo -e " ${TICK} Removed /etc/cron.d/pihole" fi - package_check lighttpd > /dev/null - if [[ $? -eq 1 ]]; then + if package_check lighttpd > /dev/null; then ${SUDO} rm -rf /etc/lighttpd/ &> /dev/null echo -e " ${TICK} Removed lighttpd" else diff --git a/gravity.sh b/gravity.sh index 75a51608..ff0343e9 100755 --- a/gravity.sh +++ b/gravity.sh @@ -268,7 +268,7 @@ gravity_DownloadBlocklistFromUrl() { port=443; else port=80 fi - bad_list=$(pihole -q -adlist hosts-file.net | head -n1 | awk -F 'Match found in ' '{print $2}') + bad_list=$(pihole -q -adlist "${domain}" | head -n1 | awk -F 'Match found in ' '{print $2}') echo -e "${OVER} ${CROSS} ${str} ${domain} is blocked by ${bad_list%:}. Using DNS on ${PIHOLE_DNS_1} to download ${url}"; echo -ne " ${INFO} ${str} Pending..." cmd_ext="--resolve $domain:$port:$ip $cmd_ext" diff --git a/requirements.txt b/requirements.txt index f2c61e42..17d62ad9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ -docker-compose -pytest -pytest-xdist -pytest-cov -testinfra -tox +docker-compose==1.23.2 +pytest==4.3.0 +pytest-xdist==1.26.1 +pytest-cov==2.6.1 +testinfra==1.19.0 +tox==3.7.0