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.

alt text

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:

alt text

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.

alt text

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: -

alt text

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

alt text

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

alt text

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.

alt text

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.

alt text

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

alt text

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. [email protected]) 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: -

alt text

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: -

alt text

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: