Basic iptables Configuration

It’s always a good idea to setup a local firewall on hosts that are on unprotected networks. The internet “winds” blow harder and harder each day, and it’s only a matter of time before some daemon has an exploit that gets taken advantage of. I use CentOS 5 for all my web servers, and here is an example of the script I use to create a DEFAULT TO DENY set of firewall rules. This script generates a file called iptables in /etc/sysconfig.

I used to create a special rule for MySQL that only allowed connections from my own network, but lately I have been omitting this rule and tunneling the connection through ssh instead. That is why it is commented out in the script below.


### SCRIPT ###
#!/bin/sh
# Drop all incoming traffic
/sbin/iptables -P INPUT DROP
# Drop all forwarded traffic
/sbin/iptables -P FORWARD DROP
# Allow all outgoing traffic
/sbin/iptables -P OUTPUT ACCEPT
# Allow returning packets
/sbin/iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
# Allow incoming traffic on port 80 for web server
/sbin/iptables -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
# Allow MySQL only from a certain network
/sbin/iptables -A INPUT -p tcp -m tcp -s XXX.XXX.XXX.0/24 --dport 3306 -j ACCEPT
# Allow local traffic
/sbin/iptables -A INPUT -i lo -j ACCEPT
# Allow incoming SSH on port 22
#/sbin/iptables -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
# Allow ping
/sbin/iptables -A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT
/sbin/iptables-save > /etc/sysconfig/iptables
chmod go-r /etc/sysconfig/iptables
/sbin/sudo service iptables restart
### /SCRIPT ###

Here is what /etc/sysconfig/iptables looks like after running this script:


# Generated by iptables-save v1.3.5 on Wed Dec 31 13:47:40 2008
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [12:8972]
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 3306 -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT
COMMIT
# Completed on Wed Dec 31 13:47:40 2008

After you are done, make sure you have iptables setup to start when the system boots.


# /sbin/chkconfig --list | grep iptables

iptables       	0:off	1:off	2:on	3:on	4:on	5:on	6:off

If it’s not on, just run:

/sbin/chkconfig iptables on

Disable SSH Root Logins on RHEL

For one reason or another RHEL does not disallow incoming ssh connections as root. This is, of course a glaring security problem which should be addressed for all systems that allow ssh connections to be made from any but the most restricted networks.

The best practice, of course, would be to make the initial ssh connection as an unprivileged user and then use the “su” command to promote yourself to root. This way, even if an attacker managed to get into the system, it would be as an unprivileged user and they would not able to do much harm. Allowing incoming ssh connections at root leaves you much more exposed to attack. Granted your root password is still protecting you, but it becomes your only layer of defense.

Ok, so how do we disallow incoming ssh connections as root on our RHEL box?

First, edit “/etc/ssh/sshd_config”

Find the section of the file that looks like this:

# Authentication:
#LoginGraceTime 2m
#PermitRootLogin yes
#StrictModes yes
#MaxAuthTries 6

Change this line:
#PermitRootLogin yes

To this:
PermitRootLogin no

Restart sshd:
/sbin/service sshd restart

MySQL Connection Over an ssl Tunnel

Rather than leave MySQL open to the world, consider firewalling it off and tunneling a connection over ssh.

This command will allow you to connect to your MySQL server on hostname.domain.com on localhost:7777.

ssh -L7777:127.0.0.1:3306 user@hostname.domain.com