Here’s my notes from doing something basic, (for the gazilionth time, again ) …
Specifically, I ran journalctl
to check on something on my home router which is just a linux debian system, and was annoyed because my router logs were getting filled up with failed ssh attempts - so, here’s what I did to fix that.
step 1. make an ipset
I ran this:
# ipset create hash:ip recently_ok timeout 86400
… to serve as a 24h long allowlist of IP addresses that can ssh without any rate limits, and then I then added this to my ~/.ssh/rc file
which gets executed on successful logins:
#!/bin/bash
ipset add -exist recently_ok $(echo "${SSH_CLIENT:-127.0.0.1}" | cut -d ' ' -f1)
… which adds or refreshes an entry in that IP set (and only works because this is actually my router, and I always just ssh in as root, so at that point I can totally modify ipsets).
I then ran netfilter-persistent save
and then I logged in a few times and looked at output of ipset list recently_ok
to make sure this is working ok.
step 2. firewall rules
in my /etc/iptables/rules.v4 files, I added the following.
-A INPUT -i wan -p tcp -m tcp --dport 22 -m set --match-set recently_ok src -j ACCEPT
-A INPUT -i wan -p tcp -m tcp --dport 22 -m state --state NEW -m recent --set --name ssh --mask 255.255.255.255 --rsource
-A INPUT -i wan -p tcp -m tcp --dport 22 -m state --state NEW -m recent --update --seconds 600 --hitcount 4 --name ssh --mask 255.255.255.255 --rsource -j DROP
-A INPUT -i wan -p tcp -m tcp --dport 22 -j ACCEPT
I then did netfilter-persistent load
to apply those.
This rate limits failed ssh attempts to 4 (or is it 3) per 10 minutes, and I could see it working from iptables -Lnv
and from cat /proc/net/xt_recent/ssh | sort -nk3
downsides and upsides of this approach:
- needs
iptables-extensions
installed for “recent” and “ipset” - needs way of storing/restoring firewall on reboot (e.g.
netfilter-persistent
) - very low dependency - doesn’t really require strange software suites from wherever
- fairly quick to set up
- ipv4 only (my isp won’t give me ipv6 without losing ipv4, so I’m IPv4 only on the internet)
-
~/ssh/rc
file runs as root (might not be an issue for purpose built server machines) -
~/ssh/rc
is openssh-server specific / e.g. it won’t work with tailscalessh, but might not matter for tailscale - kind of hard to figure out you’ve locked yourself out and debug, because you just get nothing back on 22
- still get some spammy logs
- lacks any kind of integration with central databases of bad ips across the internet (could be added)
- lacks any kind of long term reporting / analysis
- failures aren’t triggering any reverse probes or scans.
- not a honeypot like cowrie - you have no idea what’s trying to log in
- you’re not really wasting any attackers resources like with tarpit / endlessh
other options I see people on the internet doing:
- moving ports to something obscure and random
- tarpit
- endlessh
- fail2ban
- rate limiting only (which kind of works with
ControlMaster
feature of sshd) - port knocking
… and many many others. @paulwratt has SS:FragWhare which, despite its name, is actually a lot more advanced than my 6 lines of code I’ve put up in this post.