Find SSH attacker subnets in /var/log/secure: a quickref
One-liner to surface the top attacking /24 subnets in /var/log/secure during an SSH brute-force wave, plus per-username and per-minute variations.
Find SSH attacker subnets in /var/log/secure: the grep quickref
When lfd is filing a deny every few seconds and you need to know
which subnets are doing the work, do not read the log line by line.
Bucket it.
The one-liner
awk '/Failed password/ {print $11}' /var/log/secure | \
awk -F. '{print $1"."$2"."$3".0/24"}' | \
sort | uniq -c | sort -rn | head -20Sample output during a real incident:
4218 87.121.84.0/24
2107 130.12.181.0/24
812 203.0.113.0/24
611 45.146.165.0/24
402 171.244.43.0/24
That tells you four things at once: where the noise is coming from,
how concentrated it is, whether it is one subnet or a botnet, and
whether your csf.deny already covers the loud ones.
What each part does
awk '/Failed password/ {print $11}' /var/log/secure/var/log/secure is the RHEL-family auth log; on Debian/Ubuntu it is
/var/log/auth.log. Failed password is the sshd line for any
unsuccessful login. Field 11 is the source IP. Count the spaces in
a real line if you need to verify.
awk -F. '{print $1"."$2"."$3".0/24"}'Splits each IP on . and rebuilds it as the /24 it belongs to. We
bucket on /24 because attackers cycle the last octet inside a single
subnet faster than they rotate subnets.
sort | uniq -c | sort -rn | head -20Standard uniq -c histogram: count duplicates, sort highest first,
keep the loudest 20.
Variations
By username (which accounts the attacker is actually probing):
awk '/Failed password/ {print $9}' /var/log/secure | \
sort | uniq -c | sort -rn | head -20By hour (when the wave actually started):
awk '/Failed password/ {print $1, $2, substr($3,1,2)}' /var/log/secure | \
sort | uniq -c | sort -rn | head -10By minute, scoped to the last hour, to spot rate-limit-evading behaviour:
awk -v h="$(date +%H)" '/Failed password/ && $3 ~ "^"h":" {print $3}' /var/log/secure | \
sort | uniq -c | sort -rn | head -20Same idea against lfd deny entries instead of raw sshd:
awk '/lfd.*Cluster member.*Blocking/ {print $NF}' /var/log/lfd.log | \
awk -F. '{print $1"."$2"."$3".0/24"}' | \
sort | uniq -c | sort -rn | head -20When to use it
During an attack, before you start blocking. The histogram tells you
whether to deny five subnets and end the conversation, or whether
the spread is wide enough that you need a country block or
PermitRootLogin no-plus-key-only and a long sleep.
After an attack, in the writeup. head -20 of /24s is the most
information per character you can put in an incident ticket.
Related reading
This grep is the first command in the SSH brute force use case:
- The 8,127-attempt SSH brute force night and the fix
- cPanel SSH lockout recovery: when the firewall locks you out too
For the firewall side, see CSF, lfd, and Imunify360: why your firewall is killing itself.
How ServerGuard uses this
Our brute-force triage use case runs this exact pivot, ranks the top
ten /24s, and proposes a csf.deny batch that the on-call engineer
approves with one tap.
مقالات ذات صلة
- قراءة 13 دقيقة
SSH brute force on cPanel: the 8,127-attempt night and the fix
SSH brute force on cPanel: the 8,127-attempt night and the fix The first alert landed at 02:14. Five failed root logins from a single address in Bulgaria, blocked at the 5/300s threshold, business as usual. By 02:31 the inbox had nine more
- قراءة 14 دقيقة
Locked out of cPanel SSH: VNC, iptables, and the way back in
Locked out of cPanel SSH: VNC, iptables, and the way back in The terminal hangs. You hit Enter again. Nothing. You try a different SSH client. Nothing. You try from your phone's hotspot, on a different ISP, with a different public IP, and S
- قراءة 2 دقيقة
Imunify360 custom SSH port: stop blocking your admins
Imunify360 custom SSH port: stop blocking your own admin sessions You moved sshd off port 22 and now your own engineers are getting banned by Imunify360. The fix is two minutes; the documentation is buried under three FAQ pages on a vendor