Get your hands dirty with iptables,, the smart way!

I’m always seeing people playing with iptables, in seemingly “the hard way”. I’m always seeing people entering and removing rules very manually. There is an easier way!! There is still a bit of a learning curve involved, but this essentially blocks ALL traffic, unless you explicitly set a rule for it.

A while back, I found a good read on How to set up a secure Raspberry Pi web server, mail server and Owncloud installation.

Within this guide is a demonstration of how to easily manipulate iptables, without it being terribly difficult.

I’m going to focus on the section titled

“Creating a Firewall”

These will need to be tweaked a bit to work for pihole’s dhcp and dns, as well as any custom stuff you plan on doing. I mostly want to focus on the ease of using this method.

If any of you have played with iptables much, you have run sudo iptables -L to see what rules you have in place.

Create a file to hold your firewall rules by entering the following command:

sudo nano /etc/iptables.firewall.rules

This will be the file that we keep all of our rules. These are the rules borrowed from the page linked above. I’ll try and explain rules that I have tweaked for my own setup later.


#  Allow all loopback (lo0) traffic and drop all traffic to 127/8 that doesn't use lo0
-A INPUT -i lo -j ACCEPT

#  Accept all established inbound connections

#  Allow all outbound traffic - you can modify this to only allow certain traffic

#  Allow HTTP and HTTPS connections from anywhere (the normal ports for websites and SSL).
-A INPUT -p tcp --dport 80 -j ACCEPT
-A INPUT -p tcp --dport 443 -j ACCEPT

# Allows SMTP access
-A INPUT -p tcp --dport 25 -j ACCEPT
-A INPUT -p tcp --dport 465 -j ACCEPT
-A INPUT -p tcp --dport 587 -j ACCEPT

# Allows pop and pops connections
# -A INPUT -p tcp --dport 110 -j ACCEPT
# -A INPUT -p tcp --dport 995 -j ACCEPT

# Allows imap and imaps connections
-A INPUT -p tcp --dport 143 -j ACCEPT
-A INPUT -p tcp --dport 993 -j ACCEPT

#  Allow SSH connections
#  The -dport number should be the same port number you set in sshd_config
-A INPUT -p tcp -m state --state NEW --dport 22 -j ACCEPT

#  Allow ping
-A INPUT -p icmp --icmp-type echo-request -j ACCEPT

#  Log iptables denied calls
-A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables denied: " --log-level 7

#  Drop all other inbound - default deny unless explicitly allowed policy


ctrl+x and press y to save

This command takes the file you created, and doesn’t just merge into iptables, but the rules you place here, replace everything in iptables. if you rerun sudo iptables -L you will find your new rules in place.

sudo iptables-restore < /etc/iptables.firewall.rules

You will want these rules to be enforced at boot.

sudo nano /etc/network/if-pre-up.d/firewall

Then enter

/sbin/iptables-restore < /etc/iptables.firewall.rules


ctrl+x and press y to save

Then to set permissions for this new bash file.

sudo chmod +x /etc/network/if-pre-up.d/firewall

An idea I just had writing this, is to set up a cronjob for this. You could potentially have it rewrite your iptables every 6 hours, since I just had this idea, I can’t confirm that it works, use at your own discretion.

Crontab -e

Then add:

0 */6 * * * sudo bash /etc/network/if-pre-up.d/firewall

Things you will have to tweak:

  • I had an issue connecting devices to my network, and I realized that I wasn’t allowing DHCP ports. I opened ports 67 and 68 in my rules, and devices started getting leases again.

  • I use xrdp now, because I was playing with iptables, and inadvertently locked myself out of ssh. I had to use the following ports: 3389 , 3350 , 5910 . xrdp, allows you to remote-in, fix ssh, and then use terminal in putty like normal.

  • If you use Fail2Ban, you will need to set a rule.

  • If you use OpenVPN, you may need to allow port 1194.

  • Any other webservice you use, you will need to allow traffic on those ports.

  • If you use Squid or Privoxy, you could potentially reroute all traffic using iptables. I personally haven’t gotten that to work yet, but the rule suggested goes something like (Do NOT place it anywhere between *filter and COMMIT):

-A PREROUTING -i tun0 -p tcp --dport 80 -j REDIRECT --to-port 8118

  • Also within *nat you would place This rule autogenerated by openvpn


Please share your ideas of what to add to this. Everybody will have a firewall different setup. I know I had to tweak this one a bit for my own needs, but I’m looking into how to be more secure.

1 Like