Instantly share code, notes, and snippets.

Embed
What would you like to do?
Run PiHole directly on Asus-Merlin/DD-WRT Router (from jonesaaronj)
#!/bin/sh
# 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
# Installs Pi-hole
#
# 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.
# piholeDebug.sh is not installed. It does not work because dnsmasq is in wierd places
# updateDashboard.sh is not installed. To update pihole and dashboard use this script.
# setupLCD.sh is not installed
#
# Copied from https://discourse.pi-hole.net/t/run-pihole-directly-on-asus-merlin-dd-wrt-router/182
#Set this to an IP different than your router and not in your dhcp range
IPHOLE="192.168.1.254"
#Set this to your tz
TZ="America/Los_Angeles"
spinner()
{
local pid=$1
local delay="1s"
local spinstr='/-\|'
while [ "$(ps | awk '{print $1}' | grep "$pid")" ]; do
local temp=${spinstr#?}
printf " [%c] " "$spinstr"
local spinstr=${temp}${spinstr%"$temp"}
sleep ${delay}
printf "\b\b\b\b\b\b"
done
printf " \b\b\b\b"
}
installDependencies() {
echo ":::"
echo "::: Installing Dependencies"
PIHOLE_DEPS=(
bc bash curl git git-http sed rsync perl coreutils-mktemp coreutils-truncate net-tools-hostname
php5-fastcgi php5-mod-json php5-mod-openssl php5-mod-session
lighttpd lighttpd-mod-fastcgi lighttpd-mod-access lighttpd-mod-accesslog lighttpd-mod-expire
lighttpd-mod-compress lighttpd-mod-redirect lighttpd-mod-rewrite lighttpd-mod-setenv
)
for i in "${PIHOLE_DEPS[@]}"; do
opkg install "$i"
done
echo "!!! done."
}
createBridge() {
echo ":::"
echo "::: Creating Bridge Interface"
FILE=/jffs/scripts/services-start
touch "$FILE"
chmod +x "$FILE"
grep -q "$IPHOLE" "$FILE" || echo '
#Setup bridge for PiHole
ifconfig br0:1 '$IPHOLE' netmask 255.255.255.0 up
' >> "$FILE"
source "$FILE"
echo "!!! done."
}
setupPhpTZ() {
echo ":::"
echo "::: Setup php.ini with correct TZ..."
#TZ=$(cut -f1 -d "," /opt/etc/TZ)
sed -i "s|.*date.timezone.*|date.timezone = $TZ|" /opt/etc/php.ini
echo "!!! done."
}
setupDnsmasq() {
echo ":::"
echo "::: Creating dnsmasq configuration"
FILE=/jffs/configs/dnsmasq.conf.add
touch "$FILE"
grep -q "pihole" "$FILE" || echo '
# Set dnsmasq configs for PiHole
log-queries
log-async
log-facility=/opt/var/log/pihole.log
addn-hosts=/opt/etc/pihole/gravity.list
' >> "$FILE"
service restart_dnsmasq >> /dev/null
echo "!!! done."
}
setupLighttpd() {
echo ":::"
echo "::: Creating lighttpd configuration"
#Setup cache dir for compress
mkdir -p /tmp/lighttpd/compress
sed -i 's|cache_dir|"/tmp/lighttpd"|g' /opt/etc/lighttpd/conf.d/30-compress.conf
FILE=/opt/etc/lighttpd/conf.d/40-pihole.conf
touch "$FILE"
grep -q "pihole" "$FILE" || echo '
server.bind = "'$IPHOLE'"
server.error-handler-404 = "pihole/index.html"
accesslog.filename = "/opt/var/log/lighttpd/access.log"
accesslog.format = "%{%s}t|%V|%r|%s|%b"
fastcgi.server = (
".php" =>
( "localhost" =>
( "socket" => "/tmp/php-fcgi.sock",
"bin-path" => "/opt/bin/php-fcgi",
"max-procs" => 1,
"bin-environment" =>
( "PHP_FCGI_CHILDREN" => "2",
"PHP_FCGI_MAX_REQUESTS" => "1000"
)
)
)
)
# If the URL starts with /admin, it is the Web interface
$HTTP["url"] =~ "^/admin/" {
# Create a response header for debugging using curl -I
setenv.add-response-header = (
"X-Pi-hole" => "The Pi-hole Web interface is working!",
"X-Frame-Options" => "DENY"
)
}
# If the URL does not start with /admin, then it is a query for an ad domain
$HTTP["url"] =~ "^(?!/admin)/.*" {
# Create a response header for debugging using curl -I
setenv.add-response-header = ( "X-Pi-hole" => "A black hole for Internet advertisements." )
# rewrite only js requests
url.rewrite = ("(.*).js" => "pihole/index.js")
}
$HTTP["host"] =~ "ads.hulu.com|ads-v-darwin.hulu.com|ads-e-darwin.hulu.com" {
url.redirect = ( "^/published/(.*)" => "http://192.168.1.1:8200/MediaItems/pi-hole.mov")
}
' >> "$FILE"
/opt/etc/init.d/S80lighttpd restart
echo "!!! done."
}
webInterfaceGitUrl="https://github.com/pi-hole/AdminLTE.git"
webInterfaceDir="/opt/etc/.pihole_admin"
piholeGitUrl="https://github.com/pi-hole/pi-hole.git"
piholeFilesDir="/opt/etc/.pihole"
getGitFiles() {
# Setup git repos for base files and web admin
echo ":::"
echo "::: Checking for existing base files..."
if is_repo ${piholeFilesDir}; then
make_repo ${piholeFilesDir} ${piholeGitUrl}
else
update_repo ${piholeFilesDir}
fi
echo ":::"
echo "::: Checking for existing web interface..."
if is_repo ${webInterfaceDir}; then
make_repo ${webInterfaceDir} ${webInterfaceGitUrl}
else
update_repo ${webInterfaceDir}
fi
}
is_repo() {
# If the directory does not have a .git folder it is not a repo
echo -n "::: Checking $1 is a repo..."
if [ -d "$1/.git" ]; then
echo " OK!"
return 1
fi
echo " not found!!"
return 0
}
make_repo() {
# Remove the non-repod interface and clone the interface
echo -n "::: Cloning $2 into $1..."
rm -rf "$1"
git clone -q "$2" "$1" > /dev/null & spinner $!
echo " done!"
}
update_repo() {
# Pull the latest commits
echo -n "::: Updating repo in $1..."
cd "$1" || exit
git pull -q > /dev/null & spinner $!
echo " done!"
}
installScripts() {
# Install the scripts from /opt/etc/.pihole to their various locations
echo ":::"
echo "::: Installing scripts to /opt/pihole..."
mkdir -p /opt/pihole
cp /opt/etc/.pihole/pihole /opt/pihole/pihole
cp /opt/etc/.pihole/gravity.sh /opt/pihole/gravity.sh
cp /opt/etc/.pihole/advanced/Scripts/chronometer.sh /opt/pihole/chronometer.sh
cp /opt/etc/.pihole/advanced/Scripts/whitelist.sh /opt/pihole/whitelist.sh
cp /opt/etc/.pihole/advanced/Scripts/blacklist.sh /opt/pihole/blacklist.sh
cp /opt/etc/.pihole/advanced/Scripts/whitelist.sh /opt/pihole/version.sh
#make everything executable
chmod +x /opt/pihole/*.sh
#everything in /etc is actually in /opt/etc
sed -i 's|/etc|/opt/etc|g' /opt/pihole/*
#everything in /var is actually in /opt/var
sed -i 's|/var|/opt/var|g' /opt/pihole/*
#everything in /var/www/html is actually in /opt/share/www
sed -i 's|/var/www/html|/opt/share/www|g' /opt/pihole/*
#bash is in /opt/bin/bash
sed -i 's|/bin/bash|/opt/bin/bash|g' /opt/pihole/*
#in the gravity.sh script don't run gravity_reload function. It doesn't work with our dnsmasq setup
sed -i 's|^gravity_reload|s|^#|' /opt/pihole/gravity.sh
#instead just restart dnsmasq
echo 'service restart_dnsmasq' >> gravity.sh
#remove functionality from pihole that does not work correctly
sed -i 's|-ud, updateDashboard|s|^#|' /opt/pihole/pihole
sed -i 's|-up, updatePihole|s|^#|' /opt/pihole/pihole
sed -i 's|-s, setupLCD|s|^#|' /opt/pihole/pihole
sed -i 's|-d, debug|s|^#|' /opt/pihole/pihole
#create a working piholeLogflush.sh
#instead of just wiping the log completely keep the last hour of data
#then we will set a cron to run this every 5 minutes (should be fine, grep is plenty fast)
echo '
#!/usr/bin/env bash
echo -n "::: Flushing hour old data from /var/log/pihole.log ..."
grep "^$(date -d -1hour +'%b %d %H:%M:%S')" /opt/var/log/pihole.log > /opt/var/log/pihole.tmp
mv /opt/var/log/pihole.tmp /opt/var/log/pihole.log
echo "... done!"
' > /opt/pihole/piholeLogFlush.sh
#link pihole to something in our path
ln -sf /opt/pihole/pihole /opt/usr/sbin/pihole
echo "!!! done."
}
installAdmin() {
echo ":::"
echo -n "::: Installing Admin to /opt/share/www/admin..."
mkdir -p /opt/share/www/admin
rsync -a --exclude=".git*" /opt/etc/.pihole_admin/ /opt/share/www/admin/ > /dev/null & spinner $!
#everything in /etc is actually in /opt/etc
find /opt/share/www/admin/ -type f -exec sed -i -e 's|/etc|/opt/etc|g' {} \; > /dev/null & spinner $!
#everything in /var is actually in /opt/var
find /opt/share/www/admin/ -type f -exec sed -i -e 's|/var|/opt/var|g' {} \; > /dev/null & spinner $!
#fix bug in script data.php
sed -i '|function getAllQueries() {|a\\$status = "" ' /opt/share/www/admin/data.php
#enable php debug
echo 'error_reporting = -1\ndisplay_errors = On\nhtml_errors = On\n' >> /opt/share/www/admin/.user.ini
echo "!!! done."
}
installPiholeMov() {
echo ":::"
echo -n "::: Installing pi-hole movie..."
curl -s -o /opt/pihole/pi-hole.mov http://jacobsalmela.com/wp-content/uploads/2014/10/pi-hole.mov > /dev/null & spinner $!
echo " done."
}
createPiholeIpFile() {
echo ":::"
echo "::: Create PiHole Ip file..."
mkdir -p /opt/etc/pihole
echo "$IPHOLE" > /opt/etc/pihole/piholeIP
echo "!!! done."
}
createDummyHostnameFile() {
echo ":::"
echo "::: Create dummy Host file..."
echo "pi.hole" > /opt/etc/hostname
echo "!!! done."
}
createLogFile() {
# Create logfiles if necessary
echo ":::"
echo -n "::: Creating log file and changing owner to nobody..."
if [ ! -f /opt/var/log/pihole.log ]; then
touch /opt/var/log/pihole.log
chmod 640 /opt/var/log/pihole.log
chown nobody:root /var/log/pihole.log
echo " done!"
else
echo " already exists!"
fi
}
installPiholeWeb() {
# Install the web interface
echo ":::"
echo "::: Installing pihole custom index page..."
mkdir -p /opt/share/www/pihole
cp /opt/etc/.pihole/advanced/index.* /opt/share/www/pihole/.
echo "!!! done"
}
installCron() {
echo ":::"
echo "::: Installing Cron Jobs"
FILE=/jffs/scripts/init-start
touch "$FILE"
chmod +x "$FILE"
grep -q "pihole" "$FILE" || echo '
# Pi-hole: Update the ad sources once a week on Sunday at 01:59
cru a UpdateGravity "59 1 * * 7 /opt/pihole/pihole updateGravity"
# Pi-hole: Flush the log every 5 minutes, keep an hours worth of data
# Log gets too big for our puny memory
cru a FlushLog "*/5 * * * * /opt/pihole/pihole flush"
' >> "$FILE"
echo "!!! done."
}
runGravity() {
# Rub gravity.sh to build blacklists
echo ":::"
echo "::: Preparing to run gravity.sh to refresh hosts..."
if ls /opt/etc/pihole/list* 1> /dev/null 2>&1; then
echo "::: Cleaning up previous install (preserving whitelist/blacklist)"
rm /opt/etc/pihole/list.*
fi
echo "::: Running gravity.sh"
/opt/pihole/gravity.sh
}
installPiHole() {
installDependencies
createBridge
setupPhpTZ
setupDnsmasq
setupLighttpd
getGitFiles
installScripts
installAdmin
installPiholeMov
createPiholeIpFile
createDummyHostnameFile
createLogFile
installPiholeWeb
installCron
runGravity
echo "::: View the web interface at http://pi.hole/admin or http://$IP/admin"
}
updatePihole() {
installDependencies
getGitFiles
installScripts
installAdmin
installPiholeMov
installPiholeWeb
runGravity
}
function helpFunc {
echo "::: Install PiHole!"
echo ":::"
echo "::: Options:"
echo "::: -i, install"
echo "::: -u, update"
exit 1
}
if [[ $# = 0 ]]; then
helpFunc
fi
# Handle redirecting to specific functions based on arguments
case "$1" in
"-i" | "install" ) installPiHole;;
"-u" | "install" ) updatePiHole;;
* ) helpFunc;;
esac
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment