Last night, four internet addresses we had never seen before took turns at the SSH port of one of our servers. Forty-nine login attempts in total, every one of them guessing at a username that doesn't exist. By the standards of the past month, it was a quiet night.

Here is what that campaign looked like and what Vynnn's AI agents did about it, step by step, using the agents' own output and our real numbers. No lab, no staged demo.

A flood, then a swarm

Failed SSH logins per day on our internet-facing Linux servers, 20 September to 12 October 2026Failed SSH logins per day on our internet-facing Linux servers, 20 September to 12 October 2026

For eleven days in late September, our internet-facing Linux servers absorbed around 2,000 failed SSH logins a day: 22,177 in total, peaking at 2,583 on 25 September. Then the volume collapsed, and it would have been tempting to call that a win.

It wasn't. The campaign changed shape. From October the attempts came from new addresses almost every day, a few tries each: 1,457 attempts spread thin enough to slip under any tool that locks out an address after a handful of failures. Since August, 151 different addresses have tried their luck.

The wordlist is a wish list

Usernames the scanners tried, grouped by what each one hoped to findUsernames the scanners tried, grouped by what each one hoped to find

Scanners don't guess at random. They bet on accounts that ship by default and that nobody remembered to remove: admin above all, ubuntu and debian from fresh cloud images, pi and orangepi from hobby boards, oracle and odoo from business software, sol, solana and validator from crypto nodes.

One group stood out. On the biggest wave, Guard noticed claude, codex and gemini in the list and wrote in its verdict that the username list "includes AI tool names... indicating a modern wordlist." Teams now create accounts for their AI coding assistants on shared servers, and the scanners have already noticed.

The first 76 seconds

Here is what happened on the biggest coordinated wave, from the moment Guard picked up the detection to a finished response plan. No analyst touched any of it. We only opened the console afterwards, to take the screenshots below.

Each agent's time on the wave, measured by Vynnn: 76 seconds end to endEach agent's time on the wave, measured by Vynnn: 76 seconds end to end

Guard: is this real? (5 seconds)

Guard is the triage agent. It reads the detection, pulls the surrounding logs and decides whether the alert deserves anyone's attention. Five seconds in, its answer was yes, at 97% confidence: three external addresses were working through the same username list at a regular cadence, "consistent with automated credential-stuffing tooling." The busiest had made 203 attempts in six hours.

Guard's verdict: verified at triage (97%), and more certain after the investigation (98%)Guard's verdict: verified at triage (97%), and more certain after the investigation (98%)

Scout: who is knocking? (10 seconds)

While Hunter started digging, Scout took each attacking address to a dozen intelligence sources at once: abuse databases, scanner feeds, internet-wide port scans, malware and vulnerability feeds.

Two of them came back from China Mobile's network, working our server at the same time. 117.157.165.132, a fixed-line address in Lanzhou, had 143 abuse reports filed by other victims; 36.163.118.106, in Nanjing, had 476. Both carried 100% abuse confidence and were classified as malicious mass internet scanners. Scout scored them 70 and 72 out of 100, and its call on both was block.

Scout doesn't rubber-stamp, though. Another address in the campaign, on a network in Iran, had just 7 reports and 39% abuse confidence. Scout's call there: monitor, not block.

Scout traced both China Mobile addresses: 100% abuse confidence, flagged as malicious mass scannersScout traced both China Mobile addresses: 100% abuse confidence, flagged as malicious mass scanners

Hunter: did anyone get in? (32 seconds)

Hunter is the investigator. It pulled 2,250 events from around the attack, rebuilt the chain step by step with the log lines behind each step, and went after the only question that really matters: did any of those guesses work?

None did. Every attempt died at the login prompt as an invalid user. On a later wave from the same crowd, Hunter put it plainly: "Attack reached reconnaissance stage; no successful authentication or lateral movement confirmed in collected logs."

Hunter on a later wave: reconnaissance only, no successful loginHunter on a later wave: reconnaissance only, no successful login

Guard again: the final call (4 seconds)

