My firewall said Iran.

The servers were in Amsterdam.

Both statements were defensible. Neither meant what I first thought.

What started as 49 blocked firewall events led from a handful of scanning IPs, through several autonomous systems, into RIPE registry data, and eventually to twelve LIR memberships sharing the same company registration number.

Along the way, three heuristics I had been relying on broke:

  • Dense address space did not mean hostile infrastructure.
  • An ASN did not define an operator.
  • A registry country field did not tell me where the packets came from.

That ended up being more useful than the original finding.

This is part three of the series. Part one built the malware lab. Part two built Threat Meister, which turns Wazuh alerts into scored reports.

This is what happened when one of those reports surfaced something worth investigating.

Firewall blocked traffic events from filtered foreign IP addresses

The firewall activity that started the investigation.

The Trigger

The starting point was a UniFi CyberSecure export: 49 blocked inbound events over ten hours, from eleven source IPs.

There is an important caveat. I had filtered the export before beginning the investigation:

Src. Region = IR

That matters because I eventually demonstrated that the country field was inferred rather than measured. In other words, I started with a country-shaped sample and then discovered a country-related pattern.

The registry evidence still stands on its own, but the selection bias is worth stating. Forty-seven of the 49 events came from four /24s belonging to three ASNs. One IP, 185.93.89.35, produced thirty-five of them.

Its destination ports were concentrated between 3501 and 3596, but they were not scanned in order. The source port stayed fixed. Destination ports were randomized. The median gap between probes was 12.1 minutes. That pattern continued for roughly ten hours.

It looked like someone trying to complete a scan without looking like a scanner.

The proximity to RDP’s default port, 3389, makes a search for relocated RDP plausible, especially because the operator’s infrastructure exposed numerous RDP endpoints, but I have no direct evidence of that intent.

Assessment: roughly even chance.

The other source IPs also touched service-specific ports such as 1433, 3306 and 8545, commonly associated with Ethereum JSON-RPC.

Timeline of randomized 3500-range probes

Thirty-five probes from one source spread across roughly ten hours.

Three Networks That Looked Unrelated

I swept the suspicious /24s with a tool I built called link_analysis.py, enriching Shodan InternetDB results with RIPEstat, Team Cymru, GreyNoise, urlscan and abuse.ch data.

The networks initially looked very different.

AS213790 had large numbers of exposed Windows services and eleven scanner-tagged hosts.

AS215930 had 63 hosts listening on port 8000 and almost no scanner reputation, suggesting proxy infrastructure.

AS141718 had no scanner tags, no PTR records and widespread self-signed certificates.

My first interpretation was simple:

Three networks and three operators. That turned out to be wrong. Before discovering why, another pivot changed the scale of the investigation.

Hostname searches on one subnet returned eight domains.

Querying urlscan by ASN instead returned 3,257 submissions in three days and after numeration, 1,681 unique domains.

Eight versus 1,681. The data had been there. I was querying the wrong index.

One host was associated with 79 domains built from obvious word lists. Another was tied to names such as:

wellsfargoreports.com
vla-update-your-tax.com
one-drivepr0.cloud

Those looked like obvious phishing infrastructure.

So I checked them.

And that assumption broke too.

Pivoting by ASN expanded the visible domain set from eight to 1,681

Pivoting by ASN expanded the visible domain set from eight to 1,681

The Phishing Pages That Were Not Phishing Pages

I archived the suspicious domains through urlscan instead of visiting them directly.

one-drivepr0.cloud displayed a generic French-language “coming soon” page.

vla-update-your-tax.com exposed an empty Apache directory index.

verifyiptest.com returned 404s.

wellsfargoreports.com had already stopped resolving.

My initial notes called this live phishing infrastructure. It wasn’t. I had inferred functionality from domain names. Eight days later I checked again. None of the domains had converted into a functioning lure. Some had disappeared entirely, while the others remained inert.

Certificate transparency provided a better explanation. The suspicious certificates had been issued only days before the scanning reached me. One domain disappeared within forty-eight hours of certificate issuance.

The more defensible conclusion was:

I had probably caught infrastructure during a provisioning window.

The domains were registered, certificates were being issued and servers were configured, but I had not observed a completed phishing campaign.

That distinction matters.

Suspicious naming did not equal confirmed malicious content

Suspicious naming did not equal confirmed malicious content.

The Fake Analytics Loader

One domain was different.

content-website-analytics.com/script.js was not analytics.

It was a 239-byte first-stage JavaScript loader. Across five sampled websites, the file was identical by SHA-256. It created a new script element and fetched a hard-coded second stage. There was no analytics configuration, tracking ID, or measurement logic. The domain’s root returned HTTP 403.

