Raspberry Pi Gatekeeper
Go to | #1 | #2 | #3 | #4 | #5 | #6
Advertisements! I hate them, you hate them, we all hate them. What if I told you there was a way to block ad traffic from ever entering your network? Actually, this happened to me a few days ago by a coworker. I learned about a software called Pi-hole specifically designed for Raspberry Pi's that blocks all ad traffic. Sounds good, right? Now, how are you supposed to set it up?
Fresh OS Install
I first wanted to upgrade my Ubuntu version to 24.04, the latest version. (It was only released a few days ago!) I looked up some tutorials which made it seem easy to update from 22.04, which is what I thought I had. Turns out, I was still running 20.04 on my Pi! So I would need to step through the major versions, and I figured that I would prefer a clean install anyway. This shouldn't be a big deal, since I don't store any data directly on the Pi.
I downloaded the official Ubuntu Server ARM64 image and created a startup disk on a 64GB MicroSD card, but unfortunately I would get no signal when plugging in the Pi to my monitor. After a few tries, I decided to go the easy route and install the official Raspberry Pi imager. After a single try with using that utility, it worked perfectly.
Warning: If you create a startup disk, you will lose all existing data on that drive!
First-time Setup
Wifi
There were a few tricky things to set up for the first time: internet access (over wifi) and SSH access. To set up my wifi configuration, I needed to make changes to the netplan configuration file. I think the file could have slightly different names, but every time I've set it up, it was called 50-cloud-init.yaml
.
Bash | |
---|---|
While editing the file, I added the lines under wifis:
YAML | |
---|---|
After the file was saved, I ran the following commands. I'm not sure if generate
is required, but I did it anyway.
To make sure of a successful internet connection, I simply pinged my website:
Bash | |
---|---|
Now that I had an internet connection running, I checked for any software updates, but surprisingly there were none. Seems like Ubuntu 24.04 ships with all the latest software. Cool!
Bash | |
---|---|
SSH
To update my SSH configuration, I edited the sshd_config
file:
Bash | |
---|---|
There were 2 lines I needed to change in the file:
Basically, these lines allow various forms of keyboard interaction for authentication, and specifically allow password authentication. After saving the changes, I needed to restart the SSH service:
Bash | |
---|---|
At this point, if you are following along, it would be a good idea to make a note of your Pi's IP address using the command:
I didn't need to do this, since I have configured a static IP in my router settings, and I have a subdomain that points directly to that IP.
Bash
At this point, I no longer need to have my keyboard or monitor plugged into the Pi, since I can now do everything from my PC through an SSH connection. I did reboot and re-test everything first since I made a lot of changes and wanted to make sure that nothing got corrupted.
Bash | |
---|---|
Authorize Key
Now I'm back on my PC. I had already generated an SSH key pair a long time ago with...
Bash | |
---|---|
...so I didn't need to redo it. However, I had to remove my Pi's old known host, so I lazily deleted the entire known_hosts
file. If I don't do this, then I'll get network security errors and it won't allow me to connect.
Bash | |
---|---|
The reprecussions of this is that whenever I connect to a "new" SSH server, I will get a warning saying that the authenticity of the host cannot be established. If you know what you're doing, just answer "yes" to that message and it goes away after that.
I need to copy over my public key to the Pi using this command. It will ask for the server password, since I enabled PasswordAuthentication
earlier.
Bash | |
---|---|
Now, I can finally connect to my Pi through SSH. From here I will disable the authentication methods I enabled earlier.
Bash | |
---|---|
Pretty SSH Command
I lied with a few of my ssh
commands. I simplified my SSH connection using a (pretty simple) configuration.
Bash | |
---|---|
my-server-name.nicfv.com
contains an A+
dynamic DNS record that points to my public network address. Thanks, NameCheap! That means that I can use the much shorter and memorable alias to log into my Raspberry Pi.
Bash | |
---|---|
So clean! From here I followed my own advice from my backup story (#1) to get my backup server up and running again.
Pi-Hole
Pi-hole is a DNS server that blocks ad traffic from entering your network. I decided that I wanted to install it on my Raspberry Pi through Docker, a containerized environment. I downloaded the sample docker-compose.yml
file and placed it in my ~/pihole/
directory.
Docker
YAML | |
---|---|
Bash | |
---|---|
Docker installed successfully, but unfortunately required sudo
for every command. I was able to fix it using these commands:
After logging out and back in, I was now able to run docker
commands without sudo
. Now I can run the container using:
Bash | |
---|---|
I was hit again with another issue. This time, 0.0.0.0:53
was already in use. Luckily I was able to find a StackOverflow post which outlined my issue exactly.
Bash | |
---|---|
Networking
Now when I compose my docker container, it runs successfully! I can go to 192.168.0.123/admin
which takes me directly to my Pi-hole dashboard! But even still, ads were not being blocked on my network because I had not yet changed my DNS settings in my router. To do this, I visited 192.168.0.1
(Motorola modem/router) and 192.168.1.1
(Linksys router). I have a weird daisy-chain configuration, like this:
graph LR
internet(["internet"])===>
motorola{{"Motorola"}}===>
linksys{{"Linksys"}}
motorola-...->tv["TV"]
motorola-...->cam["Camera"]
motorola-...->pi["Raspberry Pi"]
linksys-.->laptop["MacBook"]
linksys-.->pc["Home PC"]
linksys-.->print["Printer"]
Basically, I changed my Motorola DNS settings (Advanced > Status > Connection > IPv4 DNS Servers) to the following, and then restarted the router:
Description | Value |
---|---|
Obtain Automatically from MSO | Disabled |
Primary DNS | 192.168.0.123 |
Secondary DNS | 1.1.1.1 |
For the Linksys router, first I disabled the DHCP server, which was a big mistake. Everything that was connected to the Linksys all of a sudden lost internet connection, even after performing a restart on all devices. After a lot of guess-and-check, I went into my MacBook, and connected to the Motorola's wifi. From here I could at least connect to the internet. I assigned a static IP of 192.168.1.99
to be on the same subnet as the Linksys. What's weird was that I had to keep the gateway assigned to 192.168.0.1
. But then finally I could log back into the web interface for the Linksys. I re-enabled the DHCP server, and changed my Linksys DNS settings (Connectivity > Local Network) to the following:
Description | Value |
---|---|
Static DNS 1 | 192.168.0.123 |
Static DNS 2 | 1.1.1.1 |
Static DNS 3 | 8.8.8.8 |
After applying the update and restarting everything, I was finally back on track. My PC and MacBook could successfully connect to the internet through the Linksys. I even printed a test page just to make sure the wireless printer still worked. At this point, all my devices on the Linksys router were successfully blocking ad traffic!
Unsolved Issues
Oddly enough, I'm having more trouble with the devices on the Motorola router than I did on the Linksys router, even though the Raspberry Pi is connected to the Motorola. Luckily, for my TV, I was able to directly change the DNS server in the network settings. From the Pi-hole dashboard, it appears to have worked, however the TV's browser must be caching some files because I can still visit blocked websites.
When I connect the MacBook to the Motorola wifi, it doesn't see the Motorola's DNS configuration (in Settings > Network > Wifi > Details > DNS) at all.
DNS Servers |
---|
75.75.75.75 |
75.75.76.76 |
2001:558:feed::1 |
2001:558:feed::2 |
The same list is shown with the terminal command:
Bash | |
---|---|
However, I can work around this by manually setting the DNS to 192.168.0.123
, but the issue here is that I have to do this every time I change networks (e.g. if I bring the MacBook to work.)
Another issue is my Android smartphone. When I connect it to the Linksys, I cannot access blocked domains. But once again, as soon as I connect to the Motorola, those domains are suddenly working again. I tried poking around in the network settings, but I could not figure out how to change the DNS. (...I have an old Android.)
Lastly, Pi-hole has a nice feature where you can access the dashboard with pi.hole/admin
in a web browser. Unfortunately, this is not working for me. I found a forum thread with my issue exactly, and the original poster claims to have figured out the solution. Frustratingly, he did not post his solution! After a few tries, I gave up on this, since I am still able to access it via the 192.168.0.123/admin
workaround.
Conclusion
Despite some issues with the networking portion of this project, as long as I do the bulk of my internet usage from the Linksys router (which I already do anyway), the Pi-hole server is doing a decent job of blocking advertisements. Some YouTube ads still get through, but the page won't load when I accidentally (or purposefully) click on them. My major appreciation goes to the Pi-hole dashboard, which shows me what requests were made from which IP at any given time. The one limitation of this is that everything under the Linksys router will show the IP address for the router itself instead of the subnet IP. Either way, this is a major improvement onto my home network security and monitoring, and while it had its difficulties, was still doable for someone with limited experience.