Home An Intermediate Iptables Configuration Walkthrough

An Intermediate Iptables Configuration Walkthrough


The built-in (kernel level) linux firewall, iptables, can be daunting to attempt to use, however is a simple redirection filter in practice. I have used iptables from everything from securing my home networks, to routing things over a VPN and through a Intrustion Prevention System (Suricata), to other advanced things such as redirecting traffic from a single user going to port 80 to a local squid proxy on a different port. Here I will teach you the basics of how iptables tools are used.


I suggest installing iptables-persistent from your distro’s package manager, as well as the iptables utilities (the latter should already be installed).

You’ll need access to the root account on the system to perform these tasks. It also must be a linux machine.

sudo apt update
sudo apt install iptables iptables-persistent

Getting ready

First remember that the order of the rules is critical. If you drop all your packets before the rest of the rules come into play, things won’t work right!

I first suggest that you take a look at your current iptables ruleset by running iptables -L -v. This should output something like:

[marshall@jerkon]{12:55 AM}: [~] $ sudo iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy DROP)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
[marshall@jerkon]{12:55 AM}: [~] $

This can varry widely depending on your current ruleset, so now you should definately do a

sudo sh -c 'iptables-save > /root/iptables.$(date -I).1'`

Which will save your current ruleset to a file that looks something like:

[marshall@jerkon]{01:00 AM}: [~] $ sudo cat /etc/iptables/rules.v4
# Generated by iptables-save v1.8.4 on Sun Nov 14 16:27:45 2021
:INPUT ACCEPT [8303406:9963142380]
:OUTPUT ACCEPT [4608688:4796631955]
:DOCKER - [0:0]
:DOCKER-USER - [0:0]
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT
# Completed on Sun Nov 14 16:27:45 2021
# Generated by iptables-save v1.8.4 on Sun Nov 14 16:27:45 2021
:PREROUTING ACCEPT [9588:1345311]
:INPUT ACCEPT [9588:1345311]
:OUTPUT ACCEPT [67180:7143813]
:POSTROUTING ACCEPT [67179:7143681]
:DOCKER - [0:0]
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A OUTPUT ! -d -m addrtype --dst-type LOCAL -j DOCKER
-A POSTROUTING -s ! -o docker0 -j MASQUERADE
-A DOCKER -i docker0 -j RETURN
# Completed on Sun Nov 14 16:27:45 2021

Important: This next command may kill your ssh session as well as other current sessions!

If you would like to flush the current tables you’re now free to do a:

iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X

Then you should reset your default policy to ACCEPT for this walkthrough:

iptables -P INPUT ACCEPT

Now you should also grab your current local IP address using something like curl ifconfig.me and whitelist that, at the top of the rules so that you won’t lock yourself out. Also make sure that stateful connections will stay open using conntrack.

iptables -i lo -j ACCEPT
iptables -o lo -j ACCEPT
iptables -I INPUT -s -j ACCEPT
iptables -I OUTPUT -d -j ACCEPT
iptables -A INPUT -m state --state NEW,ESTABLISHED -j ACCEPT

You should now make sure things like SMTP won’t work in case the box becomes compromised at some point by dropping all traffic to TCP 25 anywhere (you’ll need to not do this if this is intended to be a mail server).

iptables -A OUTPUT -p tcp --dport 25 -j DROP

Also make sure that DNS will always go through.

iptables -A INPUT -m state --state NEW -p udp --dport 53 -j ACCEPT
iptables -A INPUT -m state --state NEW -p tcp --dport 53 -j ACCEPT
iptables -A OUTPUT -m state --state NEW -p udp --dport 53 -j ACCEPT
iptables -A OUTPUT -m state --state NEW -p tcp --dport 53 -j ACCEPT

Make sure that stuff will work on the outbound:

iptables -A OUTPUT -j ACCEPT

You should also make sure that SSH inbound is open so that you can connect back in, and only have 5 active sessions at once:

ibtables -A INPUT -m tcp -p tcp --dport 22 -j ACCEPT
iptables -A INPUT -p tcp --syn --dport 22 -m connlimit --connlimit-above 5 -j REJECT

Also to demonstrate that commands can be mixed and matched we’ll make sure that the user street can only use IRC from this server.

sudo iptables -A OUTPUT -p tcp -m tcp --match multiport ! --dports 6666,6667,6697,9999 --match owner --uid-owner street -j DROP

Then you can drop all pings that are not on your LAN by doing:

iptables -A INPUT -p icmp --pcmp-type echo-request -j ACCEPT
iptables -A INPUT ! -i eth0 -p icmp --icmp-type echo-request -j DROP

Then finally you should drop all other incoming packets you didn’t explicity let through earlier by doing:

iptables -A INPUT -j DROP

After the preceding command, if you have any other things you need to drop, you’ll need to use -I instead of -A to insert further up the chain than your last DROP or you’ll end up dropping before getting to it.

So say you have an attacker, you can now do:

iptables -I INPUT -j DROP
iptables -I OUTPUT -j DROP

This will keep the ruls in order.


Once you play around with it until you get the ruleset you like, you should then run the command:

iptables-save > /etc/iptables/rules.v4

Which will restore the same iptables rules on reboot.

Note: If somehow you messed up, you can always run: iptables-restore < /rootiptables.$(date -I).1 or resore your older last reboot ruleset with iptables-restore < /etc/iptables/rules.v4.

Hope you’ve learned something, and enjoyed reading. If you have any questions, feel free to email me!

Happy New Years!

This post is licensed under CC BY 4.0 by the author.

A simple x86_64 stack based buffer overflow exploitation with gdb

I Hacked a Bank and Got Arrested in 2012

Comments powered by Disqus.