diff --git a/README.md b/README.md index 09b8852..258168c 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,11 @@ # Automated Install 1. Install Raspbian -2. Set a **static** IP address -3. Run the command below +2. Run the command below -```curl -L install.pi-hole.net | bash``` +### ```curl -L install.pi-hole.net | bash``` + +![Pi-hole automated installation](http://i.imgur.com/Un7lBlj.png) Once installed, **configure any device to use the Raspberry Pi as its DNS server and the ads will be blocked**. You can also configure your router's DHCP options to assign the Pi as clients DNS server so they do not need to do it manually. @@ -62,5 +63,6 @@ This script will work for other UNIX-like systems with some slight **modificatio ### Examples Of The Pi-hole On Other Operating Systems - [Sky-Hole](http://dlaa.me/blog/post/skyhole) +- [Pi-hole in the Cloud!](http://blog.codybunch.com/2015/07/28/Pi-Hole-in-the-cloud/) [![Donate](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif "AdminLTE Presentation")](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=3J2L3Z4DHW9UY "Donate") diff --git a/advanced/Scripts/whitelist.sh b/advanced/Scripts/whitelist.sh index d610d0a..cda557c 100755 --- a/advanced/Scripts/whitelist.sh +++ b/advanced/Scripts/whitelist.sh @@ -1,6 +1,11 @@ #!/bin/bash +whitelist=/etc/pihole/whitelist.txt +adList=/etc/pihole/gravity.list +if [[ ! -f $whitelist ]];then + touch $whitelist +fi -if [ $# = 0 ]; then +if [[ $# = 0 ]]; then echo "Immediately whitelists one or more domains." echo "Usage: whitelist.sh domain1 [domain2 ...]" fi @@ -15,28 +20,28 @@ do # Construct basic pattern to match domain name. basicpattern=$(echo $var | awk -F '[# \t]' 'NF>0&&$1!="" {print ""$1""}' | sed 's/\./\\./g') - if [ "$basicpattern" != "" ]; then + if [[ "$basicpattern" != "" ]]; then # Add to the combination pattern that will be used below - if [ "$combopattern" != "" ]; then combopattern="$combopattern|"; fi + if [[ "$combopattern" != "" ]]; then combopattern="$combopattern|"; fi combopattern="$combopattern$basicpattern" # Also add the domain to the whitelist but only if it's not already present - grep -E -q "^$basicpattern$" /etc/pihole/whitelist.txt \ - || echo "$var" >> /etc/pihole/whitelist.txt + grep -E -q "^$basicpattern$" $whitelist \ + || echo "$var" >> $whitelist fi done # Now report on and remove matched domains -if [ "$combopattern" != "" ]; then +if [[ "$combopattern" != "" ]]; then echo "Modifying hosts file..." - + # Construct pattern to match entry in hosts file. # This consists of one or more IP addresses followed by the domain name. pattern=$(echo $combopattern | awk -F '[# \t]' '{printf "%s", "^(([0-9]+\.){3}[0-9]+ +)+("$1")$"}') # Output what will be removed and then actually remove - sed -r -n 's/'"$pattern"'/ Removed: \3/p' /etc/pihole/gravity.list - sed -r -i '/'"$pattern"'/d' /etc/pihole/gravity.list + sed -r -n 's/'"$pattern"'/ Removed: \3/p' $adList + sed -r -i '/'"$pattern"'/d' $adList echo "** $# domain(s) whitelisted." # Force dnsmasq to reload /etc/pihole/gravity.list diff --git a/advanced/dnsmasq.conf b/advanced/dnsmasq.conf index 25b2138..30d7238 100644 --- a/advanced/dnsmasq.conf +++ b/advanced/dnsmasq.conf @@ -1,12 +1,47 @@ +# If you want dnsmasq to read another file, as well as /etc/hosts, use +# this. addn-hosts=/etc/pihole/gravity.list + +# The following two options make you a better netizen, since they +# tell dnsmasq to filter out queries which the public DNS cannot +# answer, and which load the servers (especially the root servers) +# unnecessarily. If you have a dial-on-demand link they also stop +# these requests from bringing up the link unnecessarily. + +# Never forward plain names (without a dot or domain part) domain-needed +# Never forward addresses in the non-routed address spaces. bogus-priv + +# If you don't want dnsmasq to read /etc/resolv.conf or any other +# file, getting its servers from this file instead (see below), then +# uncomment this. no-resolv + +# Add other name servers here, with domain specs if they are for +# non-public domains. server=8.8.8.8 server=8.8.4.4 + +# If you want dnsmasq to listen for DHCP and DNS requests only on +# specified interfaces (and the loopback) give the name of the +# interface (eg eth0) here. interface=eth0 +# Or which to listen on by address (remember to include 127.0.0.1 if +# you use this.) listen-address=127.0.0.1 + +# Set the cachesize here. cache-size=10000 + +# For debugging purposes, log each DNS query as it passes through +# dnsmasq. log-queries log-facility=/var/log/pihole.log + +# Normally responses which come from /etc/hosts and the DHCP lease +# file have Time-To-Live set as zero, which conventionally means +# do not cache further. If you are happy to trade lower load on the +# server for potentially stale date, you can set a time-to-live (in +# seconds) here. local-ttl=300 diff --git a/advanced/lighttpd.conf b/advanced/lighttpd.conf index a4253a0..3998269 100644 --- a/advanced/lighttpd.conf +++ b/advanced/lighttpd.conf @@ -1,4 +1,6 @@ server.modules = ( + "mod_access", + "mod_accesslog", "mod_expire", "mod_compress", "mod_redirect", @@ -14,6 +16,8 @@ server.pid-file = "/var/run/lighttpd.pid" server.username = "www-data" server.groupname = "www-data" server.port = 80 +accesslog.filename = "/var/log/lighttpd/access.log" +accesslog.format = "%{%s}t|%V|%r|%s|%b" index-file.names = ( "index.php", "index.html", "index.lighttpd.html" ) diff --git a/advanced/pihole.cron b/advanced/pihole.cron index a707607..47bc61f 100644 --- a/advanced/pihole.cron +++ b/advanced/pihole.cron @@ -1 +1,26 @@ -@weekly sudo /usr/local/bin/gravity.sh +# /etc/crontab: system-wide crontab +# Unlike any other crontab you don't have to run the `crontab' +# command to install the new version when you edit this file +# and files in /etc/cron.d. These files also have username fields, +# that none of the other crontabs do. + +SHELL=/bin/sh +PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin + +# m h dom mon dow user command +17 * * * * root cd / && run-parts --report /etc/cron.hourly +25 6 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily ) +47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly ) +52 6 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly ) + +# 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 + +# 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 11 * * * root /usr/local/bin/dailyLog.sh + +# 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 11 * * * root /usr/local/bin/piholeLogFlush.sh diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index 7c48fdb..55292ad 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -1,31 +1,47 @@ -#!/bin/bash -# Pi-hole automated install -# Raspberry Pi Ad-blocker +#!/usr/bin/env bash +# Pi-hole: A black hole for Internet advertisements +# by Jacob Salmela +# Network-wide ad blocking via your Raspberry Pi # -# Install with this command (from the Pi): +# pi-hole.net/donate # -# curl -s "https://raw.githubusercontent.com/jacobsalmela/pi-hole/master/automated%20install/basic-install.sh" | bash +# Install with this command (from your Pi): # -# Or run the commands below in order +# curl -L install.pi-hole.net | bash -clear -echo " _____ _ _ _ " -echo " | __ (_) | | | | " -echo " | |__) | __ | |__ ___ | | ___ " -echo " | ___/ | |__| | '_ \ / _ \| |/ _ \ " -echo " | | | | | | | | (_) | | __/ " -echo " |_| |_| |_| |_|\___/|_|\___| " -echo " " -echo " Raspberry Pi Ad-blocker " -echo " " -echo "Set a static IP before running this!" -echo " " -echo " Press Enter when ready " -echo " " -read +######## VARIABLES ######### +tmpLog=/tmp/pihole-install.log +instalLogLoc=/etc/pihole/install.log +# Get the screen size in case we need a full-screen message and so we can display a dialog that is sized nicely +screenSize=$(stty -a | tr \; \\012 | egrep 'rows|columns' | cut '-d ' -f3) + +# Find the rows and columns +rows=$(stty -a | tr \; \\012 | egrep 'rows' | cut -d' ' -f3) +columns=$(stty -a | tr \; \\012 | egrep 'columns' | cut -d' ' -f3) + +# Divide by two so the dialogs take up half of the screen, which looks nice. +r=$(( rows / 2 )) +c=$(( columns / 2 )) + +# Find IP used to route to outside world +IPv4info=$(ip route get 8.8.8.8) +IPv4dev=$(echo $IPv4info| awk '{print $5}') +IPv4addr=$(ip -o -f inet addr show dev $IPv4dev | awk '{print $4}') +IPv4gw=$(echo $IPv4info | awk '{print $3}') + +# IPv6 support to be added later +#IPv6eui64=$(ip addr show | awk '/scope\ global/ && /ff:fe/ {print $2}' | cut -d'/' -f1) +#IPv6linkLocal=$(ip addr show | awk '/inet/ && /scope\ link/ && /fe80/ {print $2}' | cut -d'/' -f1) + +availableInterfaces=$(ip -o link | awk '{print $2}' | grep -v "lo" | cut -d':' -f1) +dhcpcdFile=/etc/dhcpcd.conf + +####### FUCNTIONS ########## +backupLegacyPihole() +{ if [[ -f /etc/dnsmasq.d/adList.conf ]];then - echo "Original Pi-hole detected. Initiating sub space transport..." + 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") @@ -36,58 +52,252 @@ if [[ -f /etc/dnsmasq.d/adList.conf ]];then else : fi +} -echo "Updating the Pi..." -sudo apt-get update -sudo apt-get -y upgrade +welcomeDialogs() +{ +# Display the welcome dialog +whiptail --msgbox --backtitle "Welcome" --title "Pi-hole automated installer" "This installer will transform your Raspberry Pi into a network-wide ad blocker!" $r $c -echo "Installing tools..." -sudo apt-get -y install dnsutils -sudo apt-get -y install bc -sudo apt-get -y install toilet +# 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. -echo "Installing DNS..." -sudo apt-get -y install dnsmasq -sudo update-rc.d dnsmasq enable +In the next section, you can choose to use your current network settings (DHCP) or to manually edit them." $r $c +} -echo "Installing a Web server" -sudo apt-get -y install lighttpd php5-common php5-cgi php5 -sudo mkdir /var/www/html -sudo chown www-data:www-data /var/www/html -sudo chmod 775 /var/www/html -sudo usermod -a -G www-data pi +chooseInterface() +{ +# Turn the available interfaces into an array so it can be used with a whiptail dialog +interfacesArray=() +while read -r line +do +interfacesArray+=("$line" "available" "ON") +done <<< "$availableInterfaces" -echo "Stopping services to modify them..." -sudo service dnsmasq stop -sudo service lighttpd stop +# Find out how many interfaces are available to choose from +interfaceCount=$(echo "$availableInterfaces" | wc -l) +chooseInterfaceCmd=(whiptail --separate-output --radiolist "Choose An Interface" $r $c $interfaceCount) +chooseInterfaceOptions=$("${chooseInterfaceCmd[@]}" "${interfacesArray[@]}" 2>&1 >/dev/tty) +for desiredInterface in $chooseInterfaceOptions +do + piholeInterface=$desiredInterface + echo "Using interface: $piholeInterface" +done +} -echo "Backing up original config files and downloading Pi-hole ones..." +use4andor6() +{ +# Let use select IPv4 and/or IPv6 +cmd=(whiptail --separate-output --checklist "Select Protocols" $r $c 2) +options=(IPv4 "Block ads over IPv4" on + IPv6 "Block ads over IPv4" off) +choices=$("${cmd[@]}" "${options[@]}" 2>&1 >/dev/tty) +clear +for choice in $choices +do + case $choice in + IPv4) + echo "IPv4 selected." + useIPv4=true + ;; + IPv6) + echo "IPv6 selected." + useIPv6=true + ;; + esac +done +} + +useIPv6dialog() +{ +whiptail --msgbox --backtitle "Coming soon..." --title "IPv6 not yet supported" "I need your help for IPv6. Consider donating at: http://pi-hole.net/donate" $r $c +} + +getStaticIPv4Settings() +{ +# Ask if the user wannts 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 + # 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 + # Nothing else to do since the variables are already set above +else + # Otherwise, we need to ask the user to input their desired settings. + # Start by getting the IPv4 address (pre-filling it with info gathered from DHCP) + # Start a loop to let the user enter their information with the chance to go back and edit it if necessary + 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) + 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 + # 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 + else + # Cancelling gateway settings window + ipSettingsCorrect=False + echo "User canceled." + exit + fi + else + # Cancelling IPv4 settings window + ipSettingsCorrect=False + echo "User canceled." + exit + fi +done +# End the if statement for DHCP vs. static +fi +} + + +setStaticIPv4() +{ +# Append these lines to /etc/dhcpcd.conf to enable a static IP +echo "interface $piholeInterface +static ip_address=$IPv4addr +static routers=$IPv4gw +static domain_name_servers=$IPv4gw" | sudo tee -a $dhcpcdFile >/dev/null +sudo ip addr replace dev $piholeInterface $IPv4addr +} + +installScripts(){ +sudo curl -o /usr/local/bin/gravity.sh https://raw.githubusercontent.com/jacobsalmela/pi-hole/master/gravity.sh +sudo curl -o /usr/local/bin/chronometer.sh https://raw.githubusercontent.com/jacobsalmela/pi-hole/master/advanced/Scripts/chronometer.sh +sudo curl -o /usr/local/bin/whitelist.sh https://raw.githubusercontent.com/jacobsalmela/pi-hole/master/advanced/Scripts/whitelist.sh +sudo curl -o /usr/local/bin/piholeLogFlush.sh https://raw.githubusercontent.com/jacobsalmela/pi-hole/master/advanced/Scripts/piholeLogFlush.sh +sudo chmod 755 /usr/local/bin/{gravity,chronometer,whitelist,piholeLogFlush}.sh +} + +installConfigs(){ sudo mv /etc/dnsmasq.conf /etc/dnsmasq.conf.orig sudo mv /etc/lighttpd/lighttpd.conf /etc/lighttpd/lighttpd.conf.orig -sudo mv /var/www/html/index.lighttpd.html /var/www/html/index.lighttpd.orig -sudo curl -o /etc/dnsmasq.conf "https://raw.githubusercontent.com/jacobsalmela/pi-hole/master/advanced/dnsmasq.conf" -sudo curl -o /etc/lighttpd/lighttpd.conf "https://raw.githubusercontent.com/jacobsalmela/pi-hole/master/advanced/lighttpd.conf" -sudo lighty-enable-mod fastcgi fastcgi-php -sudo mkdir /var/www/html/pihole -sudo curl -o /var/www/html/pihole/index.html "https://raw.githubusercontent.com/jacobsalmela/pi-hole/master/advanced/index.html" +sudo curl -o /etc/dnsmasq.conf https://raw.githubusercontent.com/jacobsalmela/pi-hole/master/advanced/dnsmasq.conf +sudo curl -o /etc/lighttpd/lighttpd.conf https://raw.githubusercontent.com/jacobsalmela/pi-hole/master/advanced/lighttpd.conf +} -echo "Installing the Web interface..." +stopServices(){ +sudo service dnsmasq stop || true +sudo service lighttpd stop || true +} + +installDependencies(){ +sudo apt-get update +sudo apt-get -y upgrade +sudo apt-get -y install dnsutils bc toilet +sudo apt-get -y install dnsmasq +sudo apt-get -y install lighttpd php5-common php5-cgi php5 +} + +installWebAdmin(){ sudo wget https://github.com/jacobsalmela/AdminLTE/archive/master.zip -O /var/www/master.zip -sudo unzip /var/www/master.zip -d /var/www/html/ +sudo unzip -oq /var/www/master.zip -d /var/www/html/ sudo mv /var/www/html/AdminLTE-master /var/www/html/admin sudo rm /var/www/master.zip 2>/dev/null +} + +installPiholeWeb(){ +sudo mkdir /var/www/html/pihole +sudo mv /var/www/html/index.lighttpd.html /var/www/html/index.lighttpd.orig +sudo curl -o /var/www/html/pihole/index.html https://raw.githubusercontent.com/jacobsalmela/pi-hole/master/advanced/index.html +} + +installCron(){ +sudo mv /etc/crontab /etc/crontab.orig +sudo curl -o /etc/crontab https://raw.githubusercontent.com/jacobsalmela/pi-hole/master/advanced/pihole.cron +} + +installPiLog(){ sudo touch /var/log/pihole.log sudo chmod 644 /var/log/pihole.log sudo chown dnsmasq:root /var/log/pihole.log - -echo "Locating the Pi-hole..." -sudo curl -o /usr/local/bin/gravity.sh "https://raw.githubusercontent.com/jacobsalmela/pi-hole/master/gravity.sh" -sudo curl -o /usr/local/bin/chronometer.sh "https://raw.githubusercontent.com/jacobsalmela/pi-hole/master/advanced/Scripts/chronometer.sh" -sudo chmod 755 /usr/local/bin/gravity.sh -sudo chmod 755 /usr/local/bin/chronometer.sh - -echo "Entering the event horizon..." +} +installPihole() +{ +installDependencies +stopServices +sudo chown www-data:www-data /var/www/html +sudo chmod 775 /var/www/html +sudo usermod -a -G www-data pi +sudo lighty-enable-mod fastcgi fastcgi-php +installScripts +installConfigs +installWebAdmin +installPiholeWeb +installCron +installPiLog sudo /usr/local/bin/gravity.sh +} -echo "Restarting..." -sudo reboot +######## SCRIPT ############ +# Start the installer +welcomeDialogs + +# Just back up the original Pi-hole right away since it won't take long and it gets it out of the way +backupLegacyPihole + +# Find interfaces and let the user choose one +chooseInterface + +# Let the user decide if they want to block ads over IPv4 and/or IPv6 +use4andor6 + +# Decide is IPv4 will be used +if [[ "$useIPv4" = true ]];then + echo "Using IPv4" + getStaticIPv4Settings + setStaticIPv4 +else + useIPv4=false + echo "IPv4 will NOT be used." +fi + +# Decide is IPv6 will be used +if [[ "$useIPv6" = true ]];then + # If only IPv6 is selected, exit because it is not supported yet + if [[ "$useIPv6" = true ]] && [[ "$useIPv4" = false ]];then + useIPv6dialog + exit + else + useIPv6dialog + fi +else + useIPv6=false + echo "IPv6 will NOT be used. Consider a donation at pi-hole.net/donate" +fi + +# Install and log everything to a file +installPihole | tee $tmpLog + +# Move the log file into /etc/pihole for storage +sudo mv $tmpLog $instalLogLoc + +whiptail --msgbox --backtitle "Make it so." --title "Installation Complete!" "Configure your devices to use the Pi-hole as their DNS server using this IP: $IPv4addr. + +If you set a new IP address, it should work fine, but you may want to reboot the Pi at some point. + +The install log is in /etc/pihole." $r $c + +sudo service dnsmasq start +sudo service lighttpd start diff --git a/automated install/uninstall.sh b/automated install/uninstall.sh new file mode 100644 index 0000000..b0dd336 --- /dev/null +++ b/automated install/uninstall.sh @@ -0,0 +1,19 @@ +#!/bin/bash +# Completely uninstalls the Pi-hole + +######### 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 +sudo rm -rf /var/www/html +sudo rm /etc/dnsmasq.conf /etc/dnsmasq.conf.orig +sudo rm /etc/crontab +sudo mv /etc/crontab.orig /etc/crontab +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 ae20d43..7d9440a 100755 --- a/gravity.sh +++ b/gravity.sh @@ -4,6 +4,7 @@ # Network-wide ad blocking via your Raspberry Pi # http://pi-hole.net # Compiles a list of ad-serving domains by downloading them from multiple sources + piholeIPfile=/tmp/piholeIP 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 @@ -11,11 +12,14 @@ if [[ -f $piholeIPfile ]];then rm $piholeIPfile 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 - piholeIP=$(ip -4 addr show | awk '{match($0,/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/); ip = substr($0,RSTART,RLENGTH); print ip}' | sed '/^\s*$/d' | grep -v "127.0.0.1" | (head -n1)) + IPv4dev=$(ip route get 8.8.8.8 | awk '{print $5}') + piholeIPCIDR=$(ip -o -f inet addr show dev $IPv4dev | awk '{print $4}') + piholeIP=${piholeIPCIDR%/*} fi # Ad-list sources--one per line in single quotes -# The mahakala source is commented out due to many users having issues with it blocking legitimate domains. Uncomment at your own risk +# The mahakala source is commented out due to many users having issues with it blocking legitimate domains. +# Uncomment at your own risk sources=('https://adaway.org/hosts.txt' 'http://adblock.gjtech.net/?format=unix-hosts' #'http://adblock.mahakala.is/' @@ -45,68 +49,70 @@ if [[ -r $piholeDir/pihole.conf ]];then echo "** Local calibration requested..." . $piholeDir/pihole.conf fi + ########################### # collapse - begin formation of pihole function gravity_collapse() { -echo "** Neutrino emissions detected..." + echo "** Neutrino emissions detected..." -# Create the pihole resource directory if it doesn't exist. Future files will be stored here -if [[ -d $piholeDir ]];then + # Create the pihole resource directory if it doesn't exist. Future files will be stored here + if [[ -d $piholeDir ]];then # Temporary hack to allow non-root access to pihole directory # 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 {} \; -else + else echo "** Creating pihole directory..." mkdir $piholeDir -fi + fi } -# patternCheck - check to see if curl downloaded any new files, and then process those -# files so they are in host format. +# patternCheck - check to see if curl downloaded any new files. function gravity_patternCheck() { - patternBuffer=$1 - # check if the patternbuffer is a non-zero length file - if [[ -s "$patternBuffer" ]];then - # 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 - echo "Done." - else - # curl didn't download any host files, probably because of the date check - echo "Transporter logic detected no changes, pattern skipped..." - fi + patternBuffer=$1 + # check if the patternbuffer is a non-zero length file + if [[ -s "$patternBuffer" ]];then + # 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 + echo "List updated, transport successful..." + else + # curl didn't download any host files, probably because of the date check + echo "No changes detected, transport skipped..." + fi } -# transport - curl the specified url with any needed command extentions, then patternCheck +# transport - curl the specified url with any needed command extentions function gravity_transport() { - url=$1 - cmd_ext=$2 - agent=$3 - # tmp file, so we don't have to store the (long!) lists in RAM - patternBuffer=$(mktemp) - heisenbergCompensator="" - if [[ -r $saveLocation ]]; then - # if domain has been saved, add file for date check to only download newer - heisenbergCompensator="-z $saveLocation" - fi - # Silently curl url - curl -s $cmd_ext $heisenbergCompensator -A "$agent" $url > $patternBuffer + url=$1 + cmd_ext=$2 + agent=$3 + + # tmp file, so we don't have to store the (long!) lists in RAM + patternBuffer=$(mktemp) + heisenbergCompensator="" + if [[ -r $saveLocation ]]; then + # if domain has been saved, add file for date check to only download newer + heisenbergCompensator="-z $saveLocation" + fi - gravity_patternCheck $patternBuffer - - # Cleanup - rm -f $patternBuffer + # Silently curl url + curl -s $cmd_ext $heisenbergCompensator -A "$agent" $url > $patternBuffer + # Check for list updates + gravity_patternCheck $patternBuffer + # Cleanup + rm -f $patternBuffer } + # spinup - main gravity function function gravity_spinup() { -# 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 + # 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 url=${sources[$i]} # Get just the domain from the URL domain=$(echo "$url" | cut -d'/' -f3) @@ -117,7 +123,7 @@ do agent="Mozilla/10.0" - echo -n "Getting $domain list... " + echo -n " Getting $domain list: " # Use a case statement to download lists that need special cURL commands # to complete properly and reset the user agent when required @@ -134,33 +140,34 @@ do # Default is a simple request *) cmd_ext="" esac - gravity_transport $url $cmd_ext $agent -done + gravity_transport $url $cmd_ext $agent + done } # Schwarzchild - aggregate domains to one list and add blacklisted domains function gravity_Schwarzchild() { -# Find all active domains and compile them into one file and remove CRs -echo "** Aggregating list of domains..." -truncate -s 0 $piholeDir/$matter -for i in "${activeDomains[@]}" -do - cat $i |tr -d '\r' >> $piholeDir/$matter -done + # Find all active domains and compile them into one file and remove CRs + echo "** Aggregating list of domains..." + truncate -s 0 $piholeDir/$matter + for i in "${activeDomains[@]}" + do + cat $i |tr -d '\r' >> $piholeDir/$matter + done +} -# Append blacklist entries if they exist -if [[ -r $blacklist ]];then +# Pulsar - White/blacklist application +function gravity_pulsar() { + + # Append blacklist entries if they exist + if [[ -r $blacklist ]];then numberOf=$(cat $blacklist | sed '/^\s*$/d' | wc -l) echo "** Blacklisting $numberOf domain(s)..." cat $blacklist >> $piholeDir/$matter -fi -} + fi -function gravity_pulsar() { - -# Whitelist (if applicable) domains -if [[ -r $whitelist ]];then + # Whitelist (if applicable) domains + if [[ -r $whitelist ]];then # Remove whitelist entries numberOf=$(cat $whitelist | sed '/^\s*$/d' | wc -l) plural=; [[ "$numberOf" != "1" ]] && plural=s @@ -170,49 +177,65 @@ if [[ -r $whitelist ]];then # replace "." with "\." of each line to turn each entry into a # regexp so it can be parsed out with grep -x awk -F '[# \t]' 'NF>0&&$1!="" {print "^"$1"$"}' $whitelist | sed 's/\./\\./g' > $latentWhitelist -else + else rm $latentWhitelist -fi + fi -# Prevent our sources from being pulled into the hole -plural=; [[ "${#sources[@]}" != "1" ]] && plural=s -echo "** Whitelisting ${#sources[@]} ad list source${plural}..." -for url in ${sources[@]} -do + # Prevent our sources from being pulled into the hole + plural=; [[ "${#sources[@]}" != "1" ]] && plural=s + echo "** Whitelisting ${#sources[@]} ad list source${plural}..." + for url in ${sources[@]} + do echo "$url" | awk -F '/' '{print "^"$3"$"}' | sed 's/\./\\./g' >> $latentWhitelist -done + done -# Remove whitelist entries from list -grep -vxf $latentWhitelist $piholeDir/$matter > $piholeDir/$andLight + # Remove whitelist entries from list + grep -vxf $latentWhitelist $piholeDir/$matter > $piholeDir/$andLight } function gravity_unique() { - # Sort and remove duplicates - sort -u $piholeDir/$supernova > $piholeDir/$eventHorizon - numberOf=$(wc -l < $piholeDir/$eventHorizon) - echo "** $numberOf unique domains trapped in the event horizon." + # Sort and remove duplicates + sort -u $piholeDir/$supernova > $piholeDir/$eventHorizon + numberOf=$(wc -l < $piholeDir/$eventHorizon) + echo "** $numberOf unique domains trapped in the event horizon." } + function gravity_hostFormat() { - # Format domain list as "192.168.x.x domain.com" - echo "** Formatting domains into a HOSTS file..." - cat $piholeDir/$eventHorizon | awk '{sub(/\r$/,""); print "'"$piholeIP"' " $0}' > $piholeDir/$accretionDisc - # Copy the file over as /etc/pihole/gravity.list so dnsmasq can use it - cp $piholeDir/$accretionDisc $adList + # Format domain list as "192.168.x.x domain.com" + echo "** Formatting domains into a HOSTS file..." + cat $piholeDir/$eventHorizon | awk '{sub(/\r$/,""); print "'"$piholeIP"' " $0}' > $piholeDir/$accretionDisc + # Copy the file over as /etc/pihole/gravity.list so dnsmasq can use it + cp $piholeDir/$accretionDisc $adList } + +# blackbody - remove any remnant files from script processes +function gravity_blackbody() { + # Loop through list files + for file in $piholeDir/*.$justDomainsExtension + do + # If list is in active array then leave it (noop) else rm the list + if [[ " ${activeDomains[@]} " =~ " ${file} " ]]; then + : + else + 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 + awk '($1 !~ /^#/) { if (NF>1) {print $2} else {print $1}}' $piholeDir/$andLight | \ + sed -nr -e 's/\.{2,}/./g' -e '/\./p' > $piholeDir/$supernova - # 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 - awk '($1 !~ /^#/) { if (NF>1) {print $2} else {print $1}}' $piholeDir/$andLight | \ - sed -nr -e 's/\.{2,}/./g' -e '/\./p' > $piholeDir/$supernova + numberOf=$(wc -l < $piholeDir/$supernova) + echo "** $numberOf domains being pulled in by gravity..." - numberOf=$(wc -l < $piholeDir/$supernova) - echo "** $numberOf domains being pulled in by gravity..." - gravity_unique - - sudo kill -HUP $(pidof dnsmasq) + gravity_unique + + sudo kill -HUP $(pidof dnsmasq) } gravity_collapse @@ -221,4 +244,4 @@ gravity_Schwarzchild gravity_pulsar gravity_hostFormat gravity_advanced - +gravity_blackbody