Trying to mitigate SSH brute-force attacks on my box, I copied/pasted the following rules into my iptables
(without really understanding them, I must confess):
$> iptables-save
# Generated by iptables-save v1.4.14 on Wed Jun 11 15:13:01 2014
*filter
:INPUT ACCEPT [1255:139338]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [1099:174390]
-A INPUT -p tcp -m tcp --dport 22 -m state --state NEW -m recent --set --name SSH --rsource -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -m recent --rcheck --seconds 60 --hitcount 5 --rttl --name SSH --rsource -j LOG --log-prefix "[iptables] SSH brute-force "
-A INPUT -p tcp -m tcp --dport 22 -m recent --update --seconds 60 --hitcount 5 --rttl --name SSH --rsource -j REJECT --reject-with tcp-reset
COMMIT
# Completed on Wed Jun 11 15:13:01 2014
To my delight, it works as intended (repeated connections attempts are rejected, while legitimate attempts go through). I since realised that there are other ways to achieve the same effect: example 1, example 2.
I (believe I) understand how the other methods work, but I fail to understand how the first rule above matches only "new incoming connections from untracked sources".
This contradicts what I understand from the manual:
--set:
This will always return success
What in this rule makes it not match repeated connection attempts? I assume the first rule does not match repeated connection attempts, otherwise the subsequent rules would never kick in.
I would expect any new incoming connection to match this rule.
In the other examples, they don't mention the target -j ACCEPT
:
-A INPUT (...) -m state --state NEW -m recent --set --name SSH --rsource
So perhaps my question could be rephrased:
Is the -j
option useless when used together with --set --name [some_name]
?
As requested, here are the results of iptables -L -n -v
(ssh'ing from/to localhost, since I only have remote access right now):
Initial state:
Chain INPUT (policy ACCEPT 895 packets, 101K bytes)
pkts bytes target prot opt in out source destination
18 1080 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 state NEW recent: SET name: SSH side: source
19 962 LOG tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 recent: CHECK seconds: 60 hit_count: 5 TTL-Match name: SSH side: source LOG flags 0 level 4 prefix "[iptables] SSH brute-force "
19 962 REJECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 recent: UPDATE seconds: 60 hit_count: 5 TTL-Match name: SSH side: source reject-with tcp-reset
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 776 packets, 119K bytes)
pkts bytes target prot opt in out source destination
After attempt #4:
Chain INPUT (policy ACCEPT 1040 packets, 121K bytes)
pkts bytes target prot opt in out source destination
22 1320 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 state NEW recent: SET name: SSH side: source
19 962 LOG tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 recent: CHECK seconds: 60 hit_count: 5 TTL-Match name: SSH side: source LOG flags 0 level 4 prefix "[iptables] SSH brute-force "
19 962 REJECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 recent: UPDATE seconds: 60 hit_count: 5 TTL-Match name: SSH side: source reject-with tcp-reset
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 911 packets, 141K bytes)
pkts bytes target prot opt in out source destination
After attempt #5 (which was rejected):
Chain INPUT (policy ACCEPT 1063 packets, 122K bytes)
pkts bytes target prot opt in out source destination
23 1380 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 state NEW recent: SET name: SSH side: source
21 1054 LOG tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 recent: CHECK seconds: 60 hit_count: 5 TTL-Match name: SSH side: source LOG flags 0 level 4 prefix "[iptables] SSH brute-force "
21 1054 REJECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 recent: UPDATE seconds: 60 hit_count: 5 TTL-Match name: SSH side: source reject-with tcp-reset
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 933 packets, 144K bytes)
pkts bytes target prot opt in out source destination
Log of the "attack":
Jun 11 15:07:02 [hostname_hidden] kernel: [249278.516231] [iptables] SSH brute-force IN=lo OUT= MAC=00:00:00:00:00:00:00:00:00:00:00:00:08:00 SRC=127.0.0.1 DST=127.0.0.1 LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=59245 DF PROTO=TCP SPT=36129 DPT=22 WINDOW=0 RES=0x00 RST URGP=0
Jun 11 15:07:18 [hostname_hidden] kernel: [249294.514964] [iptables] SSH brute-force IN=lo OUT= MAC=00:00:00:00:00:00:00:00:00:00:00:00:08:00 SRC=127.0.0.1 DST=127.0.0.1 LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=59246 DF PROTO=TCP SPT=36129 DPT=22 WINDOW=0 RES=0x00 RST URGP=0