Optimal iptables Ruleset for CentOS 5.4 Web Server: Secure SSH, FTP, Apache, and MySQL Configuration


2 views

When setting up iptables for a CentOS 5.4 web server, we need to follow the principle of least privilege while maintaining necessary functionality. The default policy should be restrictive, only opening required ports for services like SSH, FTP, HTTP/HTTPS, and MySQL.

# Set default policies
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT

# Allow established connections
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# Allow loopback interface
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

For your web server with FTP, Apache, SSH, and MySQL, we need to add specific rules:

# SSH (consider changing from default port 22)
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -j ACCEPT

# FTP (active and passive modes)
iptables -A INPUT -p tcp --dport 21 -m state --state NEW -j ACCEPT
iptables -A INPUT -p tcp --dport 20 -m state --state NEW -j ACCEPT
iptables -A INPUT -p tcp --dport 60000:61000 -m state --state NEW -j ACCEPT  # Passive mode range

# HTTP/HTTPS
iptables -A INPUT -p tcp --dport 80 -m state --state NEW -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -m state --state NEW -j ACCEPT

# MySQL (limit to internal network if possible)
iptables -A INPUT -p tcp --dport 3306 -s 192.168.1.0/24 -m state --state NEW -j ACCEPT

Controlled ICMP access is important for network diagnostics:

# Essential ICMP types
iptables -A INPUT -p icmp --icmp-type echo-request -m limit --limit 1/second -j ACCEPT
iptables -A INPUT -p icmp --icmp-type destination-unreachable -j ACCEPT
iptables -A INPUT -p icmp --icmp-type time-exceeded -j ACCEPT
iptables -A INPUT -p icmp --icmp-type parameter-problem -j ACCEPT

The rule iptables -A INPUT -p tcp --dport domain -i eth0 -j ACCEPT refers to DNS traffic (port 53). This is only needed if your server is acting as a DNS resolver. For a typical web server, you only need OUTBOUND DNS for package updates and domain resolution.

Consider adding these security measures:

# Protection against common attacks
iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP  # NULL packets
iptables -A INPUT -p tcp ! --syn -m state --state NEW -j DROP  # SYN flood
iptables -A INPUT -p tcp --tcp-flags ALL ALL -j DROP  # XMAS packets
iptables -A INPUT -m connlimit --connlimit-above 50 -j DROP  # Connection limiting

For CentOS 5.4, save your rules permanently with:

service iptables save
chkconfig iptables on

This will create the /etc/sysconfig/iptables file and ensure rules persist after reboot.


When configuring a fresh CentOS 5.4 server, your initial iptables rules should implement a default-deny policy:

# Set default policies
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT

Always allow established connections to maintain session continuity:

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

For a web server with FTP, Apache, SSH and MySQL, these are the minimum required rules:

# SSH access
iptables -A INPUT -p tcp --dport 22 -j ACCEPT

# FTP services (active mode)
iptables -A INPUT -p tcp --dport 21 -j ACCEPT
iptables -A INPUT -p tcp --dport 20 -j ACCEPT

# Passive FTP ports range
iptables -A INPUT -p tcp --dport 50000:51000 -j ACCEPT

# Web services
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT

# MySQL access (restrict to localhost if possible)
iptables -A INPUT -p tcp --dport 3306 -s 127.0.0.1 -j ACCEPT

Don't forget these critical system-level allowances:

# Localhost interface
iptables -A INPUT -i lo -j ACCEPT

# ICMP (ping)
iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
iptables -A INPUT -p icmp --icmp-type destination-unreachable -j ACCEPT
iptables -A INPUT -p icmp --icmp-type time-exceeded -j ACCEPT

The rule you asked about handles DNS resolution:

iptables -A INPUT -p udp --dport 53 -j ACCEPT

This allows your server to receive DNS responses when resolving domain names. The original rule used 'domain' instead of port 53 - they are functionally equivalent.

# Rate limiting for SSH (prevent brute force)
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --set
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 4 -j DROP

# Log dropped packets
iptables -N LOGGING
iptables -A INPUT -j LOGGING
iptables -A LOGGING -m limit --limit 2/min -j LOG --log-prefix "IPTables-Dropped: " --log-level 4
iptables -A LOGGING -j DROP

Here's a complete ruleset you can save in /etc/sysconfig/iptables:

*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
:LOGGING - [0:0]

# Connection tracking
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# Services
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 21 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 20 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 50000:51000 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 443 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 3306 -s 127.0.0.1 -j ACCEPT

# System
-A INPUT -i lo -j ACCEPT
-A INPUT -p icmp --icmp-type echo-request -j ACCEPT
-A INPUT -p icmp --icmp-type destination-unreachable -j ACCEPT
-A INPUT -p icmp --icmp-type time-exceeded -j ACCEPT

# Security
-A INPUT -p tcp -m tcp --dport 22 -m state --state NEW -m recent --set
-A INPUT -p tcp -m tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 4 -j DROP

# Logging
-A INPUT -j LOGGING
-A LOGGING -m limit --limit 2/min -j LOG --log-prefix "IPTables-Dropped: " --log-level 4
-A LOGGING -j DROP

COMMIT