mail, ftp, or cpanel that points at the same server publishes the origin IP in public DNS. Once someone has that IP, they can talk to your server directly and Cloudflare never sees the traffic.
What the orange cloud actually does
cpanel, whm, webmail, webdisk, and autodiscover, all pointing at the server's main IP. When the zone gets imported into Cloudflare, those records come along, and nobody thinks about them again.
The result is a domain where www is protected and mail.example.com tells anyone who asks exactly where the server lives.
Why one leaking record is enough
Host header or with SNI for HTTPS. Your web server sees a normal request for example.com and serves it. Everything you configured at the edge is skipped, because those rules only run on traffic that reaches the edge. That includes WAF managed rules, rate limiting, bot challenges, the attack mode toggle, and even caching.
This is why the assumption fails under load rather than on a quiet day. Normal visitors still go through Cloudflare, so the site looks fine and the dashboard looks calm. Meanwhile, a credential-stuffing run against wp-login.php or a scraper hammering uncached pages arrives directly at PHP and MySQL. The server slows down or falls over while Cloudflare shows nothing unusual.
A useful first check on the support side is the origin access log. If the client IPs in it aren't from Cloudflare's ranges, the traffic isn't going through the proxy. No edge setting will fix that.
Finding leaking records with dig
dig installed (on Debian and Ubuntu it ships in dnsutils or bind9-dnsutils). Replace example.com with your domain.
BASH
# Apex and www: should return Cloudflare edge IPs if proxied
dig +short example.com A
dig +short example.com AAAA
dig +short www.example.com A
# MX returns hostnames; resolve each one it lists
dig +short example.com MX
dig +short mail.example.com A
# TXT: look for ip4: or ip6: in the SPF record
dig +short example.com TXTBASH
for h in www mail ftp cpanel whm webmail webdisk autodiscover cpcalendars cpcontacts dev staging direct origin; do
printf '%-28s A: %s AAAA: %s
' "$h.example.com" \
"(dig +short "h.example.com" A | tr '
' ' ')" \
"(dig +short "h.example.com" AAAA | tr '
' ' ')"
doneserver: cloudflare and a cf-ray header. Any name that resolves to your server's IP, or to anything outside Cloudflare's ranges, is a leak.
The TXT check matters more than people expect. An SPF record such as v=spf1 ip4:203.0.113.10 include:_spf.example.net ~all publishes the origin IP just as clearly as an A record. SPF a and mx mechanisms don't contain the IP themselves, but they point to names that resolve to it.
The final test is whether the origin answers direct requests at all. curl --resolve forces the connection to a specific IP while keeping the correct hostname and SNI. That makes it behave like a bot that already knows your origin.
BASH
# Replace 203.0.113.10 with the IP found in the leaking record
curl -sI --resolve example.com:443:203.0.113.10 https://example.com/ | head -n 5
# Compare with the normal path through Cloudflare
curl -sI https://example.com/ | grep -i -E '^(server|cf-ray):'Common leak sources and what to change
| Leak source | Why it exposes the origin | Typical change |
|---|---|---|
mail, ftp A records on the web server | Non-HTTP services can't use the standard proxy, so they stay grey | Move mail to a separate host or service; drop FTP or move it to SFTP on a different IP |
cpanel, whm, webmail, webdisk | Auto-created and imported as DNS only | Delete the unneeded ones; proxy the rest if Cloudflare supports the port, or reach the panel by server hostname over a firewalled port |
SPF ip4: with the web server IP | The IP is listed in a public TXT record | Send mail through a relay or mail service and reference its include: instead |
Forgotten dev, staging, direct names | Left grey for testing or debugging | Remove them, or proxy them and put access rules in front |
| AAAA records | Often added by the host and never proxied | Proxy or remove them, same as A records |
Keeping the origin behind the proxy for real
example.com, it can be found without any DNS record at all. Outbound mail sent from the web server, for example WordPress using local PHP mail, also puts the server IP in the Received headers of every message.
So treat hiding the IP as one layer and locking down the origin as the actual control. A workable order looks like this:
- Proxy every web hostname that can be proxied, and delete records nobody uses. For cPanel service names, check whether their ports are on Cloudflare's list of supported proxy ports before turning on the orange cloud. Otherwise the panel will stop loading.
- Separate mail from the web origin. Use a different server, a different IP, or an external mail service, and route the site's outgoing mail through authenticated SMTP to that service. A mail IP is public by design. It just shouldn't be the same machine that serves the website.
- Update SPF so it references the mail service instead of the web server's IP.
- Restrict inbound 80 and 443 on the origin to Cloudflare's published IP ranges. Use whatever firewall the server already runs (CSF, ufw, nftables, or the provider's network firewall). The exact syntax depends on the tool.
- After the cleanup, change the origin IP if you can. The old one is already recorded in history databases, and a new IP that has never appeared in DNS starts clean.
curl --resolve test again. The orange cloud protects a hostname, not a server. The server is only protected when it refuses to talk to anyone except the proxy.