The script had appeared in 5,792 urlscan submissions.

More interestingly, I found the same loader embedded in unrelated legitimate websites across different countries and hosting providers, including a genuine financial institution that I am deliberately not naming because it appears to be a victim.

The sites shared no obvious WordPress theme, plugin or developer. The loader was manually embedded into served markup rather than loaded through WordPress’s normal script-enqueue mechanism.

That is consistent with compromise. It could also result from a poisoned template or some other shared access path. I do not know the vector.

What I can say confidently is narrower:

The same static loader was hard-coded into unrelated sites and pulled remote code through infrastructure connected to the investigation.

The 239-byte script contained no analytics functionality

The 239-byte script contained no analytics functionality. It simply loaded another script.

The ASN Was the Wrong Pivot

The real reversal came from RIPE.

RIPEstat showed five prefixes announced by AS213790.

Then I queried its organization handle rather than its ASN:

whois -h whois.ripe.net -- '-i org ORG-LA1969-RIPE'

A sixth /24 appeared under the same organization and abuse contact but announced through a different ASN.

An ASN-based investigation could never have found it. Nothing was hidden. I was using the wrong key.

That led to the first major structural lesson:

An ASN is not an operator. It is one attribute of an operator.

The organization handle was a better pivot.

Then I found that two networks I had characterized as behaviorally different, AS213790 and AS215930, shared the same RIPE maintainer:

wcd

The fleet analysis had correctly described what the networks were doing. It could not tell me they were administratively connected.

AS141718, meanwhile, had no corresponding relationship. Its routes were spread across multiple leasing companies and registries.

What I had initially read as mysterious private infrastructure looked much more like ordinary rented address space whose tenants had never configured PTR records.

Pivot from ASN to organization and maintainer objects

The investigation changed when the pivot moved from ASN to organization and maintainer objects.

Twelve Memberships, One Registration Number

The wcd maintainer became the center of the investigation.

An inverse query returned 24 organization objects.

Fifteen were registered as LIRs.

Twelve of those fifteen, ORG-AOSP1-RIPE through ORG-AOSP12-RIPE, shared the same Tehran address and, more importantly, the same company registration number.

They were registered sequentially between September 2022 and January 2023, generally a few weeks apart.

Each received a final IPv4 /24 and an IPv6 allocation.

One of the fifteen LIR objects under the same maintainer closed the loop back to where this started: its org-name matched the netname on 185.93.89.0/25. The exact subnet behind thirty-six of my original forty-nine firewall events, including every one of the thirty-five from 185.93.89.35. That’s the join that matters. It isn’t just that a maintainer administers a pattern of suspicious looking allocations somewhere in RIPE’s database, tt administers the specific address space that reached my firewall.

That moved the analysis beyond:

These entities look suspiciously similar.

There was now a documentary join.

Four of the twelve ORG-AOSPn-RIPE objects, same registration number

Twelve LIR memberships shared a single company registration number.

I asked RIPE NCC whether the pattern itself violated policy. Their answer was important.

RIPE confirmed that multiple LIR accounts under one legal entity are permitted. Postal addresses are member-declared, and RIPE does not require an administrator’s location to correspond to the country associated with the resources.

So this was not evidence of a secret policy bypass. It was the policy working as designed.

That may still produce an extremely useful inventory of address space for a hosting or leasing operation, but operationally useful and policy violation are not the same claim.

Iran, Britain, America and Amsterdam

The same registration structure had resources carrying country values including:

AE
IR
GB
NL
US
DE
AZ
IQ

Eight countries.

One registrant.

That was enough to stop treating country: as physical geolocation.

The same mismatch showed up independently in a different tool’s data. 77.90.185.48, part of the same AS213790 fleet, carried a geoip.country of IR in urlscan’s own enrichment against an asn.country of GB on the ASN registration. Two unrelated data sources, the same country-field versus the reality gap.

urlscan geoip enrichment showing IR beside asn.country GB

Not just RIPE. urlscan’s own geoip enrichment tagged the same Dutch-hosted server Iranian.

So I measured the network instead.

Using Globalping, I launched traceroutes toward 185.93.89.35 from Germany, the Netherlands, Britain, the United States and Singapore.

All five converged on the same infrastructure near Amsterdam through SkyLink Data Center BV and Tube-Hosting.

From London:

 9  be102.ams-gsa1-sbb1-nc5.nl.eu
11  speed-ix.skylink-data-center.nl
12  ae0.3010.core02.eyg.as44592.net
13  ae18.1179.edge-vrf.cr1.egh.as49581.net
14  185.93.89.35

