Mastering iptables

Mastering iptables: Command Basics, Uses, and Simulating Network Scenarios for Testing

In the world of networking, controlling traffic flow is a crucial aspect of ensuring secure and reliable systems. One of the most powerful tools for managing network traffic in Linux is iptables. This blog post delves into the basics of iptables, its common uses, and how to leverage it to simulate various network scenarios for testing purposes.


What is iptables?

iptables is a command-line utility used to configure the Linux kernel’s netfilter framework. It acts as a firewall and packet filtering tool, allowing system administrators to define rules for incoming, outgoing, and forwarded packets. These rules control how traffic flows to and from a system.

iptables operates on various tables, each with a specific purpose:

  • Filter: The default table, used for packet filtering.
  • Nat: Handles Network Address Translation (NAT).
  • Mangle: Alters packet headers for advanced routing.
  • Raw: Used for configuration exemptions, bypassing connection tracking.

Each table contains multiple chains, such as INPUT, OUTPUT, and FORWARD, where rules are defined and applied.


Common iptables Commands

Below are some essential iptables commands to get started:

1. Viewing Current Rules

sudo iptables -L -v -n

This displays all current rules in verbose mode, showing details like packet and byte counts.

2. Adding Rules

To allow traffic on port 80 (HTTP):

sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
  • -A INPUT: Appends a rule to the INPUT chain.
  • -p tcp: Specifies the protocol.
  • --dport 80: Matches destination port 80.
  • -j ACCEPT: Allows the packet.

3. Deleting Rules

To delete a specific rule by its line number:

sudo iptables -D INPUT <line-number>

4. Blocking Traffic

To block all traffic from a specific IP:

sudo iptables -A INPUT -s 192.168.1.100 -j DROP

5. Saving and Restoring Rules

Save rules to a file:

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

Restore rules from a file:

sudo iptables-restore < /etc/iptables/rules.v4

Simulating Network Scenarios for Testing

One of the most exciting uses of iptables is simulating network conditions to test application behavior. Here are a few scenarios you can simulate:

1. Simulating Network Latency

Introduce a delay in packet processing to mimic high-latency networks:

sudo tc qdisc add dev eth0 root netem delay 200ms
  • tc qdisc: Traffic control command.
  • netem delay 200ms: Adds a 200ms delay.

To remove the rule:

sudo tc qdisc del dev eth0 root netem

2. Blocking Specific IPs or Subnets

To test how your application handles denial of service from a particular IP:

sudo iptables -A INPUT -s 203.0.113.0/24 -j DROP

3. Simulating Network Disconnection

Block all outbound traffic:

sudo iptables -A OUTPUT -j DROP

Restore connectivity:

sudo iptables -D OUTPUT -j DROP

4. Simulating Port Unavailability

Prevent access to a specific port, such as 22 (SSH):

sudo iptables -A INPUT -p tcp --dport 22 -j REJECT

5. Testing Connection Timeouts

Drop packets randomly to simulate an unstable connection:

sudo iptables -A INPUT -m statistic --mode random --probability 0.5 -j DROP
  • --probability 0.5: Drops approximately 50% of packets.

6. Rate Limiting Connections

To simulate limited bandwidth or prevent DDoS attacks by limiting the number of connections per second:

sudo iptables -A INPUT -p tcp --dport 80 -m limit --limit 10/second --limit-burst 20 -j ACCEPT
  • --limit 10/second: Allows 10 connections per second.
  • --limit-burst 20: Allows up to 20 connections initially.

7. Redirecting Traffic

Test application behavior when traffic is redirected to another destination:

sudo iptables -t nat -A PREROUTING -p tcp --dport 8080 -j REDIRECT --to-port 9090
  • -t nat: Specifies the NAT table.
  • PREROUTING: Alters packets before routing decisions.
  • --to-port 9090: Redirects to port 9090.

8. Simulating Packet Corruption

Introduce packet corruption to test robustness:

sudo tc qdisc add dev eth0 root netem corrupt 5%
  • corrupt 5%: Corrupts 5% of packets.

To remove the rule:

sudo tc qdisc del dev eth0 root netem

9. Delaying DNS Resolution

