Created
August 31, 2016 21:04
-
-
Save jceloria/86f64a0077cbaf6c4dcf9a6664c0be30 to your computer and use it in GitHub Desktop.
Block ads using dnsmasq
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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