0

I currently have these iptables rules on a Linux router, to block repeated SSH connections:

-A wan_ingress -p tcp --dport 22 -m state --state NEW -m recent --name sshthrottle --set -m comment --comment "Tag incoming SSH requests" -A wan_ingress -m state --state NEW -m recent --name sshthrottle --rcheck --seconds 300 --reap --hitcount 3 -j logdrop -m comment --comment "Log and drop packets" -A logdrop -j LOG --log-prefix "sshthrottle:drop " -A logdrop -j DROP 

However the problem is that it also blocks repeated successful connections, in that if I connect and disconnect successfully three times within five minutes, I also get blocked. Only for five minutes though, so until now I've just put up with it.

Since there are SSH brute forcers that automatically throttle themselves, I'd now like to extend the timeout from five minutes to a day, but this would mean I can only SSH in a limited number of times a day before I get blocked too.

So I'm wondering what the best way would be to add an additional iptables rule that says if the SSH connection was successful, remove the IP from the list used for counting the number of connection attempts.

I am thinking it would be using something like --state ESTABLISHED and a second packet counter to confirm the SSH session has been actually established (to avoid counting a lengthy unsuccessful login attempt as an established connection) however I'm not quite sure how to get that rule to trigger a removal of the IP from the original list.

3 Answers 3

1

I always configure ssh so it first knocks on a high port, disconnects, logs into port 22, and checks if the high port was knocked on by the IP within the last minute. Drop everything that didn't knock first

-1

Here's one way that seems to have worked. I added these rules after the existing ones, so that they only get reached when the connection is not yet blocked:

-A wan_ingress -p tcp --dport 22 -m state --state ESTABLISHED -m recent \ --name unblock --set -m comment --comment "Tag successful SSH connections" -A wan_ingress -p tcp --dport 22 -m state --state ESTABLISHED -m recent \ --name unblock --rcheck --seconds 10 --reap --hitcount 50 -j unblock \ -m comment --comment "Remove the IP from the sshthrottle list after successful login" -A unblock -m recent --name sshthrottle --remove -j LOG --log-prefix "unblock " 

This works by counting the number of packets sent over an established SSH connection. If at least 50 packets are sent within a 10 second window, then it jumps to the unblock table which removes the IP from the marked list and logs the fact. Once the connection has been established the --state NEW condition on the original rule ensures the IP doesn't get re-added to the marked list.

This only logs one message regardless of how many packets pass over the established connection, because the message is only logged if the IP exists in the marked list. If it doesn't exist, no log message is printed. It won't exist once the connection has been established, as --state NEW ensures only new connections are added to the list.

50 packets may need adjusting. It seemed to work for me, in that rapid SSH connections got things blocked before hitting 50 packets. When logging in successfully, 50 packets has not yet been reached so logging in and out without doing anything may still result in being blocked. Pressing enter a dozen times or running ls after logging in was enough to hit 50 packets and get the IP removed from the list of marked IPs.

-1

This is a no-brainer: Allow only logins with ssh-key and disallow password-logins completely. No need to fumble around with the firewall here.

Why would you give brute-force-ers even the statistically insignificant chance of accidentally guessing the right 24-characters password?

And if you still want to block after unsuccessful connections: that is precisely what fail2ban is for.

Again, there is no reason whatsoever to involve the firewall in this, unless you really, really mean to ask for trouble with no added benefit.

3
  • Password authentication is already disabled (not sure where in my question it said it was enabled?), but I still get thousands of connection attempts cluttering the logs on all the machines behind the firewall. My thinking is that if the firewall blocks them after a number of repeated attempts, then it will be harder for them to probe other services on the machine as well, plus my SSH logs won't be quite so full of noise. Commented Aug 8, 2023 at 5:36
  • Then it is only useless clutter you need not worry about. But still, this is exactly what fail2ban is for. And it is trivial to set up. Commented Aug 18, 2023 at 21:34
  • fail2ban is great, but it requires large dependencies like Python (so unsuitable for routers with limited storage space) and it also requires writing all the data to a log file which is periodically scanned, requiring more space and adding latency. iptables blocks instantly and requires no additional dependencies making it more suitable for my use case. Commented Aug 20, 2023 at 2:17

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.