Simulate slow DNS resolution by blocking traffic to a DNS server temporarily:

sudo iptables -A OUTPUT -p udp --dport 53 -j DROP

Restore DNS resolution:

sudo iptables -D OUTPUT -p udp --dport 53 -j DROP

10. Load Balancing Simulation

Simulate load balancing by redirecting traffic to multiple backend servers:

sudo iptables -t nat -A PREROUTING -p tcp --dport 8080 -m statistic --mode random --probability 0.5 -j DNAT --to-destination 192.168.1.2:8080
sudo iptables -t nat -A PREROUTING -p tcp --dport 8080 -j DNAT --to-destination 192.168.1.3:8080

Advanced Firewall Rules and Use Cases

1. Setting Default Policies

To drop all incoming traffic by default and allow only specified traffic:

sudo iptables -P INPUT DROP
sudo iptables -P FORWARD DROP
sudo iptables -P OUTPUT ACCEPT
  • Use specific rules to allow necessary traffic, such as SSH:
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT

2. Logging Dropped Packets

To log all dropped packets for monitoring:

sudo iptables -A INPUT -j LOG --log-prefix "Dropped Packet: " --log-level 4
sudo iptables -A INPUT -j DROP

3. NAT and Port Forwarding

Forward traffic from port 8080 to an internal service on port 80:

sudo iptables -t nat -A PREROUTING -p tcp --dport 8080 -j DNAT --to-destination 192.168.1.100:80
sudo iptables -A FORWARD -p tcp --dport 80 -d 192.168.1.100 -j ACCEPT

4. Restricting Traffic by MAC Address

Allow traffic only from specific MAC addresses:

sudo iptables -A INPUT -m mac --mac-source 00:11:22:33:44:55 -j ACCEPT

Block others:

sudo iptables -A INPUT -j DROP

5. Stateful Firewall Rules

Allow established and related connections to pass:

sudo iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

Firewall Rules for Common Services

Service: SSH

Allowing All Incoming SSH

To allow all incoming SSH connections run these commands:

sudo iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
sudo iptables -A OUTPUT -p tcp --sport 22 -m conntrack --ctstate ESTABLISHED -j ACCEPT

The second command, which allows the outgoing traffic of established SSH connections, is only necessary if the OUTPUT policy is not set to ACCEPT.

Allowing Incoming SSH from Specific IP address or Subnet

To allow incoming SSH connections from a specific IP address or subnet, specify the source. For example, if you want to allow the entire 203.0.113.0/24 subnet, run these commands:

sudo iptables -A INPUT -p tcp -s 203.0.113.0/24 --dport 22 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
sudo iptables -A OUTPUT -p tcp --sport 22 -m conntrack --ctstate ESTABLISHED -j ACCEPT

The second command, which allows the outgoing traffic of established SSH connections, is only necessary if the OUTPUT policy is not set to ACCEPT.

Allowing Outgoing SSH

If your firewall OUTPUT policy is not set to ACCEPT, and you want to allow outgoing SSH connections—your server initiating an SSH connection to another server—you can run these commands:

sudo iptables -A OUTPUT -p tcp --dport 22 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
sudo iptables -A INPUT -p tcp --sport 22 -m conntrack --ctstate ESTABLISHED -j ACCEPT

Allowing Incoming Rsync from Specific IP Address or Subnet

Rsync, which runs on port 873, can be used to transfer files from one computer to another.

To allow incoming rsync connections from a specific IP address or subnet, specify the source IP address and the destination port. For example, if you want to allow the entire 203.0.113.0/24 subnet to be able to rsync to your server, run these commands:

sudo iptables -A INPUT -p tcp -s 203.0.113.0/24 --dport 873 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
sudo iptables -A OUTPUT -p tcp --sport 873 -m conntrack --ctstate ESTABLISHED -j ACCEPT

The second command, which allows the outgoing traffic of established rsync connections, is only necessary if the OUTPUT policy is not set to ACCEPT.

Service: Web Server

Allowing All Incoming HTTP

To allow all incoming HTTP (port 80) connections run these commands:

sudo iptables -A INPUT -p tcp --dport 80 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
sudo iptables -A OUTPUT -p tcp --sport 80 -m conntrack