- You have to ensure you don’t accidentally DOS your server w/ tarpit traffic
- You have to ensure you fill up your state tables w/ tarpitted connection info
- You have to ensure you don’t flood your logs with tarpit connection information
- You need to ensure a long blacklist doesn’t affect performance
- You need to ensure that your blacklist automatically expires hosts
- You need the ability to whitelist hosts (either permanently or with time-limit)
Thankfully this is all possible, and quite easy using regular iptables and ipset.
Limiting TARPIT resource usage
You can use iptables to limit how many hosts you TARPIT without using too many system resources. See example below. This includes network bandwidth, system memory, state stable entries, and other system resources. Get too many tarpitted connections, start ignoring them. If you organize your rule set in the correct order, none of the tarpitted connections end up on your state tables. Also make sure you don’t log, unless you’re doing realtime stats with something like a custom ulog — Direct iptables tarpit logs can quickly fill up a disk.
In my experience my current hosts can easily hold 200+ hosts in a tarpit, with little noticeable effect on memory usage, traffic usage, or cpu usage. Likely I could push this further, but so far on average I’m only trapping around 130 hosts at any given moment.
The reason why I implemented the limits, was as stated in another suggestion, because my first tarpit host became flooded. This was a trivial workaround. I’ve had no issues since.
Using ipset for efficient blacklists
ipset is an great little tool that allows you to create groups of objects to use in iptables rules. Not only that, but since it can hold the objects in a hash table, the larger the ipset the faster it is compared to the equivalent linear set of iptables rules.
In addition to that, the lists can include counters (packets/bytes), timeout, and exclusion on a per object basis.
You can add/remove from ipset with most programs that automatically block, such as fail2ban, ossec, and more. Because you can set a default timeout, you can ensure that entries are expired regardless what program set the entry.
Here’s an example based on what I use on servers I manage that mitigates the risks listed above:
### Note: This does not account for all possible traffic you might need or want ### This is only an example of mitigating common risks of using a tarpit ### Use at your own risk
# Create the ipset blacklist # options: # - create : create a new ipset # - blacklist : Name of the ipset we'll reference in the iptables rule # - hash:net : Make blacklist type hash to hold network (ip/mask) data # - family inet : This is for IPv4 data (inet6 for IPv6) # - counters : We want packet/byte stats counted for each entry # - comment : So we can add a comment with each entry (handy) # - timeout 604800 : Set a default timeout of 604800 seconds (1 week) for each new entry # - nomatch : Allow us to enter exclusion entries (never match an entry) ipset create blacklist hash:net family inet counters comment timeout 604800 nomatch # Create an entry to never blacklist a trusted network # options: # - timeout 0 : entry never expires # - nomatch : Tells IPset to never match this entry (whitelist, in our usage) ipset add blacklist 22.214.171.124/24 comment "Trusted subnet, causes breakage if blocked" timeout 0 nomatch # Example to blacklist hosts # no netmask implies /32 (or /128 for ipv6) ipset add blacklist 126.96.36.199 comment "SSH Bruteforce" ipset add blacklist 188.8.131.52 comment "SQL Injection" timeout 12345 # etc...
# Flush the input table iptables -F INPUT # Drop the custom flow TAR iptables -X TAR # Set default INPUT policy to DROP iptables -P INPUT DROP # Create the chain TAR iptables -N TAR # Send all blacklisted hosts to the tarpit iptables -A INPUT -m set --match-set blacklist src -j TAR # Allow established connections # Note: after the blacklist so newly blacklisted threats are immediately ignored # Yes, that will cause the server to hold the state open until it times out. # Would you rather have a malicious host continuing its attack? iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT # Allow the services we want # Note: These create new state table entries/use up memory # Note: We do not account for synflood prevention in this example iptables -A INPUT -p tcp -m multiport --dports 22,80,443 -m tcp --syn -m conntrack --ctstate NEW -j ACCEPT iptables -A INPUT -p icmp -m icmp --icmp-type 8 -m conntrack --ctstate NEW -j ACCEPT # Send everything else to tarpit chain iptables -A INPUT -j TAR # This is the tarpit chain # Tarpit up to 10 unique connections a second, any more, and pass to next rule # Note: 10/s limit is arbitrary, adjust to your preference (experiment) iptables -A TAR -p tcp -m limit --limit 10/sec -j TARPIT --tarpit # Drop everything else that makes it this far # You can also set to REJECT which will immediately tell all connections to buzz off iptables -A TAR -j DROP
Looking at trapped hosts realtime
$ sudo tcpdump -npi eth0 'src YOUR.HOST.IP and (tcp = 0 && tcp = 0)'