Programster's Blog

Tutorials focusing on Linux, programming, and open-source

Iptables Cheatsheet

List Rules

iptables -L

What is The "Policy"?

Scripts for setting up iptables often start with setting the policy which is specified with -P or --policy. The policy can take a value of ACCEPT or DROP and is what will happen to any packets that don't manage to fit into any rules that are specified later. E.g. if you want a firewall where you block everything and want to just specify rules for what you want to accept, such as SSH, then you would set the policy of DROP. If you wanted to allow everything by default, but specify rules to block certain IPs or ports, or perhaps implement rate limiting, then you sould specify ACCEPT for your policy.

Below is an example of setting the policy accept anything that wasn't specifically covered.

sudo iptables -P INPUT ACCEPT
sudo iptables -P FORWARD ACCEPT
sudo iptables -P OUTPUT ACCEPT

Clear Rules

Below is a script to drop all rules and accept everything (so the firewall is disabled and there is no packet mangling).

#!/bin/bash
sudo iptables --flush
sudo iptables --delete-chain
sudo iptables -P INPUT ACCEPT
sudo iptables -P FORWARD ACCEPT
sudo iptables -P OUTPUT ACCEPT

Example Import Script

For reference, below is a startup script that I use for allowing SSH and FTP connections, and forwarding the FTP ports (including a custom 60000 port) to another server.

#!/bin/bash

# Flushing all rules
/sbin/iptables -F
/sbin/iptables -X

# Setting default filter policy
/sbin/iptables -P INPUT DROP
/sbin/iptables -P OUTPUT ACCEPT
/sbin/iptables -P FORWARD ACCEPT

# Allow unlimited traffic on loopback
/sbin/iptables -A INPUT -i lo -j ACCEPT
/sbin/iptables -A OUTPUT -o lo -j ACCEPT

/sbin/iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

# Allow new incoming FTP and SSH connections from anywhere
/sbin/iptables -I INPUT -p tcp --dport 20    -j ACCEPT
/sbin/iptables -I INPUT -p tcp --dport 21    -j ACCEPT
/sbin/iptables -I INPUT -p tcp --dport 60000 -j ACCEPT
/sbin/iptables -I INPUT -p tcp --dport 22    -j ACCEPT

# Forward ftp requests
HOST="10.8.0.6"
DEST_SERVER="10.1.0.69"
/sbin/iptables -t nat -A PREROUTING -d $HOST/32 -p tcp --dport 20   -j DNAT --to-destination $DEST_SERVER:20
/sbin/iptables -t nat -A PREROUTING -d $HOST/32 -p tcp --dport 21   -j DNAT --to-destination $DEST_SERVER:21
/sbin/iptables -t nat -A PREROUTING -d $HOST/32 -p tcp --dport 6000 -j DNAT --to-destination $DEST_SERVER:60000
/sbin/iptables -A FORWARD -p tcp -d $DEST_SERVER --dport 20    -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
/sbin/iptables -A FORWARD -p tcp -d $DEST_SERVER --dport 21    -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
/sbin/iptables -A FORWARD -p tcp -d $DEST_SERVER --dport 60000 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT

# All forwarded packets should look like they come from this server
/sbin/iptables -t nat -A POSTROUTING -j MASQUERADE

It would be better to use this script for port forwarding, which is far more verbose, strict, and customizeable.

Port Forwarding

Below are the commands you would need to execute to have iptables forward ports 80 and 443 to another server.

# Reroute packets destined for $HOST_PRIVATE_IP on ports 80 and 443 to go to $PROXY_IP instead.
sudo iptables -t nat -A PREROUTING -d $HOST_PRIVATE_IP/32 -p tcp --dport 80 -j DNAT --to-destination $PROXY_IP
sudo iptables -t nat -A PREROUTING -d $HOST_PRIVATE_IP/32 -p tcp --dport 443 -j DNAT --to-destination $PROXY_IP
# Accept forwarding on port 80 and 443
sudo iptables -A FORWARD -p tcp -d $PROXY_IP --dport 80 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
sudo iptables -A FORWARD -p tcp -d $PROXY_IP --dport 443 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT

You probably want the packets you are forwarding to appear as if they are coming from your host, in which case you want to add either:

/sbin/iptables -t nat -A POSTROUTING -s $PROXY_IP/32 -j SNAT --to-source $HOST_PRIVATE_IP
/sbin/iptables -t nat -A POSTROUTING -j MASQUERADE

Using the first rule allows you to be specific about applying the rule to only forwarding to certain IP's and lets you specify what the source should be, in case you don't want it to be this server. The second rule is nice and generic so that all forwarding will result in packets being shown as coming from this server which is what you want 99% of the time.

On Ubuntu, you also need to perform a few steps to allow the server to forward packets.

Edit the /etc/sysctl.conf and uncomment #net.ipv4.ip_forward=1 by changing it to:

net.ipv4.ip_forward=1

To have the change take immediate effect, execute:

sudo sysctl -p

We also need to execute the following command to enable port forwarding:

echo 1 > /proc/sys/net/ipv4/ip_forward

Rate Limiting

Please refer to my post on rate limiting.

References

Last updated: 4th August 2021
First published: 16th August 2018