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.

# 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 -d -j ACCEPT
iptables -A INPUT -s -d -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

# 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 {
  rotate 7
  size 25M
  maxage 30
      invoke-rc.d rsyslog reload > /dev/null