قراءة 2 دقيقة

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 -20

Sample 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 -20

Standard 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 -20

By 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 -10

By 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 -20

Same 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 -20

When 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.

This grep is the first command in the SSH brute force use case:

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.

شارك هذه المقالة

XLinkedInEmail
  • قراءة 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