When managing server security, we often need to temporarily block malicious IP addresses rather than permanently banning them. A common challenge is that standard iptables rules don't include built-in expiration functionality, leaving admins to manually remove bans or implement complex workarounds.
The recent
module in iptables provides exactly what we need. Here's the basic syntax:
# Block an IP for 1 hour (3600 seconds) iptables -A INPUT -p tcp --dport 22 -m recent --name SSH --set iptables -A INPUT -p tcp --dport 22 -m recent --name SSH --update --seconds 3600 --hitcount 3 -j DROP
This example blocks IPs that attempt more than 3 SSH connections within an hour.
For more dynamic control, you can combine this with a custom chain:
# Create a custom chain iptables -N TEMPBAN # Add temporary ban rules iptables -A TEMPBAN -m recent --name BADGUYS --set iptables -A TEMPBAN -j DROP # Main rule that uses the tempban iptables -A INPUT -p tcp --dport 80 -m recent --name BADGUYS --rcheck --seconds 86400 -j DROP iptables -A INPUT -p tcp --dport 80 -m connlimit --connlimit-above 50 -j TEMPBAN
This configuration bans IPs making more than 50 HTTP connections for 24 hours (86400 seconds).
For complete automation, consider adding a cron job to flush old entries:
# Add to crontab (runs every hour) 0 * * * * /sbin/iptables -D INPUT -m recent --name BADGUYS --remove
Check active bans with:
cat /proc/net/xt_recent/BADGUYS
This shows currently banned IPs and their timestamps.
For more flexibility, ipset offers direct timeout support:
# Create ipset with timeout ipset create tempban hash:ip timeout 3600 # Add to iptables iptables -A INPUT -m set --match-set tempban src -j DROP # Add banned IP (will auto-expire after 1 hour) ipset add tempban 192.168.1.100
- Timeout values are in seconds (3600 = 1 hour)
- The recent module has a default limit of 100 entries (adjustable via /proc)
- Rules are not persistent across reboots without saving
Many sysadmins face situations where they need to temporarily block malicious IP addresses - whether due to brute force attempts, scraping, or DDoS patterns. While iptables doesn't natively support rule expiration, we can achieve this through creative solutions.
The most elegant solution leverages iptables' time module (available since Linux 2.6.38):
iptables -A INPUT -s 192.168.1.100 -m time --timestart 14:00 --timestop 15:00 -j DROP
This automatically removes the block after the specified time window. For more precision, add date parameters:
iptables -A INPUT -s 192.168.1.100 -m time --datestart 2023-07-15 --datestop 2023-07-16 -j DROP
For systems without the time module, create paired cron jobs:
# Block IP at 14:00
0 14 * * * /sbin/iptables -A INPUT -s 192.168.1.100 -j DROP
# Unblock IP at 15:00
0 15 * * * /sbin/iptables -D INPUT -s 192.168.1.100 -j DROP
For dynamic IP management, implement a database-backed solution:
#!/bin/bash
# ban_management.sh
# Add new ban
add_ban() {
iptables -A INPUT -s $1 -j DROP
echo "$(date +%s) $1" >> /var/log/iptables_bans
}
# Check expirations
check_bans() {
now=$(date +%s)
while read line; do
ban_time=$(echo $line | awk '{print $1}')
ip=$(echo $line | awk '{print $2}')
if (( now - ban_time > 3600 )); then # 1 hour expiration
iptables -D INPUT -s $ip -j DROP
sed -i "/$ip/d" /var/log/iptables_bans
fi
done < /var/log/iptables_bans
}
Run this script periodically via cron for automatic cleanups.
For production systems, consider:
- Using ipset for better performance with large rule sets
- Implementing fail2ban with custom actions
- Logging all temporary blocks for audit trails
- Setting up monitoring for rule effectiveness