Simple iptables rules for a typical LAMP server

[Edit: I'm leaving this post up for historical reasons, but I've since modified the way I build my iptables firewalls—I typically add the rules I need from the command line one by one, then use CentOS's service iptables save command (available in CentOS > 6.2) to save the rules so they'll persist after a restart.]

I've seen a ton of iptables configurations on the Internet, and none of them really got to the heart of what I need to do for the majority of my LAMP-based web servers (hosted on Linode, HostGator, Hot Drupal, and elsewhere). For these servers, I just need a really simple set of rules that restricts all incoming traffic except for web (port 80/443 for http/https traffic), ssh (usually port 22), smtp (port 25), and icmp ping requests.

The script below (save it as 'firewall.bash', chmod u+x it to make it executable, and run it with $ sudo /path/to/firewall.bash, then test your server (access websites, log on to it from another Terminal session, ping it, etc., and make sure that's all working)):

<br />
#!/bin/bash<br />
#<br />
# Script to set up iptables firewall on a Linux machine.<br />
#<br />
# Drop spoofed packets.<br />
if [ -e /proc/sys/net/ipv4/conf/all/rp_filter ]<br />
then<br />
for filter in /proc/sys/net/ipv4/conf/*/rp_filter<br />
do<br />
echo 1 &gt; $filter<br />
done<br />
fi<br />
#<br />
# Remove all rules and chains<br />
/sbin/iptables -F<br />
/sbin/iptables -X<br />
#<br />
# Accept traffic from loopback interface (localhost)<br />
/sbin/iptables -A INPUT -i lo -j ACCEPT<br />
#<br />
# Accept SSH traffic (for administration)<br />
/sbin/iptables -A INPUT -p tcp --dport ssh -j ACCEPT<br />
#<br />
# Accept port traffic on ports 22, 25, 80, 443 (SSH, SMTP, Apache http/https)<br />
/sbin/iptables -A INPUT -p tcp -m multiport --destination-ports 22,25,80,443 -j ACCEPT<br />
#<br />
# Accept icmp ping requests<br />
/sbin/iptables -A INPUT -p icmp -j ACCEPT<br />
#<br />
# Allow established connections:<br />
/sbin/iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT<br />
#<br />
# Log EVERYTHING (ONLY for Debug)<br />
# /sbin/iptables -A INPUT -j LOG<br />
#<br />
# Uncomment to log the rest of the incoming messages (all of which are dropped)<br />
# with a maximum of 15 log entries per minute<br />
# /sbin/iptables -A INPUT -m limit --limit 15/minute -j LOG --log-level 7 --log-prefix "Dropped by firewall: "<br />
#<br />
# Drop all other traffic<br />
/sbin/iptables -A INPUT -j DROP<br />
/sbin/iptables -P FORWARD DROP<br />
#<br />
# End message<br />
echo " [End iptables rules setting]"<br />

Notes:

  • This script assumes iptables is located at /sbin/iptables. If it's not there, adjust the path accordingly.
  • Show your current iptables configuration by running $ sudo iptables -L
  • Flush your iptables configuration back to allowing any traffic, anywhere, by running the attached bash script (rename to flush_iptables.bash)

The comments should hopefully help explain everything that's going on here, but for a fuller explanation of iptables, read here. Note that I take no responsibility for the security of your server! Use at your own risk.