Origin IP behind a CDN: how it leaks and how to lock it
A passing scan of your hostname tests the CDN edge; the origin is often discoverable from the domain's own DNS, so find it, scan it and lock it to the CDN.
In this article 5 sections
- A scan of the public hostname goes through the CDN and reports on the CDN. It says nothing about the server behind it.
- The origin address is usually published by the domain itself: the SPF record, the MX hosts, an unproxied subdomain, a certificate in the transparency logs, a Received header on outbound mail.
- Find it the way an attacker does, pin it, scan the server itself from outside, then lock the origin firewall to the CDN's ranges and authenticate origin pulls, so the address is useless even when known.
The front door and the back door
A CDN or a cloud WAF sits in front of the server and handles the hostname. Point a scanner at that hostname and the request goes to the edge: the edge's TLS, the edge's headers, the edge's rate limits and rules. A green report is a report on the edge. The origin, the actual server, has not been touched by that scan, and whatever it exposes directly is still exposed to anyone who reaches it by address rather than by name.
| What is scanned | What it tests | What it proves about the origin |
|---|---|---|
| The public hostname, through the CDN | The edge: its WAF, TLS and rate limits | Nothing |
| The pinned origin address | The server itself, as an attacker reaches it | What a stranger on the internet can touch |
Where the origin leaks
The address is rarely well hidden, because the domain publishes it for other purposes. The SPF record is the common one. An SPF policy that uses the a mechanism authorises the domain's own A record to send mail, and that A record is the origin behind the CDN. The mx mechanism points at the mail hosts, which often sit in the same range. A literal ip4: spells it out.
$ dig +short TXT example.com
"v=spf1 a mx ip4:<address> include:_spf.<mail-provider> ~all"
$ dig +short MX example.com
$ dig +short A mail.example.com ftp.example.com staging.example.com origin.example.comBeyond SPF: subdomains that were never put behind the CDN (mail, ftp, a control panel, staging, a bare origin host), which resolve straight to the server. Certificate transparency logs, which record every certificate issued for a name, including the one on the origin host. Passive DNS databases, which keep the A record from before the CDN was introduced. The Received headers on any mail the web server sends, which name the host it came from. And application features that make the server connect outwards on request, such as pingbacks and webhook tests, which show the connecting address to whoever receives the call.
Pin the origin and scan what an attacker scans
Once the address is known, make the tools ignore the CDN. curl can do it per request; scanners that cannot take an entry in the hosts file. Run it from a machine that is not on your own network and not on any allowlist the origin trusts, because a scan from a trusted address reports what trusted addresses see.
# per request, no hosts-file change
$ curl --resolve example.com:443:<address> -sI https://example.com/
# for tools without --resolve
$ echo "<address> example.com" | sudo tee -a /etc/hostsKeep two columns in the result. The infrastructure column: which ports answer, which TLS versions are accepted, whether banners volunteer software names. The application column: unauthenticated endpoints that enumerate users, debug or log files readable in the web root, administrative paths reachable without a second factor, components behind their current release. A hardened box serving an open application is not a secure site, and the two columns are not averaged into one verdict.
Lock the origin to the CDN
The structural fix is at the origin, not at the edge. The web ports answer only to the CDN's published address ranges, with everything else denied by default. On a firewalld host:
# load the CDN's published ranges into an ipset, then allow only them on 443
$ firewall-cmd --permanent --new-ipset=cdn-v4 --type=hash:net
$ firewall-cmd --permanent --ipset=cdn-v4 --add-entries-from-file=cdn-ranges-v4.txt
$ firewall-cmd --permanent --zone=public --remove-service=http
$ firewall-cmd --permanent --zone=public --remove-service=https
$ firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source ipset="cdn-v4" port port="443" protocol="tcp" accept'
$ firewall-cmd --reload
$ firewall-cmd --ipset=cdn-v4 --get-entriesTwo details decide whether this holds. The CDN's ranges change, so the file is refreshed from the CDN's published list on a schedule and the ipset reloaded with it. And each prefix in an allow list is read back after loading: a prefix length mistyped by one character admits a large part of the internet and looks normal in the file.
Address ranges are the first lock, not the only one. Most CDNs can authenticate their pulls to the origin with a client certificate; require it at the web server, so a request from inside a CDN range that does not present the certificate is still refused. Then remove the leaks that remain: an SPF record that names only the hosts that send mail, no unproxied subdomains pointing at the origin, and, where practical, a new origin address once the lock is in place, because the old one stays in passive DNS indefinitely.
Verify from outside
Re-run the pinned scan from the same untrusted vantage. The origin refuses the connection on 443, and the hostname still serves through the CDN. Repeat after each change to the ranges or the web server configuration; turning this into a standing check rather than a one-off is the subject of prove it's shut from the outside.
$ curl --resolve example.com:443:<address> -m 5 -sI https://example.com/ ; echo "exit $?"
exit 28
# a timeout (28) or a refused connection (7) is the correct answer from the locked originStraight answers
Does a CDN protect my origin server?+
Only for traffic that passes through it. The WAF, TLS and rate limits apply at the edge. A request made directly to the origin address meets none of them, so the origin must refuse everything that is not the CDN.
How does an attacker find the origin IP behind a CDN?+
From the domain's own DNS most often: an SPF record with the a, mx or ip4 mechanisms, MX hosts in the same range, subdomains that were never proxied. Also from certificate transparency logs, passive DNS history and the headers of mail the server sends. Assume it will be found, and lock the origin as if it has been.
What is the difference between scanning the hostname and scanning the origin?+
The hostname resolves to the CDN, so the scan tests the edge. The origin is the server. Pinning the origin address with curl --resolve or a hosts-file entry, from a network the origin does not trust, tests what an attacker tests.
Once the origin is locked to the CDN, does the SPF leak still matter?+
The web ports no longer answer, but the address is still known, and any other service on it (SSH, mail, a control panel) is still reachable unless it is restricted too. Tighten the SPF record to the real mail hosts, move the origin to a fresh address where practical, and allowlist the remaining services.
Want the origin found, pinned and locked by someone working from outside your network?
Talk to an engineer.
Talk to an engineerYou’ve reached the end.
Put the reading to work
What are
you running?
Tell us about the workload, traffic and recovery requirements. Start with the server builder, or talk through the details with an engineer.
Written by the engineers who build and run the infrastructure it describes.Talk to an engineer