From London, the target sat roughly 1.2 ms beyond the Amsterdam portion of the route.

That is physically incompatible travel with Tehran.

Amsterdam to Tehran is roughly 4,270 km. Even ignoring routers and queues, the speed of light through fiber gives a round-trip floor of roughly 43 ms.

Observed increment:

About 1.2 ms.

Latency cannot tell me which rack the server sits in. It can tell me where the server is not.

Iran was excluded.

Globalping traceroute results with Amsterdam/SkyLink/Tube-Hosting hops highlighted

Five independent probes converged on the same Dutch hosting path.

That left three different answers to the question:

Where did this come from?

  1. Physical egress: Dutch hosting infrastructure.
    Confidence: almost certainly.

  2. Resource administration: a Tehran-linked LIR structure.
    Confidence: almost certainly.

  3. Actual scanner operator: unknown.

The hosts were very likely rented infrastructure. The person who launched the scan could have been anywhere.

My firewall had effectively answered the second question when I thought I was asking the first.

Geo-blocking Iran would not have stopped a single packet.

The Heuristics That Failed

This investigation also forced me to retest several ideas I had been using in infrastructure analysis.

The first was subnet density.

The suspicious networks were 13 to 58 percent populated, while one of my original benign controls was almost empty. That looked useful until I chose better controls.

A Hetzner /24 came back 50 percent populated. Another was 47 percent. Mainstream Linode and Scaleway ranges fell directly inside the supposedly suspicious density band.

Density was not measuring hostility. It was measuring how efficiently providers packed customers into address space.

That heuristic is dead.

Density-vs-scanner-tags graph

Benign hosting networks overlapped almost completely with the suspicious networks on address density.

Scanner tags survived better.

My properly populated benign controls still produced zero scanner tags, while several investigated ranges produced multiple hits.

But some suspicious subnets also returned zero.

So scanner tags appear to be high precision, low recall:

  • A hit can be meaningful.
  • No hit tells you very little.

Another heuristic, identical CVE lists across multiple hosts, also produced a false positive on Berkeley infrastructure.

It was detecting similar deployment, not malicious deployment. A university router chassis and a templated VPS farm can look identical to that metric.

Again, the signal was real. My interpretation was wrong.

Read the Lease

The investigation eventually reached RPKI and address leasing.

Some prefixes had ROAs authorizing multiple origin ASNs. That is legitimate, but it also allows a prefix to move between already authorized networks while remaining RPKI-valid. I also initially suspected one US address holder of being a bulletproof broker.

Then I pulled the global RPKI validated payload set. Its address space authorized 38 ASNs, including mainstream providers. AS213790 was simply one tenant among many.

That was not evidence of a bulletproof provider. It was evidence of an ordinary address-leasing company with at least one problematic customer. A completely separate leasing company appeared elsewhere in the loader chain.

That was the final structural lesson. The organization holding an IP allocation may not be the organisation announcing it. The organization announcing it may not be the company selling the VPS. The company selling the VPS may not know what its customer is doing. Finally, the person running the scanner may be somewhere else entirely.

That makes attribution harder.

It also tells you where the leverage sits.

Resource holder, lessor, ASN, and scanning host as different layers of one chain

The IP address, ASN, resource holder and end operator can represent different layers of the same chain.

Before Publishing This

I contacted ten organizations across this chain before writing any of this up. The transit network and the ARIN allocation holder carrying the scanning traffic, the two hosting providers behind the loader’s own address space, the national CERT for the administering jurisdiction, Google Safe Browsing and Spamhaus for the loader infrastructure, Tencent Cloud and APWG for a domain frequently co-occurring with it, and RIPE NCC for the membership pattern above.

RIPE NCC’s response is folded into the section above because it changed the argument. One other contact returned an automated out-of-office reply with no substantive content.

None of this is a claim that contacting these parties fixes anything on its own. Some of them can’t act even if they want to. A transit provider carrying a downstream customer’s traffic has limited leverage over that customer’s customer. Reporting to try and solve problems always takes precedence over publishing a post/report.

The investigation began with a firewall log filtered on a two-letter country code.

It ended with:

  • Dutch physical infrastructure
  • Tehran-linked resource administration
  • twelve LIR memberships sharing one company registration number
  • multiple address-leasing relationships
  • staged domains
  • a distributed JavaScript loader
  • several detection heuristics I no longer trust the way I did when I started

The IPs will change.

The domains will disappear.

The ASNs may change.

The structure is more durable.

An ASN is not an operator.

A registry field is not a measurement.

An address holder is not necessarily the customer using the address.

When the infrastructure matters, follow the allocation until you understand who is leasing what to whom.

Read the lease.