### Safety net
iptables -A INPUT -s 74.120.219.79 -j ACCEPT
iptables -A OUTPUT -s 74.120.219.79 -j ACCEPT
iptables -A FORWARD -s 74.120.219.79 -j ACCEPT
###
# Lists of IP addresses:
# ips used whenever a flood is detected. if an IP in this list sends too many packets...
# banned used to block packets from listed IPs for a period of time. after that...
# unbanned used to keep recently unbanned IPs from getting back in if the flood is still going
###
###
# Chains:
# flood-detected triggered if the token bucket empties
# ban-flooder if an IP in the ips list sends too many packets
# check-unban triggered when we get a packet from someone in the banned list
###
###
# init
###
iptables -N flood-detected
iptables -N ban-flooder
iptables -P ban-flooder DROP
iptables -N check-unban
###
# CHAIN INPUT: main flood-protect rules
###
# See if our IP is banned (should be the first rule in the INPUT chain after the ACCEPTs for admin IPs)
iptables -A INPUT -m recent --name banned --check -j check-unban
# Check for single-host floods (on all ports, why not?). Dumps a file in /proc/net/ipt_hashlimit/lolichan.
# Reaps unused buckets once per second (-gcinterval). This means on average an unused bucket will
# go 500ms before being reaped.
# Assume: 500 max httpd processes, 1 per bucket (-size).
# Assume: 2.5 seconds maximum to complete an http transaction.
# Calculate: max # buckets = 500 * 2.5 = 1250 (-max). If the site starts slowing down, this will limit
# the number of new connections allowed, since they won't be able to find buckets.
# Calculate: expire time = 2500ms (page wait) - 500ms (delay before reaping) = 2000ms (-expire). If
# someone hasn't connected in 2 seconds, expire their bucket and give another IP a chance.
iptables -A INPUT -p tcp -m hashlimit --hashlimit-name lolichan --hashlimit-mode srcip --hashlimit-htable-size 500 --hashlimit-htable-max 1250 --hashlimit-htable-expire 2000 --hashlimit-htable-gcinterval 1000 ! --hashlimit 20/sec -j ban-flooder
# Install the token bucket on port 80 and detect DDOS floods
iptables -A INPUT -p tcp --dport 80 -m limit --limit-burst 500 ! --limit 200/second -j flood-detected
# We're under the limit, clear the unban list on this guy. NO JUMP TARGET: this will never match
iptables -A INPUT -m recent --name unbanned --check ! --remove
###
# CHAIN check-unban: see if this IP hasn't contacted us in awhile
###
# If it hasn't been an hour, DROP. Note that there are only 2 rules to run for banned IPs!
iptables -A check-unban -m recent --name banned --check ! --seconds 3600 -j DROP
# OK, let him out of the shitcan and RETURN to the INPUT chain (where he still might get a DROP)
iptables -A check-unban -m recent --name unbanned --set --name banned --remove -j RETURN
###
# CHAIN ban-flooder: b& this IP.
###
# Move this loser from ips to banned. NO JUMP TARGET, use the chain policy (DROP)
iptables -A ban-flooder -m recent --name banned --set --name ips --remove
###
# CHAIN flood-detected: this chain activated only when a flood is encountered. IPs are tracked and b&.
###
# If this IP was just recently unbanned, DROP. This prevents just-unbanned IPs from getting
# back in while a flood is still going on.
iptables -A flood-detected -m recent --name unbanned --check -j DROP
# If we've seen this same IP X times in the last Y seconds, ban him
iptables -A flood-detected -m recent --name ips --check --hitcount X --seconds Y -j ban-flooder
# OK we haven't, update the guy in our list and RETURN
iptables -A flood-detected -m recent --name ips --update -j RETURN
# If we get here, this is the first packet we've seen from him. Create an entry in the list
iptables -A flood-detected -m recent --name ips --set -j RETURN
########## Rest of iptables script goes beneath here ##########