IPTables for CentOS

Whenever you get a new RedHat or CentOS instance you want to secure it by setting up firewall rules using the builtin in iptables . If you spinoff an Amazon EC2 instance then you’d be doing the equivalent using Security Groups, which are a slightly higher level concept but essentially performs the same function. If running a VPS on barebones CentOS, iptables is the easiest option.

Word of Caution: Its easy to lock yourself out of the system if you make a mistake when configuring iptables. I prefer writing all the rules in a script file, double checking the commands to make sure I’m not closing SSH on port 22. Also, its a good idea to remain logged in the current SSH shell after executing iptables rules and then attempt to login in a new SSH shell to ensure you still have access to the server.

Here’s the outline of what we’ll do:

  1. create file iptables_setup.sh
  2. execute file iptables_setup.sh
  3. setup rsyslog using iptables.conf
  4. setup log rotation for iptables.log

Here’s the iptables_setup.sh file that you can create in your home directory and execute once to setup iptables and save these rules so that system reloads these rules on server reboot.

#!/bin/bash
# File: /home/my-user/iptables_setup.sh

# Flush all current nat rules
iptables -t nat -F

# Flush all current rules from iptables
iptables -F

# Set access for localhost
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -s 127.0.0.1 -d 127.0.0.1 -j ACCEPT
iptables -A INPUT -s 127.0.0.1 -d 127.0.0.1 -j ACCEPT

# Accept packets belonging to established and related connections
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# Secure SSH on port 22 and prevent repeated login attempts. If someone tries to connect
# 4 or more times on port 22 within 300secs, drop all packets from that host. As soon as
# 300secs have elapsed between connection attempts, iptables will forget the host and it
# will be allowed to try and connect again.
#   1. Remote host addr of all connects on port 22 is logged to temporary list
#   2. Create a new chain LOGDROP
#   3. If host addr exists in temporary list, has 4 or more hits within 300secs jump to LOGDROP
#   4. All remaining connects can proceed and accept SSH connection
#   5. For LOGDROP chain pass packets to logging facility, prefix "iptables deny: " to msg
#   6. For LOGDROP chain drop the packets
iptables -A INPUT -p tcp -m tcp --dport 22 -m state --state NEW -m recent --set --name DEFAULT --rsource
iptables -N LOGDROP
iptables -A INPUT -p tcp -m tcp --dport 22 -m state --state NEW -m recent --update --seconds 300 --hitcount 4 --name DEFAULT --rsource -j LOGDROP
iptables -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
iptables -A LOGDROP -j LOG --log-prefix "iptables deny: " --log-level 4
iptables -A LOGDROP -j DROP

# Lock down the system
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT

# Open DNS and HTTP ports
iptables -A INPUT -p tcp -m tcp --dport 53   -j ACCEPT
iptables -A INPUT -p udp -m udp --dport 53   -j ACCEPT
iptables -A INPUT -p tcp -m tcp --dport 80   -j ACCEPT
iptables -A INPUT -p tcp -m tcp --dport 443  -j ACCEPT

# Save settings
service iptables save

# List rules
iptables -L -v

The following iptables.conf file defines the message format and content for iptables.log

# File: /etc/rsyslog.d/iptables.conf

:msg,contains,"iptables deny:" /var/log/iptables.log
& ~

The following file defines the log rotation policy and frequency for iptables.log

# File: /etc/logrotate.d/iptables

/var/log/iptables.log {
  daily
  missingok
  notifempty
  rotate 7
  size 25M
  delaycompress
  dateext
  maxage 30
  postrotate
      invoke-rc.d rsyslog reload > /dev/null
  endscript
}