### 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 ##########