This post provides a guide to configuring iptables.
Servers are constantly running and exposing services, which makes them susceptible to security risks. Unauthorized access can lead to system takeover, allowing attackers to use the server as a launching pad for further attacks or to leak private data. Therefore, implementing robust security measures is essential.
One effective security measure is to use iptables, a packet filtering firewall, to restrict access to unnecessary ports, ensuring that only the required services remain accessible.
Installing iptables #
On most Linux distributions, iptables comes pre-installed, so no additional installation steps are required.
Configuring iptables #
iptables rules are typically added through command-line inputs, but keeping track of changes can be challenging. To simplify management, a configuration script can be used to register all rules in bulk.
Creating the iptables Configuration Script #
The following script, iptables.sh
, sets up iptables with essential security configurations.
#!/bin/bash
#####################################
# Pre-Processing
#####################################
# Stop iptables service
systemctl stop iptables.service
# Reset rules
echo "" > /etc/iptables/iptables.rules
#####################################
# Basic configuration
#####################################
# Set default policies
iptables -P INPUT DROP
iptables -P OUTPUT ACCEPT
iptables -P FORWARD DROP
# Allow localhost access
iptables -A INPUT -i lo -j ACCEPT
# Allow established connections
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
########################################
# Attack Mitigation
########################################
# TCP SYN Flood attack mitigation
sysctl -w net.ipv4.tcp_syncookies=1 > /dev/null
sed -i '/net.ipv4.tcp_syncookies/d' /etc/sysctl.d/99-sysctl.conf
echo "net.ipv4.tcp_syncookies=1" >> /etc/sysctl.d/99-sysctl.conf
# Smurf attack mitigation
sysctl -w net.ipv4.icmp_echo_ignore_broadcasts=1 > /dev/null
sed -i '/net.ipv4.icmp_echo_ignore_broadcasts/d' /etc/sysctl.d/99-sysctl.conf
echo "net.ipv4.icmp_echo_ignore_broadcasts=1" >> /etc/sysctl.d/99-sysctl.conf
# Disable sending ICMP Redirect packets
sed -i '/net.ipv4.conf.*.send_redirects/d' /etc/sysctl.d/99-sysctl.conf
for dev in `ls /proc/sys/net/ipv4/conf/`
do
sysctl -w net.ipv4.conf.$dev.send_redirects=0 > /dev/null
echo "net.ipv4.conf.$dev.send_redirects=0" >> /etc/sysctl.d/99-sysctl.conf
done
# Reject ICMP Redirect packets
sed -i '/net.ipv4.conf.*.accept_redirects/d' /etc/sysctl.d/99-sysctl.conf
for dev in `ls /proc/sys/net/ipv4/conf/`
do
sysctl -w net.ipv4.conf.$dev.accept_redirects=0 > /dev/null
echo "net.ipv4.conf.$dev.accept_redirects=0" >> /etc/sysctl.d/99-sysctl.conf
done
# Reject Source Routed packets
sed -i '/net.ipv4.conf.*.accept_source_route/d' /etc/sysctl.d/99-sysctl.conf
for dev in `ls /proc/sys/net/ipv4/conf/`
do
sysctl -w net.ipv4.conf.$dev.accept_source_route=0 > /dev/null
echo "net.ipv4.conf.$dev.accept_source_route=0" >> /etc/sysctl.conf
done
# Log and drop fragmented packets
iptables -A INPUT -f -j LOG --log-prefix '[IPTABLES FRAGMENT] : '
iptables -A INPUT -f -j DROP
# Drop NetBIOS-related traffic
iptables -A INPUT -p tcp -m multiport --dports 135,137,138,139 -j DROP
iptables -A INPUT -p udp -m multiport --dports 135,137,138,139 -j DROP
iptables -A OUTPUT -p tcp -m multiport --sports 135,137,138,139 -j DROP
iptables -A OUTPUT -p udp -m multiport --sports 135,137,138,139 -j DROP
# Ping of Death attack mitigation
iptables -N LOG_PINGDEATH
iptables -A LOG_PINGDEATH -m limit --limit 1/s --limit-burst 4 -j ACCEPT
iptables -A LOG_PINGDEATH -j LOG --log-prefix '[IPTABLES PINGDEATH] : '
iptables -A LOG_PINGDEATH -j DROP
iptables -A INPUT -p icmp --icmp-type echo-request -j LOG_PINGDEATH
# Drop packets sent to broadcast or multicast addresses
iptables -A INPUT -d 255.255.255.255 -j DROP
iptables -A INPUT -d 224.0.0.1 -j DROP
# Reject IDENT requests on port 113 (to prevent email server response delays)
iptables -A INPUT -p tcp --dport 113 -j REJECT --reject-with tcp-reset
######################################
# Service-Specific Rules
######################################
# SSH: The default SSH listening port is 22, but if changed, update the dport value accordingly. Here, port 50134 is used.
iptables -A INPUT -p tcp --dport 50134 -j ACCEPT
######################################
# Additional Rules
######################################
# Log and drop any traffic that does not match the above rules
iptables -A INPUT -m limit --limit 1/s -j LOG --log-prefix '[IPTABLES INPUT] : '
iptables -A INPUT -j DROP
iptables -A FORWARD -m limit --limit 1/s -j LOG --log-prefix '[IPTABLES FORWARD] : '
iptables -A FORWARD -j DROP
######################################
# Post-Processing
######################################
# Save rules to ensure they persist after server reboots
iptables-save > /etc/iptables/iptables.rules
# Restart iptables service
systemctl restart iptables.service
Executing the Configuration Script #
Run the script using the following command:
sudo sh iptables.sh
If an error like the following occurs:
iptables v1.6.2: can't initialize iptables table `filter': Table does not exist (do you need to insmod?)
Perhaps iptables or your kernel needs to be upgraded.
Restart the server and rerun the script. If the issue persists, reinstall iptables and restart the system.
Enabling iptables #
To ensure that iptables starts at boot, enable the service with the following command:
sudo systemctl enable iptables
Conclusion #
The configuration allows only SSH while blocking unnecessary access. If additional services are required, update the script accordingly.