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
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
- nixCraft - Linux: Block Port With IPtables
- ServerFault - How can I port forward with iptables?
- nixCraft - Linux Iptables: Block All Incoming Traffic But Allow SSH
First published: 16th August 2018