diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 071fdf89..b289a1c0 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -8,4 +8,4 @@ Changes proposed in this pull request: - -@pihole/gravity +@pi-hole/gravity diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..e43b0f98 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.DS_Store diff --git a/README.md b/README.md index 1a181d6f..851e1639 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,11 @@ # Automated Install -##### Designed For Raspberry Pi A+, B, B+, 2, and Zero (with an Ethernet/Wi-Fi adapter) +##### Designed For Raspberry Pi A+, B, B+, 2, Zero, and 3B (with an Ethernet/Wi-Fi adapter) (Works on most Debian distributions!) + + +[![Join the chat at https://gitter.im/pi-hole/pi-hole](https://badges.gitter.im/pi-hole/pi-hole.svg)](https://gitter.im/pi-hole/pi-hole?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 1. Install Raspbian + 2. Run the command below ### ```curl -L https://install.pi-hole.net | bash``` @@ -29,6 +33,7 @@ reddit: [/r/pihole](https://www.reddit.com/r/pihole/) [![Pi-hole exlplained](http://i.imgur.com/qNybJDX.png)](https://vimeo.com/135965232) ## Pi-hole Projects +- [Get LED alerts for each blocked ad](http://www.stinebaugh.info/get-led-alerts-for-each-blocked-ad-using-pi-hole/) - [Pi-hole on Ubuntu 14.04 on VirtualBox](http://hbalagtas.blogspot.com/2016/02/adblocking-with-pi-hole-and-ubuntu-1404.html) - [x86 Docker container that runs Pi-hole](https://hub.docker.com/r/diginc/pi-hole/) - [Splunk: Pi-hole Visualizser](https://splunkbase.splunk.com/app/3023/) @@ -41,6 +46,7 @@ reddit: [/r/pihole](https://www.reddit.com/r/pihole/) - [Minibian Pi-hole](http://munkjensen.net/wiki/index.php/See_my_Pi-Hole#Minibian_Pi-hole) ## Coverage +- [TekThing: 5 fun, easy projects for a Raspberry Pi](https://youtu.be/QwrKlyC2kdM?t=1m42s) - [Pi-hole on Adafruit's blog](https://blog.adafruit.com/2016/03/04/pi-hole-is-a-black-hole-for-internet-ads-piday-raspberrypi-raspberry_pi/) - [The Defrag Show - MSDN/Channel 9](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) - [MacObserver Podcast 585](http://www.macobserver.com/tmo/podcast/macgeekgab-585) diff --git a/adlists.default b/adlists.default index 0d99244f..8a396729 100644 --- a/adlists.default +++ b/adlists.default @@ -5,11 +5,11 @@ # 2. run `nano /etc/pihole/adlists.list` # # 3. Uncomment or comment any of the below lists # # # -# Know of any other lists? Feel free to let us know about them, or add them # +# Know of any other lists? Feel free to let us know about them, or add them # # to this file! # ################################################################################ -# The below list amalgamates several lists we used previously. +# The below list amalgamates several lists we used previously. # See `https://github.com/StevenBlack/hosts` for details https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts @@ -31,8 +31,8 @@ http://hosts-file.net/ad_servers.txt # ADZHOSTS list. Has been known to block legitimate domains #http://optimate.dl.sourceforge.net/project/adzhosts/HOSTS.txt -# Windows 10 telemetry list - warning this one may block windows update -#https://raw.githubusercontent.com/crazy-max/HostsWindowsBlocker/master/hosts.txt +# Windows 10 telemetry list +#https://raw.githubusercontent.com/crazy-max/WindowsSpyBlocker/master/hostsBlockWindowsSpy.txt # Securemecca.com list - Also blocks "adult" sites (pornography/gambling etc) #http://securemecca.com/Downloads/hosts.txt @@ -40,6 +40,9 @@ http://hosts-file.net/ad_servers.txt # Quidsup's tracker list https://raw.githubusercontent.com/quidsup/notrack/master/trackers.txt +# Block the BBC News website Breaking News banner +#https://raw.githubusercontent.com/BreakingTheNews/BreakingTheNews.github.io/master/hosts + # Untested Lists: #https://raw.githubusercontent.com/reek/anti-adblock-killer/master/anti-adblock-killer-filters.txt diff --git a/advanced/Scripts/blacklist.sh b/advanced/Scripts/blacklist.sh old mode 100644 new mode 100755 index 70b8131a..04d4d60f --- a/advanced/Scripts/blacklist.sh +++ b/advanced/Scripts/blacklist.sh @@ -11,39 +11,37 @@ # (at your option) any later version. if [[ $# = 0 ]]; then - echo "Immediately blacklists one or more domains in the hosts file" - echo " " - echo "Usage: blacklist.sh domain1 [domain2 ...]" - echo " " - echo "Options:" - echo " -d, --delmode Remove domains from the blacklist" - echo " -nr, --noreload Update blacklist without refreshing dnsmasq" - echo " -f, --force Force updating of the hosts files, even if there are no changes" - echo " -q, --quiet output is less verbose" - exit 1 + helpFunc fi #globals -blacklist=/etc/pihole/blacklist.txt -adList=/etc/pihole/gravity.list +basename=pihole +piholeDir=/etc/$basename +adList=$piholeDir/gravity.list +blacklist=$piholeDir/blacklist.txt reload=true addmode=true force=false -versbose=true +verbose=true + domList=() domToRemoveList=() - -piholeIPfile=/tmp/piholeIP piholeIPv6file=/etc/pihole/.useIPv6 # Otherwise, the IP address can be taken directly from the machine, which will happen when the script is run by the user and not the installation script IPv4dev=$(ip route get 8.8.8.8 | awk '{for(i=1;i<=NF;i++)if($i~/dev/)print $(i+1)}') -piholeIPCIDR=$(ip -o -f inet addr show dev $IPv4dev | awk '{print $4}' | awk 'END {print}') +piholeIPCIDR=$(ip -o -f inet addr show dev "$IPv4dev" | awk '{print $4}' | awk 'END {print}') piholeIP=${piholeIPCIDR%/*} modifyHost=false +# After setting defaults, check if there's local overrides +if [[ -r $piholeDir/pihole.conf ]];then + echo "::: Local calibration requested..." + . $piholeDir/pihole.conf +fi + if [[ -f $piholeIPv6file ]];then # If the file exists, then the user previously chose to use IPv6 in the automated installer @@ -51,12 +49,27 @@ if [[ -f $piholeIPv6file ]];then fi -function HandleOther(){ +function helpFunc() +{ + echo "::: Immediately blacklists one or more domains in the hosts file" + echo ":::" + echo "::: Usage: sudo pihole.sh -b domain1 [domain2 ...]" + echo ":::" + echo "::: Options:" + echo "::: -d, --delmode Remove domains from the blacklist" + echo "::: -nr, --noreload Update blacklist without refreshing dnsmasq" + echo "::: -f, --force Force updating of the hosts files, even if there are no changes" + echo "::: -q, --quiet output is less verbose" + echo "::: -h, --help Show this help dialog" + echo "::: -l, --list Display your blacklisted domains" + exit 1 +} + +function HandleOther(){ #check validity of domain - validDomain=$(echo $1 | perl -ne'print if /\b((?=[a-z0-9-]{1,63}\.)(xn--)?[a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,63}\b/') - + validDomain=$(echo "$1" | perl -ne'print if /\b((?=[a-z0-9-]{1,63}\.)(xn--)?[a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,63}\b/') if [ -z "$validDomain" ]; then - echo $1 is not a valid argument or domain name + echo "::: $1 is not a valid argument or domain name" else domList=("${domList[@]}" $validDomain) fi @@ -66,13 +79,12 @@ function PopBlacklistFile(){ #check blacklist file exists, and if not, create it if [[ ! -f $blacklist ]];then touch $blacklist - fi - for dom in "${domList[@]}" - do - if $addmode; then - AddDomain $dom + fi + for dom in "${domList[@]}"; do + if "$addmode"; then + AddDomain "$dom" else - RemoveDomain $dom + RemoveDomain "$dom" fi done } @@ -83,39 +95,39 @@ function AddDomain(){ grep -Ex -q "$1" $blacklist || bool=true if $bool; then #domain not found in the blacklist file, add it! - if $versbose; then + if $verbose; then echo -n "::: Adding $1 to blacklist file..." fi - echo $1 >> $blacklist + echo "$1" >> $blacklist modifyHost=true echo " done!" else - if $versbose; then - echo "::: $1 already exists in blacklist.txt! No need to add" + if $verbose; then + echo "::: $1 already exists in $blacklist! No need to add" fi fi } function RemoveDomain(){ - + bool=false grep -Ex -q "$1" $blacklist || bool=true if $bool; then #Domain is not in the blacklist file, no need to Remove - if $versbose; then + if $verbose; then echo "::: $1 is NOT blacklisted! No need to remove" fi else #Domain is in the blacklist file, add to a temporary array - if $versbose; then + if $verbose; then echo "::: Un-blacklisting $dom..." fi - domToRemoveList=("${domToRemoveList[@]}" $1) - modifyHost=true - fi + domToRemoveList=("${domToRemoveList[@]}" $1) + modifyHost=true + fi } -function ModifyHostFile(){ +function ModifyHostFile(){ if $addmode; then #add domains to the hosts file if [[ -r $blacklist ]];then @@ -124,28 +136,25 @@ function ModifyHostFile(){ echo ":::" echo -n "::: Modifying HOSTS file to blacklist $numberOf domain${plural}..." if [[ -n $piholeIPv6 ]];then - cat $blacklist | awk -v ipv4addr="$piholeIP" -v ipv6addr="$piholeIPv6" '{sub(/\r$/,""); print ipv4addr" "$0"\n"ipv6addr" "$0}' >> $adList - else - cat $blacklist | awk -v ipv4addr="$piholeIP" '{sub(/\r$/,""); print ipv4addr" "$0}' >>$adList - fi - + cat $blacklist | awk -v ipv4addr="$piholeIP" -v ipv6addr="$piholeIPv6" '{sub(/\r$/,""); print ipv4addr" "$0"\n"ipv6addr" "$0}' >> $adList + else + cat $blacklist | awk -v ipv4addr="$piholeIP" '{sub(/\r$/,""); print ipv4addr" "$0}' >>$adList + fi fi else - echo ":::" - for dom in "${domToRemoveList[@]}" - do - #we need to remove the domains from the blacklist file and the host file - echo "::: $dom" - echo -n "::: removing from HOSTS file..." - echo $dom | sed 's/\./\\./g' | xargs -I {} perl -i -ne'print unless /[^.]'{}'(?!.)/;' $adList - echo " done!" - echo -n "::: removing from blackist.txt..." - echo $dom | sed 's/\./\\./g' | xargs -I {} perl -i -ne'print unless /'{}'(?!.)/;' $blacklist - echo " done!" - done - fi - + for dom in "${domToRemoveList[@]}" + do + #we need to remove the domains from the blacklist file and the host file + echo "::: $dom" + echo -n "::: removing from HOSTS file..." + echo "$dom" | sed 's/\./\\./g' | xargs -I {} perl -i -ne'print unless /[^.]'{}'(?!.)/;' $adList + echo " done!" + echo -n "::: removing from blackist.txt..." + echo "$dom" | sed 's/\./\\./g' | xargs -I {} perl -i -ne'print unless /'{}'(?!.)/;' $blacklist + echo " done!" + done + fi } function Reload() { @@ -157,7 +166,7 @@ function Reload() { if [[ $dnsmasqPid ]]; then # service already running - reload config - sudo kill -HUP $dnsmasqPid + sudo kill -HUP "$dnsmasqPid" else # service not running, start it up sudo service dnsmasq start @@ -165,26 +174,39 @@ function Reload() { echo " done!" } +function DisplayBlist() { + verbose=false + echo -e " Displaying Gravity Affected Domains \n" + count=1 + while IFS= read -r AD + do + echo "${count}: $AD" + count=$((count+1)) + done < "$blacklist" +} + ################################################### for var in "$@" do case "$var" in - "-nr"| "--noreload" ) reload=false;; + "-nr"| "--noreload" ) reload=false;; "-d" | "--delmode" ) addmode=false;; "-f" | "--force" ) force=true;; - "-q" | "--quiet" ) versbose=false;; - * ) HandleOther $var;; + "-q" | "--quiet" ) verbose=false;; + "-h" | "--help" ) helpFunc;; + "-l" | "--list" ) DisplayBlist;; + * ) HandleOther "$var";; esac done PopBlacklistFile -if $modifyHost || $force; then +if $modifyHost || $force; then ModifyHostFile else - if $versbose; then - echo "::: No changes need to be made" + if $verbose; then + echo "::: No changes need to be made" fi exit 1 fi diff --git a/advanced/Scripts/chronometer.sh b/advanced/Scripts/chronometer.sh index ebed8684..58bf300b 100755 --- a/advanced/Scripts/chronometer.sh +++ b/advanced/Scripts/chronometer.sh @@ -73,9 +73,9 @@ function outputJSON(){ CalcQueriesToday CalcblockedToday CalcPercentBlockedToday - + CalcBlockedDomains - + printf '{"domains_being_blocked":"%s","dns_queries_today":"%s","ads_blocked_today":"%s","ads_percentage_today":"%s"}\n' "$blockedDomainsTotal" "$queriesToday" "$blockedToday" "$percentBlockedToday" } @@ -88,44 +88,45 @@ function normalChrono(){ echo " $(ifconfig eth0 | awk '/inet addr/ {print $2}' | cut -d':' -f2)" echo "" uptime | cut -d' ' -f11- - uptime -p + #uptime -p #Doesn't work on all versions of uptime + uptime | awk -F'( |,|:)+' '{if ($7=="min") m=$6; else {if ($7~/^day/) {d=$6;h=$8;m=$9} else {h=$6;m=$7}}} {print d+0,"days,",h+0,"hours,",m+0,"minutes."}' echo "-------------------------------" # Uncomment to continually read the log file and display the current domain being blocked #tail -f /var/log/pihole.log | awk '/\/etc\/pihole\/gravity.list/ {if ($7 != "address" && $7 != "name" && $7 != "/etc/pihole/gravity.list") print $7; else;}' - + #uncomment next 4 lines to use original query count calculation #today=$(date "+%b %e") #todaysQueryCount=$(cat /var/log/pihole.log | grep "$today" | awk '/query/ {print $7}' | wc -l) #todaysQueryCountV4=$(cat /var/log/pihole.log | grep "$today" | awk '/query/ && /\[A\]/ {print $7}' | wc -l) #todaysQueryCountV6=$(cat /var/log/pihole.log | grep "$today" | awk '/query/ && /\[AAAA\]/ {print $7}' | wc -l) - - + + CalcQueriesToday CalcblockedToday CalcPercentBlockedToday - + CalcBlockedDomains - + echo "Blocking: $blockedDomainsTotal" #below commented line does not add up to todaysQueryCount #echo "Queries: $todaysQueryCountV4 / $todaysQueryCountV6" echo "Queries: $queriesToday" #same total calculation as dashboard echo "Pi-holed: $blockedToday ($percentBlockedToday%)" - + sleep 5 done } function displayHelp(){ - echo "Displays stats about your piHole!" - echo " " - echo "Usage: chronometer.sh [optional:-j]" - echo "Note: If no option is passed, then stats are displayed on screen, updated every 5 seconds" - echo " " - echo "Options:" - echo " -j, --json output stats as JSON formatted string" - echo " -h, --help display this help text" - + echo "::: Displays stats about your piHole!" + echo ":::" + echo "::: Usage: sudo pihole.sh -c [optional:-j]" + echo "::: Note: If no option is passed, then stats are displayed on screen, updated every 5 seconds" + echo ":::" + echo "::: Options:" + echo "::: -j, --json output stats as JSON formatted string" + echo "::: -h, --help display this help text" + exit 1 } @@ -137,7 +138,7 @@ for var in "$@" do case "$var" in "-j" | "--json" ) outputJSON;; - "-h" | "--help" ) displayHelp;; + "-h" | "--help" ) displayHelp;; * ) exit 1;; esac done diff --git a/advanced/Scripts/piholeDebug.sh b/advanced/Scripts/piholeDebug.sh new file mode 100755 index 00000000..03d1498a --- /dev/null +++ b/advanced/Scripts/piholeDebug.sh @@ -0,0 +1,310 @@ +#!/usr/bin/env bash +# 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 +# Generates pihole_debug.log in /var/log/ to be used for troubleshooting. +# +# 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. + +# Nate Brandeburg +# nate@ubiquisoft.com +# 3/24/2016 + +######## GLOBAL VARS ######## +DEBUG_LOG="/var/log/pihole_debug.log" +DNSMASQFILE="/etc/dnsmasq.conf" +PIHOLECONFFILE="/etc/dnsmasq.d/01-pihole.conf" +LIGHTTPDFILE="/etc/lighttpd/lighttpd.conf" +GRAVITYFILE="/etc/pihole/gravity.list" +HOSTSFILE="/etc/hosts" +WHITELISTFILE="/etc/pihole/whitelist.txt" +BLACKLISTFILE="/etc/pihole/blacklist.txt" +ADLISTSFILE="/etc/pihole/adlists.list" +PIHOLELOG="/var/log/pihole.log" +WHITELISTMATCHES="/tmp/whitelistmatches.list" + + +######## FIRST CHECK ######## +# Must be root to debug +if [[ $EUID -eq 0 ]]; then + echo "::: You are root... Beginning debug!" +else + echo "::: Sudo will be used for debugging." + # Check if sudo is actually installed + if [[ $(dpkg-query -s sudo) ]]; then + export SUDO="sudo" + else + echo "::: Please install sudo or run this as root." + exit 1 + fi +fi + +# Ensure the file exists, create if not, clear if exists. +if [ ! -f "$DEBUG_LOG" ]; then + $SUDO touch $DEBUG_LOG + $SUDO chmod 644 $DEBUG_LOG + $SUDO chown "$USER":root $DEBUG_LOG +else + truncate -s 0 $DEBUG_LOG +fi + +### Private functions exist here ### +function compareWhitelist { + if [ ! -f "$WHITELISTMATCHES" ]; then + $SUDO touch $WHITELISTMATCHES + $SUDO chmod 644 $WHITELISTMATCHES + $SUDO chown "$USER":root $WHITELISTMATCHES + else + truncate -s 0 $WHITELISTMATCHES + fi + + echo "#######################################" >> $DEBUG_LOG + echo "######## Whitelist Comparison #########" >> $DEBUG_LOG + echo "#######################################" >> $DEBUG_LOG + while read -r line; do + TMP=$(grep -w ".* $line$" "$GRAVITYFILE") + if [ ! -z "$TMP" ]; then + echo "$TMP" >> $DEBUG_LOG + echo "$TMP" >> $WHITELISTMATCHES + fi + done < "$WHITELISTFILE" + echo >> $DEBUG_LOG +} + +function compareBlacklist { + echo "#######################################" >> $DEBUG_LOG + echo "######## Blacklist Comparison #########" >> $DEBUG_LOG + echo "#######################################" >> $DEBUG_LOG + while read -r line; do + if [ ! -z "$line" ]; then + grep -w ".* $line$" "$GRAVITYFILE" >> $DEBUG_LOG + fi + done < "$BLACKLISTFILE" + echo >> $DEBUG_LOG +} + +function testNslookup { + TESTURL="doubleclick.com" + echo "#######################################" >> $DEBUG_LOG + echo "############ NSLookup Test ############" >> $DEBUG_LOG + echo "#######################################" >> $DEBUG_LOG + # Find a blocked url that has not been whitelisted. + if [ -s "$WHITELISTMATCHES" ]; then + while read -r line; do + CUTURL=${line#*" "} + if [ "$CUTURL" != "Pi-Hole.IsWorking.OK" ]; then + while read -r line2; do + CUTURL2=${line2#*" "} + if [ "$CUTURL" != "$CUTURL2" ]; then + TESTURL="$CUTURL" + break 2 + fi + done < "$WHITELISTMATCHES" + fi + done < "$GRAVITYFILE" + fi + + echo "NSLOOKUP of $TESTURL from PiHole:" >> $DEBUG_LOG + nslookup "$TESTURL" >> $DEBUG_LOG + echo >> $DEBUG_LOG + echo "NSLOOKUP of $TESTURL from 8.8.8.8:" >> $DEBUG_LOG + nslookup "$TESTURL" 8.8.8.8 >> $DEBUG_LOG + echo >> $DEBUG_LOG +} + +function checkProcesses { + echo "#######################################" >> $DEBUG_LOG + echo "########### Processes Check ###########" >> $DEBUG_LOG + echo "#######################################" >> $DEBUG_LOG + echo ":::" + echo "::: Logging status of lighttpd and dnsmasq..." + PROCESSES=( lighttpd dnsmasq ) + for i in "${PROCESSES[@]}" + do + echo "" >> $DEBUG_LOG + echo -n $i >> "$DEBUG_LOG" + echo " processes status:" >> $DEBUG_LOG + $SUDO systemctl -l status $i >> "$DEBUG_LOG" + done +} + +### END FUNCTIONS ### + +### Check Pi internet connections ### +# Log the IP addresses of this Pi +IPADDR=$($SUDO ifconfig | perl -nle 's/dr:(\S+)/print $1/e') +echo "::: Writing local IPs to debug log" +echo "IP Addresses of this Pi:" >> $DEBUG_LOG +echo "$IPADDR" >> $DEBUG_LOG +echo >> $DEBUG_LOG + +# Check if we can connect to the local gateway +GATEWAY_CHECK=$(ping -q -w 1 -c 1 "$(ip r | grep default | cut -d ' ' -f 3)" > /dev/null && echo ok || echo error) +echo "Gateway check:" >> $DEBUG_LOG +echo "$GATEWAY_CHECK" >> $DEBUG_LOG +echo >> $DEBUG_LOG + +compareWhitelist +compareBlacklist +testNslookup +checkProcesses + +echo "::: Writing dnsmasq.conf to debug log..." +echo "#######################################" >> $DEBUG_LOG +echo "############### Dnsmasq ###############" >> $DEBUG_LOG +echo "#######################################" >> $DEBUG_LOG +if [ -e "$DNSMASQFILE" ] +then + #cat $DNSMASQFILE >> $DEBUG_LOG + while read -r line; do + if [ ! -z "$line" ]; then + [[ "$line" =~ ^#.*$ ]] && continue + echo "$line" >> $DEBUG_LOG + fi + done < "$DNSMASQFILE" + echo >> $DEBUG_LOG +else + echo "No dnsmasq.conf file found!" >> $DEBUG_LOG + printf ":::\tNo dnsmasq.conf file found!\n" +fi + +echo "::: Writing 01-pihole.conf to debug log..." +echo "#######################################" >> $DEBUG_LOG +echo "########### 01-pihole.conf ############" >> $DEBUG_LOG +echo "#######################################" >> $DEBUG_LOG +if [ -e "$PIHOLECONFFILE" ] +then + #cat "$PIHOLECONFFILE" >> $DEBUG_LOG + while read -r line; do + if [ ! -z "$line" ]; then + [[ "$line" =~ ^#.*$ ]] && continue + echo "$line" >> $DEBUG_LOG + fi + done < "$PIHOLECONFFILE" + echo >> $DEBUG_LOG +else + echo "No 01-pihole.conf file found!" >> $DEBUG_LOG + printf ":::\tNo 01-pihole.conf file found\n" +fi + +echo "::: Writing lighttpd.conf to debug log..." +echo "#######################################" >> $DEBUG_LOG +echo "############ lighttpd.conf ############" >> $DEBUG_LOG +echo "#######################################" >> $DEBUG_LOG +if [ -e "$LIGHTTPDFILE" ] +then + #cat "$PIHOLECONFFILE" >> $DEBUG_LOG + while read -r line; do + if [ ! -z "$line" ]; then + [[ "$line" =~ ^#.*$ ]] && continue + echo "$line" >> $DEBUG_LOG + fi + done < "$LIGHTTPDFILE" + echo >> $DEBUG_LOG +else + echo "No lighttpd.conf file found!" >> $DEBUG_LOG + printf ":::\tNo lighttpd.conf file found\n" +fi + +echo "::: Writing size of gravity.list to debug log..." +echo "#######################################" >> $DEBUG_LOG +echo "############ gravity.list #############" >> $DEBUG_LOG +echo "#######################################" >> $DEBUG_LOG +if [ -e "$GRAVITYFILE" ] +then + wc -l "$GRAVITYFILE" >> $DEBUG_LOG + echo >> $DEBUG_LOG +else + echo "No gravity.list file found!" >> $DEBUG_LOG + printf ":::\tNo gravity.list file found\n" +fi + +# Write the hostname output to compare against entries in /etc/hosts, which is logged next +echo "Hostname of this pihole is: " >> $DEBUG_LOG +hostname >> $DEBUG_LOG + +echo "::: Writing hosts file to debug log..." +echo "#######################################" >> $DEBUG_LOG +echo "################ Hosts ################" >> $DEBUG_LOG +echo "#######################################" >> $DEBUG_LOG +if [ -e "$HOSTSFILE" ] +then + cat "$HOSTSFILE" >> $DEBUG_LOG + echo >> $DEBUG_LOG +else + echo "No hosts file found!" >> $DEBUG_LOG + printf ":::\tNo hosts file found!\n" +fi + +### PiHole application specific logging ### +echo "::: Writing whitelist to debug log..." +echo "#######################################" >> $DEBUG_LOG +echo "############## Whitelist ##############" >> $DEBUG_LOG +echo "#######################################" >> $DEBUG_LOG +if [ -e "$WHITELISTFILE" ] +then + cat "$WHITELISTFILE" >> $DEBUG_LOG + echo >> $DEBUG_LOG +else + echo "No whitelist.txt file found!" >> $DEBUG_LOG + printf ":::\tNo whitelist.txt file found!\n" +fi + +echo "::: Writing blacklist to debug log..." +echo "#######################################" >> $DEBUG_LOG +echo "############## Blacklist ##############" >> $DEBUG_LOG +echo "#######################################" >> $DEBUG_LOG +if [ -e "$BLACKLISTFILE" ] +then + cat "$BLACKLISTFILE" >> $DEBUG_LOG + echo >> $DEBUG_LOG +else + echo "No blacklist.txt file found!" >> $DEBUG_LOG + printf ":::\tNo blacklist.txt file found!\n" +fi + +echo "::: Writing adlists.list to debug log..." +echo "#######################################" >> $DEBUG_LOG +echo "############ adlists.list #############" >> $DEBUG_LOG +echo "#######################################" >> $DEBUG_LOG +if [ -e "$ADLISTSFILE" ] +then + cat "$ADLISTSFILE" >> $DEBUG_LOG + echo >> $DEBUG_LOG +else + echo "No adlists.list file found... using adlists.default!" >> $DEBUG_LOG + printf ":::\tNo adlists.list file found... using adlists.default!\n" +fi + + +# Continuously append the pihole.log file to the pihole_debug.log file +function dumpPiHoleLog { + trap '{ echo -e "\nFinishing debug write from interrupt... Quitting!" ; exit 1; }' INT + echo -e "::: Writing current pihole traffic to debug log...\n:::\tTry loading any/all sites that you are having trouble with now... \n:::\t(Press ctrl+C to finish)" + echo "#######################################" >> $DEBUG_LOG + echo "############# pihole.log ##############" >> $DEBUG_LOG + echo "#######################################" >> $DEBUG_LOG + if [ -e "$PIHOLELOG" ] + then + while true; do + tail -f "$PIHOLELOG" >> $DEBUG_LOG + echo >> $DEBUG_LOG + done + else + echo "No pihole.log file found!" >> $DEBUG_LOG + printf ":::\tNo pihole.log file found!\n" + fi +} + +# Anything to be done after capturing of pihole.log terminates +function finalWork { + echo "::: Finshed debugging!" +} +trap finalWork EXIT + +### Method calls for additional logging ### +dumpPiHoleLog diff --git a/advanced/Scripts/piholeLogFlush.sh b/advanced/Scripts/piholeLogFlush.sh index bbcf1ade..db97f8cb 100755 --- a/advanced/Scripts/piholeLogFlush.sh +++ b/advanced/Scripts/piholeLogFlush.sh @@ -10,4 +10,6 @@ # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. +echo -n "::: Flushing /var/log/pihole.log ..." truncate -s 0 /var/log/pihole.log +echo "... done!" diff --git a/advanced/Scripts/setupLCD.sh b/advanced/Scripts/setupLCD.sh old mode 100644 new mode 100755 diff --git a/advanced/Scripts/updateDashboard.sh b/advanced/Scripts/updateDashboard.sh old mode 100644 new mode 100755 index edf04896..6955683d --- a/advanced/Scripts/updateDashboard.sh +++ b/advanced/Scripts/updateDashboard.sh @@ -63,7 +63,7 @@ make_repo() { update_repo() { # pull the latest commits cd "$WEB_INTERFACE_DIR" - git pull + git pull } main diff --git a/advanced/Scripts/whitelist.sh b/advanced/Scripts/whitelist.sh index 853c3b79..00556476 100755 --- a/advanced/Scripts/whitelist.sh +++ b/advanced/Scripts/whitelist.sh @@ -11,38 +11,36 @@ # (at your option) any later version. if [[ $# = 0 ]]; then - echo "Immediately whitelists one or more domains in the hosts file" - echo " " - echo "Usage: whitelist.sh domain1 [domain2 ...]" - echo " " - echo "Options:" - echo " -d, --delmode Remove domains from the whitelist" - echo " -nr, --noreload Update Whitelist without refreshing dnsmasq" - echo " -f, --force Force updating of the hosts files, even if there are no changes" - echo " -q, --quiet output is less verbose" - exit 1 + helpFunc fi #globals -whitelist=/etc/pihole/whitelist.txt -adList=/etc/pihole/gravity.list +basename=pihole +piholeDir=/etc/$basename +adList=$piholeDir/gravity.list +whitelist=$piholeDir/whitelist.txt reload=true addmode=true force=false -versbose=true +verbose=true + domList=() domToRemoveList=() -piholeIPfile=/tmp/piholeIP piholeIPv6file=/etc/pihole/.useIPv6 # Otherwise, the IP address can be taken directly from the machine, which will happen when the script is run by the user and not the installation script IPv4dev=$(ip route get 8.8.8.8 | awk '{for(i=1;i<=NF;i++)if($i~/dev/)print $(i+1)}') -piholeIPCIDR=$(ip -o -f inet addr show dev $IPv4dev | awk '{print $4}' | awk 'END {print}') +piholeIPCIDR=$(ip -o -f inet addr show dev "$IPv4dev" | awk '{print $4}' | awk 'END {print}') piholeIP=${piholeIPCIDR%/*} modifyHost=false +# After setting defaults, check if there's local overrides +if [[ -r $piholeDir/pihole.conf ]];then + echo "::: Local calibration requested..." + . $piholeDir/pihole.conf +fi if [[ -f $piholeIPv6file ]];then # If the file exists, then the user previously chose to use IPv6 in the automated installer @@ -50,13 +48,28 @@ if [[ -f $piholeIPv6file ]];then fi -function HandleOther(){ +function helpFunc() +{ + echo "::: Immediately whitelists one or more domains in the hosts file" + echo ":::" + echo "::: Usage: sudo pihole.sh -w domain1 [domain2 ...]" + echo ":::" + echo "::: Options:" + echo "::: -d, --delmode Remove domains from the whitelist" + echo "::: -nr, --noreload Update Whitelist without refreshing dnsmasq" + echo "::: -f, --force Force updating of the hosts files, even if there are no changes" + echo "::: -q, --quiet output is less verbose" + echo "::: -h, --help Show this help dialog" + echo "::: -l, --list Display your whitelisted domains" + exit 1 +} + +function HandleOther(){ #check validity of domain - validDomain=$(echo $1 | perl -ne'print if /\b((?=[a-z0-9-]{1,63}\.)(xn--)?[a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,63}\b/') - + validDomain=$(echo "$1" | perl -ne'print if /\b((?=[a-z0-9-]{1,63}\.)(xn--)?[a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,63}\b/') if [ -z "$validDomain" ]; then echo "::: $1 is not a valid argument or domain name" - else + else domList=("${domList[@]}" $validDomain) fi } @@ -65,13 +78,13 @@ function PopWhitelistFile(){ #check whitelist file exists, and if not, create it if [[ ! -f $whitelist ]];then touch $whitelist - fi + fi for dom in "${domList[@]}" - do + do if $addmode; then - AddDomain $dom + AddDomain "$dom" else - RemoveDomain $dom + RemoveDomain "$dom" fi done } @@ -79,45 +92,45 @@ function PopWhitelistFile(){ function AddDomain(){ #| sed 's/\./\\./g' bool=false - + grep -Ex -q "$1" $whitelist || bool=true if $bool; then #domain not found in the whitelist file, add it! - if $versbose; then - echo -n "::: Adding $1 to whitelist.txt..." + if $verbose; then + echo -n "::: Adding $1 to $whitelist..." fi - echo $1 >> $whitelist + echo "$1" >> $whitelist modifyHost=true - if $versbose; then + if $verbose; then echo " done!" fi else - if $versbose; then - echo "::: $1 already exists in whitelist.txt, no need to add!" + if $verbose; then + echo "::: $1 already exists in $whitelist, no need to add!" fi fi } function RemoveDomain(){ - + bool=false grep -Ex -q "$1" $whitelist || bool=true if $bool; then #Domain is not in the whitelist file, no need to Remove - if $versbose; then + if $verbose; then echo "::: $1 is NOT whitelisted! No need to remove" fi else #Domain is in the whitelist file, add to a temporary array and remove from whitelist file - #if $versbose; then + #if $verbose; then #echo "::: Un-whitelisting $dom..." #fi domToRemoveList=("${domToRemoveList[@]}" $1) - modifyHost=true - fi + modifyHost=true + fi } -function ModifyHostFile(){ +function ModifyHostFile(){ if $addmode; then #remove domains in from hosts file if [[ -r $whitelist ]];then @@ -126,36 +139,36 @@ function ModifyHostFile(){ plural=; [[ "$numberOf" != "1" ]] && plural=s echo ":::" echo -n "::: Modifying HOSTS file to whitelist $numberOf domain${plural}..." - awk -F':' '{print $1}' $whitelist | while read line; do echo "$piholeIP $line"; done > /etc/pihole/whitelist.tmp - awk -F':' '{print $1}' $whitelist | while read line; do echo "$piholeIPv6 $line"; done >> /etc/pihole/whitelist.tmp + awk -F':' '{print $1}' $whitelist | while read -r line; do echo "$piholeIP $line"; done > /etc/pihole/whitelist.tmp + awk -F':' '{print $1}' $whitelist | while read -r line; do echo "$piholeIPv6 $line"; done >> /etc/pihole/whitelist.tmp echo "l" >> /etc/pihole/whitelist.tmp - grep -F -x -v -f /etc/pihole/whitelist.tmp /etc/pihole/gravity.list > /etc/pihole/gravity.tmp - rm /etc/pihole/gravity.list - mv /etc/pihole/gravity.tmp /etc/pihole/gravity.list - rm /etc/pihole/whitelist.tmp + grep -F -x -v -f $piholeDir/whitelist.tmp $adList > $piholeDir/gravity.tmp + rm $adList + mv $piholeDir/gravity.tmp $adList + rm $piholeDir/whitelist.tmp echo " done!" - + fi else #we need to add the removed domains to the hosts file echo ":::" echo "::: Modifying HOSTS file to un-whitelist domains..." for rdom in "${domToRemoveList[@]}" - do + do if [[ -n $piholeIPv6 ]];then echo -n "::: Un-whitelisting $rdom on IPv4 and IPv6..." - echo $rdom | awk -v ipv4addr="$piholeIP" -v ipv6addr="$piholeIPv6" '{sub(/\r$/,""); print ipv4addr" "$0"\n"ipv6addr" "$0}' >> $adList + echo "$rdom" | awk -v ipv4addr="$piholeIP" -v ipv6addr="$piholeIPv6" '{sub(/\r$/,""); print ipv4addr" "$0"\n"ipv6addr" "$0}' >> $adList echo " done!" else echo -n "::: Un-whitelisting $rdom on IPv4" - echo $rdom | awk -v ipv4addr="$piholeIP" '{sub(/\r$/,""); print ipv4addr" "$0}' >>$adList + echo "$rdom" | awk -v ipv4addr="$piholeIP" '{sub(/\r$/,""); print ipv4addr" "$0}' >>$adList echo " done!" fi - echo -n "::: Removing $rdom from whitelist.txt..." - echo $rdom| sed 's/\./\\./g' | xargs -I {} perl -i -ne'print unless /'{}'(?!.)/;' $whitelist + echo -n "::: Removing $rdom from $whitelist..." + echo "$rdom" | sed 's/\./\\./g' | xargs -I {} perl -i -ne'print unless /'{}'(?!.)/;' $whitelist echo " done!" done - fi + fi } function Reload() { @@ -166,7 +179,7 @@ function Reload() { if [[ $dnsmasqPid ]]; then # service already running - reload config - sudo kill -HUP $dnsmasqPid + sudo kill -HUP "$dnsmasqPid" else # service not running, start it up sudo service dnsmasq start @@ -174,16 +187,29 @@ function Reload() { echo " done!" } +function DisplayWlist() { + verbose=false + echo -e " Displaying Gravity Resistant Domains \n" + count=1 + while IFS= read -r RD + do + echo "${count}: $RD" + count=$((count+1)) + done < "$whitelist" +} + ################################################### for var in "$@" do case "$var" in - "-nr"| "--noreload" ) reload=false;; + "-nr"| "--noreload" ) reload=false;; "-d" | "--delmode" ) addmode=false;; "-f" | "--force" ) force=true;; - "-q" | "--quiet" ) versbose=false;; - * ) HandleOther $var;; + "-q" | "--quiet" ) verbose=false;; + "-h" | "--help" ) helpFunc;; + "-l" | "--list" ) DisplayWlist;; + * ) HandleOther "$var";; esac done @@ -192,11 +218,11 @@ PopWhitelistFile if $modifyHost || $force; then ModifyHostFile else - if $versbose; then - echo ":::" - echo "::: No changes need to be made" - exit 1 + if $verbose; then + echo ":::" + echo "::: No changes need to be made" fi + exit 1 fi if $reload; then diff --git a/advanced/bash-completion/pihole b/advanced/bash-completion/pihole new file mode 100644 index 00000000..e2c70558 --- /dev/null +++ b/advanced/bash-completion/pihole @@ -0,0 +1,12 @@ +_pihole() +{ + local cur prev opts + COMPREPLY=() + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + opts="whitelist blacklist debug flush updateDashboard updateGravity setupLCD chronometer uninstall help" + + COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) + return 0 +} +complete -F _pihole pihole \ No newline at end of file diff --git a/advanced/dnsmasq.conf.original b/advanced/dnsmasq.conf.original index 598d6390..9e4cc92e 100644 --- a/advanced/dnsmasq.conf.original +++ b/advanced/dnsmasq.conf.original @@ -27,8 +27,8 @@ # Replies which are not DNSSEC signed may be legitimate, because the domain # is unsigned, or may be forgeries. Setting this option tells dnsmasq to -# check that an unsigned reply is OK, by finding a secure proof that a DS -# record somewhere between the root and the domain does not exist. +# check that an unsigned reply is OK, by finding a secure proof that a DS +# record somewhere between the root and the domain does not exist. # The cost of setting this is that even queries in unsigned domains will need # one or more extra DNS queries to verify. #dnssec-check-unsigned @@ -183,11 +183,11 @@ #dhcp-range=1234::2, 1234::500, 64, 12h # Do Router Advertisements, BUT NOT DHCP for this subnet. -#dhcp-range=1234::, ra-only +#dhcp-range=1234::, ra-only # Do Router Advertisements, BUT NOT DHCP for this subnet, also try and -# add names to the DNS for the IPv6 address of SLAAC-configured dual-stack -# hosts. Use the DHCPv4 lease to derive the name, network segment and +# add names to the DNS for the IPv6 address of SLAAC-configured dual-stack +# hosts. Use the DHCPv4 lease to derive the name, network segment and # MAC address and assume that the host will also have an # IPv6 address calculated using the SLAAC alogrithm. #dhcp-range=1234::, ra-names @@ -210,9 +210,9 @@ #dhcp-range=1234::, ra-stateless, ra-names # Do router advertisements for all subnets where we're doing DHCPv6 -# Unless overriden by ra-stateless, ra-names, et al, the router +# Unless overriden by ra-stateless, ra-names, et al, the router # advertisements will have the M and O bits set, so that the clients -# get addresses and configuration from DHCPv6, and the A bit reset, so the +# get addresses and configuration from DHCPv6, and the A bit reset, so the # clients don't use SLAAC addresses. #enable-ra @@ -278,11 +278,11 @@ # any machine with Ethernet address starting 11:22:33: #dhcp-host=11:22:33:*:*:*,set:red -# Give a fixed IPv6 address and name to client with +# Give a fixed IPv6 address and name to client with # DUID 00:01:00:01:16:d2:83:fc:92:d4:19:e2:d8:b2 # Note the MAC addresses CANNOT be used to identify DHCPv6 clients. # Note also the they [] around the IPv6 address are obilgatory. -#dhcp-host=id:00:01:00:01:16:d2:83:fc:92:d4:19:e2:d8:b2, fred, [1234::5] +#dhcp-host=id:00:01:00:01:16:d2:83:fc:92:d4:19:e2:d8:b2, fred, [1234::5] # Ignore any clients which are not specified in dhcp-host lines # or /etc/ethers. Equivalent to ISC "deny unknown-clients". @@ -338,7 +338,7 @@ # Send DHCPv6 option. Note [] around IPv6 addresses. #dhcp-option=option6:dns-server,[1234::77],[1234::88] -# Send DHCPv6 option for namservers as the machine running +# Send DHCPv6 option for namservers as the machine running # dnsmasq and another. #dhcp-option=option6:dns-server,[::],[1234::88] @@ -645,4 +645,4 @@ #conf-dir=/etc/dnsmasq.d,.bak # Include all files in a directory which end in .conf -#conf-dir=/etc/dnsmasq.d/*.conf +#conf-dir=/etc/dnsmasq.d/*.conf diff --git a/advanced/index.js b/advanced/index.js new file mode 100644 index 00000000..c9da5aff --- /dev/null +++ b/advanced/index.js @@ -0,0 +1 @@ +var x = "Pi-hole: A black hole for Internet advertisements." diff --git a/advanced/lighttpd.conf b/advanced/lighttpd.conf index 5a662ffa..124371a9 100644 --- a/advanced/lighttpd.conf +++ b/advanced/lighttpd.conf @@ -53,4 +53,6 @@ $HTTP["url"] =~ "^/admin/" { $HTTP["url"] =~ "^(?!/admin)/.*" { # Create a response header for debugging using curl -I setenv.add-response-header = ( "X-Pi-hole" => "A black hole for Internet advertisements." ) + # rewrite only js requests + url.rewrite = ("(.*).js" => "pihole/index.js") } diff --git a/advanced/pihole.cron b/advanced/pihole.cron index d1c2d2cd..fc648091 100644 --- a/advanced/pihole.cron +++ b/advanced/pihole.cron @@ -14,17 +14,17 @@ 23 58 * * 1 root /usr/local/bin/updatePihole # Pi-hole: Update the ad sources once a week on Sunday at 01:59 -# Download any updates from the ad lists -59 1 * * 7 root /usr/local/bin/gravity.sh +# Download any updates from the adlists +59 1 * * 7 root /usr/local/bin/pihole updateGravity # Pi-hole: Update the Web interface shortly after gravity runs # This should also update the version number if it is changed in the dashboard repo -30 2 * * 7 root /usr/local/bin/updateDashboard.sh +30 2 * * 7 root /usr/local/bin/pihole updateDashboard # Pi-hole: Parse the log file before it is flushed and save the stats to a database # This will be used for a historical view of your Pi-hole's performance -#50 23 * * * root /usr/local/bin/dailyLog.sh +#50 23 * * * root /usr/local/bin/dailyLog.sh # note: this is outdated # Pi-hole: Flush the log daily at 11:58 so it doesn't get out of control # Stats will be viewable in the Web interface thanks to the cron job above -58 23 * * * root /usr/local/bin/piholeLogFlush.sh +58 23 * * * root /usr/local/bin/pihole flush diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index b3e6202f..139a7a4b 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -40,7 +40,7 @@ c=$(( columns / 2 )) # Find IP used to route to outside world IPv4dev=$(ip route get 8.8.8.8 | awk '{for(i=1;i<=NF;i++)if($i~/dev/)print $(i+1)}') -IPv4addr=$(ip -o -f inet addr show dev $IPv4dev | awk '{print $4}' | awk 'END {print}') +IPv4addr=$(ip -o -f inet addr show dev "$IPv4dev" | awk '{print $4}' | awk 'END {print}') IPv4gw=$(ip route get 8.8.8.8 | awk '{print $3}') availableInterfaces=$(ip -o link | awk '{print $2}' | grep -v "lo" | cut -d':' -f1) @@ -64,27 +64,20 @@ else fi -if [ -d "/etc/pihole" ]; then - # Likely an existing install - upgrade=true - else - upgrade=false -fi - ####### FUNCTIONS ########## -###All credit for the below function goes to http://fitnr.com/showing-a-bash-spinner.html -spinner() { +spinner() +{ local pid=$1 - - spin='-\|/' - i=0 - while $SUDO kill -0 $pid 2>/dev/null - do - i=$(( (i+1) %4 )) - printf "\b${spin:$i:1}" - sleep .1 - done - printf "\b" + local delay=0.50 + local spinstr='/-\|' + while [ "$(ps a | awk '{print $1}' | grep "$pid")" ]; do + local temp=${spinstr#?} + printf " [%c] " "$spinstr" + local spinstr=$temp${spinstr%"$temp"} + sleep $delay + printf "\b\b\b\b\b\b" + done + printf " \b\b\b\b" } backupLegacyPihole() { @@ -92,12 +85,17 @@ backupLegacyPihole() { if [[ -f /etc/dnsmasq.d/adList.conf ]];then echo "::: Original Pi-hole detected. Initiating sub space transport" $SUDO mkdir -p /etc/pihole/original/ - $SUDO mv /etc/dnsmasq.d/adList.conf /etc/pihole/original/adList.conf.$(date "+%Y-%m-%d") - $SUDO mv /etc/dnsmasq.conf /etc/pihole/original/dnsmasq.conf.$(date "+%Y-%m-%d") - $SUDO mv /etc/resolv.conf /etc/pihole/original/resolv.conf.$(date "+%Y-%m-%d") - $SUDO mv /etc/lighttpd/lighttpd.conf /etc/pihole/original/lighttpd.conf.$(date "+%Y-%m-%d") - $SUDO mv /var/www/pihole/index.html /etc/pihole/original/index.html.$(date "+%Y-%m-%d") - $SUDO mv /usr/local/bin/gravity.sh /etc/pihole/original/gravity.sh.$(date "+%Y-%m-%d") + $SUDO mv /etc/dnsmasq.d/adList.conf /etc/pihole/original/adList.conf."$(date "+%Y-%m-%d")" + $SUDO mv /etc/dnsmasq.conf /etc/pihole/original/dnsmasq.conf."$(date "+%Y-%m-%d")" + $SUDO mv /etc/resolv.conf /etc/pihole/original/resolv.conf."$(date "+%Y-%m-%d")" + $SUDO mv /etc/lighttpd/lighttpd.conf /etc/pihole/original/lighttpd.conf."$(date "+%Y-%m-%d")" + $SUDO mv /var/www/pihole/index.html /etc/pihole/original/index.html."$(date "+%Y-%m-%d")" + if [ ! -d /opt/pihole ]; then + $SUDO mkdir /opt/pihole + $SUDO chown "$USER":root /opt/pihole + $SUDO chmod u+srwx /opt/pihole + fi + $SUDO mv /opt/pihole/gravity.sh /etc/pihole/original/gravity.sh."$(date "+%Y-%m-%d")" else : fi @@ -111,20 +109,21 @@ welcomeDialogs() { whiptail --msgbox --backtitle "Plea" --title "Free and open source" "The Pi-hole is free, but powered by your donations: http://pi-hole.net/donate" $r $c # Explain the need for a static address - whiptail --msgbox --backtitle "Initating network interface" --title "Static IP Needed" "The Pi-hole is a SERVER so it needs a STATIC IP ADDRESS to function properly. - In the next section, you can choose to use your current network settings (DHCP) or to manually edit them." $r $c + whiptail --msgbox --backtitle "Initating network interface" --title "Static IP Needed" "The Pi-hole is a SERVER so it needs a STATIC IP ADDRESS to function properly. + +In the next section, you can choose to use your current network settings (DHCP) or to manually edit them." $r $c } verifyFreeDiskSpace() { - # 25MB is the minimum space needed (20MB install + 5MB one day of logs.) + # 50MB is the minimum space needed (45MB install (includes web admin bootstrap/jquery libraries etc) + 5MB one day of logs.) requiredFreeBytes=51200 - - existingFreeBytes=`df -lk / 2>&1 | awk '{print $4}' | head -2 | tail -1` - if ! [[ "$existingFreeBytes" =~ ^([0-9])+$ ]]; then - existingFreeBytes=`df -lk /dev 2>&1 | awk '{print $4}' | head -2 | tail -1` + + existingFreeBytes=$(df -lk / 2>&1 | awk '{print $4}' | head -2 | tail -1) + if ! [[ "$existingFreeBytes" =~ ^([0-9])+$ ]]; then + existingFreeBytes=$(df -lk /dev 2>&1 | awk '{print $4}' | head -2 | tail -1) fi - + if [[ $existingFreeBytes -lt $requiredFreeBytes ]]; then whiptail --msgbox --backtitle "Insufficient Disk Space" --title "Insufficient Disk Space" "\nYour system appears to be low on disk space. pi-hole recomends a minimum of $requiredFreeBytes Bytes.\nYou only have $existingFreeBytes Free.\n\nIf this is a new install you may need to expand your disk.\n\nTry running:\n 'sudo raspi-config'\nChoose the 'expand file system option'\n\nAfter rebooting, run this installation again.\n\ncurl -L install.pi-hole.net | bash\n" $r $c echo "$existingFreeBytes is less than $requiredFreeBytes" @@ -153,30 +152,30 @@ chooseInterface() { interfaceCount=$(echo "$availableInterfaces" | wc -l) chooseInterfaceCmd=(whiptail --separate-output --radiolist "Choose An Interface" $r $c $interfaceCount) chooseInterfaceOptions=$("${chooseInterfaceCmd[@]}" "${interfacesArray[@]}" 2>&1 >/dev/tty) - if [[ $? = 0 ]];then + if [[ $? = 0 ]]; then for desiredInterface in $chooseInterfaceOptions do - piholeInterface=$desiredInterface - echo "::: Using interface: $piholeInterface" - echo ${piholeInterface} > /tmp/piholeINT + piholeInterface=$desiredInterface + echo "::: Using interface: $piholeInterface" + echo "${piholeInterface}" > /tmp/piholeINT done else echo "::: Cancel selected, exiting...." exit 1 fi - + } cleanupIPv6() { # Removes IPv6 indicator file if we are not using IPv6 - if [ -f "/etc/pihole/.useIPv6" ] && [ ! $useIPv6 ]; then + if [ -f "/etc/pihole/.useIPv6" ] && [ ! "$useIPv6" ]; then rm /etc/pihole/.useIPv6 fi } use4andor6() { # Let use select IPv4 and/or IPv6 - cmd=(whiptail --separate-output --checklist "Select Protocols" $r $c 2) + cmd=(whiptail --separate-output --checklist "Select Protocols (press space to select)" $r $c 2) options=(IPv4 "Block ads over IPv4" on IPv6 "Block ads over IPv6" off) choices=$("${cmd[@]}" "${options[@]}" 2>&1 >/dev/tty) @@ -184,11 +183,11 @@ use4andor6() { for choice in $choices do case $choice in - IPv4 ) useIPv4=true;; - IPv6 ) useIPv6=true;; + IPv4 ) useIPv4=true;; + IPv6 ) useIPv6=true;; esac done - + if [ $useIPv4 ] && [ ! $useIPv6 ]; then getStaticIPv4Settings setStaticIPv4 @@ -230,12 +229,12 @@ useIPv6dialog() { getStaticIPv4Settings() { # Ask if the user wants to use DHCP settings as their static IP if (whiptail --backtitle "Calibrating network interface" --title "Static IP Address" --yesno "Do you want to use your current network settings as a static address? - IP address: $IPv4addr - Gateway: $IPv4gw" $r $c) then + IP address: $IPv4addr + Gateway: $IPv4gw" $r $c) then # If they choose yes, let the user know that the IP address will not be available via DHCP and may cause a conflict. whiptail --msgbox --backtitle "IP information" --title "FYI: IP Conflict" "It is possible your router could still try to assign this IP to a device, which would cause a conflict. But in most cases the router is smart enough to not do that. - If you are worried, either manually set the address, or modify the DHCP reservation pool so it does not include the IP you want. - It is also possible to use a DHCP reservation, but if you are going to do that, you might as well set a static address." $r $c +If you are worried, either manually set the address, or modify the DHCP reservation pool so it does not include the IP you want. +It is also possible to use a DHCP reservation, but if you are going to do that, you might as well set a static address." $r $c # Nothing else to do since the variables are already set above else # Otherwise, we need to ask the user to input their desired settings. @@ -244,41 +243,41 @@ getStaticIPv4Settings() { until [[ $ipSettingsCorrect = True ]] do # Ask for the IPv4 address - IPv4addr=$(whiptail --backtitle "Calibrating network interface" --title "IPv4 address" --inputbox "Enter your desired IPv4 address" $r $c $IPv4addr 3>&1 1>&2 2>&3) + IPv4addr=$(whiptail --backtitle "Calibrating network interface" --title "IPv4 address" --inputbox "Enter your desired IPv4 address" $r $c "$IPv4addr" 3>&1 1>&2 2>&3) if [[ $? = 0 ]];then - echo "::: Your static IPv4 address: $IPv4addr" - # 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) - if [[ $? = 0 ]];then - echo "::: Your static IPv4 gateway: $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? - IP address: $IPv4addr - Gateway: $IPv4gw" $r $c)then - # If the settings are correct, then we need to set the piholeIP - # Saving it to a temporary file us to retrieve it later when we run the gravity.sh script - echo ${IPv4addr%/*} > /tmp/piholeIP - echo $piholeInterface > /tmp/piholeINT - # After that's done, the loop ends and we move on - ipSettingsCorrect=True - else - # If the settings are wrong, the loop continues - ipSettingsCorrect=False - fi + echo "::: Your static IPv4 address: $IPv4addr" + # 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) + if [[ $? = 0 ]];then + echo "::: Your static IPv4 gateway: $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? + IP address: $IPv4addr + Gateway: $IPv4gw" $r $c)then + # If the settings are correct, then we need to set the piholeIP + # Saving it to a temporary file us to retrieve it later when we run the gravity.sh script + echo "${IPv4addr%/*}" > /tmp/piholeIP + echo "$piholeInterface" > /tmp/piholeINT + # After that's done, the loop ends and we move on + ipSettingsCorrect=True else - # Cancelling gateway settings window + # If the settings are wrong, the loop continues ipSettingsCorrect=False - echo "::: Cancel selected. Exiting..." - exit 1 fi else - # Cancelling IPv4 settings window + # Cancelling gateway settings window ipSettingsCorrect=False echo "::: Cancel selected. Exiting..." exit 1 fi + else + # Cancelling IPv4 settings window + ipSettingsCorrect=False + echo "::: Cancel selected. Exiting..." + exit 1 + fi done - # End the if statement for DHCP vs. static + # End the if statement for DHCP vs. static fi } @@ -292,12 +291,12 @@ setDHCPCD() { setStaticIPv4() { # Tries to set the IPv4 address - if grep -q $IPv4addr $dhcpcdFile; then + if grep -q "$IPv4addr" $dhcpcdFile; then # address already set, noop : else setDHCPCD - $SUDO ip addr replace dev $piholeInterface $IPv4addr + $SUDO ip addr replace dev "$piholeInterface" "$IPv4addr" echo ":::" echo "::: Setting IP to $IPv4addr. You may need to restart after the install is complete." echo ":::" @@ -308,7 +307,7 @@ function valid_ip() { local ip=$1 local stat=1 - + if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then OIFS=$IFS IFS='.' @@ -324,98 +323,88 @@ function valid_ip() setDNS(){ DNSChoseCmd=(whiptail --separate-output --radiolist "Select Upstream DNS Provider. To use your own, select Custom." $r $c 6) DNSChooseOptions=(Google "" on - OpenDNS "" off - Level3 "" off - Norton "" off - Comodo "" off - Custom "" off) + OpenDNS "" off + Level3 "" off + Norton "" off + Comodo "" off + Custom "" off) DNSchoices=$("${DNSChoseCmd[@]}" "${DNSChooseOptions[@]}" 2>&1 >/dev/tty) if [[ $? = 0 ]];then case $DNSchoices in - Google) - echo "::: Using Google DNS servers." - piholeDNS1="8.8.8.8" - piholeDNS2="8.8.4.4" - ;; - OpenDNS) - echo "::: Using OpenDNS servers." - piholeDNS1="208.67.222.222" - piholeDNS2="208.67.220.220" - ;; - Level3) - echo "::: Using Level3 servers." - piholeDNS1="4.2.2.1" - piholeDNS2="4.2.2.2" - ;; - Norton) - echo "::: Using Norton ConnectSafe servers." - piholeDNS1="199.85.126.10" - piholeDNS2="199.85.127.10" - ;; - Comodo) - echo "::: Using Comodo Secure servers." - piholeDNS1="8.26.56.26" - piholeDNS2="8.20.247.20" - ;; - Custom) - until [[ $DNSSettingsCorrect = True ]] - do - - strInvalid="Invalid" - - if [ ! $piholeDNS1 ]; then - if [ ! $piholeDNS2 ]; then - prePopulate="" - else - prePopulate=", $piholeDNS2" - fi - elif [ $piholeDNS1 ] && [ ! $piholeDNS2 ]; then - prePopulate="$piholeDNS1" - elif [ $piholeDNS1 ] && [ $piholeDNS2 ]; then - prePopulate="$piholeDNS1, $piholeDNS2" - fi - - piholeDNS=$(whiptail --backtitle "Specify Upstream DNS Provider(s)" --inputbox "Enter your desired upstream DNS provider(s), seperated by a comma.\n\nFor example '8.8.8.8, 8.8.4.4'" $r $c "$prePopulate" 3>&1 1>&2 2>&3) - if [[ $? = 0 ]];then - piholeDNS1=$(echo $piholeDNS | sed 's/[, \t]\+/,/g' | awk -F, '{print$1}') - piholeDNS2=$(echo $piholeDNS | sed 's/[, \t]\+/,/g' | awk -F, '{print$2}') - - if ! valid_ip $piholeDNS1 || [ ! $piholeDNS1 ]; then - piholeDNS1=$strInvalid - fi - - if ! valid_ip $piholeDNS2 && [ $piholeDNS2 ]; then - piholeDNS2=$strInvalid - fi - + Google) + echo "::: Using Google DNS servers." + piholeDNS1="8.8.8.8" + piholeDNS2="8.8.4.4" + ;; + OpenDNS) + echo "::: Using OpenDNS servers." + piholeDNS1="208.67.222.222" + piholeDNS2="208.67.220.220" + ;; + Level3) + echo "::: Using Level3 servers." + piholeDNS1="4.2.2.1" + piholeDNS2="4.2.2.2" + ;; + Norton) + echo "::: Using Norton ConnectSafe servers." + piholeDNS1="199.85.126.10" + piholeDNS2="199.85.127.10" + ;; + Comodo) + echo "::: Using Comodo Secure servers." + piholeDNS1="8.26.56.26" + piholeDNS2="8.20.247.20" + ;; + Custom) + until [[ $DNSSettingsCorrect = True ]] + do + strInvalid="Invalid" + if [ ! $piholeDNS1 ]; then + if [ ! $piholeDNS2 ]; then + prePopulate="" else - echo "::: Cancel selected, exiting...." - exit 1 + prePopulate=", $piholeDNS2" fi - - if [[ $piholeDNS1 == $strInvalid ]] || [[ $piholeDNS2 == $strInvalid ]]; then - whiptail --msgbox --backtitle "Invalid IP" --title "Invalid IP" "One or both entered IP addresses were invalid. Please try again.\n\n DNS Server 1: $piholeDNS1\n DNS Server 2: $piholeDNS2" $r $c - - if [[ $piholeDNS1 == $strInvalid ]]; then - piholeDNS1="" - fi - - if [[ $piholeDNS2 == $strInvalid ]]; then - piholeDNS2="" - fi - + elif [ $piholeDNS1 ] && [ ! $piholeDNS2 ]; then + prePopulate="$piholeDNS1" + elif [ $piholeDNS1 ] && [ $piholeDNS2 ]; then + prePopulate="$piholeDNS1, $piholeDNS2" + fi + piholeDNS=$(whiptail --backtitle "Specify Upstream DNS Provider(s)" --inputbox "Enter your desired upstream DNS provider(s), seperated by a comma.\n\nFor example '8.8.8.8, 8.8.4.4'" $r $c "$prePopulate" 3>&1 1>&2 2>&3) + if [[ $? = 0 ]];then + piholeDNS1=$(echo "$piholeDNS" | sed 's/[, \t]\+/,/g' | awk -F, '{print$1}') + piholeDNS2=$(echo "$piholeDNS" | sed 's/[, \t]\+/,/g' | awk -F, '{print$2}') + if ! valid_ip "$piholeDNS1" || [ ! "$piholeDNS1" ]; then + piholeDNS1=$strInvalid + fi + if ! valid_ip "$piholeDNS2" && [ "$piholeDNS2" ]; then + piholeDNS2=$strInvalid + fi + else + echo "::: Cancel selected, exiting...." + exit 1 + fi + if [[ $piholeDNS1 == "$strInvalid" ]] || [[ $piholeDNS2 == "$strInvalid" ]]; then + whiptail --msgbox --backtitle "Invalid IP" --title "Invalid IP" "One or both entered IP addresses were invalid. Please try again.\n\n DNS Server 1: $piholeDNS1\n DNS Server 2: $piholeDNS2" $r $c + if [[ $piholeDNS1 == "$strInvalid" ]]; then + piholeDNS1="" + fi + if [[ $piholeDNS2 == "$strInvalid" ]]; then + piholeDNS2="" + fi + DNSSettingsCorrect=False + else + if (whiptail --backtitle "Specify Upstream DNS Provider(s)" --title "Upstream DNS Provider(s)" --yesno "Are these settings correct?\n DNS Server 1: $piholeDNS1\n DNS Server 2: $piholeDNS2" $r $c) then + DNSSettingsCorrect=True + else + # If the settings are wrong, the loop continues DNSSettingsCorrect=False - else - if (whiptail --backtitle "Specify Upstream DNS Provider(s)" --title "Upstream DNS Provider(s)" --yesno "Are these settings correct?\n DNS Server 1: $piholeDNS1\n DNS Server 2: $piholeDNS2" $r $c) then - DNSSettingsCorrect=True - else - # If the settings are wrong, the loop continues - DNSSettingsCorrect=False - fi fi - done - ;; - esac + fi + done + ;; + esac else echo "::: Cancel selected. Exiting..." exit 1 @@ -423,61 +412,81 @@ setDNS(){ } versionCheckDNSmasq(){ - # Check if /etc/dnsmasq.conf is from pihole. If so replace with an original and install new in .d directory - dnsFile1="/etc/dnsmasq.conf" - dnsFile2="/etc/dnsmasq.conf.orig" - dnsSearch="addn-hosts=/etc/pihole/gravity.list" - - defaultFile="/etc/.pihole/advanced/dnsmasq.conf.original" - newFileToInstall="/etc/.pihole/advanced/01-pihole.conf" - newFileFinalLocation="/etc/dnsmasq.d/01-pihole.conf" - - if [ -f $dnsFile1 ]; then - echo -n "::: Existing dnsmasq.conf found..." - if grep -q $dnsSearch $dnsFile1; then - echo " it is from a previous pi-hole install." - echo -n "::: Backing up dnsmasq.conf to dnsmasq.conf.orig..." - $SUDO mv -f $dnsFile1 $dnsFile2 - echo " done." - echo -n "::: Restoring default dnsmasq.conf..." - $SUDO cp $defaultFile $dnsFile1 - echo " done." - else - echo " it is not a pi-hole file, leaving alone!" - fi - else - echo -n "::: No dnsmasq.conf found.. restoring default dnsmasq.conf..." - $SUDO cp $defaultFile $dnsFile1 - echo " done." - fi - - echo -n "::: Copying 01-pihole.conf to /etc/dnsmasq.d/01-pihole.conf..." - $SUDO cp $newFileToInstall $newFileFinalLocation - echo " done." - $SUDO sed -i "s/@INT@/$piholeInterface/" $newFileFinalLocation - if [[ "$piholeDNS1" != "" ]]; then - $SUDO sed -i "s/@DNS1@/$piholeDNS1/" $newFileFinalLocation - else - $SUDO sed -i '/^server=@DNS1@/d' $newFileFinalLocation - fi - if [[ "$piholeDNS2" != "" ]]; then - $SUDO sed -i "s/@DNS2@/$piholeDNS2/" $newFileFinalLocation - else - $SUDO sed -i '/^server=@DNS2@/d' $newFileFinalLocation - fi + # Check if /etc/dnsmasq.conf is from pihole. If so replace with an original and install new in .d directory + dnsFile1="/etc/dnsmasq.conf" + dnsFile2="/etc/dnsmasq.conf.orig" + dnsSearch="addn-hosts=/etc/pihole/gravity.list" + defaultFile="/etc/.pihole/advanced/dnsmasq.conf.original" + newFileToInstall="/etc/.pihole/advanced/01-pihole.conf" + newFileFinalLocation="/etc/dnsmasq.d/01-pihole.conf" + + if [ -f $dnsFile1 ]; then + echo -n "::: Existing dnsmasq.conf found..." + if grep -q $dnsSearch $dnsFile1; then + echo " it is from a previous pi-hole install." + echo -n "::: Backing up dnsmasq.conf to dnsmasq.conf.orig..." + $SUDO mv -f $dnsFile1 $dnsFile2 + echo " done." + echo -n "::: Restoring default dnsmasq.conf..." + $SUDO cp $defaultFile $dnsFile1 + echo " done." + else + echo " it is not a pi-hole file, leaving alone!" + fi + else + echo -n "::: No dnsmasq.conf found.. restoring default dnsmasq.conf..." + $SUDO cp $defaultFile $dnsFile1 + echo " done." + fi + + echo -n "::: Copying 01-pihole.conf to /etc/dnsmasq.d/01-pihole.conf..." + $SUDO cp $newFileToInstall $newFileFinalLocation + echo " done." + $SUDO sed -i "s/@INT@/$piholeInterface/" $newFileFinalLocation + if [[ "$piholeDNS1" != "" ]]; then + $SUDO sed -i "s/@DNS1@/$piholeDNS1/" $newFileFinalLocation + else + $SUDO sed -i '/^server=@DNS1@/d' $newFileFinalLocation + fi + if [[ "$piholeDNS2" != "" ]]; then + $SUDO sed -i "s/@DNS2@/$piholeDNS2/" $newFileFinalLocation + else + $SUDO sed -i '/^server=@DNS2@/d' $newFileFinalLocation + fi } installScripts() { # Install the scripts from /etc/.pihole to their various locations $SUDO echo ":::" - $SUDO echo -n "::: Installing scripts..." - $SUDO cp /etc/.pihole/gravity.sh /usr/local/bin/gravity.sh - $SUDO cp /etc/.pihole/advanced/Scripts/chronometer.sh /usr/local/bin/chronometer.sh - $SUDO cp /etc/.pihole/advanced/Scripts/whitelist.sh /usr/local/bin/whitelist.sh - $SUDO cp /etc/.pihole/advanced/Scripts/blacklist.sh /usr/local/bin/blacklist.sh - $SUDO cp /etc/.pihole/advanced/Scripts/piholeLogFlush.sh /usr/local/bin/piholeLogFlush.sh - $SUDO cp /etc/.pihole/advanced/Scripts/updateDashboard.sh /usr/local/bin/updateDashboard.sh - $SUDO chmod 755 /usr/local/bin/{gravity,chronometer,whitelist,blacklist,piholeLogFlush,updateDashboard}.sh + $SUDO echo -n "::: Installing scripts to /opt/pihole..." + if [ ! -d /opt/pihole ]; then + $SUDO mkdir /opt/pihole + $SUDO chown "$USER":root /opt/pihole + $SUDO chmod u+srwx /opt/pihole + fi + $SUDO cp /etc/.pihole/gravity.sh /opt/pihole/gravity.sh + $SUDO cp /etc/.pihole/advanced/Scripts/chronometer.sh /opt/pihole/chronometer.sh + $SUDO cp /etc/.pihole/advanced/Scripts/whitelist.sh /opt/pihole/whitelist.sh + $SUDO cp /etc/.pihole/advanced/Scripts/blacklist.sh /opt/pihole/blacklist.sh + $SUDO cp /etc/.pihole/advanced/Scripts/piholeDebug.sh /opt/pihole/piholeDebug.sh + $SUDO cp /etc/.pihole/advanced/Scripts/piholeLogFlush.sh /opt/pihole/piholeLogFlush.sh + $SUDO cp /etc/.pihole/advanced/Scripts/updateDashboard.sh /opt/pihole/updateDashboard.sh + $SUDO cp /etc/.pihole/automated\ install/uninstall.sh /opt/pihole/uninstall.sh + $SUDO cp /etc/.pihole/advanced/Scripts/setupLCD.sh /opt/pihole/setupLCD.sh + $SUDO chmod 755 /opt/pihole/{gravity,chronometer,whitelist,blacklist,piholeLogFlush,updateDashboard,uninstall,setupLCD}.sh + $SUDO cp /etc/.pihole/pihole /usr/local/bin/pihole + $SUDO chmod 755 /usr/local/bin/pihole + $SUDO cp /etc/.pihole/advanced/bash-completion/pihole /etc/bash_completion.d/pihole + . /etc/bash_completion.d/pihole + + #Tidy up /usr/local/bin directory if installing over previous install. + oldFiles=( gravity chronometer whitelist blacklist piholeLogFlush updateDashboard uninstall setupLCD piholeDebug) + for i in "${oldFiles[@]}"; do + if [ -f "/usr/local/bin/$i.sh" ]; then + $SUDO rm /usr/local/bin/"$i".sh + fi + done + $SUDO echo " done." } @@ -486,7 +495,11 @@ installConfigs() { $SUDO echo ":::" $SUDO echo "::: Installing configs..." versionCheckDNSmasq - $SUDO mv /etc/lighttpd/lighttpd.conf /etc/lighttpd/lighttpd.conf.orig + if [ ! -d "/etc/lighttpd" ]; then + $SUDO mkdir /etc/lighttpd + $SUDO chown "$USER":root /etc/lighttpd + $SUDO mv /etc/lighttpd/lighttpd.conf /etc/lighttpd/lighttpd.conf.orig + fi $SUDO cp /etc/.pihole/advanced/lighttpd.conf /etc/lighttpd/lighttpd.conf } @@ -504,44 +517,41 @@ checkForDependencies() { #requiring user input (e.g password for phpmyadmin see #218) #We'll change the logic up here, to check to see if there are any updates availible and # if so, advise the user to run apt-get update/upgrade at their own discretion - #Check to see if apt-get update has already been run today # it needs to have been run at least once on new installs! timestamp=$(stat -c %Y /var/cache/apt/) - timestampAsDate=$(date -d @$timestamp "+%b %e") + timestampAsDate=$(date -d @"$timestamp" "+%b %e") today=$(date "+%b %e") if [ ! "$today" == "$timestampAsDate" ]; then - #update package lists - echo ":::" - echo -n "::: apt-get update has not been run today. Running now..." - $SUDO apt-get -qq update & spinner $! - echo " done!" - fi + #update package lists echo ":::" - echo -n "::: Checking apt-get for upgraded packages...." - updatesToInstall=$($SUDO apt-get -s -o Debug::NoLocking=true upgrade | grep -c ^Inst) + echo -n "::: apt-get update has not been run today. Running now..." + $SUDO apt-get -qq update & spinner $! echo " done!" + fi + echo ":::" + echo -n "::: Checking apt-get for upgraded packages...." + updatesToInstall=$($SUDO apt-get -s -o Debug::NoLocking=true upgrade | grep -c ^Inst) + echo " done!" + echo ":::" + if [[ $updatesToInstall -eq "0" ]]; then + echo "::: Your pi is up to date! Continuing with pi-hole installation..." + else + echo "::: There are $updatesToInstall updates availible for your pi!" + echo "::: We recommend you run 'sudo apt-get upgrade' after installing Pi-Hole! " echo ":::" - if [[ $updatesToInstall -eq "0" ]]; then - echo "::: Your pi is up to date! Continuing with pi-hole installation..." - else - echo "::: There are $updatesToInstall updates availible for your pi!" - echo "::: We recommend you run 'sudo apt-get upgrade' after installing Pi-Hole! " - echo ":::" - fi + fi echo ":::" echo "::: Checking dependencies:" - dependencies=( dnsutils bc toilet figlet dnsmasq lighttpd php5-common php5-cgi php5 git curl unzip wget ) - for i in "${dependencies[@]}" - do - : + dependencies=( dnsutils bc toilet figlet dnsmasq lighttpd php5-common php5-cgi php5 git curl unzip wget ) + for i in "${dependencies[@]}"; do echo -n "::: Checking for $i..." - if [ $(dpkg-query -W -f='${Status}' $i 2>/dev/null | grep -c "ok installed") -eq 0 ]; then + if [ "$(dpkg-query -W -f='${Status}' "$i" 2>/dev/null | grep -c "ok installed")" -eq 0 ]; then echo -n " Not found! Installing...." - $SUDO apt-get -y -qq install $i > /dev/null & spinner $! + $SUDO apt-get -y -qq install "$i" > /dev/null & spinner $! echo " done!" else echo " already installed!" @@ -571,18 +581,18 @@ getGitFiles() { is_repo() { # If the directory does not have a .git folder it is not a repo echo -n "::: Checking $1 is a repo..." - if [ -d "$1/.git" ]; then - echo " OK!" - return 1 - fi - echo " not found!!" - return 0 + if [ -d "$1/.git" ]; then + echo " OK!" + return 1 + fi + echo " not found!!" + return 0 } make_repo() { # Remove the non-repod interface and clone the interface echo -n "::: Cloning $2 into $1..." - $SUDO rm -rf $1 + $SUDO rm -rf "$1" $SUDO git clone -q "$2" "$1" > /dev/null & spinner $! echo " done!" } @@ -590,7 +600,7 @@ make_repo() { update_repo() { # Pull the latest commits echo -n "::: Updating repo in $1..." - cd "$1" + cd "$1" || exit $SUDO git pull -q > /dev/null & spinner $! echo " done!" } @@ -618,8 +628,12 @@ installPiholeWeb() { $SUDO echo " Existing page detected, not overwriting" else $SUDO mkdir /var/www/html/pihole - $SUDO mv /var/www/html/index.lighttpd.html /var/www/html/index.lighttpd.orig - $SUDO cp /etc/.pihole/advanced/index.html /var/www/html/pihole/index.html + if [ -f /var/www/html/index.lighttpd.html ]; then + $SUDO mv /var/www/html/index.lighttpd.html /var/www/html/index.lighttpd.orig + else + printf "\n:::\tNo default index.lighttpd.html file found... not backing up" + fi + $SUDO cp /etc/.pihole/advanced/index.* /var/www/html/pihole/. $SUDO echo " done!" fi } @@ -635,16 +649,13 @@ installCron() { runGravity() { # Rub gravity.sh to build blacklists $SUDO echo ":::" - $SUDO echo "::: Preparing to run gravity.sh to refresh hosts..." + $SUDO echo "::: Preparing to run gravity.sh to refresh hosts..." if ls /etc/pihole/list* 1> /dev/null 2>&1; then - echo "::: Cleaning up previous install (preserving whitelist/blacklist)" + echo "::: Cleaning up previous install (preserving whitelist/blacklist)" $SUDO rm /etc/pihole/list.* fi - #Don't run as SUDO, this was causing issues echo "::: Running gravity.sh" - echo ":::" - - /usr/local/bin/gravity.sh + $SUDO /opt/pihole/gravity.sh } setUser(){ @@ -653,7 +664,7 @@ setUser(){ if id -u pihole > /dev/null 2>&1; then echo "::: User 'pihole' already exists" else - echo "::: User 'pihole' doesn't exist. Creating..." + echo "::: User 'pihole' doesn't exist. Creating..." $SUDO useradd -r -s /usr/sbin/nologin pihole fi } @@ -664,6 +675,9 @@ installPihole() { stopServices setUser $SUDO mkdir -p /etc/pihole/ + if [ ! -d "/var/www/html" ]; then + $SUDO mkdir -p /var/www/html + fi $SUDO chown www-data:www-data /var/www/html $SUDO chmod 775 /var/www/html $SUDO usermod -a -G www-data pihole @@ -682,8 +696,8 @@ displayFinalMessage() { # Final completion message to user whiptail --msgbox --backtitle "Make it so." --title "Installation Complete!" "Configure your devices to use the Pi-hole as their DNS server using: -$IPv4addr -$piholeIPv6 +IPv4: $IPv4addr +IPv6: $piholeIPv6 If you set a new IP address, you should restart the Pi. diff --git a/automated install/uninstall.sh b/automated install/uninstall.sh old mode 100644 new mode 100755 index ee4e80a0..484a544d --- a/automated install/uninstall.sh +++ b/automated install/uninstall.sh @@ -12,62 +12,135 @@ # Must be root to uninstall if [[ $EUID -eq 0 ]];then - echo "You are root." + echo "::: You are root." else - echo "sudo will be used for the install." + echo "::: Sudo will be used for the uninstall." # Check if it is actually installed # If it isn't, exit because the unnstall cannot complete if [[ $(dpkg-query -s sudo) ]];then export SUDO="sudo" else - echo "Please install sudo or run this as root." + echo "::: Please install sudo or run this as root." exit 1 fi fi +spinner() +{ + local pid=$1 + local delay=0.50 + local spinstr='/-\|' + while [ "$(ps a | awk '{print $1}' | grep "$pid")" ]; do + local temp=${spinstr#?} + printf " [%c] " "$spinstr" + local spinstr=$temp${spinstr%"$temp"} + sleep $delay + printf "\b\b\b\b\b\b" + done + printf " \b\b\b\b" +} + +function removeAndPurge { + # Purge dependencies +echo ":::" + # Nate 3/28/2016 - Removed `php5-cgi` and `php5` as they are removed with php5-common + dependencies=( dnsutils bc toilet figlet dnsmasq lighttpd php5-common git curl unzip wget ) + for i in "${dependencies[@]}"; do + if [ "$(dpkg-query -W --showformat='${Status}\n' "$i" 2> /dev/null | grep -c "ok installed")" -eq 1 ]; then + while true; do + read -rp "::: Do you wish to remove $i from your system? [y/n]: " yn + case $yn in + [Yy]* ) printf ":::\tRemoving %s..." "$i"; $SUDO apt-get -y remove --purge "$i" &> /dev/null & spinner $!; printf "done!\n"; break;; + [Nn]* ) printf ":::\tSkipping %s" "$i\n"; break;; + * ) printf "::: You must answer yes or no!\n";; + esac + done + else + printf ":::\tPackage %s not installed... Not removing.\n" "$i" + fi + done + + # Remove dependency config files + echo "::: Removing dnsmasq config files..." + $SUDO rm /etc/dnsmasq.conf /etc/dnsmasq.conf.orig /etc/dnsmasq.d/01-pihole.conf &> /dev/null + + # Take care of any additional package cleaning + printf "::: Auto removing remaining dependencies..." + $SUDO apt-get -y autoremove &> /dev/null & spinner $!; printf "done!\n"; + printf "::: Auto cleaning remaining dependencies..." + $SUDO apt-get -y autoclean &> /dev/null & spinner $!; printf "done!\n"; + + # Call removeNoPurge to remove PiHole specific files + removeNoPurge +} + +function removeNoPurge { + echo ":::" + # Only web directories/files that are created by pihole should be removed. + echo "::: Removing the Pi-hole Web server files..." + $SUDO rm -rf /var/www/html/admin &> /dev/null + $SUDO rm -rf /var/www/html/pihole &> /dev/null + $SUDO rm /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 [ -d "/var/www/html" ]; then + if [[ ! "$(ls -A /var/www/html)" ]]; then + $SUDO rm -rf /var/www/html &> /dev/null + fi + fi + + # Attempt to preserve backwards compatibility with older versions + # to guarantee no additional changes were made to /etc/crontab after + # the installation of pihole, /etc/crontab.pihole should be permanently + # preserved. + if [[ -f /etc/crontab.orig ]]; then + echo "::: Initial Pi-hole cron detected. Restoring the default system cron..." + $SUDO mv /etc/crontab /etc/crontab.pihole + $SUDO mv /etc/crontab.orig /etc/crontab + $SUDO service cron restart + fi + + # Attempt to preserve backwards compatibility with older versions + if [[ -f /etc/cron.d/pihole ]];then + echo "::: Removing cron.d/pihole..." + $SUDO rm /etc/cron.d/pihole &> /dev/null + fi + + echo "::: Removing config files and scripts..." + if [ ! "$(dpkg-query -W --showformat='${Status}\n' lighttpd 2> /dev/null | grep -c "ok installed")" -eq 1 ]; then + $SUDO rm -rf /etc/lighttpd/ &> /dev/null + else + if [ -f /etc/lighttpd/lighttpd.conf.orig ]; then + $SUDO mv /etc/lighttpd/lighttpd.conf.orig /etc/lighttpd/lighttpd.conf + fi + fi + + $SUDO rm /etc/dnsmasq.d/adList.conf &> /dev/null + $SUDO rm /etc/dnsmasq.d/01-pihole.conf &> /dev/null + $SUDO rm -rf /var/log/*pihole* &> /dev/null + $SUDO rm -rf /etc/pihole/ &> /dev/null + $SUDO rm -rf /etc/.pihole/ &> /dev/null + $SUDO rm -rf /opt/pihole/ &> /dev/null + $SUDO rm /usr/local/bin/pihole &> /dev/null + $SUDO rm /etc/bash_completion.d/pihole + + echo ":::" + printf "::: Finished removing PiHole from your system. Sorry to see you go!\n" + printf "::: Reach out to us at https://github.com/pi-hole/pi-hole/issues if you need help\n" + printf "::: Reinstall by simpling running\n:::\n:::\tcurl -L https://install.pi-hole.net | bash\n:::\n::: at any time!\n:::\n" + printf "::: PLEASE RESET YOUR DNS ON YOUR ROUTER/CLIENTS TO RESTORE INTERNET CONNECTIVITY!\n" +} ######### SCRIPT ########### -$SUDO apt-get -y remove --purge dnsutils bc toilet -$SUDO apt-get -y remove --purge dnsmasq -$SUDO apt-get -y remove --purge lighttpd php5-common php5-cgi php5 +echo "::: Preparing to remove packages, be sure that each may be safely removed depending on your operating system." +echo "::: (SAFE TO REMOVE ALL ON RASPBIAN)" +while true; do + read -rp "::: Do you wish to purge PiHole's dependencies from your OS? (You will be prompted for each package) [y/n]: " yn + case $yn in + [Yy]* ) removeAndPurge; break;; + + [Nn]* ) removeNoPurge; break;; + esac +done -# Only web directories/files that are created by pihole should be removed. -echo "Removing the Pi-hole Web server files..." -$SUDO rm -rf /var/www/html/admin -$SUDO rm -rf /var/www/html/pihole -$SUDO rm /var/www/html/index.lighttpd.orig -# If the web directory is empty after removing these files, then the parent html folder can be removed. -if [[ ! "$(ls -A /var/www/html)" ]]; then - $SUDO rm -rf /var/www/html -fi - -echo "Removing dnsmasq config files..." -$SUDO rm /etc/dnsmasq.conf /etc/dnsmasq.conf.orig - -# Attempt to preserve backwards compatibility with older versions -# to guarantee no additional changes were made to /etc/crontab after -# the installation of pihole, /etc/crontab.pihole should be permanently -# preserved. -if [[ -f /etc/crontab.orig ]]; then - echo "Initial Pi-hole cron detected. Restoring the default system cron..." - $SUDO mv /etc/crontab /etc/crontab.pihole - $SUDO mv /etc/crontab.orig /etc/crontab - $SUDO service cron restart -fi - -# Attempt to preserve backwards compatibility with older versions -if [[ -f /etc/cron.d/pihole ]];then - echo "Removing cron.d/pihole..." - $SUDO rm /etc/cron.d/pihole -fi - -echo "Removing config files and scripts..." -$SUDO rm /etc/dnsmasq.conf -$SUDO rm -rf /etc/lighttpd/ -$SUDO rm /var/log/pihole.log -$SUDO rm /usr/local/bin/gravity.sh -$SUDO rm /usr/local/bin/chronometer.sh -$SUDO rm /usr/local/bin/whitelist.sh -$SUDO rm /usr/local/bin/piholeLogFlush.sh -$SUDO rm -rf /etc/pihole/ diff --git a/gravity.sh b/gravity.sh index 321aec27..d77d75cf 100755 --- a/gravity.sh +++ b/gravity.sh @@ -16,14 +16,14 @@ if [[ $EUID -eq 0 ]];then echo "::: You are root." else echo "::: sudo will be used." - # Check if it is actually installed - # If it isn't, exit because the install cannot complete - if [[ $(dpkg-query -s sudo) ]];then + # Check if it is actually installed + # If it isn't, exit because the install cannot complete + if [[ $(dpkg-query -s sudo) ]];then export SUDO="sudo" - else + else echo "::: Please install sudo or run this script as root." - exit 1 - fi + exit 1 + fi fi piholeIPfile=/tmp/piholeIP @@ -31,8 +31,8 @@ piholeIPv6file=/etc/pihole/.useIPv6 adListFile=/etc/pihole/adlists.list adListDefault=/etc/pihole/adlists.default -whitelistScript=/usr/local/bin/whitelist.sh -blacklistScript=/usr/local/bin/blacklist.sh +whitelistScript=/opt/pihole/whitelist.sh +blacklistScript=/opt/pihole/blacklist.sh if [[ -f $piholeIPfile ]];then # If the file exists, it means it was exported from the installation script and we should use that value instead of detecting it in this script @@ -41,7 +41,7 @@ if [[ -f $piholeIPfile ]];then else # Otherwise, the IP address can be taken directly from the machine, which will happen when the script is run by the user and not the installation script IPv4dev=$(ip route get 8.8.8.8 | awk '{for(i=1;i<=NF;i++)if($i~/dev/)print $(i+1)}') - piholeIPCIDR=$(ip -o -f inet addr show dev $IPv4dev | awk '{print $4}' | awk 'END {print}') + piholeIPCIDR=$(ip -o -f inet addr show dev "$IPv4dev" | awk '{print $4}' | awk 'END {print}') piholeIP=${piholeIPCIDR%/*} fi @@ -50,22 +50,20 @@ if [[ -f $piholeIPv6file ]];then piholeIPv6=$(ip -6 route get 2001:4860:4860::8888 | awk -F " " '{ for(i=1;i<=NF;i++) if ($i == "src") print $(i+1) }') fi - - - # Variables for various stages of downloading and formatting the list +## Nate 3/26/2016 - Commented unused variables basename=pihole piholeDir=/etc/$basename adList=$piholeDir/gravity.list -blacklist=$piholeDir/blacklist.txt -whitelist=$piholeDir/whitelist.txt -latentWhitelist=$piholeDir/latentWhitelist.txt +#blacklist=$piholeDir/blacklist.txt +#whitelist=$piholeDir/whitelist.txt +#latentWhitelist=$piholeDir/latentWhitelist.txt justDomainsExtension=domains matterandlight=$basename.0.matterandlight.txt supernova=$basename.1.supernova.txt eventHorizon=$basename.2.eventHorizon.txt accretionDisc=$basename.3.accretionDisc.txt -eyeOfTheNeedle=$basename.4.wormhole.txt +#eyeOfTheNeedle=$basename.4.wormhole.txt # After setting defaults, check if there's local overrides if [[ -r $piholeDir/pihole.conf ]];then @@ -73,22 +71,20 @@ if [[ -r $piholeDir/pihole.conf ]];then . $piholeDir/pihole.conf fi - -spinner(){ - local pid=$1 - local delay=0.001 - local spinstr='/-\|' - - spin='-\|/' - i=0 - while $SUDO kill -0 $pid 2>/dev/null - do - i=$(( (i+1) %4 )) - printf "\b${spin:$i:1}" - sleep .1 - done - printf "\b" +spinner() { + local pid=$1 + local delay=0.50 + local spinstr='/-|' + while [ "$(ps a | awk '{print $1}' | grep "$pid")" ]; do + local temp=${spinstr#?} + printf " [%c] " "$spinstr" + local spinstr=$temp${spinstr%"$temp"} + sleep $delay + printf "\b\b\b\b\b\b" + done + printf " \b\b\b\b" } + ########################### # collapse - begin formation of pihole function gravity_collapse() { @@ -99,7 +95,7 @@ function gravity_collapse() { #custom file found, use this instead of default echo -n "::: Custom adList file detected. Reading..." sources=() - while read -a line; do + while read -r line; do #Do not read commented out or blank lines if [[ $line = \#* ]] || [[ ! $line ]]; then echo "" > /dev/null @@ -107,12 +103,12 @@ function gravity_collapse() { sources+=($line) fi done < $adListFile - echo " done!" + echo " done!" else #no custom file found, use defaults! echo -n "::: No custom adlist file detected, reading from default file..." - sources=() - while read -a line; do + sources=() + while read -r line; do #Do not read commented out or blank lines if [[ $line = \#* ]] || [[ ! $line ]]; then echo "" > /dev/null @@ -120,8 +116,8 @@ function gravity_collapse() { sources+=($line) fi done < $adListDefault - echo " done!" - fi + echo " done!" + fi # Create the pihole resource directory if it doesn't exist. Future files will be stored here if [[ -d $piholeDir ]];then @@ -129,12 +125,12 @@ function gravity_collapse() { # Will update later, needed for existing installs, new installs should # create this directory as non-root $SUDO chmod 777 $piholeDir - find "$piholeDir" -type f -exec $SUDO chmod 666 {} \; & spinner $! - echo "." + echo ":::" + echo "::: Existing pihole directory found" else - echo -n "::: Creating pihole directory..." - mkdir $piholeDir & spinner $! - echo " done!" + echo "::: Creating pihole directory..." + mkdir $piholeDir + $SUDO chmod 777 $piholeDir fi } @@ -146,7 +142,7 @@ function gravity_patternCheck() { # Some of the blocklists are copyright, they need to be downloaded # and stored as is. They can be processed for content after they # have been saved. - cp $patternBuffer $saveLocation + cp "$patternBuffer" "$saveLocation" echo " List updated, transport successful!" else # curl didn't download any host files, probably because of the date check @@ -169,17 +165,16 @@ function gravity_transport() { fi # Silently curl url - curl -s $cmd_ext $heisenbergCompensator -A "$agent" $url > $patternBuffer + curl -s $cmd_ext $heisenbergCompensator -A "$agent" $url > $patternBuffer # Check for list updates - gravity_patternCheck $patternBuffer - + gravity_patternCheck "$patternBuffer" # Cleanup - rm -f $patternBuffer + rm -f "$patternBuffer" } # spinup - main gravity function function gravity_spinup() { - echo "::: " + echo ":::" # Loop through domain list. Download each one and remove commented lines (lines beginning with '# 'or '/') and # blank lines for ((i = 0; i < "${#sources[@]}"; i++)) do @@ -198,17 +193,17 @@ function gravity_spinup() { # Use a case statement to download lists that need special cURL commands # to complete properly and reset the user agent when required case "$domain" in - "adblock.mahakala.is") - agent='Mozilla/5.0 (X11; Linux x86_64; rv:30.0) Gecko/20100101 Firefox/30.0' - cmd_ext="-e http://forum.xda-developers.com/" - ;; + "adblock.mahakala.is") + agent='Mozilla/5.0 (X11; Linux x86_64; rv:30.0) Gecko/20100101 Firefox/30.0' + cmd_ext="-e http://forum.xda-developers.com/" + ;; - "pgl.yoyo.org") - cmd_ext="-d mimetype=plaintext -d hostformat=hosts" - ;; + "pgl.yoyo.org") + cmd_ext="-d mimetype=plaintext -d hostformat=hosts" + ;; - # Default is a simple request - *) cmd_ext="" + # Default is a simple request + *) cmd_ext="" esac gravity_transport "$url" "$cmd_ext" "$agent" done @@ -216,55 +211,46 @@ function gravity_spinup() { # Schwarzchild - aggregate domains to one list and add blacklisted domains function gravity_Schwarzchild() { - echo "::: " + echo "::: " # Find all active domains and compile them into one file and remove CRs echo -n "::: Aggregating list of domains..." - truncate -s 0 $piholeDir/$matterandlight & spinner $! + truncate -s 0 $piholeDir/$matterandlight & spinner $! for i in "${activeDomains[@]}" do - cat $i |tr -d '\r' >> $piholeDir/$matterandlight + cat "$i" | tr -d '\r' >> $piholeDir/$matterandlight done echo " done!" - } - function gravity_Blacklist(){ # Append blacklist entries if they exist echo -n "::: Running blacklist script to update HOSTS file...." $blacklistScript -f -nr -q > /dev/null & spinner $! - + numBlacklisted=$(wc -l < "/etc/pihole/blacklist.txt") plural=; [[ "$numBlacklisted" != "1" ]] && plural=s - echo " $numBlacklisted domain${plural} blacklisted!" - - + echo " $numBlacklisted domain${plural} blacklisted!" } - function gravity_Whitelist() { - echo ":::" + echo ":::" # Prevent our sources from being pulled into the hole plural=; [[ "${sources[@]}" != "1" ]] && plural=s - echo -n "::: Adding ${#sources[@]} ad list source${plural} to the whitelist..." - + echo -n "::: Adding ${#sources[@]} adlist source${plural} to the whitelist..." + urls=() - for url in ${sources[@]} + for url in "${sources[@]}" do tmp=$(echo "$url" | awk -F '/' '{print $3}') urls=("${urls[@]}" $tmp) done echo " done!" - + echo -n "::: Running whitelist script to update HOSTS file...." - $whitelistScript -f -nr -q ${urls[@]} > /dev/null & spinner $! - + $whitelistScript -f -nr -q "${urls[@]}" > /dev/null & spinner $! numWhitelisted=$(wc -l < "/etc/pihole/whitelist.txt") plural=; [[ "$numWhitelisted" != "1" ]] && plural=s - echo " $numWhitelisted domain${plural} whitelisted!" - - - + echo " $numWhitelisted domain${plural} whitelisted!" } function gravity_unique() { @@ -277,20 +263,21 @@ function gravity_unique() { } function gravity_hostFormat() { - # Format domain list as "192.168.x.x domain.com" + # Format domain list as "192.168.x.x domain.com" echo "::: Formatting domains into a HOSTS file..." - # If there is a value in the $piholeIPv6, then IPv6 will be used, so the awk command modified to create a line for both protocols - if [[ -n $piholeIPv6 ]];then - #Add dummy domain Pi-Hole.IsWorking.OK to the top of gravity.list to make ping result return a friendlier looking domain! - echo -e "$piholeIP Pi-Hole.IsWorking.OK \n$piholeIPv6 Pi-Hole.IsWorking.OK" > $piholeDir/$accretionDisc - cat $piholeDir/$eventHorizon | awk -v ipv4addr="$piholeIP" -v ipv6addr="$piholeIPv6" '{sub(/\r$/,""); print ipv4addr" "$0"\n"ipv6addr" "$0}' >> $piholeDir/$accretionDisc - - else - # Otherwise, just create gravity.list as normal using IPv4 - #Add dummy domain Pi-Hole.IsWorking.OK to the top of gravity.list to make ping result return a friendlier looking domain! - echo -e "$piholeIP Pi-Hole.IsWorking.OK" > $piholeDir/$accretionDisc - cat $piholeDir/$eventHorizon | awk -v ipv4addr="$piholeIP" '{sub(/\r$/,""); print ipv4addr" "$0}' >> $piholeDir/$accretionDisc - fi + hostname=$( $piholeDir/$accretionDisc + cat $piholeDir/$eventHorizon | awk -v ipv4addr="$piholeIP" -v ipv6addr="$piholeIPv6" '{sub(/\r$/,""); print ipv4addr" "$0"\n"ipv6addr" "$0}' >> $piholeDir/$accretionDisc + else + # Otherwise, just create gravity.list as normal using IPv4 + # Add hostname and dummy domain to the top of gravity.list to make ping result return a friendlier looking domain! Also allows for an easy way to access the Pi-hole admin console (pi.hole/admin) + echo -e "$piholeIP $hostname\n$piholeIP pi.hole" > $piholeDir/$accretionDisc + cat $piholeDir/$eventHorizon | awk -v ipv4addr="$piholeIP" '{sub(/\r$/,""); print ipv4addr" "$0}' >> $piholeDir/$accretionDisc + fi + # Copy the file over as /etc/pihole/gravity.list so dnsmasq can use it cp $piholeDir/$accretionDisc $adList } @@ -301,49 +288,52 @@ function gravity_blackbody() { for file in $piholeDir/*.$justDomainsExtension do # If list is in active array then leave it (noop) else rm the list - if [[ " ${activeDomains[@]} " =~ " ${file} " ]]; then + if [[ " ${activeDomains[@]} " =~ ${file} ]]; then : else - rm -f $file + rm -f "$file" fi done } function gravity_advanced() { - - # Remove comments and print only the domain name # Most of the lists downloaded are already in hosts file format but the spacing/formating is not contigious # This helps with that and makes it easier to read # It also helps with debugging so each stage of the script can be researched more in depth echo -n "::: Formatting list of domains to remove comments...." awk '($1 !~ /^#/) { if (NF>1) {print $2} else {print $1}}' $piholeDir/$matterandlight | sed -nr -e 's/\.{2,}/./g' -e '/\./p' > $piholeDir/$supernova & spinner $! - echo " done!" - + echo " done!" + numberOf=$(wc -l < $piholeDir/$supernova) echo "::: $numberOf domains being pulled in by gravity..." - + gravity_unique - } function gravity_reload() { #Clear no longer needed files... echo ":::" echo -n "::: Cleaning up un-needed files..." - $SUDO rm /etc/pihole/pihole.* + $SUDO rm $piholeDir/pihole.*.txt echo " done!" - + # Reload hosts file echo ":::" echo -n "::: Refresh lists in dnsmasq..." + + #ensure /etc/dnsmasq.d/01-pihole.conf is pointing at the correct list! + #First escape forward slashes in the path: + adList=${adList//\//\\\/} + #Now replace the line in dnsmasq file + $SUDO sed -i "s/^addn-hosts.*/addn-hosts=$adList/" /etc/dnsmasq.d/01-pihole.conf dnsmasqPid=$(pidof dnsmasq) find "$piholeDir" -type f -exec $SUDO chmod 666 {} \; & spinner $! if [[ $dnsmasqPid ]]; then # service already running - reload config - $SUDO kill -HUP $dnsmasqPid & spinner $! + $SUDO kill -HUP "$dnsmasqPid" & spinner $! else # service not running, start it up $SUDO service dnsmasq start & spinner $! diff --git a/pihole b/pihole new file mode 100755 index 00000000..5ff26246 --- /dev/null +++ b/pihole @@ -0,0 +1,114 @@ +#!/bin/bash +# 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 +# Controller for all pihole scripts and functions. +# +# 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. + +# Must be root to use this tool +if [[ ! $EUID -eq 0 ]];then + #echo "::: You are root." +#else + #echo "::: Sudo will be used for this tool." + # Check if it is actually installed + # If it isn't, exit because the pihole cannot be invoked without privileges. + if [[ $(dpkg-query -s sudo) ]];then + export SUDO="sudo" + else + echo "::: Please install sudo or run this as root." + exit 1 + fi +fi + +function whitelistFunc { + shift + $SUDO /opt/pihole/whitelist.sh "$@" + exit 1 +} + +function blacklistFunc { + shift + $SUDO /opt/pihole/blacklist.sh "$@" + exit 1 +} + +function debugFunc { + $SUDO /opt/pihole/piholeDebug.sh + exit 1 +} + +function flushFunc { + $SUDO /opt/pihole/piholeLogFlush.sh + exit 1 +} + +function updateDashboardFunc { + $SUDO /opt/pihole/updateDashboard.sh + exit 1 +} + +function updateGravityFunc { + $SUDO /opt/pihole/gravity.sh + exit 1 +} + +function setupLCDFunction { + $SUDO /opt/pihole/setupLCD.sh + exit 1 +} + +function chronometerFunc { + shift + $SUDO /opt/pihole/chronometer.sh "$@" + exit 1 +} + + +function uninstallFunc { + $SUDO /opt/pihole/uninstall.sh + exit 1 +} + +function helpFunc { + echo "::: Control all PiHole specific functions!" + echo ":::" + echo "::: Usage: pihole.sh [options]" + printf ":::\tAdd -h after -w (whitelist), -b (blacklist), or -c (chronometer) for more information on usage\n" + echo ":::" + echo "::: Options:" + echo "::: -w, whitelist Whitelist domains" + echo "::: -b, blacklist Blacklist domains" + echo "::: -d, debug Start a debugging session if having trouble" + echo "::: -f, flush Flush the pihole.log file" + echo "::: -u, updateDashboard Update the web dashboard manually" + echo "::: -g, updateGravity Update the list of ad-serving domains" + echo "::: -s, setupLCD Automatically configures the Pi to use the 2.8 LCD screen to display stats on it" + echo "::: -c, chronometer Calculates stats and displays to an LCD" + echo "::: -h, help Show this help dialog" + echo "::: uninstall Uninstall Pi-Hole from your system!" + exit 1 +} + +if [[ $# = 0 ]]; then + helpFunc +fi + +# Handle redirecting to specific functions based on arguments +case "$1" in +"-w" | "whitelist" ) whitelistFunc "$@";; +"-b" | "blacklist" ) blacklistFunc "$@";; +"-d" | "debug" ) debugFunc;; +"-f" | "flush" ) flushFunc;; +"-u" | "updateDashboard" ) updateDashboardFunc;; +"-g" | "updateGravity" ) updateGravityFunc;; +"-s" | "setupLCD" ) setupLCDFunction;; +"-c" | "chronometer" ) chronometerFunc "$@";; +"-h" | "help" ) helpFunc;; +"uninstall" ) uninstallFunc;; +* ) helpFunc;; +esac