The primary use of iptables is as a host-based software firewall. It intercepts network traffic and applies filters to it, deciding what to permit, and what to deny. Iptables is very flexbile, but in its most common configuration it is used to simply filter incoming connections based on source, destination, protocol and port. In other functions, it is used to log traffic, filter outgoing connections, masquerade IP addresses for NAT and limit traffic rates. It is indispensable for maintaining the security of a server, but there’s other things its functions can be used for – simulating application failures.
It’s a relatively common testing scenario – you want to find out what happens when a service or resource becomes unavailable, and want to see how other applications handle this. For example, if your MySQL database goes down, what will Tomcat do? You could simulate this by shutting down the database, but if there are other nodes in the cluster, or other users accessing the database, this may not be possible.
A nice simple solution is to make an ad ad hoc addition to the iptables on the server that is noticing the failure. In the Tomcat/MySQL example, this will be a change to the application host running Tomcat. Since it’s attempting a connection to the MySQL database on port 3306, all that you need to do is configure iptables to block outgoing traffic with a destination port of 3306. Like this:
# iptables -A OUTPUT -p tcp --dport 3306 -j DROP
Check that the iptables ruleset has been updated with:
# iptables -L -n Chain INPUT (policy ACCEPT) target prot opt source destination RH-Firewall-1-INPUT all -- 0.0.0.0/0 0.0.0.0/0 Chain FORWARD (policy ACCEPT) target prot opt source destination RH-Firewall-1-INPUT all -- 0.0.0.0/0 0.0.0.0/0 Chain OUTPUT (policy ACCEPT) target prot opt source destination DROP tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:3306 <<====== This line here has been added Chain RH-Firewall-1-INPUT (2 references) target prot opt source destination ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0 icmp type 255 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:22 /* SSH */ ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:80 /* http */ ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:8080 /* tomcat */ REJECT all -- 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited
This will have the effect of intercepting all outbound traffic heading to port 3306 on any destination host, and dropping it outright. The application will be unable to reach the database, although all other hosts will have no interruption of service.
One your testing is complete, you can undo the previous command by simply replacing the "-A" option ("append") with "-D" ("delete"):
# iptables -D OUTPUT -p tcp --dport 3306 -j DROP
There are many other ways of using this technique. You could block a hosts ability to use DNS (UDP, port 53):
# iptables -A OUTPUT -p udp --dport 53 -j DROP
Prevent a host from accessing Internet websites (HTTP, port 80 and 443):
# iptables -A OUTPUT -p tcp --dport 80 -j DROP # iptables -A OUTPUT -p tcp --dport 443 -j DROP
Or block a host from reaching anything that isn't a private local address, by using the negation operator ("!"):
# iptables -A OUTPUT -d ! 10.0.0.0/8 -j DROP
Which will look like this:
Chain OUTPUT (policy ACCEPT) target prot opt source destination DROP all -- 0.0.0.0/0 !10.0.0.0/8
This method could be use for testing monitoring, to force an automated cluster failover, or to eliminate extra traffic when tracing a bug.
The iptables command can be used as a powerful tool for exercising very fine-grained control over your host networking. A site-wide network catastrophe can effectively be locally simulated with one simple trouble-free command. Write it down.
Matt Parsons is a freelance Linux specialist who has designed, built and supported Unix and Linux systems in the finance, telecommunications and media industries.
He lives and works in London.