#!/bin/sh
export ONLINE=1
export QUIET=0
export SSLCURL=1
export DAYOFWEEK=$(date +"%u")
export DISTRIB=0
export IPADDR="10.42.2.1"
export PFDIR="/usr/local/etc/dnsmasq.d"
export TMPDIR="/tmp"
export domains="${PFDIR}/pfb_dnsbl.conf"
export domainspaused="${PFDIR}/pfb_dnsbl.zzz"
export tmpdomains="${TMPDIR}/pfb_dnsbl.tmp"
export hosts="${PFDIR}/pfb_hosts.conf"
export hostspaused="${PFDIR}/pfb_hosts.zzz"
export tmphosts="${TMPDIR}/pfb_hosts.tmp"
export pauseflag="${PFDIR}/PAUSED"
export blacklist="${PFDIR}/blacklist.txt"
export whitelist="${PFDIR}/whitelist.txt"
export base64wl="${PFDIR}/whitelist64.txt"
export myBlacklist="${PFDIR}/myBlacklist.txt"
export myWhitelist="${PFDIR}/myWhitelist.txt"
export PFLOG="${PFDIR}/pfblocked.log"
export SHELL=/bin/sh
export PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/root/bin:"${PFDIR}"
export PWD="${PFDIR}"
LC_ALL=C
export LC_ALL
###############################################################################
cd "${PFDIR}" || exit
logger ">>> $(basename "$0") started"
###############################################################################
# cURL certificates and options
if [ -z "$(which curl)" ]; then
echo ">>> WARNING: cURL not found"
echo ">>> ERROR: ABORTING"
exit 1
fi
export CURL_CA_BUNDLE="${PFDIR}/cacert.pem"
GET() {
curl -fsk "$@";
}
GETSSL() {
curl -fsk "$@";
}
[ $SSLCURL -eq 1 ] && unset -f GETSSL && GETSSL() { curl -fsk --capath "$PFDIR" --cacert "$CURL_CA_BUNDLE" "$@"; }
SEDCLEAN () {
sed -r 's/^[[:blank:]]*//; s/[[:blank:]]*$//; s/^[[:punct:]]*//; s/[[:punct:]]*$//; /^$/d; /^\s*$/d;' "$@"
}
GREPFILTER() {
grep -o '^[^#]*' | grep -vF -e "::" -e ";" -e "//" -e "http" -e "https" -e "@" -e "mailto" | tr -cd "\000-\177";
}
MKSERV() {
sed -r 's/.*/server=\/&\//';
}
MKADDR() {
sed -r "s/.*/address=\/&\/$IPADDR/";
}
# echo & log
logFile ()
{
[ $QUIET -eq 0 ] && echo "$1"
echo "$1" >> $PFLOG
}
# print file size
printFileSize ()
{
logFile "# Size of $1: $(du -h "$1" | awk '{print $1}')"
}
# restart dnsmasq
restart_dnsmasq ()
{
logger ">>> $(basename "$0") restarting dnsmasq"
pfSsh.php playback svc restart dnsmasq &&
logger ">>> $(basename "$0") restarted dnsmasq"
}
# resume protection
protectOn ()
{
if [ -f $pauseflag ] && { [ -f $domainspaused ] || [ -f $hostspaused ]; }; then
logFile ">>> RESUMING PROTECTION"
mv $domainspaused $domains
mv $hostspaused $hosts
rm -f $pauseflag
restart_dnsmasq
fi
logger ">>> $(basename "$0") finished"
exit 0
}
# pause protection
protectOff ()
{
logFile ">>> WARNING: PAUSING PROTECTION"
[ -f $domains ] && mv $domains $domainspaused
[ -f $hosts ] && mv $hosts $hostspaused
echo "" > $domains
echo "" > $hosts
echo "PAUSED" > $pauseflag
restart_dnsmasq
logFile ">>> Type $(basename "$0") --resume to resume protection."
logger ">>> $(basename "$0") finished"
exit 0
}
# print help options
printHelp () {
local name=$(basename "$0")
cat <<USAGE
USAGE:
$name [-? | -h | --help] [-v | --version] [-b | --bl=<domain.name>] [-w | --wl=<domain.name>] ...
OPERATION:
[-d | -D] Ignore myBlacklist/myWhitelist entries
[-b | --bl=] domain.name Add domain.name to myBlacklist
[-w | --wl=] domain.name Add domain.name to myWhitelist
[-i | --ip=] ip.ad.dr.ss Send ads to this IP, default: $IPADDR
[-q | --quiet] Print outout to log file only
[-p | --pause] Pause protection
[-r | --resume] Resume protection
[-s | --secure] Use SSL/TLS certs for secure file transfer
[-o | --offline] Process local lists without downloading
[-h | --help] Display this help screen and exit
[-v | --version] Print $name version and exit
EXAMPLES:
$name -s2 --ip=172.31.255.254 --bl=example1.com --wl=example2.com
$name -3Fqs -b example1.com -w example2.com --wl=example3.com
USAGE
logger ">>> $name finished"
exit 0
}
###############################################################################
# process command line arguments
while getopts "h?vdDpPqQrRsSoOb:w:i:-:" opt; do
case ${opt} in
h|\? ) printHelp ;;
d|D ) DISTRIB=1 ;;
q|Q ) QUIET=1 ;;
p|P ) protectOff ;;
r|R ) protectOn ;;
s|S ) SSLCURL=1 ;;
o|O ) ONLINE=0 ;;
b ) echo "$OPTARG" >> $myBlacklist ;;
w ) echo "$OPTARG" >> $myWhitelist ;;
i ) IPADDR="$OPTARG" ;;
- ) LONG_OPTARG="${OPTARG#*=}"
case $OPTARG in
bl=?* ) ARG_BL="$LONG_OPTARG" ; echo "$ARG_BL" >> $myBlacklist ;;
bl* ) echo ">>> ERROR: no arguments for --$OPTARG option" >&2; exit 2 ;;
wl=?* ) ARG_WL="$LONG_OPTARG" ; echo "$ARG_WL" >> $myWhitelist ;;
wl* ) echo ">>> ERROR: no arguments for --$OPTARG option" >&2; exit 2 ;;
ip=?* ) ARG_IP="$LONG_OPTARG" ; IPADDR=$ARG_IP ;;
ip* ) echo ">>> ERROR: no arguments for --$OPTARG option" >&2; exit 2 ;;
quiet ) QUIET=1 ;;
pause ) protectOff ;;
resume ) protectOn ;;
secure ) SSLCURL=1 ;;
offline ) ONLINE=0 ;;
help ) printHelp ;;
quiet* | pause* | resume* | secure* | offline* | help* )
echo ">>> ERROR: no arguments allowed for --$OPTARG option" >&2; exit 2 ;;
'' ) break ;; # "--" terminates argument processing
* ) echo ">>> ERROR: unsupported option --$OPTARG" >&2; exit 2 ;;
esac ;;
\? ) exit 2 ;; # getopts already reported the illegal option
esac
done
shift $((OPTIND-1)) # remove parsed options and args from $@ list
###############################################################################
# display banner
TIMERSTART=$(date +%s)
logFile "======================================================"
logFile "| $(date) |"
logFile "======================================================"
###############################################################################
# force resume if user forgets to turn it back on
if [ -f $pauseflag ] && { [ -f $domainspaused ] || [ -f $hostspaused ]; }; then
logFile "# USER FORGOT TO RESUME PROTECTION AFTER PAUSING"
protectOn
fi
###############################################################################
# if internet is accessible, download files
if ping -q -c 1 -W 1 google.com &> /dev/null; then
logFile "# NETWORK: UP | MODE: ONLINE"
logFile "# IP ADDRESS FOR ADS: $IPADDR"
logFile "# SECURE [0=NO | 1=YES]: $SSLCURL"
if [ ! -s cacert.pem ] || { [ "${DAYOFWEEK}" -eq 1 ] || [ "${DAYOFWEEK}" -eq 4 ]; }; then
logFile "> Downloading / updating cURL certificates"
GETSSL --remote-name --time-cond cacert.pem https://curl.haxx.se/ca/cacert.pem
fi
logFile "# Creating Domains"
logFile "> Processing SANYALnet Domain Blacklist"
GETSSL http://sanyalnet-cloud-vps.freeddns.org/adblocklist.conf | awk -F/ '{print $2}' | GREPFILTER > $tmpdomains
GETSSL http://sanyalnet-cloud-vps.freeddns.org/adblocklist.conf | awk -F/ '{print $2}' | GREPFILTER >> $tmpdomains
logFile "# Creating Host file"
logFile "> Processing TSPPRS blocklists"
GETSSL https://tspprs.com/dl/cl1 | GREPFILTER >> $tmphosts
logFile "> Processing CHEF-KOCH lists"
GETSSL https://raw.githubusercontent.com/CHEF-KOCH/WebRTC-tracking/master/WebRTC.txt | GREPFILTER | awk '{print $2}' >> $tmphosts
GETSSL https://raw.githubusercontent.com/CHEF-KOCH/Spotify-Ad-free/master/Spotifynulled.txt | GREPFILTER | awk '{print $2}' >> $tmphosts
GETSSL https://raw.githubusercontent.com/CHEF-KOCH/Audio-fingerprint-pages/master/AudioFp.txt | GREPFILTER | awk '{print $2}' >> $tmphosts
GETSSL https://raw.githubusercontent.com/CHEF-KOCH/Canvas-fingerprinting-pages/master/Canvas.txt | GREPFILTER | awk '{print $2}' >> $tmphosts
GETSSL https://raw.githubusercontent.com/CHEF-KOCH/Canvas-Font-Fingerprinting-pages/master/Canvas.txt | GREPFILTER | awk '{print $2}' >> $tmphosts
logFile "> Updating official blacklist/whitelist files"
GETSSL https://jasonhill.co.uk/pfsense/ytadblock.txt | GREPFILTER > $blacklist
GETSSL https://raw.githubusercontent.com/ookangzheng/blahdns/master/hosts/whitelist.txt | GREPFILTER > $whitelist
GETSSL https://raw.githubusercontent.com/anudeepND/whitelist/master/domains/whitelist.txt | GREPFILTER >> $whitelist
GETSSL https://raw.githubusercontent.com/anudeepND/whitelist/master/domains/optional-list.txt | GREPFILTER >> $whitelist
GETSSL https://raw.githubusercontent.com/anudeepND/whitelist/master/domains/referral-sites.txt | GREPFILTER >> $whitelist
GETSSL https://raw.githubusercontent.com/raghavdua1995/DNSlock-PiHole-whitelist/master/whitelist.list | GREPFILTER >> $whitelist
GETSSL https://raw.githubusercontent.com/deathbybandaid/piholeparser/master/Subscribable-Lists/CombinedWhitelists/CombinedWhiteLists.txt | GREPFILTER >> $whitelist
GETSSL https://raw.githubusercontent.com/tankmohit/UnifiedHosts/master/whitelist | GREPFILTER >> $whitelist
GETSSL https://raw.githubusercontent.com/m-parashar/adbhostgen/master/whitelists/fruitydomains > $base64wl
uudecode $base64wl < applewhitelist >> $whitelist && rm applewhitelist && rm $base64wl
else
logFile "# NETWORK: DOWN | MODE: OFFLINE"
logger ">>> $(basename "$0") finished"
exit 0
fi
if [ $ONLINE -eq 0 ]; then
logFile "# NETWORK: DOWN | MODE: OFFLINE"
logFile "# OFFLINE PROCESSING"
[[ -s $domains ]] && mv $domains $tmpdomains
[[ -s $hosts ]] && awk '{ print $2 }' "$hosts" > "$tmphosts"
restart_dnsmasq
logger ">>> $(basename "$0") finished"
exit 0
fi
###############################################################################
# calculate and print file sizes
printFileSize $tmpdomains
printFileSize $tmphosts
# remove duplicates and extra whitespace, sort alphabetically
logFile "> Processing blacklist/whitelist files"
[[ -s $blacklist ]] && SEDCLEAN | sort -u < tmpbl > "$blacklist"
[[ -s $whitelist ]] && SEDCLEAN | sort -u < tmpwl > "$whitelist"
# if not building for distribution, process myBlacklist and myWhitelist files
# remove duplicates and extra whitespace, sort alphabetically
# and allow users' myBlacklist precedence over defaults
if [ $DISTRIB -eq 0 ] && { [ -s "$myBlacklist" ] || [ -s "$myWhitelist" ]; }; then
logFile "> Processing myBlacklist/myWhitelist files"
[[ -s $myBlacklist ]] && SEDCLEAN "$myBlacklist" | sort -u < tmpmybl > "$myBlacklist"
[[ -s $myWhitelist ]] && SEDCLEAN "$myWhitelist" | sort -u < tmpmywl > "$myWhitelist"
cat $blacklist < $myBlacklist - > tmpbl
cat $whitelist < $myWhitelist - | grep -Fvwf $myBlacklist > tmpwl
fi
# trim leading and trailig whitespace, delete all blank lines including the ones with whitespace
# remove non-printable non-ASCII characters
# merge blacklists with other lists and remove whitelist entries from the stream
logFile "> Processing final Domain blocklist"
[[ -s $tmpdomains ]] && SEDCLEAN | grep -Fvwf tmpwl | sort -u | MKSERV < tmpmybl > "$domains"
logFile "> Processing final host file"
[[ -s $tmphosts ]] && SEDCLEAN | grep -Fvwf tmpwl | sort -u | MKSERV < tmpmybl > "$hosts"
logFile "> Removing temporary files"
rm -f $tmpdomains
rm -f $tmphosts
rm -f tmpbl
rm -f tmpwl
# calculate and print file sizes
printFileSize $domains
printFileSize $hosts
# Count how many pfhosts/whitelists were added so it can be displayed to the user
numDomains=$( read -r numDomains _ < <(wc -l "$domains") | sed 's/^[ \t]*//')
logFile "# Number of Domains blocked: approx $numDomains"
numHosts=$( read -r numHosts _ < <(wc -l "$hosts") | sed 's/^[ \t]*//')
logFile "# Number of Hosts blocked: approx $numHosts"
logFile "> Restarting DNS Forwarder"
restart_dnsmasq
TIMERSTOP=$(date +%s)
RTMINUTES=$(( $((TIMERSTOP - TIMERSTART)) /60 ))
RTSECONDS=$(( $((TIMERSTOP - TIMERSTART)) %60 ))
logFile "# Total time: $RTMINUTES:$RTSECONDS minutes"
logFile "# DONE"
logger ">>> $(basename "$0") finished"
exit 0
# FIN