diff --git a/README.md b/README.md index 77f259e6..c0f413ca 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ The Pi-hole[®](https://pi-hole.net/trademark-rules-and-brand-guidelines/) is a BountySource ## One-Step Automated Install -Those who want to get started quickly and conveniently, may install Pi-hole using the following command: +Those who want to get started quickly and conveniently may install Pi-hole using the following command: #### `curl -sSL https://install.pi-hole.net | bash` @@ -46,14 +46,14 @@ sudo bash basic-install.sh Once the installer has been run, you will need to [configure your router to have **DHCP clients use Pi-hole as their DNS server**](https://discourse.pi-hole.net/t/how-do-i-configure-my-devices-to-use-pi-hole-as-their-dns-server/245) which ensures that all devices connecting to your network will have content blocked without any further intervention. -If your router does not support setting the DNS server, you can [use Pi-hole's built in DHCP server](https://discourse.pi-hole.net/t/how-do-i-use-pi-holes-built-in-dhcp-server-and-why-would-i-want-to/3026); just be sure to disable DHCP on your router first (if it has that feature available). +If your router does not support setting the DNS server, you can [use Pi-hole's built-in DHCP server](https://discourse.pi-hole.net/t/how-do-i-use-pi-holes-built-in-dhcp-server-and-why-would-i-want-to/3026); just be sure to disable DHCP on your router first (if it has that feature available). As a last resort, you can always manually set each device to use Pi-hole as their DNS server. ----- ## Pi-hole is free, but powered by your support -There are many reoccurring costs involved with maintaining free, open source, and privacy respecting software; expenses which [our volunteer developers](https://github.com/orgs/pi-hole/people) pitch in to cover out-of-pocket. This is just one example of how strongly we feel about our software, as well as the importance of keeping it maintained. +There are many reoccurring costs involved with maintaining free, open source, and privacy-respecting software; expenses which [our volunteer developers](https://github.com/orgs/pi-hole/people) pitch in to cover out-of-pocket. This is just one example of how strongly we feel about our software, as well as the importance of keeping it maintained. Make no mistake: **your support is absolutely vital to help keep us innovating!** @@ -70,7 +70,7 @@ Sending a donation using our links below is **extremely helpful** in offsetting 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_ -- [UNIXstickers.com](http://unixstickers.refr.cc/jacobs) _save $5 when you spend $9 using our 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_ - [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_ @@ -82,7 +82,7 @@ We welcome _everyone_ to contribute to issue reports, suggest new features, and If you have something to add - anything from a typo through to a whole new feature, we're happy to check it out! Just make sure to fill out our template when submitting your request; the questions that it asks will help the volunteers quickly understand what you're aiming to achieve. -You'll find that the [install script](https://github.com/pi-hole/pi-hole/blob/master/automated%20install/basic-install.sh) and the [debug script](https://github.com/pi-hole/pi-hole/blob/master/advanced/Scripts/piholeDebug.sh) have an abundance of comments, which will help you better understand how Pi-hole works. They're also a valuable resource to those who want to learn how to write scripts or code a program! We encourage anyone who likes to tinker to read through it, and submit a pull request for us to review. +You'll find that the [install script](https://github.com/pi-hole/pi-hole/blob/master/automated%20install/basic-install.sh) and the [debug script](https://github.com/pi-hole/pi-hole/blob/master/advanced/Scripts/piholeDebug.sh) have an abundance of comments, which will help you better understand how Pi-hole works. They're also a valuable resource to those who want to learn how to write scripts or code a program! We encourage anyone who likes to tinker to read through it and submit a pull request for us to review. ### Presentations about Pi-hole Word-of-mouth continues to help our project grow immensely, and so we are helping make this easier for people. @@ -110,7 +110,7 @@ While we are primarily reachable on our Pi-hole Blacklist Demo @@ -137,7 +137,7 @@ Some notable features include: * Detailed graphs and doughnut charts * Top lists of domains and clients * A filterable and sortable query log -* Long Term Statistics to view data over user defined time ranges +* Long Term Statistics to view data over user-defined time ranges * The ability to easily manage and configure Pi-hole features * ... and all the main features of the Command Line Interface! @@ -148,7 +148,7 @@ There are several ways to [access the dashboard](https://discourse.pi-hole.net/t 3. `http://pi.hole/` (when using Pi-hole as your DNS server) ## Faster-than-light Engine -FTLDNS[™](https://pi-hole.net/trademark-rules-and-brand-guidelines/) is a lightweight, purpose-built daemon used to provide statistics needed for the Web Interface, and its API can be easily integrated into your own projects. As the name implies, FTLDNS does this all *very quickly*! +FTLDNS is a lightweight, purpose-built daemon used to provide statistics needed for the Web Interface, and its API can be easily integrated into your own projects. As the name implies, FTLDNS does this all *very quickly*! Some of the statistics you can integrate include: * Total number of domains being blocked @@ -165,40 +165,46 @@ The API can be accessed via [`telnet`](https://github.com/pi-hole/FTL), the Web ----- ## The Origin Of Pi-hole -Pi-hole being a **advertising-aware DNS/Web server**, makes use of the following technologies: +Pi-hole being an **advertising-aware DNS/Web server**, makes use of the following technologies: * [`dnsmasq`](http://www.thekelleys.org.uk/dnsmasq/doc.html) - a lightweight DNS and DHCP server * [`curl`](https://curl.haxx.se) - A command line tool for transferring data with URL syntax -* [`lighttpd`](https://www.lighttpd.net) - webserver designed and optimized for high performance +* [`lighttpd`](https://www.lighttpd.net) - web server designed and optimized for high performance * [`php`](https://secure.php.net) - a popular general-purpose web scripting language * [AdminLTE Dashboard](https://github.com/almasaeed2010/AdminLTE) - premium admin control panel based on Bootstrap 3.x -While quite outdated at this point, [this original blog post about Pi-hole](https://jacobsalmela.com/2015/06/16/block-millions-ads-network-wide-with-a-raspberry-pi-hole-2-0/) goes into **great detail** about how Pi-hole was originally setup and how it works. Syntactically, it's no longer accurate, but the same basic principles and logic still apply to Pi-hole's current state. +While quite outdated at this point, [this original blog post about Pi-hole](https://jacobsalmela.com/2015/06/16/block-millions-ads-network-wide-with-a-raspberry-pi-hole-2-0/) goes into **great detail** about how Pi-hole was originally set up and how it works. Syntactically, it's no longer accurate, but the same basic principles and logic still apply to Pi-hole's current state. + ----- ## Coverage -- [Software Engineering Daily: Interview with the creator of Pi-hole](https://softwareengineeringdaily.com/2018/05/29/pi-hole-ad-blocker-hardware-with-jacob-salmela/) -- [Bloomberg Business Week: Brotherhood of the Ad blockers](https://www.bloomberg.com/news/features/2018-05-10/inside-the-brotherhood-of-pi-hole-ad-blockers) -- [Securing DNS across all of my devices with Pi-Hole + DNS-over-HTTPS + 1.1.1.1](https://scotthelme.co.uk/securing-dns-across-all-of-my-devices-with-pihole-dns-over-https-1-1-1-1/) -- [Adafruit: installing Pi-hole on a Pi Zero W](https://learn.adafruit.com/pi-hole-ad-blocker-with-pi-zero-w/install-pi-hole) -- [Lifehacker: Turn A Raspberry Pi Into An Ad Blocker With A Single Command](https://www.lifehacker.com.au/2015/02/turn-a-raspberry-pi-into-an-ad-blocker-with-a-single-command/) -- [MakeUseOf: Adblock Everywhere: The Raspberry Pi-Hole Way](http://www.makeuseof.com/tag/adblock-everywhere-raspberry-pi-hole-way/) -- [Catchpoint: Ad-Blocking on Apple iOS9: Valuing the End User Experience](http://blog.catchpoint.com/2015/09/14/ad-blocking-apple/) -- [Security Now Netcast: Pi-hole](https://www.youtube.com/watch?v=p7-osq_y8i8&t=100m26s) -- [TekThing: Raspberry Pi-Hole Makes Ads Disappear!](https://youtu.be/8Co59HU2gY0?t=2m) -- [Foolish Tech Show](https://youtu.be/bYyena0I9yc?t=2m4s) -- [Block Ads on All Home Devices for $53.18](https://medium.com/@robleathern/block-ads-on-all-home-devices-for-53-18-a5f1ec139693#.gj1xpgr5d) -- [Pi-Hole for Ubuntu 14.04](http://www.boyter.org/2015/12/pi-hole-ubuntu-14-04/) -- [MacObserver Podcast 585](https://www.macobserver.com/tmo/podcast/macgeekgab-585) -- [The Defrag Show: Endoscope USB Camera, The Final [HoloLens] Vote, Adblock Pi and more](https://channel9.msdn.com/Shows/The-Defrag-Show/Defrag-Endoscope-USB-Camera-The-Final-HoloLens-Vote-Adblock-Pi-and-more?WT.mc_id=dlvr_twitter_ch9#time=20m39s) -- [Adafruit: Pi-hole is a black hole for internet ads](https://blog.adafruit.com/2016/03/04/pi-hole-is-a-black-hole-for-internet-ads-piday-raspberrypi-raspberry_pi/) -- [Digital Trends: 5 Fun, Easy Projects You Can Try With a $35 Raspberry Pi](https://youtu.be/QwrKlyC2kdM?t=1m42s) -- [Adafruit: Raspberry Pi Quick Look at Pi Hole ad blocking server with Tony D](https://www.youtube.com/watch?v=eg4u2j1HYlI) -- [Devacron: OrangePi Zero as an Ad-Block server with Pi-Hole](http://www.devacron.com/orangepi-zero-as-an-ad-block-server-with-pi-hole/) -- [Linux Pro: The Hole Truth](http://www.linuxpromagazine.com/Issues/2017/200/The-sysadmin-s-daily-grind-Pi-hole) -- [CryptoAUSTRALIA: How We Tried 5 Privacy Focused Raspberry Pi Projects](https://blog.cryptoaustralia.org.au/2017/10/05/5-privacy-focused-raspberry-pi-projects/) -- [CryptoAUSTRALIA: Pi-hole Workshop](https://blog.cryptoaustralia.org.au/2017/11/02/pi-hole-network-wide-ad-blocker/) -- [Know How 355: Killing ads with a Raspberry Pi-Hole!](https://www.twit.tv/shows/know-how/episodes/355) +- [Lifehacker: Turn A Raspberry Pi Into An Ad Blocker With A Single Command](https://www.lifehacker.com.au/2015/02/turn-a-raspberry-pi-into-an-ad-blocker-with-a-single-command/) (Feburary, 2015) +- [MakeUseOf: Adblock Everywhere: The Raspberry Pi-Hole Way](http://www.makeuseof.com/tag/adblock-everywhere-raspberry-pi-hole-way/) (March, 2015) +- [Catchpoint: Ad-Blocking on Apple iOS9: Valuing the End User Experience](http://blog.catchpoint.com/2015/09/14/ad-blocking-apple/) (September, 2015) +- [Security Now Netcast: Pi-hole](https://www.youtube.com/watch?v=p7-osq_y8i8&t=100m26s) (October, 2015) +- [TekThing: Raspberry Pi-Hole Makes Ads Disappear!](https://youtu.be/8Co59HU2gY0?t=2m) (December, 2015) +- [Foolish Tech Show](https://youtu.be/bYyena0I9yc?t=2m4s) (December, 2015) +- [Block Ads on All Home Devices for $53.18](https://medium.com/@robleathern/block-ads-on-all-home-devices-for-53-18-a5f1ec139693#.gj1xpgr5d) (December, 2015) +- [Pi-Hole for Ubuntu 14.04](http://www.boyter.org/2015/12/pi-hole-ubuntu-14-04/) (December, 2015) +- [MacObserver Podcast 585](https://www.macobserver.com/tmo/podcast/macgeekgab-585) (December, 2015) +- [The Defrag Show: Endoscope USB Camera, The Final [HoloLens] Vote, Adblock Pi and more](https://channel9.msdn.com/Shows/The-Defrag-Show/Defrag-Endoscope-USB-Camera-The-Final-HoloLens-Vote-Adblock-Pi-and-more?WT.mc_id=dlvr_twitter_ch9#time=20m39s) (January, 2016) +- [Adafruit: Pi-hole is a black hole for internet ads](https://blog.adafruit.com/2016/03/04/pi-hole-is-a-black-hole-for-internet-ads-piday-raspberrypi-raspberry_pi/) (March, 2016) +- [Digital Trends: 5 Fun, Easy Projects You Can Try With a $35 Raspberry Pi](https://youtu.be/QwrKlyC2kdM?t=1m42s) (March, 2016) +- [Adafruit: Raspberry Pi Quick Look at Pi Hole ad blocking server with Tony D](https://www.youtube.com/watch?v=eg4u2j1HYlI) (June, 2016) +- [Devacron: OrangePi Zero as an Ad-Block server with Pi-Hole](http://www.devacron.com/orangepi-zero-as-an-ad-block-server-with-pi-hole/) (December, 2016) +- [Linux Pro: The Hole Truth](http://www.linuxpromagazine.com/Issues/2017/200/The-sysadmin-s-daily-grind-Pi-hole) (July, 2017) +- [Adafruit: installing Pi-hole on a Pi Zero W](https://learn.adafruit.com/pi-hole-ad-blocker-with-pi-zero-w/install-pi-hole) (August, 2017) +- [CryptoAUSTRALIA: How We Tried 5 Privacy Focused Raspberry Pi Projects](https://blog.cryptoaustralia.org.au/2017/10/05/5-privacy-focused-raspberry-pi-projects/) (October, 2017) +- [CryptoAUSTRALIA: Pi-hole Workshop](https://blog.cryptoaustralia.org.au/2017/11/02/pi-hole-network-wide-ad-blocker/) (November, 2017) +- [Know How 355: Killing ads with a Raspberry Pi-Hole!](https://www.twit.tv/shows/know-how/episodes/355) (November, 2017) +- [Hobohouse: Block Advertising on your Network with Pi-hole and Raspberry Pi](https://hobo.house/2018/02/27/block-advertising-with-pi-hole-and-raspberry-pi/) (March, 2018) +- [Scott Helme: Securing DNS across all of my devices with Pi-Hole + DNS-over-HTTPS + 1.1.1.1](https://scotthelme.co.uk/securing-dns-across-all-of-my-devices-with-pihole-dns-over-https-1-1-1-1/) (April, 2018) +- [Scott Helme: Catching and dealing with naughty devices on my home network](https://scotthelme.co.uk/catching-naughty-devices-on-my-home-network/) (April, 2018) +- [Bloomberg Business Week: Brotherhood of the Ad blockers](https://www.bloomberg.com/news/features/2018-05-10/inside-the-brotherhood-of-pi-hole-ad-blockers) (May, 2018) +- [Software Engineering Daily: Interview with the creator of Pi-hole](https://softwareengineeringdaily.com/2018/05/29/pi-hole-ad-blocker-hardware-with-jacob-salmela/) (May, 2018) +- [Raspberry Pi: Block ads at home using Pi-hole and a Raspberry Pi](https://www.raspberrypi.org/blog/pi-hole-raspberry-pi/) (July, 2018) +- [Troy Hunt: Mmm... Pi-hole...](https://www.troyhunt.com/mmm-pi-hole/) (September, 2018) +- [PEBKAK Podcast: Interview With Jacob Salmela](https://www.jerseystudios.net/2018/10/11/150-pi-hole/) (October, 2018) ----- diff --git a/advanced/01-pihole.conf b/advanced/01-pihole.conf index 85d260b2..3f4e4bc5 100644 --- a/advanced/01-pihole.conf +++ b/advanced/01-pihole.conf @@ -1,13 +1,11 @@ # Pi-hole: A black hole for Internet advertisements -# (c) 2015, 2016 by Jacob Salmela -# Network-wide ad blocking via your Raspberry Pi -# http://pi-hole.net -# dnsmasq config for Pi-hole +# (c) 2017 Pi-hole, LLC (https://pi-hole.net) +# Network-wide ad blocking via your own hardware. # -# Pi-hole is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 2 of the License, or -# (at your option) any later version. +# Dnsmasq config for Pi-hole's FTLDNS +# +# This file is copyright under the latest version of the EUPL. +# Please see LICENSE file for your rights under this license. ############################################################################### # FILE AUTOMATICALLY POPULATED BY PI-HOLE INSTALL/UPDATE PROCEDURE. # @@ -16,14 +14,17 @@ # IF YOU WISH TO CHANGE THE UPSTREAM SERVERS, CHANGE THEM IN: # # /etc/pihole/setupVars.conf # # # -# ANY OTHER CHANGES SHOULD BE MADE IN A SEPERATE CONFIG FILE # -# OR IN /etc/dnsmasq.conf # +# ANY OTHER CHANGES SHOULD BE MADE IN A SEPARATE CONFIG FILE # +# WITHIN /etc/dnsmasq.d/yourname.conf # ############################################################################### addn-hosts=/etc/pihole/gravity.list addn-hosts=/etc/pihole/black.list addn-hosts=/etc/pihole/local.list +user=pihole +group=pihole + domain-needed localise-queries @@ -39,7 +40,7 @@ interface=@INT@ cache-size=10000 -log-queries=extra +log-queries log-facility=/var/log/pihole.log local-ttl=2 diff --git a/advanced/Scripts/chronometer.sh b/advanced/Scripts/chronometer.sh index 046a98c4..7c2d8b52 100755 --- a/advanced/Scripts/chronometer.sh +++ b/advanced/Scripts/chronometer.sh @@ -8,6 +8,7 @@ # # This file is copyright under the latest version of the EUPL. # Please see LICENSE file for your rights under this license. +LC_ALL=C LC_NUMERIC=C # Retrieve stats from FTL engine @@ -243,7 +244,7 @@ get_sys_stats() { disk_total="${disk_raw[1]}" disk_perc="${disk_raw[2]}" - net_gateway=$(route -n | awk '$4 == "UG" {print $2;exit}') + net_gateway=$(ip route | grep default | cut -d ' ' -f 3 | head -n 1) # Get DHCP stats, if feature is enabled if [[ "$DHCP_ACTIVE" == "true" ]]; then @@ -478,7 +479,7 @@ chronoFunc() { ${COL_LIGHT_RED}Press Ctrl-C to exit${COL_NC} ${COL_DARK_GRAY}$scr_line_str${COL_NC}" else - echo -e "|¯¯¯(¯)_|¯|_ ___|¯|___$phc_ver_str| ¯_/¯|_| ' \\/ _ \\ / -_)$lte_ver_str|_| |_| |_||_\\___/_\\___|$ftl_ver_str ${COL_DARK_GRAY}$scr_line_str${COL_NC}" + echo -e "|¯¯¯(¯)_|¯|_ ___|¯|___$phc_ver_str\\n| ¯_/¯|_| ' \\/ _ \\ / -_)$lte_ver_str\\n|_| |_| |_||_\\___/_\\___|$ftl_ver_str\\n ${COL_DARK_GRAY}$scr_line_str${COL_NC}" fi printFunc " Hostname: " "$sys_name" "$host_info" diff --git a/advanced/Scripts/list.sh b/advanced/Scripts/list.sh index 87e4ab44..c1d95aae 100755 --- a/advanced/Scripts/list.sh +++ b/advanced/Scripts/list.sh @@ -13,6 +13,7 @@ basename=pihole piholeDir=/etc/"${basename}" whitelist="${piholeDir}"/whitelist.txt blacklist="${piholeDir}"/blacklist.txt + readonly regexlist="/etc/pihole/regex.list" reload=false addmode=true diff --git a/advanced/Scripts/piholeDebug.sh b/advanced/Scripts/piholeDebug.sh index b8377f73..cb66f97c 100755 --- a/advanced/Scripts/piholeDebug.sh +++ b/advanced/Scripts/piholeDebug.sh @@ -119,7 +119,7 @@ PIHOLE_WEB_SERVER_ERROR_LOG_FILE="${WEB_SERVER_LOG_DIRECTORY}/error.log" #SUPPORTED_OS=("Raspbian" "Ubuntu" "Fedora" "Debian" "CentOS") # Store Pi-hole's processes in an array for easy use and parsing -PIHOLE_PROCESSES=( "dnsmasq" "lighttpd" "pihole-FTL" ) +PIHOLE_PROCESSES=( "lighttpd" "pihole-FTL" ) # Store the required directories in an array so it can be parsed through #REQUIRED_DIRECTORIES=("${CORE_GIT_DIRECTORY}" @@ -337,8 +337,6 @@ get_program_version() { case "${program_name}" in "lighttpd") program_version="$(${program_name} -v |& head -n1 | cut -d '/' -f2 | cut -d ' ' -f1)" ;; - "dnsmasq") program_version="$(${program_name} -v |& head -n1 | awk '{print $3}')" - ;; "php") program_version="$(${program_name} -v |& head -n1 | cut -d '-' -f1 | cut -d ' ' -f2)" ;; # If a match is not found, show an error @@ -358,7 +356,6 @@ get_program_version() { # and their versions, using the functions above. check_critical_program_versions() { # Use the function created earlier and bundle them into one function that checks all the version numbers - get_program_version "dnsmasq" get_program_version "lighttpd" get_program_version "php" } @@ -640,11 +637,12 @@ ping_internet() { compare_port_to_service_assigned() { local service_name="${1}" # The programs we use may change at some point, so they are in a varible here - local resolver="dnsmasq" + local resolver="pihole-FTL" local web_server="lighttpd" local ftl="pihole-FTL" + + # If the service is a Pi-hole service, highlight it in green if [[ "${service_name}" == "${resolver}" ]] || [[ "${service_name}" == "${web_server}" ]] || [[ "${service_name}" == "${ftl}" ]]; then - # if port 53 is dnsmasq, show it in green as it's standard log_write "[${COL_GREEN}${port_number}${COL_NC}] is in use by ${COL_GREEN}${service_name}${COL_NC}" # Otherwise, else @@ -657,7 +655,7 @@ check_required_ports() { echo_current_diagnostic "Ports in use" # Since Pi-hole needs 53, 80, and 4711, check what they are being used by # so we can detect any issues - local resolver="dnsmasq" + local resolver="pihole-FTL" local web_server="lighttpd" local ftl="pihole-FTL" # Create an array for these ports in use @@ -682,7 +680,7 @@ check_required_ports() { continue fi # Use a case statement to determine if the right services are using the right ports - case "${port_number}" in + case "$(echo "$port_number" | rev | cut -d: -f1 | rev)" in 53) compare_port_to_service_assigned "${resolver}" ;; 80) compare_port_to_service_assigned "${web_server}" @@ -836,9 +834,13 @@ process_status(){ local status_of_process status_of_process=$(systemctl is-active "${i}") else - # Otherwise, use the service command + # Otherwise, use the service command and mock the output of `systemctl is-active` local status_of_process - status_of_process=$(service "${i}" status | awk '/Active:/ {print $2}') &> /dev/null + if service "${i}" status | grep -E 'is\srunning' &> /dev/null; then + status_of_process="active" + else + status_of_process="inactive" + fi fi # and print it out to the user if [[ "${status_of_process}" == "active" ]]; then @@ -907,7 +909,7 @@ parse_file() { #shellcheck disable=SC2016 IFS=$'\r\n' command eval 'file_info=( $(cat "${filename}") )' else - read -a file_info <<< $filename + read -r -a file_info <<< "$filename" fi # Set a named variable for better readability local file_lines diff --git a/advanced/Scripts/piholeLogFlush.sh b/advanced/Scripts/piholeLogFlush.sh index 4847282f..561fbce7 100755 --- a/advanced/Scripts/piholeLogFlush.sh +++ b/advanced/Scripts/piholeLogFlush.sh @@ -58,6 +58,8 @@ else # Delete most recent 24 hours from FTL's database, leave even older data intact (don't wipe out all history) deleted=$(sqlite3 "${DBFILE}" "DELETE FROM queries WHERE timestamp >= strftime('%s','now')-86400; select changes() from queries limit 1") + # Restart pihole-FTL to force reloading history + sudo pihole restartdns fi if [[ "$@" != *"quiet"* ]]; then diff --git a/advanced/Scripts/updatecheck.sh b/advanced/Scripts/updatecheck.sh index 767c5461..257c1929 100755 --- a/advanced/Scripts/updatecheck.sh +++ b/advanced/Scripts/updatecheck.sh @@ -37,30 +37,55 @@ function get_local_version() { git describe --long --dirty --tags || return 1 } +# Source the setupvars config file +# shellcheck disable=SC1091 +. /etc/pihole/setupVars.conf + if [[ "$2" == "remote" ]]; then if [[ "$3" == "reboot" ]]; then sleep 30 fi - GITHUB_CORE_VERSION="$(json_extract tag_name "$(curl -q 'https://api.github.com/repos/pi-hole/pi-hole/releases/latest' 2> /dev/null)")" - GITHUB_WEB_VERSION="$(json_extract tag_name "$(curl -q 'https://api.github.com/repos/pi-hole/AdminLTE/releases/latest' 2> /dev/null)")" - GITHUB_FTL_VERSION="$(json_extract tag_name "$(curl -q 'https://api.github.com/repos/pi-hole/FTL/releases/latest' 2> /dev/null)")" + GITHUB_VERSION_FILE="/etc/pihole/GitHubVersions" + + GITHUB_CORE_VERSION="$(json_extract tag_name "$(curl -s 'https://api.github.com/repos/pi-hole/pi-hole/releases/latest' 2> /dev/null)")" + echo -n "${GITHUB_CORE_VERSION}" > "${GITHUB_VERSION_FILE}" + + if [[ "${INSTALL_WEB_INTERFACE}" == true ]]; then + GITHUB_WEB_VERSION="$(json_extract tag_name "$(curl -s 'https://api.github.com/repos/pi-hole/AdminLTE/releases/latest' 2> /dev/null)")" + echo -n " ${GITHUB_WEB_VERSION}" >> "${GITHUB_VERSION_FILE}" + fi - echo -n "${GITHUB_CORE_VERSION} ${GITHUB_WEB_VERSION} ${GITHUB_FTL_VERSION}" > "/etc/pihole/GitHubVersions" + GITHUB_FTL_VERSION="$(json_extract tag_name "$(curl -s 'https://api.github.com/repos/pi-hole/FTL/releases/latest' 2> /dev/null)")" + echo -n " ${GITHUB_FTL_VERSION}" >> "${GITHUB_VERSION_FILE}" else + LOCAL_BRANCH_FILE="/etc/pihole/localbranches" + CORE_BRANCH="$(get_local_branch /etc/.pihole)" - WEB_BRANCH="$(get_local_branch /var/www/html/admin)" + echo -n "${CORE_BRANCH}" > "${LOCAL_BRANCH_FILE}" + + if [[ "${INSTALL_WEB_INTERFACE}" == true ]]; then + WEB_BRANCH="$(get_local_branch /var/www/html/admin)" + echo -n " ${WEB_BRANCH}" >> "${LOCAL_BRANCH_FILE}" + fi + FTL_BRANCH="$(pihole-FTL branch)" + echo -n " ${FTL_BRANCH}" >> "${LOCAL_BRANCH_FILE}" - echo -n "${CORE_BRANCH} ${WEB_BRANCH} ${FTL_BRANCH}" > "/etc/pihole/localbranches" + LOCAL_VERSION_FILE="/etc/pihole/localversions" CORE_VERSION="$(get_local_version /etc/.pihole)" - WEB_VERSION="$(get_local_version /var/www/html/admin)" - FTL_VERSION="$(pihole-FTL version)" + echo -n "${CORE_VERSION}" > "${LOCAL_VERSION_FILE}" - echo -n "${CORE_VERSION} ${WEB_VERSION} ${FTL_VERSION}" > "/etc/pihole/localversions" + if [[ "${INSTALL_WEB_INTERFACE}" == true ]]; then + WEB_VERSION="$(get_local_version /var/www/html/admin)" + echo -n " ${WEB_VERSION}" >> "${LOCAL_VERSION_FILE}" + fi + + FTL_VERSION="$(pihole-FTL version)" + echo -n " ${FTL_VERSION}" >> "${LOCAL_VERSION_FILE}" fi diff --git a/advanced/Scripts/webpage.sh b/advanced/Scripts/webpage.sh index c3dede05..0b5c351e 100755 --- a/advanced/Scripts/webpage.sh +++ b/advanced/Scripts/webpage.sh @@ -110,7 +110,7 @@ SetWebPassword() { # Prevents a bug if the user presses Ctrl+C and it continues to hide the text typed. # So we reset the terminal via stty if the user does press Ctrl+C trap '{ echo -e "\nNo password will be set" ; stty sane ; exit 1; }' INT - read -s -p "Enter New Password (Blank for no password): " PASSWORD + read -s -r -p "Enter New Password (Blank for no password): " PASSWORD echo "" if [ "${PASSWORD}" == "" ]; then @@ -119,12 +119,13 @@ SetWebPassword() { exit 0 fi - read -s -p "Confirm Password: " CONFIRM + read -s -r -p "Confirm Password: " CONFIRM echo "" fi if [ "${PASSWORD}" == "${CONFIRM}" ] ; then - hash=$(HashPassword "${PASSWORD}") + # We do not wrap this in brackets, otherwise BASH will expand any appropriate syntax + hash=$(HashPassword "$PASSWORD") # Save hash to file change_setting "WEBPASSWORD" "${hash}" echo -e " ${TICK} New password set" @@ -525,14 +526,24 @@ Teleporter() { php /var/www/html/admin/scripts/pi-hole/php/teleporter.php > "pi-hole-teleporter_${datetimestamp}.zip" } -audit() +addAudit() { - echo "${args[2]}" >> /etc/pihole/auditlog.list + shift # skip "-a" + shift # skip "audit" + for var in "$@" + do + echo "${var}" >> /etc/pihole/auditlog.list + done +} + +clearAudit() +{ + echo -n "" > /etc/pihole/auditlog.list } SetPrivacyLevel() { - # Set privacy level. Minimum is 0, maximum is 3 - if [ "${args[2]}" -ge 0 ] && [ "${args[2]}" -le 3 ]; then + # Set privacy level. Minimum is 0, maximum is 4 + if [ "${args[2]}" -ge 0 ] && [ "${args[2]}" -le 4 ]; then changeFTLsetting "PRIVACYLEVEL" "${args[2]}" fi } @@ -565,7 +576,8 @@ main() { "-i" | "interface" ) SetListeningMode "$@";; "-t" | "teleporter" ) Teleporter;; "adlist" ) CustomizeAdLists;; - "audit" ) audit;; + "audit" ) addAudit "$@";; + "clearaudit" ) clearAudit;; "-l" | "privacylevel" ) SetPrivacyLevel;; * ) helpFunc;; esac diff --git a/advanced/Templates/pihole-FTL.conf b/advanced/Templates/pihole-FTL.conf deleted file mode 100644 index 03f42932..00000000 --- a/advanced/Templates/pihole-FTL.conf +++ /dev/null @@ -1,84 +0,0 @@ -### This file contains parameters for FTL behavior. -### At install, all parameters are commented out. The user can select desired options. -### Options shown are the default configuration. No modification is needed for most -### installations. -### Visit https://docs.pi-hole.net/ftldns/configfile/ for more detailed parameter explanations - -## Socket Listening -## Listen only for local socket connections or permit all connections -## Options: localonly, all -#SOCKET_LISTENING=localonly - -## Query Display -## Display all queries? Set to no to hide query display -## Options: yes, no -#QUERY_DISPLAY=yes - -## AAA Query Analysis -## Allow FTL to analyze AAAA queries from pihole.log? -## Options: yes, no -#AAAA_QUERY_ANALYSIS=yes - -## Resolve IPv6 -## Should FTL try to resolve IPv6 addresses to host names? -## Options: yes, no -#RESOLVE_IPV6=yes - -## Resolve IPv4 -## Should FTL try to resolve IPv4 addresses to host names? -## Options: yes, no -#RESOLVE_IPV4=yes - -## Max Database Days -## How long should queries be stored in the database (days)? -## Setting this to 0 disables the database -## See: https://docs.pi-hole.net/ftldns/database/ -## Options: number of days -#MAXDBDAYS=365 - -## Database Interval -## How often do we store queries in FTL's database (minutes)? -## See: https://docs.pi-hole.net/ftldns/database/ -## Options: number of minutes -#DBINTERVAL=1.0 - -## Database File -## Specify path and filename of FTL's SQLite3 long-term database. -## Setting this to DBFILE= disables the database altogether -## See: https://docs.pi-hole.net/ftldns/database/ -## Option: path to db file -#DBFILE=/etc/pihole/pihole-FTL.db - -## Max Log Age -## Up to how many hours of queries should be imported from the database and logs (hours)? -## Maximum is 744 (31 days) -## Options: number of days -#MAXLOGAGE=24.0 - -## FTL Port -## On which port should FTL be listening? -## Options: tcp port -#FTLPORT=4711 - -## Privacy Level -## Which privacy level is used? -## See: https://docs.pi-hole.net/ftldns/privacylevels/ -## Options: 0, 1, 2, 3 -#PRIVACYLEVEL=0 - -## Ignore Localhost -## Should FTL ignore queries coming from the local machine? -## Options: yes, no -#IGNORE_LOCALHOST=no - -## Blocking Mode -## How should FTL reply to blocked queries? -## See: https://docs.pi-hole.net/ftldns/blockingmode/ -## Options: NULL, IP-AAAA-NODATA, IP, NXDOMAIN -#BLOCKINGMODE=NULL - -## Regex Debug Mode -## Controls if FTLDNS should print extended details about regex matching into pihole-FTL.log. -## See: https://docs.pi-hole.net/ftldns/regex/overview/ -## Options: true, false -#REGEX_DEBUGMODE=false diff --git a/advanced/Templates/pihole-FTL.service b/advanced/Templates/pihole-FTL.service index ecc7a52a..d19e2bd5 100644 --- a/advanced/Templates/pihole-FTL.service +++ b/advanced/Templates/pihole-FTL.service @@ -26,17 +26,26 @@ start() { if is_running; then echo "pihole-FTL is already running" else - touch /var/log/pihole-FTL.log /run/pihole-FTL.pid /run/pihole-FTL.port /var/log/pihole.log + # Touch files to ensure they exist (create if non-existing, preserve if existing) + touch /var/log/pihole-FTL.log /var/log/pihole.log + touch /run/pihole-FTL.pid /run/pihole-FTL.port + touch /etc/pihole/dhcp.leases mkdir -p /var/run/pihole mkdir -p /var/log/pihole chown pihole:pihole /var/run/pihole /var/log/pihole rm /var/run/pihole/FTL.sock 2> /dev/null - chown pihole:pihole /var/log/pihole-FTL.log /run/pihole-FTL.pid /run/pihole-FTL.port - chown pihole:pihole /etc/pihole /etc/pihole/dhcp.leases /var/log/pihole.log + # Ensure that permissions are set so that pihole-FTL can edit all necessary files + chown pihole:pihole /run/pihole-FTL.pid /run/pihole-FTL.port + chown pihole:pihole /etc/pihole /etc/pihole/dhcp.leases 2> /dev/null + chown pihole:pihole /var/log/pihole-FTL.log /var/log/pihole.log chmod 0644 /var/log/pihole-FTL.log /run/pihole-FTL.pid /run/pihole-FTL.port /var/log/pihole.log - setcap CAP_NET_BIND_SERVICE,CAP_NET_RAW,CAP_NET_ADMIN+eip "$(which pihole-FTL)" echo "nameserver 127.0.0.1" | /sbin/resolvconf -a lo.piholeFTL - su -s /bin/sh -c "/usr/bin/pihole-FTL" "$FTLUSER" + if setcap CAP_NET_BIND_SERVICE,CAP_NET_RAW,CAP_NET_ADMIN+eip "$(which pihole-FTL)"; then + su -s /bin/sh -c "/usr/bin/pihole-FTL" "$FTLUSER" + else + echo "Warning: Starting pihole-FTL as root because setting capabilities is not supported on this system" + pihole-FTL + fi echo fi } @@ -78,7 +87,7 @@ status() { echo "[ ] pihole-FTL is not running" exit 1 fi -} +} ### main logic ### diff --git a/advanced/Templates/pihole.cron b/advanced/Templates/pihole.cron index 02a63b74..8dc98721 100644 --- a/advanced/Templates/pihole.cron +++ b/advanced/Templates/pihole.cron @@ -16,7 +16,9 @@ # Pi-hole: Update the ad sources once a week on Sunday at a random time in the # early morning. Download any updates from the adlists -59 1 * * 7 root PATH="$PATH:/usr/local/bin/" pihole updateGravity +# Squash output to log, then splat the log to stdout on error to allow for +# standard crontab job error handling. +59 1 * * 7 root PATH="$PATH:/usr/local/bin/" pihole updateGravity >/var/log/pihole_updateGravity.log || cat /var/log/pihole_updateGravity.log # Pi-hole: Flush the log daily at 00:00 # The flush script will use logrotate if available diff --git a/advanced/index.php b/advanced/index.php index cad59ec7..49eb0f45 100644 --- a/advanced/index.php +++ b/advanced/index.php @@ -8,6 +8,8 @@ // Sanitise HTTP_HOST output $serverName = htmlspecialchars($_SERVER["HTTP_HOST"]); +// Remove external ipv6 brackets if any +$serverName = preg_replace('/^\[(.*)\]$/', '${1}', $serverName); if (!is_file("/etc/pihole/setupVars.conf")) die("[ERROR] File not found: /etc/pihole/setupVars.conf"); diff --git a/advanced/lighttpd.conf.debian b/advanced/lighttpd.conf.debian index b5bece72..d9c4a110 100644 --- a/advanced/lighttpd.conf.debian +++ b/advanced/lighttpd.conf.debian @@ -72,4 +72,5 @@ $HTTP["url"] =~ "^/admin/\.(.*)" { } # 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" diff --git a/advanced/lighttpd.conf.fedora b/advanced/lighttpd.conf.fedora index 43d94d84..27bc33cc 100644 --- a/advanced/lighttpd.conf.fedora +++ b/advanced/lighttpd.conf.fedora @@ -90,4 +90,5 @@ $HTTP["url"] =~ "^/admin/\.(.*)" { } # 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" diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index 10e43b6c..4cb2a467 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -38,14 +38,14 @@ lighttpdConfig=/etc/lighttpd/lighttpd.conf # This is a file used for the colorized output coltable=/opt/pihole/COL_TABLE -# We store several other folders and +# We store several other directories and webInterfaceGitUrl="https://github.com/pi-hole/AdminLTE.git" webInterfaceDir="/var/www/html/admin" piholeGitUrl="https://github.com/pi-hole/pi-hole.git" PI_HOLE_LOCAL_REPO="/etc/.pihole" # These are the names of pi-holes files, stored in an array PI_HOLE_FILES=(chronometer list piholeDebug piholeLogFlush setupLCD update version gravity uninstall webpage) -# This folder is where the Pi-hole scripts will be installed +# This directory is where the Pi-hole scripts will be installed PI_HOLE_INSTALL_DIR="/opt/pihole" PI_HOLE_CONFIG_DIR="/etc/pihole" useUpdateVars=false @@ -59,6 +59,7 @@ IPV6_ADDRESS="" # By default, query logging is enabled and the dashboard is set to be installed QUERY_LOGGING=true INSTALL_WEB_INTERFACE=true +PRIVACY_LEVEL=0 if [ -z "${USER}" ]; then USER="$(id -un)" @@ -66,9 +67,11 @@ fi # Find the rows and columns will default to 80x24 if it can not be detected -screen_size=$(stty size 2>/dev/null || echo 24 80) -rows=$(echo "${screen_size}" | awk '{print $1}') -columns=$(echo "${screen_size}" | awk '{print $2}') +screen_size=$(stty size || printf '%d %d' 24 80) +# Set rows variable to contain first number +printf -v rows '%d' "${screen_size%% *}" +# Set columns variable to contain second number +printf -v columns '%d' "${screen_size##* }" # Divide by two so the dialogs take up half of the screen, which looks nice. r=$(( rows / 2 )) @@ -139,10 +142,19 @@ show_ascii_berry() { " } +is_command() { + # Checks for existence of string passed in as only function argument. + # Exit value of 0 when exists, 1 if not exists. Value is the result + # of the `command` shell built-in call. + local check_command="$1" + + command -v "${check_command}" >/dev/null 2>&1 +} + # Compatibility distro_check() { # If apt-get is installed, then we know it's part of the Debian family -if command -v apt-get &> /dev/null; then +if is_command apt-get ; then # Set some global variables here # We don't set them earlier since the family might be Red Hat, so these values would be different PKG_MANAGER="apt-get" @@ -163,13 +175,12 @@ if command -v apt-get &> /dev/null; then iproute_pkg="iproute" fi # Check for and determine version number (major and minor) of current php install - if command -v php &> /dev/null; then - phpInsVersion="$(php -v | head -n1 | grep -Po '(?<=PHP )[^ ]+')" - echo -e " ${INFO} Existing PHP installation detected : PHP version $phpInsVersion" - phpInsMajor="$(echo "$phpInsVersion" | cut -d\. -f1)" - phpInsMinor="$(echo "$phpInsVersion" | cut -d\. -f2)" + if is_command php ; then + printf " %b Existing PHP installation detected : PHP version %s\\n" "${INFO}" "$(php <<< "")" + printf -v phpInsMajor "%d" "$(php <<< "")" + printf -v phpInsMinor "%d" "$(php <<< "")" # Is installed php version 7.0 or greater - if [ "$(echo "$phpInsMajor.$phpInsMinor < 7.0" | bc )" == 0 ]; then + if [ "${phpInsMajor}" -ge 7 ]; then phpInsNewer=true fi fi @@ -225,9 +236,9 @@ if command -v apt-get &> /dev/null; then } # If apt-get is not found, check for rpm to see if it's a Red Hat family OS -elif command -v rpm &> /dev/null; then +elif is_command rpm ; then # Then check if dnf or yum is the package manager - if command -v dnf &> /dev/null; then + if is_command dnf ; then PKG_MANAGER="dnf" else PKG_MANAGER="yum" @@ -237,28 +248,28 @@ elif command -v rpm &> /dev/null; then UPDATE_PKG_CACHE=":" PKG_INSTALL=(${PKG_MANAGER} install -y) PKG_COUNT="${PKG_MANAGER} check-update | egrep '(.i686|.x86|.noarch|.arm|.src)' | wc -l" - INSTALLER_DEPS=(dialog git iproute net-tools newt procps-ng which) + INSTALLER_DEPS=(dialog git iproute newt procps-ng which) PIHOLE_DEPS=(bc bind-utils cronie curl findutils nmap-ncat sudo unzip wget libidn2 psmisc) PIHOLE_WEB_DEPS=(lighttpd lighttpd-fastcgi php-common php-cli php-pdo) LIGHTTPD_USER="lighttpd" LIGHTTPD_GROUP="lighttpd" LIGHTTPD_CFG="lighttpd.conf.fedora" # If the host OS is Fedora, - if grep -qi 'fedora' /etc/redhat-release; then + if grep -qiE 'fedora|fedberry' /etc/redhat-release; then # all required packages should be available by default with the latest fedora release # ensure 'php-json' is installed on Fedora (installed as dependency on CentOS7 + Remi repository) PIHOLE_WEB_DEPS+=('php-json') # or if host OS is CentOS, - elif grep -qi 'centos' /etc/redhat-release; then + elif grep -qiE 'centos|scientific' /etc/redhat-release; then # Pi-Hole currently supports CentOS 7+ with PHP7+ SUPPORTED_CENTOS_VERSION=7 SUPPORTED_CENTOS_PHP_VERSION=7 # Check current CentOS major release version - CURRENT_CENTOS_VERSION=$(rpm -q --queryformat '%{VERSION}' centos-release) + CURRENT_CENTOS_VERSION=$(grep -oP '(?<= )[0-9]+(?=\.)' /etc/redhat-release) # Check if CentOS version is supported if [[ $CURRENT_CENTOS_VERSION -lt $SUPPORTED_CENTOS_VERSION ]]; then - echo -e " ${CROSS} CentOS $CURRENT_CENTOS_VERSION is not suported." - echo -e " Please update to CentOS release $SUPPORTED_CENTOS_VERSION or later" + printf " %b CentOS %s is not supported.\\n" "${CROSS}" "${CURRENT_CENTOS_VERSION}" + printf " Please update to CentOS release %s or later.\\n" "${SUPPORTED_CENTOS_VERSION}" # exit the installer exit fi @@ -266,9 +277,9 @@ elif command -v rpm &> /dev/null; then EPEL_PKG="epel-release" rpm -q ${EPEL_PKG} &> /dev/null || rc=$? if [[ $rc -ne 0 ]]; then - echo -e " ${INFO} Enabling EPEL package repository (https://fedoraproject.org/wiki/EPEL)" + printf " %b Enabling EPEL package repository (https://fedoraproject.org/wiki/EPEL)\\n" "${INFO}" "${PKG_INSTALL[@]}" ${EPEL_PKG} &> /dev/null - echo -e " ${TICK} Installed ${EPEL_PKG}" + printf " %b Installed %s\\n" "${TICK}" "${EPEL_PKG}" fi # The default php on CentOS 7.x is 5.4 which is EOL @@ -285,42 +296,45 @@ elif command -v rpm &> /dev/null; then # The PHP version available via default repositories is older than version 7 if ! whiptail --defaultno --title "PHP 7 Update (recommended)" --yesno "PHP 7.x is recommended for both security and language features.\\nWould you like to install PHP7 via Remi's RPM repository?\\n\\nSee: https://rpms.remirepo.net for more information" ${r} ${c}; then # User decided to NOT update PHP from REMI, attempt to install the default available PHP version - echo -e " ${INFO} User opt-out of PHP 7 upgrade on CentOS. Deprecated PHP may be in use." + printf " %b User opt-out of PHP 7 upgrade on CentOS. Deprecated PHP may be in use.\\n" "${INFO}" : # continue with unsupported php version else - echo -e " ${INFO} Enabling Remi's RPM repository (https://rpms.remirepo.net)" + printf " %b Enabling Remi's RPM repository (https://rpms.remirepo.net)\\n" "${INFO}" "${PKG_INSTALL[@]}" "https://rpms.remirepo.net/enterprise/${REMI_PKG}-$(rpm -E '%{rhel}').rpm" &> /dev/null # enable the PHP 7 repository via yum-config-manager (provided by yum-utils) "${PKG_INSTALL[@]}" "yum-utils" &> /dev/null yum-config-manager --enable ${REMI_REPO} &> /dev/null - echo -e " ${TICK} Remi's RPM repository has been enabled for PHP7" + printf " %b Remi's RPM repository has been enabled for PHP7\\n" "${TICK}" # trigger an install/update of PHP to ensure previous version of PHP is updated from REMI if "${PKG_INSTALL[@]}" "php-cli" &> /dev/null; then - echo -e " ${TICK} PHP7 installed/updated via Remi's RPM repository" + printf " %b PHP7 installed/updated via Remi's RPM repository\\n" "${TICK}" else - echo -e " ${CROSS} There was a problem updating to PHP7 via Remi's RPM repository" + printf " %b There was a problem updating to PHP7 via Remi's RPM repository\\n" "${CROSS}" exit 1 fi fi fi fi else - # If not a supported version of Fedora or CentOS, - echo -e " ${CROSS} Unsupported RPM based distribution" - # exit the installer - exit + # Warn user of unsupported version of Fedora or CentOS + if ! whiptail --defaultno --title "Unsupported RPM based distribution" --yesno "Would you like to continue installation on an unsupported RPM based distribution?\\n\\nPlease ensure the following packages have been installed manually:\\n\\n- lighttpd\\n- lighttpd-fastcgi\\n- PHP version 7+" ${r} ${c}; then + printf " %b Aborting installation due to unsupported RPM based distribution\\n" "${CROSS}" + exit # exit the installer + else + printf " %b Continuing installation with unsupported RPM based distribution\\n" "${INFO}" + fi fi -# If neither apt-get or rmp/dnf are found +# If neither apt-get or yum/dnf package managers were found else # it's not an OS we can support, - echo -e " ${CROSS} OS distribution not supported" + printf " %b OS distribution not supported\\n" "${CROSS}" # so exit the installer exit fi } -# A function for checking if a folder is a git repository +# A function for checking if a directory is a git repository is_repo() { # Use a named, local variable instead of the vague $1, which is the first argument passed to this function # These local variables should always be lowercase @@ -335,7 +349,7 @@ is_repo() { if [[ -d "${directory}" ]]; then # move into the directory cd "${directory}" - # Use git to check if the folder is a repo + # Use git to check if the directory is a repo # git -C is not used here to support git versions older than 1.8.4 git status --short &> /dev/null || rc=$? # If the command was not successful, @@ -357,7 +371,7 @@ make_repo() { # The message to display when this function is running str="Clone ${remoteRepo} into ${directory}" # Display the message and use the color table to preface the message with an "info" indicator - echo -ne " ${INFO} ${str}..." + printf " %b %s..." "${INFO}" "${str}" # If the directory exists, if [[ -d "${directory}" ]]; then # delete everything in it so git can clone into it @@ -366,7 +380,7 @@ make_repo() { # Clone the repo and return the return code from this command git clone -q --depth 1 "${remoteRepo}" "${directory}" &> /dev/null || return $? # Show a colored message showing it's status - echo -e "${OVER} ${TICK} ${str}" + printf "%b %b %s\\n" "${OVER}" "${TICK}" "${str}" # Always return 0? Not sure this is correct return 0 } @@ -390,14 +404,14 @@ update_repo() { # Move into the directory that was passed as an argument cd "${directory}" &> /dev/null || return 1 # Let the user know what's happening - echo -ne " ${INFO} ${str}..." + printf " %b %s..." "${INFO}" "${str}" # Stash any local commits as they conflict with our working code git stash --all --quiet &> /dev/null || true # Okay for stash failure git clean --quiet --force -d || true # Okay for already clean directory # Pull the latest commits git pull --quiet &> /dev/null || return $? # Show a completion message - echo -e "${OVER} ${TICK} ${str}" + printf "%b %b %s\\n" "${OVER}" "${TICK}" "${str}" # Move back into the original directory cd "${curdir}" &> /dev/null || return 1 return 0 @@ -413,19 +427,19 @@ getGitFiles() { # A local variable containing the message to be displayed local str="Check for existing repository in ${1}" # Show the message - echo -ne " ${INFO} ${str}..." + printf " %b %s..." "${INFO}" "${str}" # Check if the directory is a repository if is_repo "${directory}"; then # Show that we're checking it - echo -e "${OVER} ${TICK} ${str}" + printf "%b %b %s\\n" "${OVER}" "${TICK}" "${str}" # Update the repo, returning an error message on failure - update_repo "${directory}" || { echo -e "\\n ${COL_LIGHT_RED}Error: Could not update local repository. Contact support.${COL_NC}"; exit 1; } + update_repo "${directory}" || { printf "\\n %b: Could not update local repository. Contact support.%b\\n" "${COL_LIGHT_RED}" "${COL_NC}"; exit 1; } # If it's not a .git repo, else # Show an error - echo -e "${OVER} ${CROSS} ${str}" + printf "%b %b %s\\n" "${OVER}" "${CROSS}" "${str}" # Attempt to make the repository, showing an error on failure - make_repo "${directory}" "${remoteRepo}" || { echo -e "\\n ${COL_LIGHT_RED}Error: Could not update local repository. Contact support.${COL_NC}"; exit 1; } + make_repo "${directory}" "${remoteRepo}" || { printf "\\n %bError: Could not update local repository. Contact support.%b\\n" "${COL_LIGHT_RED}" "${COL_NC}"; exit 1; } fi # echo a blank line echo "" @@ -442,30 +456,41 @@ resetRepo() { # Store the message in a variable str="Resetting repository within ${1}..." # Show the message - echo -ne " ${INFO} ${str}" + printf " %b %s..." "${INFO}" "${str}" # Use git to remove the local changes git reset --hard &> /dev/null || return $? # And show the status - echo -e "${OVER} ${TICK} ${str}" + printf "%b %b %s\\n" "${OVER}" "${TICK}" "${str}" # Returning success anyway? return 0 } -# We need to know the IPv4 information so we can effectively setup the DNS server -# Without this information, we won't know where to Pi-hole will be found find_IPv4_information() { + # Detects IPv4 address used for communication to WAN addresses. + # Accepts no arguments, returns no values. + # Named, local variables local route + local IPv4bare + # Find IP used to route to outside world by checking the the route to Google's public DNS server route=$(ip route get 8.8.8.8) - # Use awk to strip out just the interface device as it is used in future commands - IPv4dev=$(awk '{for (i=1; i<=NF; i++) if ($i~/dev/) print $(i+1)}' <<< "${route}") - # Get just the IP address - IPv4bare=$(awk '{print $7}' <<< "${route}") - # Append the CIDR notation to the IP address - IPV4_ADDRESS=$(ip -o -f inet addr show | grep "${IPv4bare}" | awk '{print $4}' | awk 'END {print}') - # Get the default gateway (the way to reach the Internet) - IPv4gw=$(awk '{print $3}' <<< "${route}") + + # Get just the interface IPv4 address + # shellcheck disable=SC2059,SC2086 + # disabled as we intentionally want to split on whitespace and have printf populate + # the variable with just the first field. + printf -v IPv4bare "$(printf ${route#*src })" + # Get the default gateway IPv4 address (the way to reach the Internet) + # shellcheck disable=SC2059,SC2086 + printf -v IPv4gw "$(printf ${route#*via })" + + if ! valid_ip "${IPv4bare}" ; then + IPv4bare="127.0.0.1" + 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}') } # Get available interfaces that are UP @@ -502,36 +527,36 @@ verifyFreeDiskSpace() { # If the existing space is not an integer, if ! [[ "${existing_free_kilobytes}" =~ ^([0-9])+$ ]]; then # show an error that we can't determine the free space - echo -e " ${CROSS} ${str}" - echo -e " ${INFO} Unknown free disk space!" - echo -e " ${INFO} We were unable to determine available free disk space on this system." - echo -e " ${INFO} You may override this check, however, it is not recommended" - echo -e " ${INFO} The option '${COL_LIGHT_RED}--i_do_not_follow_recommendations${COL_NC}' can override this" - echo -e " ${INFO} e.g: curl -L https://install.pi-hole.net | bash /dev/stdin ${COL_LIGHT_RED}