Brew: Bell’s HopSlam
Until recently, I had previously been using a small Debian virtual machine on my ESXi box to host a small Pi-Hole instance.
This served me fine in most cases, but being as I often patch, I often found myself in a situation where DNS would be down for a short period of time for my entire network.
Upon finding an old RPi1 sitting around doing nothing, I decided I would see if the old device could handle my small amounts of network traffic and be put back into use.
While I personally set mine up to act also as a DHCP server, I will not be covering that and will assume you are keeping your current router as that.
Items and Cost
Hardware
- RPi1 256mb w/ case: $free
- 16GB Microcenter SD card: $4
- A good 2.5a PSU: $10
- Network Cable: $free
Software
- raspbian-lite
- pihole
- unbound
- log2ram
- various scripts
Getting Started
First thing is first. You have your parts and depending on what you have laying around, you may find that you are able to do this cheaply, like I have. You could use any RPi and the following items should work. Keep in mind that I did do some tweaks to compensate for the low memory footprint of the RPi’s 256MB, and I would most likely increase unbound’s cache and log2ram’s size of I were using a RPi3+, so you may want to tweak these items as you see fit.
Installing Software
Once you obtain your copy of raspbian-lite, you will want to get that imaged to your SD card. We have various methods for that, either the GUI etcher.io or good ol’ fashion dd.
dd bs=4M if=2018-11-13-raspbian-stretch.img of=/dev/sdX conv=fsync
Prior to un-mounting or ejecting your card. You will want to touch a file named ssh to the root of the sdcard. This will tell raspbian to start the ssh server upon boot. Without this, you will require a keyboard and monitor to do the initial installation.
Plug your device in and get it booted. Look up the DHCP table on your router and find the IP address of the newly booted device. Once you have this IP you will ssh into your device with the default username and password (pi/raspberry) and start configuring. I would advise patching as well.
$ sudo apt update
$ sudo apt upgrade
$ sudo reboot
The first item of business, will be to execute the raspi-config command as sudo. Once executed I utilized the following options:
- Advanced / Expand Filesystem
- Advanced / Memory Split (1MB to video)
- Network Options (Hostname)
- Overclock / Turbo (optional)
If you notice, I did not modify the default username and password. In fact i removed that account and created my own local account with sudo rights. This is completely optional.
Now we will want to install log2ram. I installed this to help alleviate the wear and tear on the SD card. This script essentially creates a tmpfs and will write back your logs to the SD card once an hour.
$ sudo apt-get install git net-tools
$ git clone https://github.com/azlux/log2ram.git
$ cd log2ram
$ chmod +x install.sh && sudo ./install.sh
Then it is off to install pi-hole. The only whitelist I utilize are the ones set my default in the installer, these work well enough for my personal taste. I also installed the webserver, as I like the graphs and it allows you to access them via your phone with this handy app. I set the IP to static, as this is a network device which should be hard set, in my opinion.
I do this in my regular users home directory. We will also set the web interface login password.
$ git clone --depth 1 https://github.com/pi-hole/pi-hole.git pi-hole
$ sudo pi-hole/automated\ install/basic-install.sh
$ pihole -a -p
I manage a majority of my pihole via CLI. The documentation provided below offers up a ton of information on how to manage everything. I suggest you take the time to take a look. You can also manage everything via the web interface and using the password you have set above.
https://docs.pi-hole.net/core/pihole-command/
Next up we will install unbound as a recursive server utilizing DNSSEC. I applied some default configuration settings that I will not go to far into detail here, but you can follow the following link to review and cross reference for yourself.
https://www.nlnetlabs.nl/documentation/unbound/unbound.conf/
You may also find the pihole site’s documentation on this process useful, this can be found at the following link.
https://docs.pi-hole.net/guides/unbound/
$ apt-get install unbound
$ sudo curl https://www.internic.net/domain/named.root -o /var/lib/unbound/root.hints
Remove all previous configuration files in /etc/unbound/unbound.conf.d and create the the following file with these settings.
$ sudo rm /etc/unbound/unbound.conf.d/*
$ sudo vi /etc/unbound/unbound.conf.d/dnssec-recursive.conf
server:
extended-statistics: yes
verbosity: 0
interface: 127.0.0.1
port: 5353
do-ip4: yes
do-udp: yes
do-tcp: yes
do-ip6: no
qname-minimisation: yes
prefetch: yes
use-caps-for-id: no
harden-glue: yes
harden-dnssec-stripped: yes
auto-trust-anchor-file: "/var/lib/unbound/root.key"
root-hints: "/var/lib/unbound/root.hints"
edns-buffer-size: 1472
cache-min-ttl: 3600
cache-max-ttl: 86400
num-threads: 1
msg-cache-size: 4m
rrset-cache-size: 8m
so-rcvbuf: 1m
so-sndbuf: 1m
private-address: 192.168.0.0/16
private-address: 169.254.0.0/16
private-address: 172.16.0.0/12
private-address: 10.0.0.0/8
private-address: fd00::/8
private-address: fe80::/10
Now lets get unbound fired up and do a test to see if we are accepting connections, as expected.
$ systemctl enabled unbound
$ systemctl start unbound
$ dig google.com @127.0.0.1 -p 5353
; <<>> DiG 9.10.3-P4-Raspbian <<>> google.com @127.0.0.1 -p 5353
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 56918
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1472
;; QUESTION SECTION:
;google.com. IN A
;; ANSWER SECTION:
google.com. 540 IN A 216.58.216.110
;; Query time: 0 msec
;; SERVER: 127.0.0.1#5353(127.0.0.1)
;; WHEN: Sat Jan 26 17:06:01 EST 2019
;; MSG SIZE rcvd: 55
Then we will setup pi-hole to utilize this server and forward domain request to your router for proper network dns resolution on your lan, by adding the following first to /etc/dnsmasq.d/01-pihole.conf. We will assume your lan is named local.
server=127.0.0.1#5353
server=/local/192.168.1.1
server=/1.168.192.in-addr.arpa/192.168.1.1
Modifying /etc/pihole/setupVars.conf is also essential if you want this to survive an upgrade. While we are in there, lets exclude our own local domains from the top permitted domains.
PIHOLE_DNS_1=127.0.0.1#5353
CONDITIONAL_FORWARDING=true
CONDITIONAL_FORWARDING_IP=192.168.1.1
CONDITIONAL_FORWARDING_DOMAIN=local
CONDITIONAL_FORWARDING_REVERSE=1.168.192.in-addr.arpa
API_EXCLUDE_DOMAINS=*.local
If you are no longer interested in having your pihole host showing up in your top clients, you can add the following to /etc/pihole/pihole-FTL.conf.
IGNORE_LOCALHOST=yes
I found that I initially felt that pi-hole blocked too many items at once. This caused some issues with sites such as amazon, slickdeals, etc. Thankfully others have felt the same and there is a pretty common whitelist and referral list put together from the community. This list can be found at the following link.
https://github.com/anudeepND/whitelist
cd /opt
sudo git clone https://github.com/anudeepND/whitelist.git
cd whitelist/scripts
sudo chmod +x whitelist.sh
sudo ./whitelist.sh
sudo chmod +x referral.sh
sudo ./referral.sh
The instructions are simple. I have placed both this and updating the gravitational list into a crontab and let them run nightly to update the files as needed. I created a quick script, /usr/local/sbin/update-all-list.sh
#!/bin/sh
/usr/local/bin/pihole -g >/dev/null
/opt/whitelist/scripts/whitelist.sh >/dev/null
/opt/whitelist/scripts/referral.sh >/dev/null
This is then set to run as root in crontab, at 4am each night.
0 4 * * * /usr/local/sbin/update-all-list.sh
Last but not least. You will need to modify your routers configuration to send out the ip of your pi-hole to dhcp clients. I will leave this up to you, as each configuration varies. While you are in the configuration, you may want to also consider blocking all outgoing dns queries from anything BUT your pihole IP. You can create a destination nat that will loop back any outgoing queries, besides your pihole, back to your internal dns. I will cover this for Mikrotik routers in another post, but your configuration will be specific to your setup.
I usually like to give the whole thing a reboot as well, to ensure everything comes up as expected.
If you wish to preload your cache. I created this quick script that will populate your unbound cache. It will pull down and pre-cache the top 2000 sites from Alexa.com. I found that this does help reduce query time, but it most likely isn’t a best or required practice. It does require the bsdtar package.
curl -s http://s3.amazonaws.com/alexa-static/top-1m.csv.zip | bsdtar -xf - -C /tmp
head -2000 /tmp/top-1m.csv | awk 'BEGIN { FS = "," } ; { print $2 }' | while read i; do dig @127.0.0.1 -p 5353 $i +noall; done
rm /tmp/top-1m.csv
Here are some example before and after results.
Uncached:
real 11m20.024s
user 3m34.427s
sys 1m1.165s
Cached:
real 4m40.492s
user 3m26.011s
sys 0m58.139s
Good luck!

