Skip to content

Instantly share code, notes, and snippets.

@jceloria
Created August 31, 2016 21:04
Show Gist options
  • Select an option

  • Save jceloria/86f64a0077cbaf6c4dcf9a6664c0be30 to your computer and use it in GitHub Desktop.

Select an option

Save jceloria/86f64a0077cbaf6c4dcf9a6664c0be30 to your computer and use it in GitHub Desktop.
Block ads using dnsmasq
#!/usr/bin/env bash
SELF=${0##*/}; SDIR=${0%/*}; PATH+=:${SDIR}
################################################################################
# Block ads using dnsmasq
#
# *REQUIREMENTS*
# The Ubiquiti router I wrote this for did not ship with a GNU coreutils
# timeout binary. I instead used a Python timeout script provided by:
# https://github.com/timwarnock/timeout.py/blob/master/timeout.py
#
# Copyright © 2016 by John Celoria <[REDACTED]>.
#
# This program 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, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
#################################### config ####################################
# Set some defaults
VERSION=0.5
CURL_CMD="curl -s --location"
HOST_FILES=(
http://www.mvps.org/winhelp2002/hosts.txt
http://pgl.yoyo.org/adservers/serverlist.php?hostformat=hosts
http://jansal.googlecode.com/svn/trunk/adblock/hosts
)
# Additional custom adblock dnsmasq entries
ADDITIONAL=(
address=/cloudservices.roku.com/127.0.0.1
)
# Adblock exceptions (supports regex)
EXCEPTIONS=(
localhost
googleadservices\.com
po\.st
)
# Name of the dnsmasq adblock config file
DNSMASQ_CONF="/etc/dnsmasq.d/dnsmasq.adblock.conf"
################################################################################
##################################### subs #####################################
# Print usage information
function help() {
cat << EOF
Usage: ${SELF} [OPTION]...
Block ads using dnsmasq
-h Display this help message and exit
-n Don't update dnsmasq config, only print output
-q Quiet output
EOF
return
}
################################################################################
# Logging function
log() {
local level levels=(notice warning crit)
level="+($(IFS='|';echo "${levels[*]}"))"
shopt -s extglob; case ${1} in
${level}) level=${1}; shift ;;
*) level=notice ;;
esac; shopt -u extglob
[[ -z ${RETVAL} ]] && { for RETVAL in "${!levels[@]}"; do
[[ ${levels[${RETVAL}]} = "${level}" ]] && break
done }
logger -s -p ${level} -t "[${SELF}:${FUNCNAME[1]}()]" $@;
}
################################################################################
# Log and then exit
function die() { local retval=${RETVAL:-$?}; log "$@"; exit ${retval}; }
################################################################################
# Sanity checks
while getopts ":hnq" opt; do
case ${opt} in
h) help >&2; exit 1 ;;
n) NO_UPDATE=1 ;;
q) QUIET=1 ;;
\?) echo "Invalid option: -${OPTARG}" >&2 ;;
:) echo "Option -${OPTARG} requires an argument." >&2; exit 1 ;;
esac
done; shift $((${OPTIND} - 1))
req_progs=(curl logger timeout)
for p in ${req_progs[@]}; do
hash "$p" 2>&- || \
{ echo >&2 " Required program \"$p\" not found in \$PATH."; exit 1; }
done
################################################################################
##################################### main #####################################
[[ ${QUIET} -eq 1 ]] && exec >${LOGFILE:-/dev/null} 2>&1
# Redirect output and update config, unless -n flag is given
[[ ! ${NO_UPDATE} ]] && exec 3>&1 1>${DNSMASQ_CONF}
# Check if our WAN link is up
[[ ${NO_UPDATE} ]] || log "Testing connection to default gateway"
WAN_GW=$(ip route show | awk '$1~/default/{print $3}')
timeout 60 sh -c "until ping -q -c3 ${WAN_GW}; do false; done" \
> /dev/null 2>&- || die "Unable to connect to WAN gateway"
[[ ${NO_UPDATE} ]] || log "Updating ${DNSMASQ_CONF}"
echo '##### BEGIN adblock #####'
{
# Add our custom additional entries
(IFS=$'\n'; echo "${ADDITIONAL[*]}")
# Build a regex from our exception list
regex="($(IFS='|'; echo "${EXCEPTIONS[*]}"))"
# Retrieve and process requested host files and format for dnsmasq
${CURL_CMD} ${HOST_FILES[*]} | while read -a split; do
# Filter out lines that aren't /etc/hosts entries
[[ ${split[0]} =~ ^(127|::|0.0.0.0) ]] || continue
# Remove entries matching our exception list
[[ ${split[1]} =~ ${regex} ]] && continue
echo "address=/${split[1]}/127.0.0.1"
done
} | tr -d '\r' | sort -u
echo '##### END adblock #######'
[[ ${NO_UPDATE} ]] || {
log $(/etc/init.d/dnsmasq force-reload || echo -n "[ERROR]")
}
exit 0
################################################################################
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment