Hey socket, meet 'finger' !

I seem to have been using a tool called firehol since, well, pretty much forever. It's always worked well for me, but I've always had to spend time maintaining rules, blacklisting abusive IP addresses and keeping an eye out for potential port scans.

Recently however I've noticed some new features creeping in the kernel and sure enough, the firehol guys have made said features available in userland via some fairly straight-forward rules, and all of a sudden, Linux has a built-in IDS available pretty much off-the-bat! (Intrusion Detection System)

From my perspective, I'm interested in blocking traffic from sources I believe to be suspect and potentially abusive in one way or another, and I don't want to have to sit here watching log files 24x7 and manually adding blacklist rules to the ruleset. So, this is what my new firehol configuration looks like;

version 6

world="eth0"
local="<space separated list of my local IPS>"
ipset4 create whitelist hash:net
ipset4 add whitelist "$local"
iptrap4 trap src 86400 inface "${world}" proto tcp dport 22 \
    src not ipset:whitelist state NEW 
blacklist4 full inface "${world}" src ipset:trap except src ipset:whitelist

interface eth0 public
  ipv4 server  icmp    accept
  ipv4 server  https   accept 
  client  all  accept

interface vpn0 vpn
  policy accept

The new kernel feature that we're making use of is ipset, which allows you to build sets of IP's dynamically, then apply rules to those sets of IP's. So specifically, taking apart the iptrap line;

trap - the name of the iplist we're going to build
src - means were going to inspect the source address
86400 - means if we add the IP to the list, it'll stay for 24h
inface "${world}" - means we only consider traffic on "eth0"
proto tcp - TCP traffic only 
dport 22 - Only traffic on port 22 (i.e. SSH)
src not ipset:whitelist state NEW - traffic not from a friendly IP and in a NEW state

So effectively we're saying, if we get any traffic on port 22, i.e. if anybody tries to access the SSH port on the machine, their IP address gets added to the ipset called trap. We then follow this up with the blacklist command, which blocks traffic to and from all IP's in the trap ipset.

Why is this useful? Indeed why don't we just block port 22? Well, typically the first thing a potential attacker will do is to probe port 22 to see if a SSH exploit is possible, and on the first hit, his IP is blocked completely - so nothing else he tries will do anything. Historically blocking port 22 would just block the first round of hundreds of different attack vectors, now, finger in the first socket and Zzzzt! - he's dead!

Expanding on this, if you have a static IP, add it to 'whitelist' and you can SSH in yourself, and there is support for layered port knocking, which is a mechanism for adding your own back-door through the firewall which nobody else is going to be able to Navigate (if you do it properly), but will still give you SSH access from anywhere - including a blacklisted IP.

You can inspect the list of blocked IP's at any time from the shell, for example;

# ipset list trap
Name: trap
Type: hash:ip
Revision: 2
Header: family inet hashsize 1024 maxelem 65536 timeout 3600
Size in memory: 17224
References: 6
Members:
109.236.80.115 timeout 85618
40.115.4.172 timeout 83809
185.93.185.252 timeout 85816
193.201.225.27 timeout 79629
81.200.89.208 timeout 86399
46.101.76.178 timeout 74859
86.153.252.217 timeout 84136
61.155.203.54 timeout 76765
104.40.177.254 timeout 80798

More here...

Is it me or is keeping up with all this becoming a full time job ?!