Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/pi-hole/pi-hole.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacob Salmela <jacob.salmela@pi-hole.net>2018-12-09 23:33:58 +0300
committerGitHub <noreply@github.com>2018-12-09 23:33:58 +0300
commitf65f793a0d0d7dbc5882be38858c986f42b8c776 (patch)
treecb921f69dd95c09e5c9070ead83425d64b4d1b1d
parentddbdb51d209fa9eea2451a1bebfaeaef23a9b77b (diff)
parentf7ad4898056d3836c4a8533c73bb08824702142b (diff)
Merge pull request #2496 from pi-hole/release/v4.1v4.1
Release v4.1
-rw-r--r--README.md72
-rw-r--r--advanced/01-pihole.conf23
-rwxr-xr-xadvanced/Scripts/chronometer.sh5
-rwxr-xr-xadvanced/Scripts/list.sh1
-rwxr-xr-xadvanced/Scripts/piholeDebug.sh24
-rwxr-xr-xadvanced/Scripts/piholeLogFlush.sh2
-rwxr-xr-xadvanced/Scripts/updatecheck.sh43
-rwxr-xr-xadvanced/Scripts/webpage.sh28
-rw-r--r--advanced/Templates/pihole-FTL.conf84
-rw-r--r--advanced/Templates/pihole-FTL.service21
-rw-r--r--advanced/Templates/pihole.cron4
-rw-r--r--advanced/index.php2
-rw-r--r--advanced/lighttpd.conf.debian1
-rw-r--r--advanced/lighttpd.conf.fedora1
-rwxr-xr-xautomated install/basic-install.sh866
-rwxr-xr-xautomated install/uninstall.sh2
-rwxr-xr-xgravity.sh65
-rwxr-xr-xpihole57
-rw-r--r--test/test_automated_install.py7
-rw-r--r--test/test_centos_fedora_support.py13
20 files changed, 737 insertions, 584 deletions
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
<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>
## 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 <a href="https://discourse.pi-hole.net/"
## Breakdown of Features
### The Command Line Interface
-The `pihole` command has all the functionality necessary to be able to fully administer the Pi-hole, without the need of the Web Interface. It's fast, user-friendly, and auditable by anyone with understanding of `bash`.
+The `pihole` command has all the functionality necessary to be able to fully administer the Pi-hole, without the need of the Web Interface. It's fast, user-friendly, and auditable by anyone with an understanding of `bash`.
<a href="https://pi-hole.github.io/graphics/Screenshots/blacklist-cli.gif"><img src="https://pi-hole.github.io/graphics/Screenshots/blacklist-cli.gif" alt="Pi-hole Blacklist Demo"/></a>
@@ -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: <code>/etc/pihole/setupVars.conf</code>");
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 <<< "<?php echo PHP_VERSION ?>")"
+ printf -v phpInsMajor "%d" "$(php <<< "<?php echo PHP_MAJOR_VERSION ?>")"
+ printf -v phpInsMinor "%d" "$(php <<< "<?php echo PHP_MINOR_VERSION ?>")"
# 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}<option>${COL_NC}"
+ printf " %b %s\\n" "${CROSS}" "${str}"
+ printf " %b Unknown free disk space! \\n" "${INFO}"
+ printf " We were unable to determine available free disk space on this system.\\n"
+ printf " You may override this check, however, it is not recommended.\\n"
+ printf " The option '%b--i_do_not_follow_recommendations%b' can override this.\\n" "${COL_LIGHT_RED}" "${COL_NC}"
+ printf " e.g: curl -L https://install.pi-hole.net | bash /dev/stdin %b<option>%b\\n" "${COL_LIGHT_RED}" "${COL_NC}"
# exit with an error code
exit 1
# If there is insufficient free disk space,
elif [[ "${existing_free_kilobytes}" -lt "${required_free_kilobytes}" ]]; then
# show an error message
- echo -e " ${CROSS} ${str}"
- echo -e " ${INFO} Your system disk appears to only have ${existing_free_kilobytes} KB free"
- echo -e " ${INFO} It is recommended to have a minimum of ${required_free_kilobytes} KB to run the Pi-hole"
+ printf " %b %s\\n" "${CROSS}" "${str}"
+ printf " %b Your system disk appears to only have %s KB free\\n" "${INFO}" "${existing_free_kilobytes}"
+ printf " It is recommended to have a minimum of %s KB to run the Pi-hole\\n" "${required_free_kilobytes}"
# if the vcgencmd command exists,
- if command -v vcgencmd &> /dev/null; then
+ if is_command vcgencmd ; then
# it's probably a Raspbian install, so show a message about expanding the filesystem
- echo -e " ${INFO} If this is a new install you may need to expand your disk"
- echo -e " ${INFO} Run 'sudo raspi-config', and choose the 'expand file system' option"
- echo -e " ${INFO} After rebooting, run this installation again"
- echo -e " ${INFO} e.g: curl -L https://install.pi-hole.net | bash"
+ printf " If this is a new install you may need to expand your disk\\n"
+ printf " Run 'sudo raspi-config', and choose the 'expand file system' option\\n"
+ printf " After rebooting, run this installation again\\n"
+ printf " e.g: curl -L https://install.pi-hole.net | bash\\n"
fi
# Show there is not enough free space
- echo -e "\\n ${COL_LIGHT_RED}Insufficient free space, exiting...${COL_NC}"
+ printf "\\n %bInsufficient free space, exiting...%b\\n" "${COL_LIGHT_RED}" "${COL_NC}"
# and exit with an error
exit 1
# Otherwise,
else
# Show that we're running a disk space check
- echo -e " ${TICK} ${str}"
+ printf " %b %s\\n" "${TICK}" "${str}"
fi
}
@@ -549,7 +574,7 @@ chooseInterface() {
local firstLoop=1
# Find out how many interfaces are available to choose from
- interfaceCount=$(echo "${availableInterfaces}" | wc -l)
+ interfaceCount=$(wc -l <<< "${availableInterfaces}")
# If there is one interface,
if [[ "${interfaceCount}" -eq 1 ]]; then
@@ -576,13 +601,13 @@ chooseInterface() {
# Now run the command using the interfaces saved into the array
chooseInterfaceOptions=$("${chooseInterfaceCmd[@]}" "${interfacesArray[@]}" 2>&1 >/dev/tty) || \
# If the user chooses Cancel, exit
- { echo -e " ${COL_LIGHT_RED}Cancel was selected, exiting installer${COL_NC}"; exit 1; }
+ { printf " %bCancel was selected, exiting installer%b\\n" "${COL_LIGHT_RED}" "${COL_NC}"; exit 1; }
# For each interface
for desiredInterface in ${chooseInterfaceOptions}; do
# Set the one the user selected as the interface to use
PIHOLE_INTERFACE=${desiredInterface}
# and show this information to the user
- echo -e " ${INFO} Using interface: $PIHOLE_INTERFACE"
+ printf " %b Using interface: %s\\n" "${INFO}" "${PIHOLE_INTERFACE}"
done
fi
}
@@ -592,21 +617,24 @@ chooseInterface() {
# See https://github.com/pi-hole/pi-hole/issues/1473#issuecomment-301745953
testIPv6() {
# first will contain fda2 (ULA)
- first="$(cut -f1 -d":" <<< "$1")"
+ printf -v first "%s" "${1%%:*}"
# value1 will contain 253 which is the decimal value corresponding to 0xfd
value1=$(( (0x$first)/256 ))
# will contain 162 which is the decimal value corresponding to 0xa2
value2=$(( (0x$first)%256 ))
# the ULA test is testing for fc00::/7 according to RFC 4193
if (( (value1&254)==252 )); then
+ # echoing result to calling function as return value
echo "ULA"
fi
# the GUA test is testing for 2000::/3 according to RFC 4291
if (( (value1&112)==32 )); then
+ # echoing result to calling function as return value
echo "GUA"
fi
# the LL test is testing for fe80::/10 according to RFC 4193
if (( (value1)==254 )) && (( (value2&192)==128 )); then
+ # echoing result to calling function as return value
echo "Link-local"
fi
}
@@ -632,17 +660,17 @@ useIPv6dialog() {
# set the IPv6 address to the ULA address
IPV6_ADDRESS="${ULA_ADDRESS}"
# Show this info to the user
- echo -e " ${INFO} Found IPv6 ULA address, using it for blocking IPv6 ads"
+ printf " %b Found IPv6 ULA address, using it for blocking IPv6 ads\\n" "${INFO}"
# Otherwise, if the GUA_ADDRESS has a value,
elif [[ ! -z "${GUA_ADDRESS}" ]]; then
# Let the user know
- echo -e " ${INFO} Found IPv6 GUA address, using it for blocking IPv6 ads"
+ printf " %b Found IPv6 GUA address, using it for blocking IPv6 ads\\n" "${INFO}"
# And assign it to the global variable
IPV6_ADDRESS="${GUA_ADDRESS}"
# If none of those work,
else
# explain that IPv6 blocking will not be used
- echo -e " ${INFO} Unable to find IPv6 ULA/GUA address, IPv6 adblocking will not be enabled"
+ printf " %b Unable to find IPv6 ULA/GUA address, IPv6 adblocking will not be enabled\\n" "${INFO}"
# So set the variable to be empty
IPV6_ADDRESS=""
fi
@@ -667,7 +695,7 @@ use4andor6() {
# or IPv6 (on by default if available)
IPv6 "Block ads over IPv6" on)
# In a variable, show the choices available; exit if Cancel is selected
- choices=$("${cmd[@]}" "${options[@]}" 2>&1 >/dev/tty) || { echo -e " ${COL_LIGHT_RED}Cancel was selected, exiting installer${COL_NC}"; exit 1; }
+ choices=$("${cmd[@]}" "${options[@]}" 2>&1 >/dev/tty) || { printf " %bCancel was selected, exiting installer%b\\n" "${COL_LIGHT_RED}" "${COL_NC}"; exit 1; }
# For each choice available,
for choice in ${choices}
do
@@ -690,12 +718,12 @@ use4andor6() {
useIPv6dialog
fi
# Echo the information to the user
- echo -e " ${INFO} IPv4 address: ${IPV4_ADDRESS}"
- echo -e " ${INFO} IPv6 address: ${IPV6_ADDRESS}"
+ printf " %b IPv4 address: %s\\n" "${INFO}" "${IPV4_ADDRESS}"
+ printf " %b IPv6 address: %s\\n" "${INFO}" "${IPV6_ADDRESS}"
# If neither protocol is selected,
if [[ ! "${useIPv4}" ]] && [[ ! "${useIPv6}" ]]; then
# Show an error in red
- echo -e " ${COL_LIGHT_RED}Error: Neither IPv4 or IPv6 selected${COL_NC}"
+ printf " %bError: Neither IPv4 or IPv6 selected%b\\n" "${COL_LIGHT_RED}" "${COL_NC}"
# and exit with an error
exit 1
fi
@@ -725,13 +753,13 @@ It is also possible to use a DHCP reservation, but if you are going to do that,
IPV4_ADDRESS=$(whiptail --backtitle "Calibrating network interface" --title "IPv4 address" --inputbox "Enter your desired IPv4 address" ${r} ${c} "${IPV4_ADDRESS}" 3>&1 1>&2 2>&3) || \
# Cancelling IPv4 settings window
{ ipSettingsCorrect=False; echo -e " ${COL_LIGHT_RED}Cancel was selected, exiting installer${COL_NC}"; exit 1; }
- echo -e " ${INFO} Your static IPv4 address: ${IPV4_ADDRESS}"
+ printf " %b Your static IPv4 address: %s\\n" "${INFO}" "${IPV4_ADDRESS}"
# Ask for the gateway
IPv4gw=$(whiptail --backtitle "Calibrating network interface" --title "IPv4 gateway (router)" --inputbox "Enter your desired IPv4 default gateway" ${r} ${c} "${IPv4gw}" 3>&1 1>&2 2>&3) || \
# Cancelling gateway settings window
{ ipSettingsCorrect=False; echo -e " ${COL_LIGHT_RED}Cancel was selected, exiting installer${COL_NC}"; exit 1; }
- echo -e " ${INFO} Your static IPv4 gateway: ${IPv4gw}"
+ printf " %b Your static IPv4 gateway: %s\\n" "${INFO}" "${IPv4gw}"
# Give the user a chance to review their settings before moving on
if whiptail --backtitle "Calibrating network interface" --title "Static IP Address" --yesno "Are these settings correct?
@@ -748,79 +776,98 @@ It is also possible to use a DHCP reservation, but if you are going to do that,
fi
}
-# dhcpcd is very annoying,
+# configure networking via dhcpcd
setDHCPCD() {
- # but we can append these lines to dhcpcd.conf to enable a static IP
- echo "interface ${PIHOLE_INTERFACE}
- static ip_address=${IPV4_ADDRESS}
- static routers=${IPv4gw}
- static domain_name_servers=127.0.0.1" | tee -a /etc/dhcpcd.conf >/dev/null
+ # check if the IP is already in the file
+ if grep -q "${IPV4_ADDRESS}" /etc/dhcpcd.conf; then
+ printf " %b Static IP already configured\\n" "${INFO}"
+ # If it's not,
+ else
+ # we can append these lines to dhcpcd.conf to enable a static IP
+ echo "interface ${PIHOLE_INTERFACE}
+ static ip_address=${IPV4_ADDRESS}
+ static routers=${IPv4gw}
+ static domain_name_servers=127.0.0.1" | tee -a /etc/dhcpcd.conf >/dev/null
+ # Then use the ip command to immediately set the new address
+ ip addr replace dev "${PIHOLE_INTERFACE}" "${IPV4_ADDRESS}"
+ # Also give a warning that the user may need to reboot their system
+ printf " %b Set IP address to %s \\n You may need to restart after the install is complete\\n" "${TICK}" "${IPV4_ADDRESS%/*}"
+ fi
}
-setStaticIPv4() {
+# configure networking ifcfg-xxxx file found at /etc/sysconfig/network-scripts/
+# this function requires the full path of an ifcfg file passed as an argument
+setIFCFG() {
# Local, named variables
local IFCFG_FILE
local IPADDR
local CIDR
+ IFCFG_FILE=$1
+ printf -v IPADDR "%s" "${IPV4_ADDRESS%%/*}"
+ # check if the desired IP is already set
+ if grep -Eq "${IPADDR}(\\b|\\/)" "${IFCFG_FILE}"; then
+ printf " %b Static IP already configured\\n" "${INFO}"
+ # Otherwise,
+ else
+ # Put the IP in variables without the CIDR notation
+ printf -v CIDR "%s" "${IPV4_ADDRESS##*/}"
+ # Backup existing interface configuration:
+ cp "${IFCFG_FILE}" "${IFCFG_FILE}".pihole.orig
+ # Build Interface configuration file using the GLOBAL variables we have
+ {
+ echo "# Configured via Pi-hole installer"
+ echo "DEVICE=$PIHOLE_INTERFACE"
+ echo "BOOTPROTO=none"
+ echo "ONBOOT=yes"
+ echo "IPADDR=$IPADDR"
+ echo "PREFIX=$CIDR"
+ echo "GATEWAY=$IPv4gw"
+ echo "DNS1=$PIHOLE_DNS_1"
+ echo "DNS2=$PIHOLE_DNS_2"
+ echo "USERCTL=no"
+ }> "${IFCFG_FILE}"
+ # Use ip to immediately set the new address
+ ip addr replace dev "${PIHOLE_INTERFACE}" "${IPV4_ADDRESS}"
+ # If NetworkMangler command line interface exists and ready to mangle,
+ if is_command nmcli && nmcli general status &> /dev/null; then
+ # Tell NetworkManagler to read our new sysconfig file
+ nmcli con load "${IFCFG_FILE}" > /dev/null
+ fi
+ # Show a warning that the user may need to restart
+ printf " %b Set IP address to %s\\n You may need to restart after the install is complete\\n" "${TICK}" "${IPV4_ADDRESS%%/*}"
+ fi
+}
+
+setStaticIPv4() {
+ # Local, named variables
+ local IFCFG_FILE
+ local CONNECTION_NAME
# For the Debian family, if dhcpcd.conf exists,
if [[ -f "/etc/dhcpcd.conf" ]]; then
- # check if the IP is already in the file
- if grep -q "${IPV4_ADDRESS}" /etc/dhcpcd.conf; then
- echo -e " ${INFO} Static IP already configured"
- # If it's not,
- else
- # set it using our function
- setDHCPCD
- # Then use the ip command to immediately set the new address
- ip addr replace dev "${PIHOLE_INTERFACE}" "${IPV4_ADDRESS}"
- # Also give a warning that the user may need to reboot their system
- echo -e " ${TICK} Set IP address to ${IPV4_ADDRESS%/*}
- You may need to restart after the install is complete"
- fi
- # If it's not Debian, check if it's the Fedora family by checking for the file below
- elif [[ -f "/etc/sysconfig/network-scripts/ifcfg-${PIHOLE_INTERFACE}" ]];then
+ # configure networking via dhcpcd
+ setDHCPCD
+ return 0
+ fi
+ # If a DHCPCD config file was not found, check for an ifcfg config file based on interface name
+ if [[ -f "/etc/sysconfig/network-scripts/ifcfg-${PIHOLE_INTERFACE}" ]];then
# If it exists,
IFCFG_FILE=/etc/sysconfig/network-scripts/ifcfg-${PIHOLE_INTERFACE}
- IPADDR=$(echo "${IPV4_ADDRESS}" | cut -f1 -d/)
- # check if the desired IP is already set
- if grep -Eq "${IPADDR}(\\b|\\/)" "${IFCFG_FILE}"; then
- echo -e " ${INFO} Static IP already configured"
- # Otherwise,
- else
- # Put the IP in variables without the CIDR notation
- CIDR=$(echo "${IPV4_ADDRESS}" | cut -f2 -d/)
- # Backup existing interface configuration:
- cp "${IFCFG_FILE}" "${IFCFG_FILE}".pihole.orig
- # Build Interface configuration file using the GLOBAL variables we have
- {
- echo "# Configured via Pi-hole installer"
- echo "DEVICE=$PIHOLE_INTERFACE"
- echo "BOOTPROTO=none"
- echo "ONBOOT=yes"
- echo "IPADDR=$IPADDR"
- echo "PREFIX=$CIDR"
- echo "GATEWAY=$IPv4gw"
- echo "DNS1=$PIHOLE_DNS_1"
- echo "DNS2=$PIHOLE_DNS_2"
- echo "USERCTL=no"
- }> "${IFCFG_FILE}"
- # Use ip to immediately set the new address
- ip addr replace dev "${PIHOLE_INTERFACE}" "${IPV4_ADDRESS}"
- # If NetworkMangler command line interface exists and ready to mangle,
- if command -v nmcli &> /dev/null && nmcli general status &> /dev/null; then
- # Tell NetworkManagler to read our new sysconfig file
- nmcli con load "${IFCFG_FILE}" > /dev/null
- fi
- # Show a warning that the user may need to restart
- echo -e " ${TICK} Set IP address to ${IPV4_ADDRESS%/*}
- You may need to restart after the install is complete"
+ setIFCFG "${IFCFG_FILE}"
+ return 0
+ fi
+ # if an ifcfg config does not exists for the interface name, try the connection name via network manager
+ if is_command nmcli && nmcli general status &> /dev/null; then
+ CONNECTION_NAME=$(nmcli dev show "${PIHOLE_INTERFACE}" | grep 'GENERAL.CONNECTION' | cut -d: -f2 | sed 's/^System//' | xargs | tr ' ' '_')
+ if [[ -f "/etc/sysconfig/network-scripts/ifcfg-${CONNECTION_NAME}" ]];then
+ # If it exists,
+ IFCFG_FILE=/etc/sysconfig/network-scripts/ifcfg-${CONNECTION_NAME}
+ setIFCFG "${IFCFG_FILE}"
+ return 0
fi
- # If all that fails,
- else
- # show an error and exit
- echo -e " ${INFO} Warning: Unable to locate configuration file to set static IPv4 address"
- exit 1
fi
+ # If previous conditions failed, show an error and exit
+ printf " %b Warning: Unable to locate configuration file to set static IPv4 address\\n" "${INFO}"
+ exit 1
}
# Check an IP address to see if it is a valid one
@@ -858,7 +905,6 @@ setDNS() {
DNSChooseOptions=(Google ""
OpenDNS ""
Level3 ""
- Norton ""
Comodo ""
DNSWatch ""
Quad9 ""
@@ -869,54 +915,49 @@ setDNS() {
DNSchoices=$(whiptail --separate-output --menu "Select Upstream DNS Provider. To use your own, select Custom." ${r} ${c} 7 \
"${DNSChooseOptions[@]}" 2>&1 >/dev/tty) || \
# exit if Cancel is selected
- { echo -e " ${COL_LIGHT_RED}Cancel was selected, exiting installer${COL_NC}"; exit 1; }
+ { printf " %bCancel was selected, exiting installer%b\\n" "${COL_LIGHT_RED}" "${COL_NC}"; exit 1; }
# Display the selection
- echo -ne " ${INFO} Using "
+ 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)
- echo "Google DNS servers"
+ printf "Google DNS servers\\n"
PIHOLE_DNS_1="8.8.8.8"
PIHOLE_DNS_2="8.8.4.4"
;;
OpenDNS)
- echo "OpenDNS servers"
+ printf "OpenDNS servers\\n"
PIHOLE_DNS_1="208.67.222.222"
PIHOLE_DNS_2="208.67.220.220"
;;
Level3)
- echo "Level3 servers"
+ printf "Level3 servers\\n"
PIHOLE_DNS_1="4.2.2.1"
PIHOLE_DNS_2="4.2.2.2"
;;
- Norton)
- echo "Norton ConnectSafe servers"
- PIHOLE_DNS_1="199.85.126.10"
- PIHOLE_DNS_2="199.85.127.10"
- ;;
Comodo)
- echo "Comodo Secure servers"
+ printf "Comodo Secure servers\\n"
PIHOLE_DNS_1="8.26.56.26"
PIHOLE_DNS_2="8.20.247.20"
;;
DNSWatch)
- echo "DNS.WATCH servers"
+ printf "DNS.WATCH servers\\n"
PIHOLE_DNS_1="84.200.69.80"
PIHOLE_DNS_2="84.200.70.40"
;;
Quad9)
- echo "Quad9 servers"
+ printf "Quad9 servers\\n"
PIHOLE_DNS_1="9.9.9.9"
PIHOLE_DNS_2="149.112.112.112"
;;
FamilyShield)
- echo "FamilyShield servers"
+ printf "FamilyShield servers\\n"
PIHOLE_DNS_1="208.67.222.123"
PIHOLE_DNS_2="208.67.220.123"
;;
Cloudflare)
- echo "Cloudflare servers"
+ printf "Cloudflare servers\\n"
PIHOLE_DNS_1="1.1.1.1"
PIHOLE_DNS_2="1.0.0.1"
;;
@@ -942,10 +983,13 @@ setDNS() {
# 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) || \
- { echo -e " ${COL_LIGHT_RED}Cancel was selected, exiting installer${COL_NC}"; exit 1; }
- #
- PIHOLE_DNS_1=$(echo "${piholeDNS}" | sed 's/[, \t]\+/,/g' | awk -F, '{print$1}')
- PIHOLE_DNS_2=$(echo "${piholeDNS}" | sed 's/[, \t]\+/,/g' | awk -F, '{print$2}')
+ { 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
@@ -998,23 +1042,45 @@ setLogging() {
LogChooseOptions=("On (Recommended)" "" on
Off "" off)
# Get the user's choice
- LogChoices=$("${LogToggleCommand[@]}" "${LogChooseOptions[@]}" 2>&1 >/dev/tty) || (echo -e " ${COL_LIGHT_RED}Cancel was selected, exiting installer${COL_NC}" && exit 1)
+ LogChoices=$("${LogToggleCommand[@]}" "${LogChooseOptions[@]}" 2>&1 >/dev/tty) || (printf " %bCancel was selected, exiting installer%b\\n" "${COL_LIGHT_RED}" "${COL_NC}" && exit 1)
case ${LogChoices} in
# If it's on
"On (Recommended)")
- echo -e " ${INFO} Logging On."
+ printf " %b Logging On.\\n" "${INFO}"
# Set the GLOBAL variable to true so we know what they selected
QUERY_LOGGING=true
;;
# Otherwise, it's off,
Off)
- echo -e " ${INFO} Logging Off."
+ printf " %b Logging Off.\\n" "${INFO}"
# So set it to false
QUERY_LOGGING=false
;;
esac
}
+# Allow the user to set their FTL privacy level
+setPrivacyLevel() {
+ local LevelCommand
+ local LevelOptions
+
+ LevelCommand=(whiptail --separate-output --radiolist "Select a privacy mode for FTL." "${r}" "${c}" 6)
+
+ # The default selection is level 0
+ LevelOptions=(
+ "0" "Show everything" on
+ "1" "Hide domains" off
+ "2" "Hide domains and clients" off
+ "3" "Anonymous mode" off
+ "4" "Disabled statistics" off
+ )
+
+ # Get the user's choice
+ PRIVACY_LEVEL=$("${LevelCommand[@]}" "${LevelOptions[@]}" 2>&1 >/dev/tty) || (echo -e " ${COL_LIGHT_RED}Cancel was selected, exiting installer${COL_NC}" && exit 1)
+
+ printf " %b Privacy level %d" "${INFO}" "${PRIVACY_LEVEL}"
+}
+
# Function to ask the user if they want to install the dashboard
setAdminFlag() {
# Local, named variables
@@ -1027,16 +1093,16 @@ setAdminFlag() {
# with the default being enabled
WebChooseOptions=("On (Recommended)" "" on
Off "" off)
- WebChoices=$("${WebToggleCommand[@]}" "${WebChooseOptions[@]}" 2>&1 >/dev/tty) || (echo -e " ${COL_LIGHT_RED}Cancel was selected, exiting installer${COL_NC}" && exit 1)
+ WebChoices=$("${WebToggleCommand[@]}" "${WebChooseOptions[@]}" 2>&1 >/dev/tty) || (printf " %bCancel was selected, exiting installer%b\\n" "${COL_LIGHT_RED}" "${COL_NC}" && exit 1)
# Depending on their choice
case ${WebChoices} in
"On (Recommended)")
- echo -e " ${INFO} Web Interface On"
+ printf " %b Web Interface On\\n" "${INFO}"
# Set it to true
INSTALL_WEB_INTERFACE=true
;;
Off)
- echo -e " ${INFO} Web Interface Off"
+ printf " %b Web Interface Off\\n" "${INFO}"
# or false
INSTALL_WEB_INTERFACE=false
;;
@@ -1048,16 +1114,16 @@ setAdminFlag() {
# with the default being enabled
WebChooseOptions=("On (Recommended)" "" on
Off "" off)
- WebChoices=$("${WebToggleCommand[@]}" "${WebChooseOptions[@]}" 2>&1 >/dev/tty) || (echo -e " ${COL_LIGHT_RED}Cancel was selected, exiting installer${COL_NC}" && exit 1)
+ WebChoices=$("${WebToggleCommand[@]}" "${WebChooseOptions[@]}" 2>&1 >/dev/tty) || (printf " %bCancel was selected, exiting installer%b\\n" "${COL_LIGHT_RED}" "${COL_NC}" && exit 1)
# Depending on their choice
case ${WebChoices} in
"On (Recommended)")
- echo -e " ${INFO} Web Server On"
+ printf " %b Web Server On\\n" "${INFO}"
# set it to true, as clearly seen below.
INSTALL_WEB_SERVER=true
;;
Off)
- echo -e " ${INFO} Web Server Off"
+ printf " %b Web Server Off\\n" "${INFO}"
# or false
INSTALL_WEB_SERVER=false
;;
@@ -1083,23 +1149,46 @@ chooseBlocklists() {
HostsFile "Hosts-file.net Ads" on)
# In a variable, show the choices available; exit if Cancel is selected
- choices=$("${cmd[@]}" "${options[@]}" 2>&1 >/dev/tty) || { echo -e " ${COL_LIGHT_RED}Cancel was selected, exiting installer${COL_NC}"; rm "${adlistFile}" ;exit 1; }
+ choices=$("${cmd[@]}" "${options[@]}" 2>&1 >/dev/tty) || { printf " %bCancel was selected, exiting installer%b\\n" "${COL_LIGHT_RED}" "${COL_NC}"; rm "${adlistFile}" ;exit 1; }
# For each choice available,
for choice in ${choices}
do
- # Set the values to true
- case ${choice} in
- StevenBlack ) echo "https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts" >> "${adlistFile}";;
- MalwareDom ) echo "https://mirror1.malwaredomains.com/files/justdomains" >> "${adlistFile}";;
- Cameleon ) echo "http://sysctl.org/cameleon/hosts" >> "${adlistFile}";;
- ZeusTracker ) echo "https://zeustracker.abuse.ch/blocklist.php?download=domainblocklist" >> "${adlistFile}";;
- DisconTrack ) echo "https://s3.amazonaws.com/lists.disconnect.me/simple_tracking.txt" >> "${adlistFile}";;
- DisconAd ) echo "https://s3.amazonaws.com/lists.disconnect.me/simple_ad.txt" >> "${adlistFile}";;
- HostsFile ) echo "https://hosts-file.net/ad_servers.txt" >> "${adlistFile}";;
- esac
+ appendToListsFile "${choice}"
done
}
+# Accept a string parameter, it must be one of the default lists
+# This function allow to not duplicate code in chooseBlocklists and
+# in installDefaultBlocklists
+appendToListsFile() {
+ case $1 in
+ StevenBlack ) echo "https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts" >> "${adlistFile}";;
+ MalwareDom ) echo "https://mirror1.malwaredomains.com/files/justdomains" >> "${adlistFile}";;
+ Cameleon ) echo "http://sysctl.org/cameleon/hosts" >> "${adlistFile}";;
+ ZeusTracker ) echo "https://zeustracker.abuse.ch/blocklist.php?download=domainblocklist" >> "${adlistFile}";;
+ DisconTrack ) echo "https://s3.amazonaws.com/lists.disconnect.me/simple_tracking.txt" >> "${adlistFile}";;
+ DisconAd ) echo "https://s3.amazonaws.com/lists.disconnect.me/simple_ad.txt" >> "${adlistFile}";;
+ HostsFile ) echo "https://hosts-file.net/ad_servers.txt" >> "${adlistFile}";;
+ esac
+}
+
+# Used only in unattended setup
+# If there is already the adListFile, we keep it, else we create it using all default lists
+installDefaultBlocklists() {
+ # In unattended setup, could be useful to use userdefined blocklist.
+ # If this file exists, we avoid overriding it.
+ if [[ -f "${adlistFile}" ]]; then
+ return;
+ fi
+ appendToListsFile StevenBlack
+ appendToListsFile MalwareDom
+ appendToListsFile Cameleon
+ appendToListsFile ZeusTracker
+ appendToListsFile DisconTrack
+ appendToListsFile DisconAd
+ appendToListsFile HostsFile
+}
+
# Check if /etc/dnsmasq.conf is from pi-hole. If so replace with an original and install new in .d directory
version_check_dnsmasq() {
# Local, named variables
@@ -1112,39 +1201,39 @@ version_check_dnsmasq() {
# If the dnsmasq config file exists
if [[ -f "${dnsmasq_conf}" ]]; then
- echo -ne " ${INFO} Existing dnsmasq.conf found..."
+ printf " %b Existing dnsmasq.conf found..." "${INFO}"
# If gravity.list is found within this file, we presume it's from older versions on Pi-hole,
if grep -q ${dnsmasq_pihole_id_string} ${dnsmasq_conf}; then
- echo " it is from a previous Pi-hole install."
- echo -ne " ${INFO} Backing up dnsmasq.conf to dnsmasq.conf.orig..."
+ printf " it is from a previous Pi-hole install.\\n"
+ printf " %b Backing up dnsmasq.conf to dnsmasq.conf.orig..." "${INFO}"
# so backup the original file
mv -f ${dnsmasq_conf} ${dnsmasq_conf_orig}
- echo -e "${OVER} ${TICK} Backing up dnsmasq.conf to dnsmasq.conf.orig..."
- echo -ne " ${INFO} Restoring default dnsmasq.conf..."
+ printf "%b %b Backing up dnsmasq.conf to dnsmasq.conf.orig...\\n" "${OVER}" "${TICK}"
+ printf " %b Restoring default dnsmasq.conf..." "${INFO}"
# and replace it with the default
cp ${dnsmasq_original_config} ${dnsmasq_conf}
- echo -e "${OVER} ${TICK} Restoring default dnsmasq.conf..."
+ printf "%b %b Restoring default dnsmasq.conf...\\n" "${OVER}" "${TICK}"
# Otherwise,
else
# Don't to anything
- echo " it is not a Pi-hole file, leaving alone!"
+ printf " it is not a Pi-hole file, leaving alone!\\n"
fi
else
# If a file cannot be found,
- echo -ne " ${INFO} No dnsmasq.conf found... restoring default dnsmasq.conf..."
+ printf " %b No dnsmasq.conf found... restoring default dnsmasq.conf..." "${INFO}"
# restore the default one
cp ${dnsmasq_original_config} ${dnsmasq_conf}
- echo -e "${OVER} ${TICK} No dnsmasq.conf found... restoring default dnsmasq.conf..."
+ printf "%b %b No dnsmasq.conf found... restoring default dnsmasq.conf...\\n" "${OVER}" "${TICK}"
fi
- echo -en " ${INFO} Copying 01-pihole.conf to /etc/dnsmasq.d/01-pihole.conf..."
+ printf " %b Copying 01-pihole.conf to /etc/dnsmasq.d/01-pihole.conf..." "${INFO}"
# Check to see if dnsmasq directory exists (it may not due to being a fresh install and dnsmasq no longer being a dependency)
if [[ ! -d "/etc/dnsmasq.d" ]];then
mkdir "/etc/dnsmasq.d"
fi
# Copy the new Pi-hole DNS config file into the dnsmasq.d directory
cp ${dnsmasq_pihole_01_snippet} ${dnsmasq_pihole_01_location}
- echo -e "${OVER} ${TICK} Copying 01-pihole.conf to /etc/dnsmasq.d/01-pihole.conf"
+ printf "%b %b Copying 01-pihole.conf to /etc/dnsmasq.d/01-pihole.conf\\n" "${OVER}" "${TICK}"
# Replace our placeholder values with the GLOBAL DNS variables that we populated earlier
# First, swap in the interface to listen on
sed -i "s/@INT@/$PIHOLE_INTERFACE/" ${dnsmasq_pihole_01_location}
@@ -1198,7 +1287,7 @@ clean_existing() {
installScripts() {
# Local, named variables
local str="Installing scripts from ${PI_HOLE_LOCAL_REPO}"
- echo -ne " ${INFO} ${str}..."
+ printf " %b %s..." "${INFO}" "${str}"
# Clear out script files from Pi-hole scripts directory.
clean_existing "${PI_HOLE_INSTALL_DIR}" "${PI_HOLE_FILES[@]}"
@@ -1220,27 +1309,26 @@ installScripts() {
install -o "${USER}" -Dm755 -t "${PI_HOLE_INSTALL_DIR}" ./advanced/Scripts/COL_TABLE
install -o "${USER}" -Dm755 -t /usr/local/bin/ pihole
install -Dm644 ./advanced/bash-completion/pihole /etc/bash_completion.d/pihole
- echo -e "${OVER} ${TICK} ${str}"
+ printf "%b %b %s\\n" "${OVER}" "${TICK}" "${str}"
# Otherwise,
else
# Show an error and exit
- echo -e "${OVER} ${CROSS} ${str}
- ${COL_LIGHT_RED}Error: Local repo ${PI_HOLE_LOCAL_REPO} not found, exiting installer${COL_NC}"
+ printf "%b %b %s\\n" "${OVER}" "${CROSS}" "${str}"
+ printf "\\t\\t%bError: Local repo %s not found, exiting installer%b\\n" "${COL_LIGHT_RED}" "${PI_HOLE_LOCAL_REPO}" "${COL_NC}"
return 1
fi
}
# Install the configs from PI_HOLE_LOCAL_REPO to their various locations
installConfigs() {
- echo ""
- echo -e " ${INFO} Installing configs from ${PI_HOLE_LOCAL_REPO}..."
+ 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 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/nul; then
- echo -e " ${COL_LIGHT_RED}Error: Unable to initialize configuration file ${PI_HOLE_CONFIG_DIR}/pihole-FTL.conf"
+ if ! install -o pihole -g 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
fi
@@ -1264,6 +1352,8 @@ installConfigs() {
fi
# and copy in the config file Pi-hole needs
cp ${PI_HOLE_LOCAL_REPO}/advanced/${LIGHTTPD_CFG} /etc/lighttpd/lighttpd.conf
+ # 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
sed -i 's/^\(server\.error-handler-404\s*=\s*\).*$/\1"pihole\/custom\.php"/' /etc/lighttpd/lighttpd.conf
@@ -1282,14 +1372,14 @@ install_manpage() {
# Copy Pi-hole man pages and call mandb to update man page database
# Default location for man files for /usr/local/bin is /usr/local/share/man
# on lightweight systems may not be present, so check before copying.
- echo -en " ${INFO} Testing man page installation"
- if ! command -v mandb &>/dev/null; then
+ printf " %b Testing man page installation" "${INFO}"
+ if ! is_command mandb ; then
# if mandb is not present, no manpage support
- echo -e "${OVER} ${INFO} man not installed"
+ printf "%b %b man not installed\\n" "${OVER}" "${INFO}"
return
elif [[ ! -d "/usr/local/share/man" ]]; then
# appropriate directory for Pi-hole's man page is not present
- echo -e "${OVER} ${INFO} man pages not installed"
+ printf "%b %b man pages not installed\\n" "${OVER}" "${INFO}"
return
fi
if [[ ! -d "/usr/local/share/man/man8" ]]; then
@@ -1306,13 +1396,13 @@ install_manpage() {
cp ${PI_HOLE_LOCAL_REPO}/manpages/pihole-FTL.conf.5 /usr/local/share/man/man5/pihole-FTL.conf.5
if mandb -q &>/dev/null; then
# Updated successfully
- echo -e "${OVER} ${TICK} man pages installed and database updated"
+ printf "%b %b man pages installed and database updated\\n" "${OVER}" "${TICK}"
return
else
# Something is wrong with the system's man installation, clean up
# our files, (leave everything how we found it).
rm /usr/local/share/man/man8/pihole.8 /usr/local/share/man/man8/pihole-FTL.8 /usr/local/share/man/man5/pihole-FTL.conf.5
- echo -e "${OVER} ${CROSS} man page db not updated, man pages not installed"
+ printf "%b %b man page db not updated, man pages not installed\\n" "${OVER}" "${CROSS}"
fi
}
@@ -1320,22 +1410,22 @@ stop_service() {
# Stop service passed in as argument.
# Can softfail, as process may not be installed when this is called
local str="Stopping ${1} service"
- echo -ne " ${INFO} ${str}..."
- if command -v systemctl &> /dev/null; then
+ printf " %b %s..." "${INFO}" "${str}"
+ if is_command systemctl ; then
systemctl stop "${1}" &> /dev/null || true
else
service "${1}" stop &> /dev/null || true
fi
- echo -e "${OVER} ${TICK} ${str}..."
+ printf "%b %b %s...\\n" "${OVER}" "${TICK}" "${str}"
}
# Start/Restart service passed in as argument
start_service() {
# Local, named variables
local str="Starting ${1} service"
- echo -ne " ${INFO} ${str}..."
+ printf " %b %s..." "${INFO}" "${str}"
# If systemctl exists,
- if command -v systemctl &> /dev/null; then
+ if is_command systemctl ; then
# use that to restart the service
systemctl restart "${1}" &> /dev/null
# Otherwise,
@@ -1343,16 +1433,16 @@ start_service() {
# fall back to the service command
service "${1}" restart &> /dev/null
fi
- echo -e "${OVER} ${TICK} ${str}"
+ printf "%b %b %s...\\n" "${OVER}" "${TICK}" "${str}"
}
# Enable service so that it will start with next reboot
enable_service() {
# Local, named variables
local str="Enabling ${1} service to start on reboot"
- echo -ne " ${INFO} ${str}..."
+ printf " %b %s..." "${INFO}" "${str}"
# If systemctl exists,
- if command -v systemctl &> /dev/null; then
+ if is_command systemctl ; then
# use that to enable the service
systemctl enable "${1}" &> /dev/null
# Otherwise,
@@ -1360,16 +1450,16 @@ enable_service() {
# use update-rc.d to accomplish this
update-rc.d "${1}" defaults &> /dev/null
fi
- echo -e "${OVER} ${TICK} ${str}"
+ printf "%b %b %s...\\n" "${OVER}" "${TICK}" "${str}"
}
# Disable service so that it will not with next reboot
disable_service() {
# Local, named variables
local str="Disabling ${1} service"
- echo -ne " ${INFO} ${str}..."
+ printf " %b %s..." "${INFO}" "${str}"
# If systemctl exists,
- if command -v systemctl &> /dev/null; then
+ if is_command systemctl ; then
# use that to disable the service
systemctl disable "${1}" &> /dev/null
# Otherwise,
@@ -1377,12 +1467,12 @@ disable_service() {
# use update-rc.d to accomplish this
update-rc.d "${1}" disable &> /dev/null
fi
- echo -e "${OVER} ${TICK} ${str}"
+ printf "%b %b %s...\\n" "${OVER}" "${TICK}" "${str}"
}
check_service_active() {
# If systemctl exists,
- if command -v systemctl &> /dev/null; then
+ if is_command systemctl ; then
# use that to check the status of the service
systemctl is-enabled "${1}" &> /dev/null
# Otherwise,
@@ -1394,25 +1484,25 @@ check_service_active() {
# Systemd-resolved's DNSStubListener and dnsmasq can't share port 53.
disable_resolved_stublistener() {
- echo -en " ${INFO} Testing if systemd-resolved is enabled"
+ printf " %b Testing if systemd-resolved is enabled\\n" "${INFO}"
# Check if Systemd-resolved's DNSStubListener is enabled and active on port 53
if check_service_active "systemd-resolved"; then
# Check if DNSStubListener is enabled
- echo -en " ${OVER} ${INFO} Testing if systemd-resolved DNSStub-Listener is active"
+ printf " %b %b Testing if systemd-resolved DNSStub-Listener is active" "${OVER}" "${INFO}"
if ( grep -E '#?DNSStubListener=yes' /etc/systemd/resolved.conf &> /dev/null ); then
# Disable the DNSStubListener to unbind it from port 53
# Note that this breaks dns functionality on host until dnsmasq/ftl are up and running
- echo -en "${OVER} ${TICK} Disabling systemd-resolved DNSStubListener"
+ printf "%b %b Disabling systemd-resolved DNSStubListener" "${OVER}" "${TICK}"
# Make a backup of the original /etc/systemd/resolved.conf
# (This will need to be restored on uninstallation)
sed -r -i.orig 's/#?DNSStubListener=yes/DNSStubListener=no/g' /etc/systemd/resolved.conf
- echo -e " and restarting systemd-resolved"
+ printf " and restarting systemd-resolved\\n"
systemctl reload-or-restart systemd-resolved
else
- echo -e "${OVER} ${INFO} Systemd-resolved does not need to be restarted"
+ printf "%b %b Systemd-resolved does not need to be restarted\\n" "${OVER}" "${INFO}"
fi
else
- echo -e "${OVER} ${INFO} Systemd-resolved is not enabled"
+ printf "%b %b Systemd-resolved is not enabled\\n" "${OVER}" "${INFO}"
fi
}
@@ -1425,16 +1515,15 @@ update_package_cache() {
# Local, named variables
local str="Update local cache of available packages"
- echo ""
- echo -ne " ${INFO} ${str}..."
+ printf " %b %s..." "${INFO}" "${str}"
# Create a command from the package cache variable
if eval "${UPDATE_PKG_CACHE}" &> /dev/null; then
- echo -e "${OVER} ${TICK} ${str}"
+ printf "%b %b %s\\n" "${OVER}" "${TICK}" "${str}"
# Otherwise,
else
# show an error and exit
- echo -e "${OVER} ${CROSS} ${str}"
- echo -ne " ${COL_LIGHT_RED}Error: Unable to update package cache. Please try \"${UPDATE_PKG_CACHE}\"${COL_NC}"
+ 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}"
return 1
fi
}
@@ -1444,22 +1533,20 @@ update_package_cache() {
notify_package_updates_available() {
# Local, named variables
local str="Checking ${PKG_MANAGER} for upgraded packages"
- echo -ne "\\n ${INFO} ${str}..."
+ printf "\\n %b %s..." "${INFO}" "${str}"
# Store the list of packages in a variable
updatesToInstall=$(eval "${PKG_COUNT}")
if [[ -d "/lib/modules/$(uname -r)" ]]; then
if [[ "${updatesToInstall}" -eq 0 ]]; then
- echo -e "${OVER} ${TICK} ${str}... up to date!"
- echo ""
+ printf "%b %b %s... up to date!\\n\\n" "${OVER}" "${TICK}" "${str}"
else
- echo -e "${OVER} ${TICK} ${str}... ${updatesToInstall} updates available"
- echo -e " ${INFO} ${COL_LIGHT_GREEN}It is recommended to update your OS after installing the Pi-hole! ${COL_NC}"
- echo ""
+ printf "%b %b %s... %s updates available\\n" "${OVER}" "${TICK}" "${str}" "${updatesToInstall}"
+ printf " %b %bIt is recommended to update your OS after installing the Pi-hole!%b\\n\\n" "${INFO}" "${COL_LIGHT_GREEN}" "${COL_NC}"
fi
else
- echo -e "${OVER} ${CROSS} ${str}
- Kernel update detected. If the install fails, please reboot and try again\\n"
+ printf "%b %b %s\\n" "${OVER}" "${CROSS}" "${str}"
+ printf " Kernel update detected. If the install fails, please reboot and try again\\n"
fi
}
@@ -1473,10 +1560,10 @@ install_dependent_packages() {
# If it equals 1,
if [[ "${counter}" == 1 ]]; then
#
- echo -e " ${INFO} Installer Dependency checks..."
+ printf " %b Installer Dependency checks...\\n" "${INFO}"
else
#
- echo -e " ${INFO} Main Dependency checks..."
+ printf " %b Main Dependency checks...\\n" "${INFO}"
fi
# Install packages passed in via argument array
@@ -1489,12 +1576,12 @@ install_dependent_packages() {
# amount of download traffic.
# NOTE: We may be able to use this installArray in the future to create a list of package that were
# installed by us, and remove only the installed packages, and not the entire list.
- if command -v debconf-apt-progress &> /dev/null; then
+ if is_command debconf-apt-progress ; then
# For each package,
for i in "${argArray1[@]}"; do
- echo -ne " ${INFO} Checking for $i..."
+ printf " %b Checking for %s..." "${INFO}" "${i}"
if dpkg-query -W -f='${Status}' "${i}" 2>/dev/null | grep "ok installed" &> /dev/null; then
- echo -e "${OVER} ${TICK} Checking for $i"
+ printf "%b %b Checking for %s\\n" "${OVER}" "${TICK}" "${i}"
else
echo -e "${OVER} ${INFO} Checking for $i (will be installed)"
installArray+=("${i}")
@@ -1505,17 +1592,17 @@ install_dependent_packages() {
debconf-apt-progress -- "${PKG_INSTALL[@]}" "${installArray[@]}"
return
fi
- echo ""
+ printf "\\n"
return 0
fi
# Install Fedora/CentOS packages
for i in "${argArray1[@]}"; do
- echo -ne " ${INFO} Checking for $i..."
+ printf " %b Checking for %s..." "${INFO}" "${i}"
if ${PKG_MANAGER} -q list installed "${i}" &> /dev/null; then
- echo -e "${OVER} ${TICK} Checking for $i"
+ printf "%b %b Checking for %s" "${OVER}" "${TICK}" "${i}"
else
- echo -e "${OVER} ${INFO} Checking for $i (will be installed)"
+ printf "%b %b Checking for %s (will be installed)" "${OVER}" "${INFO}" "${i}"
installArray+=("${i}")
fi
done
@@ -1523,17 +1610,16 @@ install_dependent_packages() {
"${PKG_INSTALL[@]}" "${installArray[@]}" &> /dev/null
return
fi
- echo ""
+ printf "\\n"
return 0
}
# Install the Web interface dashboard
installPiholeWeb() {
- echo ""
- echo " ${INFO} Installing blocking page..."
+ printf "\\n %b Installing blocking page...\\n" "${INFO}"
local str="Creating directory for blocking page, and copying files"
- echo -ne " ${INFO} ${str}..."
+ printf " %b %s..." "${INFO}" "${str}"
# Install the directory
install -d /var/www/html/pihole
# and the blockpage
@@ -1544,26 +1630,25 @@ installPiholeWeb() {
rm "/var/www/html/pihole/index.js"
fi
- echo -e "${OVER} ${TICK} ${str}"
+ printf "%b %b %s\\n" "${OVER}" "${TICK}" "${str}"
local str="Backing up index.lighttpd.html"
- echo -ne " ${INFO} ${str}..."
+ printf " %b %s..." "${INFO}" "${str}"
# If the default index file exists,
if [[ -f "/var/www/html/index.lighttpd.html" ]]; then
# back it up
mv /var/www/html/index.lighttpd.html /var/www/html/index.lighttpd.orig
- echo -e "${OVER} ${TICK} ${str}"
+ printf "%b %b %s\\n" "${OVER}" "${TICK}" "${str}"
# Otherwise,
else
# don't do anything
- echo -e "${OVER} ${CROSS} ${str}
- No default index.lighttpd.html file found... not backing up"
+ printf "%b %b %s\\n" "${OVER}" "${CROSS}" "${str}"
+ printf " No default index.lighttpd.html file found... not backing up\\n"
fi
# Install Sudoers file
- echo ""
local str="Installing sudoer file"
- echo -ne " ${INFO} ${str}..."
+ printf "\\n %b %s..." "${INFO}" "${str}"
# Make the .d directory if it doesn't exist
mkdir -p /etc/sudoers.d/
# and copy in the pihole sudoers file
@@ -1579,22 +1664,21 @@ installPiholeWeb() {
fi
# Set the strict permissions on the file
chmod 0440 /etc/sudoers.d/pihole
- echo -e "${OVER} ${TICK} ${str}"
+ printf "%b %b %s\\n" "${OVER}" "${TICK}" "${str}"
}
# Installs a cron file
installCron() {
# Install the cron job
local str="Installing latest Cron script"
- echo ""
- echo -ne " ${INFO} ${str}..."
+ printf "\\n %b %s..." "${INFO}" "${str}"
# Copy the cron file over from the local repo
cp ${PI_HOLE_LOCAL_REPO}/advanced/Templates/pihole.cron /etc/cron.d/pihole
# Randomize gravity update time
sed -i "s/59 1 /$((1 + RANDOM % 58)) $((3 + RANDOM % 2))/" /etc/cron.d/pihole
# Randomize update checker time
sed -i "s/59 17/$((1 + RANDOM % 58)) $((12 + RANDOM % 8))/" /etc/cron.d/pihole
- echo -e "${OVER} ${TICK} ${str}"
+ printf "%b %b %s\\n" "${OVER}" "${TICK}" "${str}"
}
# Gravity is a very important script as it aggregates all of the domains into a single HOSTS formatted list,
@@ -1607,44 +1691,47 @@ runGravity() {
# Check if the pihole user exists and create if it does not
create_pihole_user() {
local str="Checking for user 'pihole'"
- echo -ne " ${INFO} ${str}..."
+ printf " %b %s..." "${INFO}" "${str}"
# If the user pihole exists,
if id -u pihole &> /dev/null; then
# just show a success
- echo -ne "${OVER} ${TICK} ${str}"
+ printf "%b %b %s\\n" "${OVER}" "${TICK}" "${str}"
# Otherwise,
else
- echo -ne "${OVER} ${CROSS} ${str}"
+ printf "%b %b %s" "${OVER}" "${CROSS}" "${str}"
local str="Creating user 'pihole'"
- echo -ne " ${INFO} ${str}..."
+ printf "%b %b %s..." "${OVER}" "${INFO}" "${str}"
# create her with the useradd command
- useradd -r -s /usr/sbin/nologin pihole
- echo -ne "${OVER} ${TICK} ${str}"
+ if useradd -r -s /usr/sbin/nologin pihole; then
+ printf "%b %b %s\\n" "${OVER}" "${TICK}" "${str}"
+ else
+ printf "%b %b %s\\n" "${OVER}" "${CROSS}" "${str}"
+ fi
fi
}
# Allow HTTP and DNS traffic
configureFirewall() {
- echo ""
+ printf "\\n"
# If a firewall is running,
if firewall-cmd --state &> /dev/null; then
# ask if the user wants to install Pi-hole's default firewall rules
whiptail --title "Firewall in use" --yesno "We have detected a running firewall\\n\\nPi-hole currently requires HTTP and DNS port access.\\n\\n\\n\\nInstall Pi-hole default firewall rules?" ${r} ${c} || \
- { echo -e " ${INFO} Not installing firewall rulesets."; return 0; }
- echo -e " ${TICK} Configuring FirewallD for httpd and pihole-FTL"
+ { printf " %b Not installing firewall rulesets.\\n" "${INFO}"; return 0; }
+ printf " %b Configuring FirewallD for httpd and pihole-FTL\\n" "${TICK}"
# Allow HTTP and DNS traffic
firewall-cmd --permanent --add-service=http --add-service=dns
# Reload the firewall to apply these changes
firewall-cmd --reload
return 0
# Check for proper kernel modules to prevent failure
- elif modinfo ip_tables &> /dev/null && command -v iptables &> /dev/null; then
+ elif modinfo ip_tables &> /dev/null && is_command iptables ; then
# If chain Policy is not ACCEPT or last Rule is not ACCEPT
# then check and insert our Rules above the DROP/REJECT Rule.
if iptables -S INPUT | head -n1 | grep -qv '^-P.*ACCEPT$' || iptables -S INPUT | tail -n1 | grep -qv '^-\(A\|P\).*ACCEPT$'; then
whiptail --title "Firewall in use" --yesno "We have detected a running firewall\\n\\nPi-hole currently requires HTTP and DNS port access.\\n\\n\\n\\nInstall Pi-hole default firewall rules?" ${r} ${c} || \
- { echo -e " ${INFO} Not installing firewall rulesets."; return 0; }
- echo -e " ${TICK} Installing new IPTables firewall rulesets"
+ { printf " %b Not installing firewall rulesets.\\n" "${INFO}"; return 0; }
+ printf " %b Installing new IPTables firewall rulesets\\n" "${TICK}"
# Check chain first, otherwise a new rule will duplicate old ones
iptables -C INPUT -p tcp -m tcp --dport 80 -j ACCEPT &> /dev/null || iptables -I INPUT 1 -p tcp -m tcp --dport 80 -j ACCEPT
iptables -C INPUT -p tcp -m tcp --dport 53 -j ACCEPT &> /dev/null || iptables -I INPUT 1 -p tcp -m tcp --dport 53 -j ACCEPT
@@ -1655,11 +1742,11 @@ configureFirewall() {
# Otherwise,
else
# no firewall is running
- echo -e " ${INFO} No active firewall detected.. skipping firewall configuration"
+ printf " %b No active firewall detected.. skipping firewall configuration\\n" "${INFO}"
# so just exit
return 0
fi
- echo -e " ${INFO} Skipping firewall configuration"
+ printf " %b Skipping firewall configuration\\n" "${INFO}"
}
#
@@ -1695,6 +1782,10 @@ finalExports() {
echo "LIGHTTPD_ENABLED=${LIGHTTPD_ENABLED}"
}>> "${setupVars}"
+ # Set the privacy level
+ sed -i '/PRIVACYLEVEL/d' "${PI_HOLE_CONFIG_DIR}/pihole-FTL.conf"
+ echo "PRIVACYLEVEL=${PRIVACY_LEVEL}" >> "${PI_HOLE_CONFIG_DIR}/pihole-FTL.conf"
+
# Bring in the current settings and the functions to manipulate them
source "${setupVars}"
source "${PI_HOLE_LOCAL_REPO}/advanced/Scripts/webpage.sh"
@@ -1710,8 +1801,7 @@ finalExports() {
installLogrotate() {
local str="Installing latest logrotate script"
- echo ""
- echo -ne " ${INFO} ${str}..."
+ printf "\\n %b %s..." "${INFO}" "${str}"
# Copy the file over from the local repo
cp ${PI_HOLE_LOCAL_REPO}/advanced/Templates/logrotate /etc/pihole/logrotate
# Different operating systems have different user / group
@@ -1726,7 +1816,7 @@ installLogrotate() {
#
sed -i "s/# su #/su ${logusergroup}/g;" /etc/pihole/logrotate
fi
- echo -e "${OVER} ${TICK} ${str}"
+ printf "%b %b %s\\n" "${OVER}" "${TICK}" "${str}"
}
# At some point in the future this list can be pruned, for now we'll need it to ensure updates don't break.
@@ -1769,13 +1859,13 @@ installPihole() {
# Give pihole access to the Web server group
usermod -a -G ${LIGHTTPD_GROUP} pihole
# If the lighttpd command is executable,
- if [[ -x "$(command -v lighty-enable-mod)" ]]; then
+ if is_command lighty-enable-mod ; then
# enable fastcgi and fastcgi-php
lighty-enable-mod fastcgi fastcgi-php > /dev/null || true
else
# Otherwise, show info about installing them
- echo -e " ${INFO} Warning: 'lighty-enable-mod' utility not found
- Please ensure fastcgi is enabled if you experience issues\\n"
+ printf " %b Warning: 'lighty-enable-mod' utility not found\\n" "${INFO}"
+ printf " Please ensure fastcgi is enabled if you experience issues\\n"
fi
fi
fi
@@ -1785,12 +1875,12 @@ installPihole() {
fi
# Install base files and web interface
if ! installScripts; then
- echo -e " {CROSS} Failure in dependent script copy function."
+ printf " %b Failure in dependent script copy function.\\n" "${CROSS}"
exit 1
fi
# Install config files
if ! installConfigs; then
- echo -e " {CROSS} Failure in dependent config copy function."
+ printf " %b Failure in dependent config copy function.\\n" "${CROSS}"
exit 1
fi
# If the user wants to install the dashboard,
@@ -1803,7 +1893,7 @@ installPihole() {
# Install the logrotate file
installLogrotate
# Check if FTL is installed
- FTLdetect || echo -e " ${CROSS} FTL Engine not installed"
+ FTLdetect || printf " %b FTL Engine not installed\\n" "${CROSS}"
# Configure the firewall
if [[ "${useUpdateVars}" == false ]]; then
configureFirewall
@@ -1819,18 +1909,18 @@ installPihole() {
# SELinux
checkSelinux() {
# If the getenforce command exists,
- if command -v getenforce &> /dev/null; then
+ if is_command getenforce ; then
# Store the current mode in a variable
enforceMode=$(getenforce)
- echo -e "\\n ${INFO} SELinux mode detected: ${enforceMode}"
+ printf "\\n %b SELinux mode detected: %s\\n" "${INFO}" "${enforceMode}"
# If it's enforcing,
if [[ "${enforceMode}" == "Enforcing" ]]; then
# Explain Pi-hole does not support it yet
whiptail --defaultno --title "SELinux Enforcing Detected" --yesno "SELinux is being ENFORCED on your system! \\n\\nPi-hole currently does not support SELinux, but you may still continue with the installation.\\n\\nNote: Web Admin will not be fully functional unless you set your policies correctly\\n\\nContinue installing Pi-hole?" ${r} ${c} || \
- { echo -e "\\n ${COL_LIGHT_RED}SELinux Enforcing detected, exiting installer${COL_NC}"; exit 1; }
- echo -e " ${INFO} Continuing installation with SELinux Enforcing
- ${INFO} Please refer to official SELinux documentation to create a custom policy"
+ { printf "\\n %bSELinux Enforcing detected, exiting installer%b\\n" "${COL_LIGHT_RED}" "${COL_NC}"; exit 1; }
+ printf " %b Continuing installation with SELinux Enforcing\\n" "${INFO}"
+ printf " %b Please refer to official SELinux documentation to create a custom policy\\n" "${INFO}"
fi
fi
}
@@ -1890,18 +1980,18 @@ update_dialogs() {
UpdateCmd=$(whiptail --title "Existing Install Detected!" --menu "\\n\\nWe have detected an existing install.\\n\\nPlease choose from the following options: \\n($strAdd)" ${r} ${c} 2 \
"${opt1a}" "${opt1b}" \
"${opt2a}" "${opt2b}" 3>&2 2>&1 1>&3) || \
- { echo -e " ${COL_LIGHT_RED}Cancel was selected, exiting installer${COL_NC}"; exit 1; }
+ { printf " %bCancel was selected, exiting installer%b\\n" "${COL_LIGHT_RED}" "${COL_NC}"; exit 1; }
# Set the variable based on if the user chooses
case ${UpdateCmd} in
# repair, or
${opt1a})
- echo -e " ${INFO} ${opt1a} option selected"
+ printf " %b %s option selected\\n" "${INFO}" "${opt1a}"
useUpdateVars=true
;;
# reconfigure,
${opt2a})
- echo -e " ${INFO} ${opt2a} option selected"
+ printf " %b %s option selected\\n" "${INFO}" "${opt2a}"
useUpdateVars=false
;;
esac
@@ -1939,6 +2029,7 @@ get_available_branches() {
cd "${directory}" || return 1
# Get reachable remote branches, but store STDERR as STDOUT variable
output=$( { git ls-remote --heads --quiet | cut -d'/' -f3- -; } 2>&1 )
+ # echo status for calling function to capture
echo "$output"
return
}
@@ -1972,16 +2063,16 @@ checkout_pull_branch() {
oldbranch="$(git symbolic-ref HEAD)"
str="Switching to branch: '${branch}' from '${oldbranch}'"
- echo -ne " ${INFO} $str"
+ printf " %b %s" "${INFO}" "$str"
git checkout "${branch}" --quiet || return 1
- echo -e "${OVER} ${TICK} $str"
+ printf "%b %b %s\\n" "${OVER}" "${TICK}" "$str"
git_pull=$(git pull || return 1)
if [[ "$git_pull" == *"up-to-date"* ]]; then
- echo -e " ${INFO} ${git_pull}"
+ printf " %b %s\\n" "${INFO}" "${git_pull}"
else
- echo -e "$git_pull\\n"
+ printf "%s\\n" "$git_pull"
fi
return 0
@@ -1990,17 +2081,17 @@ checkout_pull_branch() {
clone_or_update_repos() {
# If the user wants to reconfigure,
if [[ "${reconfigure}" == true ]]; then
- echo " ${INFO} Performing reconfiguration, skipping download of local repos"
+ printf " %b Performing reconfiguration, skipping download of local repos\\n" "${INFO}"
# Reset the Core repo
resetRepo ${PI_HOLE_LOCAL_REPO} || \
- { echo -e " ${COL_LIGHT_RED}Unable to reset ${PI_HOLE_LOCAL_REPO}, exiting installer${COL_NC}"; \
+ { printf " %bUnable to reset %s, exiting installer%b\\n" "${COL_LIGHT_RED}" "${PI_HOLE_LOCAL_REPO}" "${COL_NC}"; \
exit 1; \
}
# If the Web interface was installed,
if [[ "${INSTALL_WEB_INTERFACE}" == true ]]; then
# reset it's repo
resetRepo ${webInterfaceDir} || \
- { echo -e " ${COL_LIGHT_RED}Unable to reset ${webInterfaceDir}, exiting installer${COL_NC}"; \
+ { printf " %bUnable to reset %s, exiting installer%b\\n" "${COL_LIGHT_RED}" "${webInterfaceDir}" "${COL_NC}"; \
exit 1; \
}
fi
@@ -2008,14 +2099,14 @@ clone_or_update_repos() {
else
# so get git files for Core
getGitFiles ${PI_HOLE_LOCAL_REPO} ${piholeGitUrl} || \
- { echo -e " ${COL_LIGHT_RED}Unable to clone ${piholeGitUrl} into ${PI_HOLE_LOCAL_REPO}, unable to continue${COL_NC}"; \
+ { printf " %bUnable to clone %s into %s, unable to continue%b\\n" "${COL_LIGHT_RED}" "${piholeGitUrl}" "${PI_HOLE_LOCAL_REPO}" "${COL_NC}"; \
exit 1; \
}
# If the Web interface was installed,
if [[ "${INSTALL_WEB_INTERFACE}" == true ]]; then
# get the Web git files
getGitFiles ${webInterfaceDir} ${webInterfaceGitUrl} || \
- { echo -e " ${COL_LIGHT_RED}Unable to clone ${webInterfaceGitUrl} into ${webInterfaceDir}, exiting installer${COL_NC}"; \
+ { printf " %bUnable to clone %s into ${webInterfaceDir}, exiting installer%b\\n" "${COL_LIGHT_RED}" "${webInterfaceGitUrl}" "${COL_NC}"; \
exit 1; \
}
fi
@@ -2028,19 +2119,19 @@ FTLinstall() {
local binary="${1}"
local latesttag
local str="Downloading and Installing FTL"
- echo -ne " ${INFO} ${str}..."
+ printf " %b %s..." "${INFO}" "${str}"
# Find the latest version tag for FTL
latesttag=$(curl -sI https://github.com/pi-hole/FTL/releases/latest | grep "Location" | awk -F '/' '{print $NF}')
# Tags should always start with v, check for that.
if [[ ! "${latesttag}" == v* ]]; then
- echo -e "${OVER} ${CROSS} ${str}"
- echo -e " ${COL_LIGHT_RED}Error: Unable to get latest release location from GitHub${COL_NC}"
+ printf "%b %b %s\\n" "${OVER}" "${CROSS}" "${str}"
+ printf " %bError: Unable to get latest release location from GitHub%b\\n" "${COL_LIGHT_RED}" "${COL_NC}"
return 1
fi
# Move into the temp ftl directory
- pushd "$(mktemp -d)" > /dev/null || { echo "Unable to make temporary directory for FTL binary download"; return 1; }
+ pushd "$(mktemp -d)" > /dev/null || { printf "Unable to make temporary directory for FTL binary download\\n"; return 1; }
# Always replace pihole-FTL.service
install -T -m 0755 "${PI_HOLE_LOCAL_REPO}/advanced/Templates/pihole-FTL.service" "/etc/init.d/pihole-FTL"
@@ -2068,46 +2159,49 @@ FTLinstall() {
# If we downloaded binary file (as opposed to text),
if sha1sum --status --quiet -c "${binary}".sha1; then
- echo -n "transferred... "
+ printf "transferred... "
# Stop FTL
stop_service pihole-FTL &> /dev/null
# Install the new version with the correct permissions
install -T -m 0755 "${binary}" /usr/bin/pihole-FTL
# Move back into the original directory the user was in
- popd > /dev/null || { echo "Unable to return to original directory after FTL binary download."; return 1; }
+ popd > /dev/null || { printf "Unable to return to original directory after FTL binary download.\\n"; return 1; }
# Install the FTL service
- echo -e "${OVER} ${TICK} ${str}"
+ printf "%b %b %s\\n" "${OVER}" "${TICK}" "${str}"
# dnsmasq can now be stopped and disabled if it exists
if which dnsmasq &> /dev/null; then
if check_service_active "dnsmasq";then
- echo " ${INFO} FTL can now resolve DNS Queries without dnsmasq running separately"
+ printf " %b FTL can now resolve DNS Queries without dnsmasq running separately\\n" "${INFO}"
stop_service dnsmasq
disable_service dnsmasq
fi
fi
- #ensure /etc/dnsmasq.conf contains `conf-dir=/etc/dnsmasq.d`
- confdir="conf-dir=/etc/dnsmasq.d"
- conffile="/etc/dnsmasq.conf"
- if ! grep -q "$confdir" "$conffile"; then
- echo "$confdir" >> "$conffile"
+ # Backup existing /etc/dnsmasq.conf if present and ensure that
+ # /etc/dnsmasq.conf contains only "conf-dir=/etc/dnsmasq.d"
+ local conffile="/etc/dnsmasq.conf"
+ if [[ -f "${conffile}" ]]; then
+ printf " %b Backing up %s to %s.old\\n" "${INFO}" "${conffile}" "${conffile}"
+ mv "${conffile}" "${conffile}.old"
fi
+ # Create /etc/dnsmasq.conf
+ echo "conf-dir=/etc/dnsmasq.d" > "${conffile}"
return 0
# Otherwise,
else
# the download failed, so just go back to the original directory
- popd > /dev/null || { echo "Unable to return to original directory after FTL binary download."; return 1; }
- echo -e "${OVER} ${CROSS} ${str}"
- echo -e " ${COL_LIGHT_RED}Error: Download of binary from Github failed${COL_NC}"
+ popd > /dev/null || { printf "Unable to return to original directory after FTL binary download.\\n"; return 1; }
+ printf "%b %b %s\\n" "${OVER}" "${CROSS}" "${str}"
+ printf " %bError: Download of %s/%s failed (checksum error)%b\\n" "${COL_LIGHT_RED}" "${url}" "${binary}" "${COL_NC}"
return 1
fi
# Otherwise,
else
- popd > /dev/null || { echo "Unable to return to original directory after FTL binary download."; return 1; }
- echo -e "${OVER} ${CROSS} ${str}"
+ popd > /dev/null || { printf "Unable to return to original directory after FTL binary download.\\n"; return 1; }
+ printf "%b %b %s\\n" "${OVER}" "${CROSS}" "${str}"
# The URL could not be found
- echo -e " ${COL_LIGHT_RED}Error: URL not found${COL_NC}"
+ printf " %bError: URL %s/%s not found%b\\n" "${COL_LIGHT_RED}" "${url}" "${binary}" "${COL_NC}"
return 1
fi
}
@@ -2118,7 +2212,7 @@ get_binary_name() {
machine=$(uname -m)
local str="Detecting architecture"
- echo -ne " ${INFO} ${str}..."
+ printf " %b %s..." "${INFO}" "${str}"
# If the machine is arm or aarch
if [[ "${machine}" == "arm"* || "${machine}" == *"aarch"* ]]; then
# ARM
@@ -2130,32 +2224,27 @@ get_binary_name() {
lib=$(ldd /bin/ls | grep -E '^\s*/lib' | awk '{ print $1 }')
#
if [[ "${lib}" == "/lib/ld-linux-aarch64.so.1" ]]; then
- echo -e "${OVER} ${TICK} Detected ARM-aarch64 architecture"
+ printf "%b %b Detected ARM-aarch64 architecture\\n" "${OVER}" "${TICK}"
# set the binary to be used
binary="pihole-FTL-aarch64-linux-gnu"
#
elif [[ "${lib}" == "/lib/ld-linux-armhf.so.3" ]]; then
#
if [[ "${rev}" -gt 6 ]]; then
- echo -e "${OVER} ${TICK} Detected ARM-hf architecture (armv7+)"
+ printf "%b %b Detected ARM-hf architecture (armv7+)\\n" "${OVER}" "${TICK}"
# set the binary to be used
binary="pihole-FTL-arm-linux-gnueabihf"
# Otherwise,
else
- echo -e "${OVER} ${TICK} Detected ARM-hf architecture (armv6 or lower) Using ARM binary"
+ printf "%b %b Detected ARM-hf architecture (armv6 or lower) Using ARM binary\\n" "${OVER}" "${TICK}"
# set the binary to be used
binary="pihole-FTL-arm-linux-gnueabi"
fi
else
- echo -e "${OVER} ${TICK} Detected ARM architecture"
+ printf "%b %b Detected ARM architecture\\n" "${OVER}" "${TICK}"
# set the binary to be used
binary="pihole-FTL-arm-linux-gnueabi"
fi
- elif [[ "${machine}" == "ppc" ]]; then
- # PowerPC
- echo -e "${OVER} ${TICK} Detected PowerPC architecture"
- # set the binary to be used
- binary="pihole-FTL-powerpc-linux-gnu"
elif [[ "${machine}" == "x86_64" ]]; then
# This gives the architecture of packages dpkg installs (for example, "i386")
local dpkgarch
@@ -2164,22 +2253,22 @@ get_binary_name() {
# Special case: This is a 32 bit OS, installed on a 64 bit machine
# -> change machine architecture to download the 32 bit executable
if [[ "${dpkgarch}" == "i386" ]]; then
- echo -e "${OVER} ${TICK} Detected 32bit (i686) architecture"
+ printf "%b %b Detected 32bit (i686) architecture\\n" "${OVER}" "${TICK}"
binary="pihole-FTL-linux-x86_32"
else
# 64bit
- echo -e "${OVER} ${TICK} Detected x86_64 architecture"
+ printf "%b %b Detected x86_64 architecture\\n" "${OVER}" "${TICK}"
# set the binary to be used
binary="pihole-FTL-linux-x86_64"
fi
else
# Something else - we try to use 32bit executable and warn the user
if [[ ! "${machine}" == "i686" ]]; then
- echo -e "${OVER} ${CROSS} ${str}..."
- echo -e " ${INFO} ${COL_LIGHT_RED}Not able to detect architecture (unknown: ${machine}), trying 32bit executable${COL_NC}"
- echo -e " ${INFO} Contact Pi-hole Support if you experience issues (e.g: FTL not running)"
+ printf "%b %b %s...\\n" "${OVER}" "${CROSS}" "${str}"
+ printf " %b %bNot able to detect architecture (unknown: %s), trying 32bit executable%b\\n" "${INFO}" "${COL_LIGHT_RED}" "${machine}" "${COL_NC}"
+ printf " %b Contact Pi-hole Support if you experience issues (e.g: FTL not running)\\n" "${INFO}"
else
- echo -e "${OVER} ${TICK} Detected 32bit (i686) architecture"
+ printf "%b %b Detected 32bit (i686) architecture\\n" "${OVER}" "${TICK}"
fi
binary="pihole-FTL-linux-x86_32"
fi
@@ -2190,7 +2279,7 @@ FTLcheckUpdate() {
#In the next section we check to see if FTL is already installed (in case of pihole -r).
#If the installed version matches the latest version, then check the installed sha1sum of the binary vs the remote sha1sum. If they do not match, then download
- echo -e " ${INFO} Checking for existing FTL binary..."
+ printf " %b Checking for existing FTL binary...\\n" "${INFO}"
local ftlLoc
ftlLoc=$(which pihole-FTL 2>/dev/null)
@@ -2219,7 +2308,8 @@ FTLcheckUpdate() {
path="${ftlBranch}/${binary}"
# shellcheck disable=SC1090
if ! check_download_exists "$path"; then
- echo -e " ${INFO} Branch \"${ftlBranch}\" is not available.\\n ${INFO} Use ${COL_LIGHT_GREEN}pihole checkout ftl [branchname]${COL_NC} to switch to a valid branch."
+ printf " %b Branch \"%s\" is not available.\\n" "${INFO}" "${ftlBranch}"
+ printf " %b Use %bpihole checkout ftl [branchname]%b to switch to a valid branch.\\n" "${INFO}" "${COL_LIGHT_GREEN}" "${COL_NC}"
return 2
fi
@@ -2230,10 +2320,10 @@ FTLcheckUpdate() {
localSha1=$(sha1sum "$(which pihole-FTL)" | cut -d ' ' -f 1)
if [[ "${remoteSha1}" != "${localSha1}" ]]; then
- echo -e " ${INFO} Checksums do not match, downloading from ftl.pi-hole.net."
+ printf " %b Checksums do not match, downloading from ftl.pi-hole.net.\\n" "${INFO}"
return 0
else
- echo -e " ${INFO} Checksum of installed binary matches remote. No need to download!"
+ printf " %b Checksum of installed binary matches remote. No need to download!\\n" "${INFO}"
return 1
fi
else
@@ -2249,16 +2339,16 @@ FTLcheckUpdate() {
if [[ "${FTLversion}" != "${FTLlatesttag}" ]]; then
return 0
else
- echo -e " ${INFO} Latest FTL Binary already installed (${FTLlatesttag}). Confirming Checksum..."
+ printf " %b Latest FTL Binary already installed (%s). Confirming Checksum...\\n" "${INFO}" "${FTLlatesttag}"
remoteSha1=$(curl -sSL --fail "https://github.com/pi-hole/FTL/releases/download/${FTLversion%$'\r'}/${binary}.sha1" | cut -d ' ' -f 1)
localSha1=$(sha1sum "$(which pihole-FTL)" | cut -d ' ' -f 1)
if [[ "${remoteSha1}" != "${localSha1}" ]]; then
- echo -e " ${INFO} Corruption detected..."
+ printf " %b Corruption detected...\\n" "${INFO}"
return 0
else
- echo -e " ${INFO} Checksum correct. No need to download!"
+ printf " %b Checksum correct. No need to download!\\n" "${INFO}"
return 1
fi
fi
@@ -2270,14 +2360,11 @@ FTLcheckUpdate() {
# Detect suitable FTL binary platform
FTLdetect() {
- echo ""
- echo -e " ${INFO} FTL Checks..."
+ printf "\\n %b FTL Checks...\\n\\n" "${INFO}"
if FTLcheckUpdate ; then
FTLinstall "${binary}" || return 1
fi
-
- echo ""
}
make_temporary_log() {
@@ -2302,37 +2389,37 @@ main() {
######## FIRST CHECK ########
# Must be root to install
local str="Root user check"
- echo ""
+ printf "\\n"
# If the user's id is zero,
if [[ "${EUID}" -eq 0 ]]; then
# they are root and all is good
- echo -e " ${TICK} ${str}"
+ printf " %b %s\\n" "${TICK}" "${str}"
# Show the Pi-hole logo so people know it's genuine since the logo and name are trademarked
show_ascii_berry
make_temporary_log
# Otherwise,
else
# They do not have enough privileges, so let the user know
- echo -e " ${CROSS} ${str}"
- echo -e " ${INFO} ${COL_LIGHT_RED}Script called with non-root privileges${COL_NC}"
- echo -e " ${INFO} The Pi-hole requires elevated privileges to install and run"
- echo -e " ${INFO} Please check the installer for any concerns regarding this requirement"
- echo -e " ${INFO} Make sure to download this script from a trusted source\\n"
- echo -ne " ${INFO} Sudo utility check"
+ printf " %b %s\\n" "${CROSS}" "${str}"
+ printf " %b %bScript called with non-root privileges%b\\n" "${INFO}" "${COL_LIGHT_RED}" "${COL_NC}"
+ printf " The Pi-hole requires elevated privileges to install and run\\n"
+ printf " Please check the installer for any concerns regarding this requirement\\n"
+ printf " Make sure to download this script from a trusted source\\n\\n"
+ printf " %b Sudo utility check" "${INFO}"
# If the sudo command exists,
- if command -v sudo &> /dev/null; then
- echo -e "${OVER} ${TICK} Sudo utility check"
+ if is_command sudo ; then
+ printf "%b %b Sudo utility check\\n" "${OVER}" "${TICK}"
# Download the install script and run it with admin rights
exec curl -sSL https://raw.githubusercontent.com/pi-hole/pi-hole/master/automated%20install/basic-install.sh | sudo bash "$@"
exit $?
# Otherwise,
else
# Let them know they need to run it as root
- echo -e "${OVER} ${CROSS} Sudo utility check"
- echo -e " ${INFO} Sudo is needed for the Web Interface to run pihole commands\\n"
- echo -e " ${INFO} ${COL_LIGHT_RED}Please re-run this installer as root${COL_NC}"
+ printf "%b %b Sudo utility check\\n" "${OVER}" "${CROSS}"
+ printf " %b Sudo is needed for the Web Interface to run pihole commands\\n\\n" "${INFO}"
+ printf " %b %bPlease re-run this installer as root${COL_NC}\\n" "${INFO}" "${COL_LIGHT_RED}"
exit 1
fi
fi
@@ -2344,9 +2431,11 @@ main() {
if [[ -f "${setupVars}" ]]; then
# if it's running unattended,
if [[ "${runUnattended}" == true ]]; then
- echo -e " ${INFO} Performing unattended setup, no whiptail dialogs will be displayed"
+ printf " %b Performing unattended setup, no whiptail dialogs will be displayed\\n" "${INFO}"
# Use the setup variables
useUpdateVars=true
+ # also disable debconf-apt-progress dialogs
+ export DEBIAN_FRONTEND="noninteractive"
# Otherwise,
else
# show the available options (repair/reconfigure)
@@ -2357,7 +2446,7 @@ main() {
# Start the installer
# Verify there is enough disk space for the install
if [[ "${skipSpaceCheck}" == true ]]; then
- echo -e " ${INFO} Skipping free disk space verification"
+ printf" %b Skipping free disk space verification\\n" "${INFO}"
else
verifyFreeDiskSpace
fi
@@ -2393,9 +2482,22 @@ main() {
setAdminFlag
# Let the user decide if they want query logging enabled...
setLogging
+ # Let the user decide the FTL privacy level
+ setPrivacyLevel
else
+ # Setup adlist file if not exists
+ installDefaultBlocklists
+
# Source ${setupVars} to use predefined user variables in the functions
source ${setupVars}
+
+ # Get the privacy level if it exists (default is 0)
+ if [[ -f "${PI_HOLE_CONFIG_DIR}/pihole-FTL.conf" ]]; then
+ PRIVACY_LEVEL=$(sed -ne 's/PRIVACYLEVEL=\(.*\)/\1/p' "${PI_HOLE_CONFIG_DIR}/pihole-FTL.conf")
+
+ # If no setting was found, default to 0
+ PRIVACY_LEVEL="${PRIVACY_LEVEL:-0}"
+ fi
fi
# Clone/Update the repos
clone_or_update_repos
@@ -2454,16 +2556,19 @@ main() {
start_service lighttpd
enable_service lighttpd
else
- echo -e " ${INFO} Lighttpd is disabled, skipping service restart"
+ printf " %b Lighttpd is disabled, skipping service restart\\n" "${INFO}"
fi
fi
- echo -e " ${INFO} Restarting services..."
+ printf " %b Restarting services...\\n" "${INFO}"
# Start services
# Enable FTL
- start_service pihole-FTL
+ # Ensure the service is enabled before trying to start it
+ # Fixes a problem reported on Ubuntu 18.04 where trying to start
+ # the service before enabling causes installer to exit
enable_service pihole-FTL
+ start_service pihole-FTL
# Download and compile the aggregated block list
runGravity
@@ -2481,33 +2586,32 @@ main() {
# If there is a password,
if (( ${#pw} > 0 )) ; then
# display the password
- echo -e " ${INFO} Web Interface password: ${COL_LIGHT_GREEN}${pw}${COL_NC}"
- echo -e " ${INFO} This can be changed using 'pihole -a -p'\\n"
+ printf " %b Web Interface password: %b%s%b\\n" "${INFO}" "${COL_LIGHT_GREEN}" "${pw}" "${COL_NC}"
+ printf " %b This can be changed using 'pihole -a -p'\\n\\n" "${INFO}"
fi
fi
if [[ "${useUpdateVars}" == false ]]; then
# If the Web interface was installed,
if [[ "${INSTALL_WEB_INTERFACE}" == true ]]; then
- echo -e " ${INFO} View the web interface at http://pi.hole/admin or http://${IPV4_ADDRESS%/*}/admin"
- echo ""
+ printf " %b View the web interface at http://pi.hole/admin or http://%s/admin\\n\\n" "${INFO}" "${IPV4_ADDRESS%/*}"
fi
# Explain to the user how to use Pi-hole as their DNS server
- echo -e " ${INFO} You may now configure your devices to use the Pi-hole as their DNS server"
- [[ -n "${IPV4_ADDRESS%/*}" ]] && echo -e " ${INFO} Pi-hole DNS (IPv4): ${IPV4_ADDRESS%/*}"
- [[ -n "${IPV6_ADDRESS}" ]] && echo -e " ${INFO} Pi-hole DNS (IPv6): ${IPV6_ADDRESS}"
- echo -e " ${INFO} If you set a new IP address, please restart the server running the Pi-hole"
+ printf " %b You may now configure your devices to use the Pi-hole as their DNS server\\n" "${INFO}"
+ [[ -n "${IPV4_ADDRESS%/*}" ]] && printf " %b Pi-hole DNS (IPv4): %s\\n" "${INFO}" "${IPV4_ADDRESS%/*}"
+ [[ -n "${IPV6_ADDRESS}" ]] && printf " %b Pi-hole DNS (IPv6): %s\\n" "${INFO}" "${IPV6_ADDRESS}"
+ printf " %b If you set a new IP address, please restart the server running the Pi-hole\\n" "${INFO}"
INSTALL_TYPE="Installation"
else
INSTALL_TYPE="Update"
fi
# Display where the log file is
- echo -e "\\n ${INFO} The install log is located at: ${installLogLoc}
- ${COL_LIGHT_GREEN}${INSTALL_TYPE} Complete! ${COL_NC}"
+ printf "\\n %b The install log is located at: %s\\n" "${INFO}" "${installLogLoc}"
+ printf "%b%s Complete! %b\\n" "${COL_LIGHT_GREEN}" "${INSTALL_TYPE}" "${COL_NC}"
if [[ "${INSTALL_TYPE}" == "Update" ]]; then
- echo ""
+ printf "\\n"
/usr/local/bin/pihole version --current
fi
}
diff --git a/automated install/uninstall.sh b/automated install/uninstall.sh
index 9322de92..52760cfb 100755
--- a/automated install/uninstall.sh
+++ b/automated install/uninstall.sh
@@ -106,7 +106,7 @@ removeNoPurge() {
${SUDO} rm -rf /var/www/html/pihole &> /dev/null
${SUDO} rm -f /var/www/html/index.lighttpd.orig &> /dev/null
- # If the web directory is empty after removing these files, then the parent html folder can be removed.
+ # If the web directory is empty after removing these files, then the parent html directory can be removed.
if [ -d "/var/www/html" ]; then
if [[ ! "$(ls -A /var/www/html)" ]]; then
${SUDO} rm -rf /var/www/html &> /dev/null
diff --git a/gravity.sh b/gravity.sh
index 50c37784..75a51608 100755
--- a/gravity.sh
+++ b/gravity.sh
@@ -68,11 +68,35 @@ else
exit 1
fi
+# Source pihole-FTL from install script
+pihole_FTL="${piholeDir}/pihole-FTL.conf"
+if [[ -f "${pihole_FTL}" ]]; then
+ source "${pihole_FTL}"
+fi
+
+if [[ -z "${BLOCKINGMODE}" ]] ; then
+ BLOCKINGMODE="NULL"
+fi
+
# Determine if superseded pihole.conf exists
if [[ -r "${piholeDir}/pihole.conf" ]]; then
echo -e " ${COL_LIGHT_RED}Ignoring overrides specified within pihole.conf! ${COL_NC}"
fi
+# Determine if Pi-hole blocking is disabled
+# If this is the case, we want to update
+# gravity.list.bck and black.list.bck instead of
+# gravity.list and black.list
+detect_pihole_blocking_status() {
+ if [[ "${BLOCKING_ENABLED}" == false ]]; then
+ echo -e " ${INFO} Pi-hole blocking is disabled"
+ adList="${adList}.bck"
+ blackList="${blackList}.bck"
+ else
+ echo -e " ${INFO} Pi-hole blocking is enabled"
+ fi
+}
+
# Determine if DNS resolution is available before proceeding
gravity_CheckDNSResolutionAvailable() {
local lookupDomain="pi.hole"
@@ -182,7 +206,7 @@ gravity_SetDownloadOptions() {
activeDomains[$i]="${saveLocation}"
# Default user-agent (for Cloudflare's Browser Integrity Check: https://support.cloudflare.com/hc/en-us/articles/200170086-What-does-the-Browser-Integrity-Check-do-)
- agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.0 Safari/537.36"
+ agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36"
# Provide special commands for blocklists which may need them
case "${domain}" in
@@ -216,6 +240,39 @@ gravity_DownloadBlocklistFromUrl() {
str="Status:"
echo -ne " ${INFO} ${str} Pending..."
+ blocked=false
+ case $BLOCKINGMODE in
+ "IP-NODATA-AAAA"|"IP")
+ if [[ $(dig "${domain}" +short | grep "${IPV4_ADDRESS}" -c) -ge 1 ]]; then
+ blocked=true
+ fi;;
+ "NXDOMAIN")
+ if [[ $(dig "${domain}" | grep "NXDOMAIN" -c) -ge 1 ]]; then
+ blocked=true
+ fi;;
+ "NULL"|*)
+ if [[ $(dig "${domain}" +short | grep "0.0.0.0" -c) -ge 1 ]]; then
+ blocked=true
+ fi;;
+ esac
+
+ if [[ "${blocked}" == true ]]; then
+ printf -v ip_addr "%s" "${PIHOLE_DNS_1%#*}"
+ if [[ ${PIHOLE_DNS_1} != *"#"* ]]; then
+ port=53
+ else
+ printf -v port "%s" "${PIHOLE_DNS_1#*#}"
+ fi
+ ip=$(dig "@${ip_addr}" -p "${port}" +short "${domain}")
+ if [[ $(echo "${url}" | awk -F '://' '{print $1}') = "https" ]]; then
+ port=443;
+ else port=80
+ fi
+ bad_list=$(pihole -q -adlist hosts-file.net | 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"
+ fi
# shellcheck disable=SC2086
httpCode=$(curl -s -L ${cmd_ext} ${heisenbergCompensator} -w "%{http_code}" -A "${agent}" "${url}" -o "${patternBuffer}" 2> /dev/null)
@@ -464,7 +521,7 @@ gravity_ShowBlockCount() {
fi
if [[ -f "${regexFile}" ]]; then
- num=$(grep -c "^(?!#)" "${regexFile}")
+ num=$(grep -cv "^#" "${regexFile}")
echo -e " ${INFO} Number of regex filters: ${num}"
fi
}
@@ -522,7 +579,7 @@ gravity_ParseBlacklistDomains() {
mv "${piholeDir}/${whitelistMatter}" "${piholeDir}/${accretionDisc}"
else
# There was no whitelist file, so use preEventHorizon instead of whitelistMatter.
- mv "${piholeDir}/${preEventHorizon}" "${piholeDir}/${accretionDisc}"
+ cp "${piholeDir}/${preEventHorizon}" "${piholeDir}/${accretionDisc}"
fi
# Move the file over as /etc/pihole/gravity.list so dnsmasq can use it
@@ -621,6 +678,8 @@ if [[ "${forceDelete:-}" == true ]]; then
echo -e "${OVER} ${TICK} ${str}"
fi
+detect_pihole_blocking_status
+
# Determine which functions to run
if [[ "${skipDownload}" == false ]]; then
# Gravity needs to download blocklists
diff --git a/pihole b/pihole
index 8be03f79..d4681752 100755
--- a/pihole
+++ b/pihole
@@ -10,7 +10,14 @@
# Please see LICENSE file for your rights under this license.
readonly PI_HOLE_SCRIPT_DIR="/opt/pihole"
-readonly wildcardlist="/etc/dnsmasq.d/03-pihole-wildcard.conf"
+readonly gravitylist="/etc/pihole/gravity.list"
+readonly blacklist="/etc/pihole/black.list"
+
+# setupVars is not readonly here because in some funcitons (checkout),
+# it might get set again when the installer is sourced. This causes an
+# error due to modifying a readonly variable.
+setupVars="/etc/pihole/setupVars.conf"
+
readonly colfile="${PI_HOLE_SCRIPT_DIR}/COL_TABLE"
source "${colfile}"
@@ -73,7 +80,7 @@ reconfigurePiholeFunc() {
updateGravityFunc() {
"${PI_HOLE_SCRIPT_DIR}"/gravity.sh "$@"
- exit 0
+ exit $?
}
queryFunc() {
@@ -127,9 +134,11 @@ restartDNS() {
if [[ "${status}" -eq 0 ]]; then
[[ -t 1 ]] && echo -e "${OVER} ${TICK} ${str}"
+ return 0
else
[[ ! -t 1 ]] && local OVER=""
echo -e "${OVER} ${CROSS} ${output}"
+ return 1
fi
}
@@ -146,10 +155,13 @@ Time:
elif [[ "${1}" == "0" ]]; then
# Disable Pi-hole
- sed -i 's/^addn-hosts=\/etc\/pihole\/gravity.list/#addn-hosts=\/etc\/pihole\/gravity.list/' /etc/dnsmasq.d/01-pihole.conf
- sed -i 's/^addn-hosts=\/etc\/pihole\/black.list/#addn-hosts=\/etc\/pihole\/black.list/' /etc/dnsmasq.d/01-pihole.conf
- if [[ -e "$wildcardlist" ]]; then
- mv "$wildcardlist" "/etc/pihole/wildcard.list"
+ if [[ -e "${gravitylist}" ]]; then
+ mv "${gravitylist}" "${gravitylist}.bck"
+ echo "" > "${gravitylist}"
+ fi
+ if [[ -e "${blacklist}" ]]; then
+ mv "${blacklist}" "${blacklist}.bck"
+ echo "" > "${blacklist}"
fi
if [[ $# > 1 ]]; then
local error=false
@@ -187,19 +199,25 @@ Time:
fi
local str="Pi-hole Disabled"
+ sed -i "/BLOCKING_ENABLED=/d" "${setupVars}"
+ echo "BLOCKING_ENABLED=false" >> "${setupVars}"
fi
else
# Enable Pi-hole
echo -e " ${INFO} Enabling blocking"
local str="Pi-hole Enabled"
- sed -i 's/^#addn-hosts/addn-hosts/' /etc/dnsmasq.d/01-pihole.conf
- if [[ -e "/etc/pihole/wildcard.list" ]]; then
- mv "/etc/pihole/wildcard.list" "$wildcardlist"
+ if [[ -e "${gravitylist}.bck" ]]; then
+ mv "${gravitylist}.bck" "${gravitylist}"
fi
+ if [[ -e "${blacklist}.bck" ]]; then
+ mv "${blacklist}.bck" "${blacklist}"
+ fi
+ sed -i "/BLOCKING_ENABLED=/d" "${setupVars}"
+ echo "BLOCKING_ENABLED=true" >> "${setupVars}"
fi
- restartDNS
+ restartDNS reload
echo -e "${OVER} ${TICK} ${str}"
}
@@ -242,8 +260,6 @@ Options:
}
statusFunc() {
- local addnConfigs
-
# Determine if service is running on port 53 (Cr: https://superuser.com/a/806331)
if (echo > /dev/tcp/127.0.0.1/53) >/dev/null 2>&1; then
if [[ "${1}" != "web" ]]; then
@@ -257,16 +273,14 @@ statusFunc() {
return 0
fi
- # Determine if Pi-hole's addn-hosts configs are commented out
- addnConfigs=$(grep -i "addn-hosts=/" /etc/dnsmasq.d/01-pihole.conf)
-
- if [[ "${addnConfigs}" =~ "#" ]]; then
+ # Determine if Pi-hole's blocking is enabled
+ if grep -q "BLOCKING_ENABLED=false" /etc/pihole/setupVars.conf; then
# A config is commented out
case "${1}" in
"web") echo 0;;
*) echo -e " ${CROSS} Pi-hole blocking is Disabled";;
esac
- elif [[ -n "${addnConfigs}" ]]; then
+ elif grep -q "BLOCKING_ENABLED=true" /etc/pihole/setupVars.conf; then
# Configs are set
case "${1}" in
"web") echo 1;;
@@ -276,11 +290,10 @@ statusFunc() {
# No configs were found
case "${1}" in
"web") echo 99;;
- *) echo -e " ${INFO} No hosts file linked to dnsmasq, adding it in enabled state";;
+ *) echo -e " ${INFO} Pi-hole blocking will be enabled";;
esac
- # Add addn-host= to dnsmasq
- echo "addn-hosts=/etc/pihole/gravity.list" >> /etc/dnsmasq.d/01-pihole.conf
- restartDNS
+ # Enable blocking
+ pihole enable
fi
}
@@ -303,7 +316,7 @@ tailFunc() {
# Colour everything else as gray
tail -f /var/log/pihole.log | sed -E \
-e "s,($(date +'%b %d ')| dnsmasq[.*[0-9]]),,g" \
- -e "s,(.*(gravity.list|black.list| config ).* is (${IPV4_ADDRESS%/*}|${IPV6_ADDRESS:-NULL}).*),${COL_RED}&${COL_NC}," \
+ -e "s,(.*(gravity.list|black.list|regex.list| config ).* is (0.0.0.0|::|NXDOMAIN|${IPV4_ADDRESS%/*}|${IPV6_ADDRESS:-NULL}).*),${COL_RED}&${COL_NC}," \
-e "s,.*(query\\[A|DHCP).*,${COL_NC}&${COL_NC}," \
-e "s,.*,${COL_GRAY}&${COL_NC},"
exit 0
diff --git a/test/test_automated_install.py b/test/test_automated_install.py
index 876b06eb..a2593d83 100644
--- a/test/test_automated_install.py
+++ b/test/test_automated_install.py
@@ -81,6 +81,7 @@ def test_setupVars_saved_to_file(Pihole):
{}
mkdir -p /etc/dnsmasq.d
version_check_dnsmasq
+ echo "" > /etc/pihole/pihole-FTL.conf
finalExports
cat /etc/pihole/setupVars.conf
'''.format(set_setup_vars))
@@ -501,8 +502,10 @@ def test_FTL_download_unknown_fails_no_errors(Pihole):
''')
expected_stdout = cross_box + ' Downloading and Installing FTL'
assert expected_stdout in download_binary.stdout
- error = 'Error: URL not found'
- assert error in download_binary.stdout
+ error1 = 'Error: URL https://github.com/pi-hole/FTL/releases/download/'
+ assert error1 in download_binary.stdout
+ error2 = 'not found'
+ assert error2 in download_binary.stdout
def test_FTL_binary_installed_and_responsive_no_errors(Pihole):
diff --git a/test/test_centos_fedora_support.py b/test/test_centos_fedora_support.py
index 8318e44a..df53d73f 100644
--- a/test/test_centos_fedora_support.py
+++ b/test/test_centos_fedora_support.py
@@ -31,20 +31,13 @@ def test_release_supported_version_check_centos(Pihole):
'''
confirms installer exits on unsupported releases of CentOS
'''
- # mock CentOS release < 7 (unsupported)
- mock_command_2(
- 'rpm',
- {"-q --queryformat '%{VERSION}' centos-release'": (
- '5',
- '0'
- )},
- Pihole
- )
+ # modify /etc/redhat-release to mock an unsupported CentOS release
+ Pihole.run('echo "CentOS Linux release 6.9" > /etc/redhat-release')
distro_check = Pihole.run('''
source /opt/pihole/basic-install.sh
distro_check
''')
- expected_stdout = cross_box + (' CentOS is not suported.')
+ expected_stdout = cross_box + (' CentOS 6 is not supported.')
assert expected_stdout in distro_check.stdout
expected_stdout = 'Please update to CentOS release 7 or later'
assert expected_stdout in distro_check.stdout