In this post, you will find the essential information about the Iptables with examples.
raw [PREROUTING]: Tpically to mark packets that should not be handled by the connection tracking
system (i.e. don’t keep note of their state; don’t act as a stateful firewall on these packets).
This is done using the NOTRACK
target.
nat [PREROUTING]: Only the first packet in a stream of packets hits this table, and al subsequent packets of that stream follow whatever is determined with the first packet.
filter chain: The firewall. ACCEPT
, DROP
, or REJECT
packets them depending on filters on the INPUT
chain (packets destined for this host), OUTPUT
chain (packets generated by this host), or FORWARD
chain.
Connection tracking is done to let the Netfilter framework know the state of a
specific connection. Firewalls that implement this are generally called stateful
firewalls. A stateful firewall is generally much more secure than non-stateful
firewalls since it allows us to write much tighter rule-sets.
Within iptables, packets can be related to tracked connections in four different
so called states. These are known as NEW
, ESTABLISHED
, RELATED
and INVALID
.
All of the connection tracking is done by special framework within the kernel called conntrack. There are also more specific parts of conntrack that handles the TCP, UDP or ICMP protocols among others. These modules grab specific, unique, information from the packets, so that they may keep track of each stream of data. The information that conntrack gathers is then used to tell conntrack in which state the stream is currently in. For example, UDP streams are, generally, uniquely identified by their destination IP address, source IP address, destination port and source port.
All connection tracking is handled in the PREROUTING chain, except locally generated packets which are handled in the OUTPUT chain. If we send the initial packet in a stream, the state gets set to NEW within the OUTPUT chain, and when we receive a return packet, the state gets changed in the PREROUTING chain to ESTABLISHED, and so on source.
# Installation
sudo apt install iptables-persistent netfilter-persistent
# To save changes
sudo netfilter-persistent save
# List Rules in filter table
sudo iptables -L
sudo iptables -L --line-numbers -n
sudo iptables -S
# Other tables
sudo iptables -L -t nat
sudo iptables -L -t mangle
sudo iptables -L -t raw
# Allow loopback
sudo iptables -A INPUT -i lo -j ACCEPT
# Instead of add, you can insert directly into a place within the chain:
sudo iptables -I INPUT 1 -i lo -j ACCEPT
# Allow Established and Related Incoming Connections
sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# Drop Invalid Packets
sudo iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
# Allow Incoming SSH (22/2224)
sudo iptables -A INPUT -p tcp --dport 2224 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
# Allow Incoming HTTP (80) and HTTPS (443)
sudo iptables -A INPUT -p tcp --dport 80 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 443 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
3 -m conntrack --ctstate ESTABLISHED -j ACCEPT
# Allow Incoming MYSQL Request (3306)
sudo iptables -A INPUT -p tcp --dport 3306 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
# Allow ICMP PING
iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
Using MASQUERADE
any outgoing packet from the interface will have whatever IP address that is
assigned to the interface.
# assigne to eth1 interface IP to outgoing packets
sudo iptables -t nat -A POSTROUTING -s 10.20.40.0/24 \
-o eth1 -j MASQUERADE
# Any outgoing packet from eth0 will have the source IP of 192.168.1.1
sudo iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to 192.168.1.1
# Any incoming packet destined to 10.10.20.10:9991 will be forwarded
# to 10.10.30.126:22
sudo iptables -t nat -A PREROUTING -d 10.10.20.10/32 \
-p tcp -m tcp --dport 9991 -j DNAT --to-destination 10.10.30.126:22
# Typically, you would want the default target for the INPUT
# chain to be DROP. However, before setting that, make sure
# you have rules in place to accept incoming traffic;
# otherwise, you may lose your access
sudo iptables -P INPUT ACCEPT
sudo iptables -P FORWARD ACCEPT
sudo iptables -P OUTPUT ACCEPT
# Delete a rule be replacing -A to -D:
sudo iptables -t nat -D POSTROUTING -o eth0 -j SNAT --to 192.168.1.1
# Or list rules and identify the chain number of a rule
sudo iptables -L --line-numbers -v
# And then delete rule 16 from the chain INPUT
sudo iptables -D INPUT 16
# Remove rules of chain INPUT
sudo iptables -F INPUT
# Remove chain INPUT
sudo iptables -X INPUT
You can mark a packet using TRACE
and see the chain of rules that are applied on it:
sudo iptables -traw -A PREROUTING -i eth0 -p udp -m udp --dport 3000 -j TRACE
# Then look at the logs:
sudo dmesg -wH