How to Check If Your Cloudflare Origin Is Exposed
Running behind Cloudflare doesn't automatically hide your origin. Here's a systematic checklist to verify whether your origin IP is discoverable.
Moving your domain to Cloudflare doesn't automatically hide your origin server. The IP masking only works if every path that could disclose the address is closed. In practice, most Cloudflare-protected sites have at least one disclosure vector — a grey-cloud subdomain, a historical DNS record, an SPF entry, or a certificate that places the domain in a public log tied to the origin IP. This is a methodical checklist for finding them.
Step 1: Confirm your main domain is proxied
Start with the basics. Resolve your apex domain and www subdomain and check whether the returned IP belongs to Cloudflare:
dig +short A yourdomain.com
dig +short A www.yourdomain.comCross-reference the result with Cloudflare's published IP ranges:
curl -s https://www.cloudflare.com/ips-v4
# Compare: is your returned IP in one of these CIDRs?If the IP is not in Cloudflare's ranges, the record is DNS-only and your origin is directly exposed for the main domain. This is the highest-severity finding.
Step 2: Enumerate all subdomains
Subdomains are the most common source of origin IP leakage. Use passive DNS enumeration to find all subdomains associated with your domain:
# Subfinder (passive, doesn't generate traffic to the target)
subfinder -d yourdomain.com -silent -all
# Amass (passive mode)
amass enum -passive -d yourdomain.com
# Certificate Transparency via crt.sh
curl -s "https://crt.sh/?q=%.yourdomain.com&output=json" \
| jq -r '.[].name_value' | sort -u | grep -v '^\*'Collect all subdomains from multiple sources. CT logs in particular surface subdomains that passive DNS misses.
Step 3: Check each subdomain's proxy status
For each subdomain, resolve the A record and check whether it's a Cloudflare IP or a direct origin IP:
#!/bin/bash
# Read Cloudflare IP ranges
CF_IPS=$(curl -s https://www.cloudflare.com/ips-v4)
check_proxied() {
local host=$1
local ip=$(dig +short A $host | grep -E '^[0-9]+\.' | head -1)
if [ -z "$ip" ]; then
echo "$host: no A record"
return
fi
# Simple Cloudflare check (first octet heuristic for 104.x, 172.x ranges)
if echo "$CF_IPS" | python3 -c "
import sys, ipaddress
ranges = [ipaddress.ip_network(l.strip()) for l in sys.stdin if l.strip()]
ip = ipaddress.ip_address('$ip')
print('CLOUDFLARE' if any(ip in r for r in ranges) else 'DIRECT')
"; then
echo "$host -> $ip"
fi
}
while read sub; do
check_proxied "$sub"
done < subdomains.txtAny subdomain resolving to a non-Cloudflare IP should be investigated. If it's on the same physical server as your web application, it exposes the origin IP.
Step 4: Check DNS history
Even if your current DNS records are all proxied, historical records may expose the original IP. Two approaches:
# SecurityTrails API (requires free API key)
curl -s "https://api.securitytrails.com/v1/history/yourdomain.com/dns/a" \
-H "APIKEY: YOUR_API_KEY" \
| jq '.records[].values[].ip'
# ViewDNS (web interface)
# https://viewdns.info/iphistory/?domain=yourdomain.comIf historical records show an IP that predates Cloudflare, test whether that IP still serves your site:
curl -sk --resolve yourdomain.com:443:HISTORICAL_IP \
https://yourdomain.com/ -o /dev/null -w "%{http_code}"A non-4xx response means the origin at that IP is still active. Cloudflare added but origin never changed.
Step 5: Check SPF records for IP disclosure
SPF records frequently contain explicit IP addresses of mail-sending servers. If your web application and mail server share an IP, SPF discloses it:
dig TXT yourdomain.com | grep -i spf
dig TXT mail.yourdomain.com | grep -i spf
# Parse include: chains
python3 -c "
import subprocess, re
def check_spf(domain, depth=0):
if depth > 5: return
result = subprocess.run(['dig', '+short', 'TXT', domain], capture_output=True, text=True)
for line in result.stdout.splitlines():
if 'spf' in line.lower():
print(' ' * depth + f'{domain}: {line}')
for inc in re.findall(r'include:(\S+)', line):
check_spf(inc, depth+1)
check_spf('yourdomain.com')
"Look for ip4: and ip6: entries. Any IP listed should be cross-referenced against your origin IP.
Step 6: Shodan and Censys certificate search
SSL/TLS certificates contain the domain name. Shodan and Censys index certificates from direct IP scans:
# Shodan (requires free API key for CLI)
shodan search "ssl.cert.subject.cn:yourdomain.com" --fields ip_str,port,org
# Alternative: Shodan web search
# Query: ssl:"yourdomain.com"
# Censys (requires account)
# Search: parsed.names: yourdomain.comAny IP returned that isn't in Cloudflare's ranges is a direct origin disclosure via certificate. This approach works because Cloudflare-proxied connections use Cloudflare's certificate at the edge; the origin certificate is served only on direct connections, which Shodan makes during its scans.
Step 7: Check email headers
Send a test email to a mailbox you control and inspect the full headers. Look for Received: headers showing the sending IP:
# In Gmail: three-dot menu → "Show original"
# Look for:
Received: from yourdomain.com (yourdomain.com [198.51.100.42])
by mx.google.com with ESMTP id ...The IP in brackets is your mail server's outbound IP. If this is the same IP as your web origin, it's now disclosed in every email you send.
Step 8: Test direct origin access
Once you have a candidate origin IP, verify it still serves your application and is accessible on ports 80/443:
# HTTP
curl -sk -H "Host: yourdomain.com" http://CANDIDATE_IP/ -o /dev/null -w "%{http_code}"
# HTTPS
curl -sk -H "Host: yourdomain.com" https://CANDIDATE_IP/ -o /dev/null -w "%{http_code}"
# Check what ports are open
nmap -Pn -p 80,443,8080,8443,22,3306,5432 CANDIDATE_IPIf port 443 responds with your application, the origin is reachable directly. Check what else is open — port 3306 (MySQL), 5432 (PostgreSQL), 6379 (Redis) open to the internet is a critical finding that Cloudflare's proxy would have obscured but not actually protected against.
Consolidating findings
After running through all eight steps, categorize findings:
- Critical: Main domain A record DNS-only; origin IP exposed AND database ports open
- High: Origin IP exposed via any vector (historical DNS, subdomain, certificate, SPF)
- Medium: Grey-cloud subdomain that doesn't share origin IP but reveals IP range or org
- Informational: Historical IP no longer active; SPF ip4: entry pointing to a mail-only server on separate IP
Remediation priority
- Change the origin IP if it's widely known — new IP buys time while you fix the structural issues
- Firewall the origin: accept connections on 443/80 only from Cloudflare's IP ranges
- Move non-HTTP services to separate IPs that don't host the web application
- Update SPF to remove
ip4:entries for the web origin IP; use mail provider'sinclude:instead - Delete or proxy any grey-cloud subdomains that point to the same IP as the web origin
- Enable Cloudflare Authenticated Origin Pulls (mTLS) to ensure only Cloudflare can reach the origin on 443
Orb44's Cloudflare origin check automates steps 1–6 of this checklist. It correlates subdomains, historical DNS, certificate logs, and SPF records to identify origin IP leakage vectors, and alerts you when new exposure appears after changes — for example, when a deployment adds a new subdomain that isn't proxied. Check your site at orb44.com.
FAQ: I firewalled port 443 to Cloudflare IPs only. Is the origin IP still a problem?
Less so for application security, but the IP is still disclosed and the security posture still has gaps. Attackers can verify which IP is your origin even if they can't connect to it on 443. If other ports are open (SSH on 22, database ports, management interfaces), those remain accessible regardless of the 443 firewall rule. The IP being known also enables reverse-engineering the hosting provider for social engineering or abuse report attacks. Full mitigation means the IP is undiscoverable and all ports are firewalled.
FAQ: How often should I run this check?
After any DNS change, after any deployment that changes subdomains or certificates, and on a periodic basis (monthly at minimum). DNS configuration changes are a common source of re-exposure — an engineer adds a subdomain for a new service, sets it to DNS-only to get it working quickly, and the origin IP is exposed again. Continuous monitoring catches this faster than periodic manual audits.
FAQ: Does Cloudflare's own tool detect origin exposure?
Cloudflare's dashboard shows proxy status per record but doesn't cross-reference unproxied records with your origin IP, doesn't check historical DNS, doesn't search CT logs, and doesn't correlate SPF records. It tells you the current state of records you've already added to your Cloudflare zone — it doesn't find the exposure vectors that exist outside the Cloudflare dashboard.