mirror of
https://github.com/pi-hole/pi-hole
synced 2025-01-09 07:30:56 +00:00
0efda04920
There were a lot of places (like in help functions) that used multiple echo calls instead of heredocs. Personal opinion but this seems cleaner.
250 lines
7.0 KiB
Bash
Executable File
250 lines
7.0 KiB
Bash
Executable File
#!/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
|
|
# Whitelists domains
|
|
#
|
|
# 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.
|
|
|
|
|
|
helpFunc() {
|
|
cat << EOM
|
|
::: Immediately whitelists one or more domains in the hosts file
|
|
:::
|
|
::: Usage: pihole -w domain1 [domain2 ...]
|
|
:::
|
|
::: Options:
|
|
::: -d, --delmode Remove domains from the whitelist
|
|
::: -nr, --noreload Update Whitelist without refreshing dnsmasq
|
|
::: -f, --force Force updating of the hosts files, even if there are no changes
|
|
::: -q, --quiet output is less verbose
|
|
::: -h, --help Show this help dialog
|
|
::: -l, --list Display your whitelisted domains
|
|
EOM
|
|
exit 1
|
|
}
|
|
|
|
if [[ $# = 0 ]]; then
|
|
helpFunc
|
|
fi
|
|
|
|
#globals
|
|
basename=pihole
|
|
piholeDir=/etc/${basename}
|
|
adList=${piholeDir}/gravity.list
|
|
whitelist=${piholeDir}/whitelist.txt
|
|
reload=true
|
|
addmode=true
|
|
force=false
|
|
verbose=true
|
|
|
|
domList=()
|
|
domToRemoveList=()
|
|
|
|
piholeIPfile=/etc/pihole/piholeIP
|
|
piholeIPv6file=/etc/pihole/.useIPv6
|
|
|
|
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
|
|
piholeIP=$(cat ${piholeIPfile})
|
|
#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
|
|
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}')
|
|
piholeIP=${piholeIPCIDR%/*}
|
|
fi
|
|
|
|
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
|
|
piholeIPv6=$(ip -6 route get 2001:4860:4860::8888 | awk -F " " '{ for(i=1;i<=NF;i++) if ($i == "src") print $(i+1) }')
|
|
fi
|
|
|
|
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/')
|
|
if [ -z "$validDomain" ]; then
|
|
echo "::: $1 is not a valid argument or domain name"
|
|
else
|
|
domList=("${domList[@]}" ${validDomain})
|
|
fi
|
|
}
|
|
|
|
PopWhitelistFile() {
|
|
#check whitelist file exists, and if not, create it
|
|
if [[ ! -f ${whitelist} ]];then
|
|
touch ${whitelist}
|
|
fi
|
|
for dom in "${domList[@]}"
|
|
do
|
|
if ${addmode}; then
|
|
AddDomain "$dom"
|
|
else
|
|
RemoveDomain "$dom"
|
|
fi
|
|
done
|
|
}
|
|
|
|
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 ${verbose}; then
|
|
echo -n "::: Adding $1 to $whitelist..."
|
|
fi
|
|
echo "$1" >> ${whitelist}
|
|
modifyHost=true
|
|
if ${verbose}; then
|
|
echo " done!"
|
|
fi
|
|
else
|
|
if ${verbose}; then
|
|
echo "::: $1 already exists in $whitelist, no need to add!"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
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 ${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 $verbose; then
|
|
#echo "::: Un-whitelisting $dom..."
|
|
#fi
|
|
domToRemoveList=("${domToRemoveList[@]}" $1)
|
|
modifyHost=true
|
|
fi
|
|
}
|
|
|
|
ModifyHostFile() {
|
|
if ${addmode}; then
|
|
#remove domains in from hosts file
|
|
if [[ -r ${whitelist} ]];then
|
|
# Remove whitelist entries
|
|
numberOf=$(cat ${whitelist} | sed '/^\s*$/d' | wc -l)
|
|
plural=; [[ "$numberOf" != "1" ]] && plural=s
|
|
echo ":::"
|
|
echo -n "::: Modifying HOSTS file to whitelist $numberOf domain${plural}..."
|
|
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 ${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
|
|
if grep -q "$rdom" /etc/pihole/*.domains; then
|
|
echo "::: AdLists contain $rdom, re-adding block"
|
|
if [[ -n ${piholeIPv6} ]];then
|
|
echo -n "::: Restoring block for $rdom on IPv4 and IPv6..."
|
|
echo "$rdom" | awk -v ipv4addr="$piholeIP" -v ipv6addr="$piholeIPv6" '{sub(/\r$/,""); print ipv4addr" "$0"\n"ipv6addr" "$0}' >> ${adList}
|
|
echo " done!"
|
|
else
|
|
echo -n "::: Restoring block for $rdom on IPv4..."
|
|
echo "$rdom" | awk -v ipv4addr="$piholeIP" '{sub(/\r$/,""); print ipv4addr" "$0}' >>${adList}
|
|
echo " done!"
|
|
fi
|
|
fi
|
|
echo -n "::: Removing $rdom from $whitelist..."
|
|
echo "$rdom" | sed 's/\./\\./g' | xargs -I {} perl -i -ne'print unless /'{}'(?!.)/;' ${whitelist}
|
|
echo " done!"
|
|
done
|
|
fi
|
|
}
|
|
|
|
Reload() {
|
|
# Reload hosts file
|
|
echo ":::"
|
|
echo -n "::: Refresh lists in dnsmasq..."
|
|
dnsmasqPid=$(pidof dnsmasq)
|
|
|
|
if [[ ${dnsmasqPid} ]]; then
|
|
# service already running - reload config
|
|
if [ -x "$(command -v systemctl)" ]; then
|
|
systemctl restart dnsmasq
|
|
else
|
|
service dnsmasq restart
|
|
fi
|
|
else
|
|
# service not running, start it up
|
|
if [ -x "$(command -v systemctl)" ]; then
|
|
systemctl start dnsmasq
|
|
else
|
|
service dnsmasq start
|
|
fi
|
|
fi
|
|
echo " done!"
|
|
}
|
|
|
|
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;;
|
|
"-d" | "--delmode" ) addmode=false;;
|
|
"-f" | "--force" ) force=true;;
|
|
"-q" | "--quiet" ) verbose=false;;
|
|
"-h" | "--help" ) helpFunc;;
|
|
"-l" | "--list" ) DisplayWlist;;
|
|
* ) HandleOther "$var";;
|
|
esac
|
|
done
|
|
|
|
PopWhitelistFile
|
|
|
|
if ${modifyHost} || ${force}; then
|
|
ModifyHostFile
|
|
else
|
|
if ${verbose}; then
|
|
echo ":::"
|
|
echo "::: No changes need to be made"
|
|
fi
|
|
exit 1
|
|
fi
|
|
|
|
if ${reload}; then
|
|
Reload
|
|
fi
|