With Scout's intelligence and Hunter's investigation in hand, Guard judged the incident a second time: verified, 98% confidence, and a recommendation to block every attacking address at the firewall.

Enforcer: what do we do about it? (35 seconds)

Enforcer turned that verdict into an eight-action containment plan, led by the block on all five attacking addresses. Every action came with a runbook, a rollback and a way to check it worked. Its follow-up list went further: alert on any SSH attempt from the attackers' /24 ranges for 30 days, "watch for AI-tool username wordlist patterns (claude, codex, gemini)", "disable password authentication, enforce key-only auth", and "consider restricting SSH to VPN/bastion-only access".

Enforcer's plan opens with the block: all five attacking addressesEnforcer's plan opens with the block: all five attacking addresses

Zooming out: who was knocking

Across the whole campaign, Scout traced 62 of the attacking addresses to 29 countries. The United States (8), Argentina (7) and China (6) led the list, followed by Russia, Vietnam, Indonesia, the Netherlands and Uzbekistan.

Scout's lookups on every SSH attacker: countries, block or monitor calls, and the loudest fourScout's lookups on every SSH attacker: countries, block or monitor calls, and the loudest four

The loudest four addresses alone carry 165,034 abuse reports, and all four sit on just two hosting networks. One of them, a proxy node in Andorra, went from 27,553 to 30,698 reports in ten days while we watched. The long tail is the more interesting part: 28 of the 41 addresses Scout said to block were not in data centres at all, but on home and telecom connections. That pattern is typical of hijacked routers and devices doing the knocking on someone else's behalf.

Why Enforcer asked before it blocked

This is the part we like best, because at first glance it looks like a hiccup. As the swarm spread across fresh addresses, each wave ended with the same question from Enforcer: block these too? Approve (5).

That's the system doing exactly what we told it to, for three reasons.

  1. The line is yours. Enforcer acts alone only on the action types you have pre-approved. Everything else arrives drafted, ticked and waiting. On our own servers, IP blocks were set to ask first, so it asked.
  2. Home addresses get recycled. Two-thirds of the addresses Scout wanted blocked were home and telecom connections. Today's hijacked router is tomorrow's paying customer on the same IP. Blocking a whole swarm forever is how you end up blocking real people.
  3. The plan grows with doubt. Hunter had flagged one weak signal it couldn't fully rule out, at 35% confidence, so Enforcer also included heavier steps: isolate the server, reset the targeted accounts. Those are exactly the actions you want a person to glance at first.

How Enforcer decides what runs on its own and what waits for one clickHow Enforcer decides what runs on its own and what waits for one click

Once you trust it, pre-approve IP blocks and Enforcer writes them straight into your AWS WAF, after checking each one against the guardrails above. We recommend starting with batch approval, watching what the agents propose for a few weeks, then moving the action types you're comfortable with to automatic.

The scorecard

QuestionAgentTimeAnalyst needed
Is this a real attack?Guard5 sNo
Who is behind it?Scout10 s, in parallelNo
Did anyone get in?Hunter32 s, in parallelNo
Final verdictGuard4 sNo
What do we do?Enforcer35 sNo
Pull the triggerYou, or your pre-approvalOne clickYour choice

End to end: 76 seconds from detection to a plan ready to approve.

If this is knocking on your servers too

Enforcer's own follow-up list makes a good checklist. Here it is, in plain words.

  • Turn off password logins for SSH. Keys only. Every attempt in this campaign was a guess, and a guess can't match a key.
  • Remove or rename default accounts on internet-facing machines: ubuntu, pi, admin and friends.
  • Treat AI assistant accounts as service accounts. No password, no SSH from the internet, the narrowest sudo rights you can give them.
  • Put SSH behind a VPN, a bastion or your cloud's session manager. A scanner can't guess its way into a port it can't reach.
  • Watch the pattern, not the address. Lockouts that count failures per IP miss a swarm spread across dozens of addresses.

The scanners will be back tonight, from a fresh set of addresses. So will the agents.