Create a DNS Sinkhole
What?
A DNS sinkhole is a server that has been configured to hand out false addresses for all domains that we don’t want to access on the network we’re using. Pi-hole was designed as a DNS sinkhole for advertisements, but can easily be configured to block more. This is a quick tutorial, showing you how to get a Pi-hole server setup, hardened and configured on your network in 60 minutes.
Feel free to skip any part of this guide, it’s just a quick note for me to rebuild everything should the need arise.
Hardware requirements
To follow this example you will need:
- Raspberry Pi with an ethernet port (I will be using a Raspberry Pi 3 model B+, which is overkill but I had one hanging around)
- Ethernet cable
- If you want network-level blocking, a router that allows you to configure the DNS server
Install OS
Download the latest Raspberry Pi OS (32-bit) Lite, install to a new SD card. I generally use Win32DiskImager but there are plenty on options.
On the first boot, SSH is disabled which means you will need to boot into the device with a keyboard and a monitor attached. Log in with the username “pi” and the password “raspberry”, both of which we’ll be changing.
SSH
After booting the raspberry-pi, type
sudo raspi-config
and hit enter. You will be presented with a screen that looks like this:
First, highlight number 1 and hit enter then set a strong password that you will remember. Once the has been set, highlight Interfacing Options, then SSH, and hit enabled. Accept the prompts then finish.
At this point, I normally shut down the raspberry-pi by typing
sudo shutdown -h now
then plug my ethernet cable in and switch it back on. I normally set the raspberry-pi to a set IP address on my router, then SSH in using PuTTY: -
Finally, let’s change the SSH port. This is because everyone knows that SSH is on port 22, so we’ll use a different port for our box. To ensure there are no conflicts, I like to use a port number greater than 1024. I also like to use a different SSH port for the different devices on my network, whether or not they talk to the outside world. I normally generate the port I’m going to use for the machine by running
shuf -i 1025-32767 -n 1
Write down the number you’ve generated and use that as the SSH port. Next, we’ll make a backup of the SSH config file by running:
sudo cp /etc/ssh/ssh_config /etc/ssh/ssh_config.dist
which leaves us with a copy of the config file in the same location but with a new extension. Then we open the configuration file to edit by running
sudo nano /etc/ssh/sshd_config
The highlighted lines in the above screenshot are where we’re looking first.
- Uncomment “Port 22” bt deleting the “#”, then add our new port number.
- Scroll down until you find “#MaxAuthTries”, uncomment this and set to a reasonable 3.
- Scroll down until you find “ChallengeResponseAuthentication”, change to “yes”.
- Not necessary, but since I’m not planning to use a monitor or a GUI with this installation, scroll down until you find “X11Forwarding” and change to “no”.
- Scroll down until you find “#ClientAliveInterval”, uncomment and add 300 to the end (e.g. ClientAliveInterval 300). This gives you 5 minutes of inactivity before the SSH session is killed.
Once you have made these changes, type CTRL+x to exit, answer y to save changes, and then press Enter to overwrite the original file. Make sure that the daemon can read the file by running
sudo sshd -t
if there are errors you’ll need to fix them (there won’t be if all you’ve done is the above). Finally, we need to restart the daemon by running
sudo systemctl restart ssh
(note, this won’t kill your current SSH session). To test that it has worked, I like to open a second PuTTY session and attempt to login via the new port. If it works, all is good with our configurations so far.
Update the server
Before we continue, let’s make sure the server is up to date by running
sudo apt update
then
sudo apt upgrade
Changing username
In my opinion, the best way to do this is to rename the “pi” user, rather than create a new one. By renaming the “pi” user, you can ensure that your new user is in all of the correct system groups and everything will work as normal.
Since we can’t rename a user we’re currently using, the first thing you’ll need to do is enable the root user. To do this run
sudo passwd root
and choose a secure password that is different from the pi user’s password. We’ll disable the root user at the end, but it’s still good practice to use a different password.
If you’re going to be doing this using PuTTY, next you need to enable “root” login over SSH. Open the configuration file to edit by running
sudo nano /etc/ssh/sshd_config
and locate “#PermitRootLogin”. Remove the comment and change the value to “yes”. Type CTRL+x to exit, answer y to save changes, and then press Enter to overwrite the original file. Restart the daemon by running
sudo systemctl restart ssh
(note, this won’t kill your current SSH session) and finally, ensure that the daemon can read the changes by running
sudo sshd -t
Close your PuTTY session and start it again, but this time login using “root” as the username and your secure password. To change the pi username to “elephant”, run the command
usermod -l elephant pi
Pick a username you’ll remember, but don’t make it too easy (i.e. administrator or admin are not recommended).
Once you’ve done this, you need to change the user’s home directory name to the same as the username. This can be done by running:
usermod -m -d /home/elephant elephant
Now close your PuTTY session and start it again, but this time login using “elephant” as the username with your password that was the “pi” user password. Open the configuration file to edit by running
sudo nano /etc/ssh/sshd_config
and locate “PermitRootLogin”. Add the comment back so that it reads “#PermitRootLogin”. Type CTRL+x to exit, answer y to save changes, and then press Enter to overwrite the original file. Restart the daemon by running
sudo systemctl restart ssh
(note, this won’t kill your current SSH session) and finally, ensure that the daemon can read the changes by running
sudo sshd -t
Assuming “sudo nano” worked, your new user still has sudo privileges so you can disable the root user by running
sudo passwd -l root
Two-Factor Authenication
Two-factor authentication is something I bang on about to anyone that I can make listen. It’s not perfect, but it’s much better than relying on a password alone. In this example, I’m going to use Google Authenticator as it’s an open-source token generator. Is using a time-based one-time password application perfect? No. Is it adequate for this? I believe so. If you’re not sure, look up the differences between U2F and TOTP.
First, you need to install Google Authenticator on your phone. This is an application in the Google Play store.
Make sure that you are logged in to the user that we’re going to be using on the Raspberry-Pi and run the command
sudo apt install libpam-google-authenticator
This will install the Google Authenticator on your device. Once installed, run
google-authenticator
(without sudo). When prompted, enter “y” to confirm that you want authentication to be time-based.
Before you do anything else, make a note of your scratch codes and save them somewhere safe. These codes will let you log in with SSH if you lose your phone. Open the Google authenticator app on your phone and scan the QR code that has been created on the screen. If the PuTTY window has not generated the QR code correctly (i.e. the window was too small so it got squished), select manual entry. Enter the account name (i.e. elehant@raspberrypi) and the key should be the secret key displayed under the QR code. Ensure that time-based is enabled.
Next, back in the raspberry-pi save the authenticator file then go through the prompts answering as you see fit. I normally answer “y”, “n” and “y”.
We need to update the Linux Pluggable Authentication Module to say we want to use Google Authenticator. Run
sudo cp /etc/pam.d/sshd sshd.dist
to back up the original file. Then run
sudo nano /etc/pam.d/sshd
to open for editing. Add this line
auth required pam_google_authenticator.so
so that the file looks like this: -
Type CTRL+x to exit, answer y to save changes, and then press Enter to overwrite the original file. Restart the daemon by running
sudo systemctl restart ssh
then open a new PuTTY session and try and log in. Do not close your current PuTTY session in case something goes wrong! This time you should be asked for your Verification, which is the 6 digit code that refreshes every 30 seconds in your Google Authenticator app on your phone.
Now, if you so choose, you could forward the SSH port out through your router to allow you to connect from outside of your network.
Fail2Ban
Fail2ban is designed to help block malicious agents from accessing our device. It scans log files and bans IPs that show signs of being malicious. I install this on every Raspberry-Pi I build, regardless of how often it will be on the internet.
First, let’s install by running
sudo apt-get install fail2ban
Once installed, you need to make a copy of jail.conf called “jail.local”. This can be done by running
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
After you’ve created this new file, we need to edit it so we’ll open it by running
sudo nano /etc/fail2ban/jail.local
This file is big, so rather than scrolling type CTRL+w to search, type “sshd” and press enter. Under [sshd], add the following and delete anything else until the next section:
[sshd]
enabled = true
filter = sshd
port = ssh,1234
banaction = iptables-allports
bantime = -1
maxretry = 3
logpath = %(sshd_log)s
backend = %(sshd_backend)s
Where I’ve put 1234 above, you need to add the port number you have specified for SSH. Scroll down to [dropbear] and paste in the following: -
[dropbear]
enabled = true
port = ssh,1234
banaction = iptables-multiport
bantime = -1
maxretry = 3
logpath = %(dropbear_log)s
backend = %(dropbear_backend)s
Finally, scroll down to [selinux-ssh] and paste in the following: -
[selinux-ssh]
enabled = true
port = ssh,1234
banaction = iptables-multiport
bantime = -1
maxretry = 3
logpath = %(auditd_log)s
When you’re finished, it should look like this: -
Type CTRL+x to exit, answer y to save changes, and then press Enter to overwrite the file. Before we restart the service, we’ll ensure that the jails we’ve just enabled have log files otherwise fail2ban fails to start. So run:
sudo touch /var/log/auth.log
then
mkdir –vp /var/log/audit
and finally
sudo touch /var/log/audit/audit.log
To make it start running with our new config, run:
sudo service fail2ban restart
You can see the status of the service by running:
systemctl status fail2ban.service
and you can see the tail of the log by running
tail /var/log/fail2ban.log
Pi-hole
Installing Pi-hole is easy. You can just run the command:
curl -sSL https://install.pi-hole.net | bash
and it does everything automatically for you. Make sure that if you enable the web-interface (I suggest you do) that you note down the password during installation (we can change this later).
On your router, ensure that the raspberry-pi has a fixed IP address, then change the DNS on the router to point to the raspberry-pi and you’re done!
I may do a post later on about blocklists but for now, this is enough to get you started.
Share on: