iptables Baseline Firewall Configuration

This document outlines a baseline iptables firewall configuration for a Linux system, covering INPUT (traffic destined for the local machine), FORWARD (traffic passing through the machine), and NAT (Network Address Translation) rules. This configuration typically aims to secure the host, allow specific services, and manage network traffic in scenarios like routing or gateway roles.

WARNING: iptables configuration changes are applied immediately and can lock you out of your system if not configured carefully. Always test new rules in a safe environment or ensure you have a recovery plan (e.g., console access).

1. INPUT Chain: Protecting the Local Host

The INPUT chain processes packets destined for the local machine. This configuration sets up custom chains for explicit allowance and denial, leveraging connection tracking for established sessions.

# Create custom chains for inbound traffic management
iptables -N allow_inbound
iptables -N deny_inbound
 
# Allow established and related connections (crucial for maintaining active sessions like SSH)
iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
 
# Allow all traffic on the loopback interface (localhost)
iptables -A INPUT -i lo -j ACCEPT
 
# Drop invalid packets (packets that cannot be associated with an existing connection)
iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
 
# Jump to custom 'allow_inbound' chain for new connections
iptables -A INPUT -m conntrack --ctstate NEW -j allow_inbound
 
# Jump to custom 'deny_inbound' chain for explicit rejections/logging
iptables -A INPUT -j deny_inbound
 
# Log and then drop any traffic that falls through previous rules
iptables -A INPUT -j LOG --log-prefix '** EXPLICIT-DENY-INBOUND **'
iptables -A INPUT -j DROP
 
# Set the default policy for the INPUT chain to DROP (most secure default)
# This means any packet not explicitly ALLOWED will be dropped.
iptables -P INPUT DROP

allow_inbound Chain (Custom Rules for Allowed New Connections)

This chain defines specific rules for new incoming connections that should be permitted.

# Allow SSH from a specific IP address
iptables -A allow_inbound -p tcp --dport 22 -s 192.0.2.68 -j ACCEPT
 
# Allow a custom service (e.g., web interface) from a specific IP address
iptables -A allow_inbound -p tcp --dport 10000 -s 192.0.2.68 -j ACCEPT

deny_inbound Chain (Custom Rules for Explicitly Denied/Logged Connections)

This chain handles logging and explicitly rejecting certain types of inbound traffic.

# Log denied inbound traffic
iptables -A deny_inbound -j LOG --log-prefix '** DENY-INBOUND **'
 
# Reject UDP traffic with ICMP port unreachable message
iptables -A deny_inbound -p udp -j REJECT --reject-with icmp-port-unreachable
 
# Reject TCP traffic with TCP reset message
iptables -A deny_inbound -p tcp -j REJECT --reject-with tcp-reset
 
# Reject other protocols with ICMP proto unreachable message
iptables -A deny_inbound -j REJECT --reject-with icmp-proto-unreachable

2. FORWARD Chain: Routing Traffic Through the Host

The FORWARD chain processes packets that are not destined for the local machine but are intended to be routed through it to another destination. This is relevant for routers or machines acting as gateways.

# Create custom chains for forward traffic management
iptables -N snat           # For Source NAT rules
iptables -N allow_forward
iptables -N deny_forward
 
# Allow established and related forward connections
iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
 
# Jump to SNAT chain for packets requiring Source NAT
iptables -A FORWARD -j snat
 
# Jump to custom 'allow_forward' chain for explicit forward allowances
iptables -A FORWARD -j allow_forward
 
# Jump to custom 'deny_forward' chain for explicit forward rejections/logging
iptables -A FORWARD -j deny_forward
 
# Log and then drop any forward traffic that falls through previous rules
iptables -A FORWARD -j LOG --log-prefix '** EXPLICIT-DENY-FORWARD **'
iptables -A FORWARD -j DROP
 
# Set the default policy for the FORWARD chain to DROP
iptables -P FORWARD DROP

snat Chain (Source NAT)

This chain is used to apply Source Network Address Translation (SNAT) to outgoing packets.

# Example: Allow traffic from an internal subnet on a specific interface to be SNAT'd
iptables -A snat -i eth1 -s 192.168.2.0/24 -j ACCEPT

allow_forward Chain (Custom Rules for Allowed Forward Connections)

This chain defines specific rules for forwarding traffic that should be permitted.

# Example: Allow TCP traffic on port 443 from a specific source IP to a specific destination IP
iptables -A allow_forward -d 192.168.2.100 -s 203.0.113.50 -p tcp --dport 443 -j ACCEPT

deny_forward Chain (Custom Rules for Explicitly Denied Forward Connections)

This chain handles logging and explicitly rejecting certain types of forward traffic.

# Log denied forward traffic
iptables -A deny_forward -j LOG --log-prefix '** DENY-FORWARD **'
 
# Reject forward traffic with ICMP host unreachable message
iptables -A deny_forward -j REJECT --reject-with icmp-host-unreachable

3. NAT Table: Network Address Translation

The nat table is used for Network Address Translation. It’s distinct from the filter table and primarily handles modifying packet headers to change source or destination IP addresses/ports.

SNAT (Source NAT)

SNAT modifies the source IP address of packets. MASQUERADE is a special form of SNAT where the outgoing interface’s IP address is automatically used as the source IP, suitable for interfaces with dynamic IP addresses.

# Example: Masquerade outgoing traffic from an internal subnet to the external interface's IP
iptables -t nat -A POSTROUTING -s 192.168.2.0/24 -o eth0 -j MASQUERADE
  • -t nat: Specifies the NAT table.
  • -A POSTROUTING: Appends the rule to the POSTROUTING chain (executed after routing decisions).
  • -s 192.168.2.0/24: Matches packets originating from this source subnet.
  • -o eth0: Matches packets exiting via the eth0 interface.
  • -j MASQUERADE: Changes the source IP to the IP of the eth0 interface.

DNAT (Destination NAT)

DNAT modifies the destination IP address of packets, commonly used for port forwarding (e.g., exposing an internal service to the outside world).

# Example: Forward incoming TCP traffic on port 443 on eth0 to an internal host
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 443 -j DNAT --to 192.168.2.100:443
  • -A PREROUTING: Appends the rule to the PREROUTING chain (executed before routing decisions).
  • -i eth0: Matches packets entering via the eth0 interface.
  • -p tcp --dport 443: Matches TCP packets destined for port 443.
  • -j DNAT --to 192.168.2.100:443: Changes the destination IP to 192.168.2.100 and the destination port to 443.