With it’s single network port, low memory and low CPU speed, a Pi may not seem capable of filtering traffic at a very high bandwidth. This article describes how to make a small filter system that can block IP addresses on the inside or outside of your network while not having any noticeable effect on the network speed. And no, it’s not just blocking the DNS, it’s really blocking the traffic.
Before going any further, check that your router allows you to disable it’s DHCP server. Without being able to do this you’re unlikely to be able to make this work.
Use a Raspberry Pi as your DHCP server.
Set the router address in the DHCP options to the Pi address.
Enable packet forwarding on the Pi, which will forward packets to the real router.
Use iptables to block forwarding from IP addresses.
My reason for creating this was to have a filter that can block a child’s X-Box One from the internet easily and on a schedule. However, the system will block any IP, whether it’s internal or external to my network.
1 Raspberry Pi, ideally with Ethernet. I use an old Version 1 Model B.
1 SD card to fit the Pi. 8Gb is fine and comes quite cheap from Amazon.
1 power supply for the Pi.
1 Ethernet cable – WiFi would work, but may be a bit too slow.
Raspbian OS on th ePi.
Optional but recommended, a case for the Pi.
What we’ll end up with is a system where outbound packets are routed through the Pi, but not incoming ones. The single network interface of the Pi is adequate with packets routed into the Pi and on to the router via the same interface. Since incoming traffic makes up the vast majority on most networks, this means the Pi doesn’t have to work too hard. I found no difference in my download speed with the Pi in place, but my upload went from 18MBit/Sec to 16. The two teenage kids here haven’t noticed anything affecting their online gaming, so latency can’t be affected much either. To make it work, all internal systems (well all the ones you may want to block) need to be persuaded to send their data to the Pi instead of the router. The Pi filters the traffic and forwards it to the router to be sent out to the Internet. Incoming packets are sent straight from the router to the device that needs them without going through the Pi and being slowed at all.
I’ll assume the Pi is already set up and running in headless mode. Headless isn’t essential, but I think it’s much nicer to leave the Pi running out of the way somewhere and connect to it over the network. This project is all done from the Linux command prompt, so an SSH connection is all you need. If you prefer, at least for the initial setup, a monitor and keyboard on the Pi is fine.
Make sure the Pi has a static IP configured, along with a static Gateway and DNS servers. Otherwise, when the Router DHCP is disabled, the Pi will have no way to get it’s configuration.
Next install the additional software needed on the Pi. This is just iptables and udhcpd, which are both available from the raspbian repository. To get them just type this at the command prompt
sudo apt-get update
sudo apt-get install iptables
sudo apt-get install udhcpd
The iptables package allows you to manage the packet filtering. The actual filtering is built into the Linux kernel. The udhcpd package is a DHCP server that will allow you to push the configuration out to the other machines on your network.
A couple of configuration options need to be set on the Pi and now is a good time to do it.
sudo nano /etc/sysctl.conf
In this file find the line starting with
And set it to
That will allow the pi to forward any packet sent to it that isn’t actually addressed to it on to the correct destination.
Now look for a line like this
#net.ipv4.conf.all.send_redirects = 0
This is commented out, as signified by the # at the beginning. Replace the line with these three lines.
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.eth0.send_redirects = 0
You may also want to change the comment above it to say you now are a router. The three lines there set the send_redirects option to disabled. Without this, the first time any traffic gets routed via the Pi, it tells the machine that sent it to talk directly to the router, which undoes all the work we’re doing here. There are three lines as it seems a bit random whether you need to set this for the ethernet interface (eth0) all interfaces or the default. Setting all three makes sure it works. If you are using WiFi instead of Ethernet you’ll want to add another line with wlan0 in place of eth0 too.
Re-boot the Pi to make all that sink in.
The next step is to change the DHCP in your network over to using the Pi. Installing udhcpd should have created a default config, edit this with the following commnd.
sudo nano /etc/udhcpd.conf
Some parts you need to change are the range start and end. I Use 192.168.7.100 to 192.168.7.254 as the DHCP range, most people have a 0 or 1 where my 7 is. For now, set all the options to be the same as the ones in you router. The ones that really matter are DNS and router, which should be the address of your router. While playing with this, it’s a good idea to set the lease time to something low like 1 hour. The 10 day default would mean waiting 10 days to test any changes.
Now it’s configured, it’s time to enable it by editing it’s control file like so.
sudo nano /etc/default/udhcpd
The file tells you what you need to change to enable the DHCP server. Once done, you can manually start it with this command.
sudo service udhcpd start
Now log into your router and turn off it’s DHCP server. No network should have multiple DHCP servers. If you have a windows box around, type ipconfig /release into a CMD prompt then ipconfig/renew. The machine should get the details from the Pi now. You can confirm this with ipconfig /all where the DHCP server will be listed.
Now its time to make all outbound traffic go via the Pi. All you need to do for this is edit the DHCP server config on the Pi again. Set the router option to the IP of the Pi. Restart the udhcpd service to make that config sink in. Once the DHCP leases expire and renew, they will start routing packets to the internet via the Pi.
The whole point of doing this is so you can block specific IPs. If those IPs are devices on your network, you’ll need to edit the DHCP configuration to add static leases so those devices always get the same IP address. the dumpleases command on the Pi will list what devices have what IP at the moment. I’ve found you can alter these and when the lease expires, the device is quite happy on it’s new IP.
This command on the Pi will show all the current iptables rules along with a count of bytes and packets that have matched the rule.
sudo iptables -v -L
Where -v makes it show the packet and byte counts and -L lists the rules. To block an address on your network from accessing the outside world, use this command.
sudo iptables -A FORWARD -s X.X.X.X -j DROP
Where X.X.X.X is the IP you want to block. -s means look for that IP as the source of the packet. Outgoing packets from your network will be coming from the blocked device and dropped. The -A parameter means add it to a table and in this case we want the FORWARD table.
To unblock a device on your network, use this command.
sudo iptables -D FORWARD -s $1 -j DROP
Where everything is as above, except -D for delete instead of -A for add.
If you want to block an IP in the outside world, you would use -d for destination so the outbound packets trigger the rule.
In this article I’ve describes my setup for manually blocking devices but you can go a lot further. Cron jobs could be used to add and remove rules on a schedule. A simple CGI script would allow a web interface to be created. You could even put this together with some previous blog entries and use Google home to voice activate the blocks.
The Pi is powerful enough to handle the traffic in one direction and that’s enough to effectively block connections. You don’t even need to add a second network interface. Blocking traffic one way is all you need to do. Anything already in progress when the IP is blocked soon stops happening when the outgoing packets don’t get through.