When you proxy traffic through Cloudflare, attackers can still bypass your protection if they discover your origin server's real IP address. Private Origins is Cloudflare's framework for ensuring connections to your server come exclusively through Cloudflare's network, blocking direct access attempts and preventing reconnaissance that could expose vulnerabilities.
This guide walks you through configuring Private Origins step-by-step, from initial setup to verification and ongoing maintenance.
Understanding Private Origins
Private Origins isn't a single toggle—it's a combination of techniques that work together:
- Authenticated Origin Pulls: Forces your server to verify that incoming HTTPS connections originated from Cloudflare by checking client certificates
- Origin IP firewall rules: Blocks all traffic except connections from Cloudflare's published IP ranges
- Origin certificate encryption: Ensures end-to-end TLS encryption between Cloudflare and your server
- DNS obfuscation: Keeps your real IP out of public records
When properly configured, attackers who discover your origin IP cannot connect to your server directly. All requests must pass through Cloudflare's edge network, where your security rules, rate limits, and WAF policies apply.
Prerequisites
Before you begin:
- Active Cloudflare account with your domain proxied (orange cloud enabled)
- Root or sudo access to your origin server
- Web server running Apache, Nginx, or similar
- SSH access to your server
- Basic familiarity with your firewall management tool (iptables, firewalld, ufw, etc.)
Step 1: Install a Cloudflare Origin Certificate
Cloudflare Origin Certificates provide free TLS encryption between Cloudflare's edge and your server. Unlike Let's Encrypt certificates, these are trusted only by Cloudflare, which is perfect for origin security.
Generate the Certificate
- Log into the Cloudflare dashboard
- Select your domain
- Navigate to SSL/TLS → Origin Server
- Click Create Certificate
- Choose these settings: - Let Cloudflare generate a private key and CSR: recommended for simplicity - Hostnames: your domain and wildcard subdomain (example.com, .example.com) - Validity*: 15 years is fine for origin certificates
- Click Create
- Copy both the Origin Certificate and Private Key immediately—you won't see the private key again
Install on Your Server
Create certificate files on your origin:
sudo mkdir -p /etc/ssl/cloudflare
sudo nano /etc/ssl/cloudflare/cert.pem
Paste the Origin Certificate, save and exit. Then create the private key:
sudo nano /etc/ssl/cloudflare/key.pem
Paste the Private Key, save and exit. Set secure permissions:
sudo chmod 600 /etc/ssl/cloudflare/key.pem
sudo chmod 644 /etc/ssl/cloudflare/cert.pem
Configure Your Web Server
For Nginx, edit your site configuration:
server {
listen 443 ssl http2;
server_name example.com www.example.com;
ssl_certificate /etc/ssl/cloudflare/cert.pem;
ssl_certificate_key /etc/ssl/cloudflare/key.pem;
ssl_protocols TLSv1.2 TLSv1.3;
# Rest of your configuration
}
Test and reload:
sudo nginx -t
sudo systemctl reload nginx
For Apache, edit your VirtualHost:
<VirtualHost *:443>
ServerName example.com
ServerAlias www.example.com
SSLEngine on
SSLCertificateFile /etc/ssl/cloudflare/cert.pem
SSLCertificateKeyFile /etc/ssl/cloudflare/key.pem
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
# Rest of your configuration
</VirtualHost>
Test and restart:
sudo apachectl configtest
sudo systemctl restart apache2
Set Cloudflare SSL Mode
In the Cloudflare dashboard under SSL/TLS → Overview, set the mode to Full (strict). This ensures Cloudflare validates your origin certificate.
Step 2: Enable Authenticated Origin Pulls
Authenticated Origin Pulls add mutual TLS authentication, requiring Cloudflare to present a valid client certificate when connecting to your origin.
Download Cloudflare's Client Certificate
Cloudflare publishes an authenticated origin pull CA certificate. Download it to your server:
sudo curl -o /etc/ssl/cloudflare/origin-pull-ca.pem \
https://developers.cloudflare.com/ssl/static/authenticated_origin_pull_ca.pem
sudo chmod 644 /etc/ssl/cloudflare/origin-pull-ca.pem
Configure Your Web Server
For Nginx, add to your SSL server block:
server {
listen 443 ssl http2;
ssl_certificate /etc/ssl/cloudflare/cert.pem;
ssl_certificate_key /etc/ssl/cloudflare/key.pem;
ssl_client_certificate /etc/ssl/cloudflare/origin-pull-ca.pem;
ssl_verify_client on;
# Rest of your configuration
}
For Apache, add to your VirtualHost:
<VirtualHost *:443>
SSLEngine on
SSLCertificateFile /etc/ssl/cloudflare/cert.pem
SSLCertificateKeyFile /etc/ssl/cloudflare/key.pem
SSLCACertificateFile /etc/ssl/cloudflare/origin-pull-ca.pem
SSLVerifyClient require
SSLVerifyDepth 1
# Rest of your configuration
</VirtualHost>
Test configuration and reload your web server.
Enable in Cloudflare Dashboard
- Go to SSL/TLS → Origin Server
- Scroll to Authenticated Origin Pulls
- Toggle to On
Test your site loads correctly through Cloudflare. If you see connection errors, double-check your web server configuration and certificate paths.
Step 3: Restrict Traffic to Cloudflare IPs
Now configure your firewall to accept HTTPS connections only from Cloudflare's network.
Get Cloudflare IP Ranges
Cloudflare publishes their IP ranges. You'll need both IPv4 and IPv6 lists. Create a script to update them automatically:
sudo mkdir -p /etc/cloudflare
sudo nano /usr/local/bin/update-cloudflare-ips.sh
Add this script:
#!/bin/bash
curl -s https://www.cloudflare.com/ips-v4 -o /etc/cloudflare/ips-v4.txt
curl -s https://www.cloudflare.com/ips-v6 -o /etc/cloudflare/ips-v6.txt
Make it executable and run it:
sudo chmod +x /usr/local/bin/update-cloudflare-ips.sh
sudo /usr/local/bin/update-cloudflare-ips.sh
Configure Firewall Rules
Using UFW (Ubuntu/Debian):
# Allow SSH first - critical!
sudo ufw allow 22/tcp
# Allow HTTP for redirects
sudo ufw allow 80/tcp
# Delete any existing HTTPS allow rules
sudo ufw status numbered
# Note the number of any 443/tcp rules and delete them
# Allow HTTPS only from Cloudflare IPs
for ip in $(cat /etc/cloudflare/ips-v4.txt); do
sudo ufw allow from $ip to any port 443 proto tcp
done
for ip in $(cat /etc/cloudflare/ips-v6.txt); do
sudo ufw allow from $ip to any port 443 proto tcp
done
# Enable firewall if not already enabled
sudo ufw enable
sudo ufw status
Using firewalld (CentOS/RHEL/Rocky):
# Create a custom zone for Cloudflare
sudo firewall-cmd --permanent --new-zone=cloudflare
sudo firewall-cmd --permanent --zone=cloudflare --add-service=http
sudo firewall-cmd --permanent --zone=cloudflare --add-service=https
# Add Cloudflare IPs to the zone
for ip in $(cat /etc/cloudflare/ips-v4.txt); do
sudo firewall-cmd --permanent --zone=cloudflare --add-source=$ip
done
for ip in $(cat /etc/cloudflare/ips-v6.txt); do
sudo firewall-cmd --permanent --zone=cloudflare --add-source=$ip
done
# Remove HTTPS from public zone
sudo firewall-cmd --permanent --zone=public --remove-service=https
# Reload firewall
sudo firewall-cmd --reload
sudo firewall-cmd --list-all-zones | grep -A 10 cloudflare
Using iptables directly:
# Flush existing HTTPS rules (be careful)
sudo iptables -D INPUT -p tcp --dport 443 -j ACCEPT
# Allow Cloudflare IPs
for ip in $(cat /etc/cloudflare/ips-v4.txt); do
sudo iptables -I INPUT -p tcp -s $ip --dport 443 -j ACCEPT
done
# Drop all other HTTPS traffic
sudo iptables -A INPUT -p tcp --dport 443 -j DROP
# Save rules
sudo iptables-save | sudo tee /etc/iptables/rules.v4
Automate IP Updates
Cloudflare occasionally updates their IP ranges. Schedule your update script:
sudo crontab -e
Add this line to check weekly:
0 3 * * 0 /usr/local/bin/update-cloudflare-ips.sh && /usr/local/bin/apply-firewall-rules.sh
Create the apply script with your firewall commands from above.
Step 4: Lock Down DNS Records
Even with origin protection, your real IP might leak through DNS history or public records.
Audit Your DNS
- Check all DNS records in Cloudflare's DNS dashboard
- Ensure your A and AAAA records for web traffic point through Cloudflare (orange cloud icon)
- Look for any records that expose your origin IP: - Old A records for direct access - MX records pointing to the same IP - TXT records with IP references - Subdomains not proxied through Cloudflare
Separate Mail Server IPs
If you run mail on the same server, either:
- Move email to a different IP or server (recommended)
- Accept that your mail server IP will be public
- Use Cloudflare Area 1 or a third-party mail gateway
MX records cannot be proxied, so mail server IPs are inherently discoverable.
Change Your Origin IP
If your origin IP is already public, consider requesting a new IP from your hosting provider after implementing these protections. This gives you a clean slate.
Step 5: Additional Hardening
Disable Direct IP Access
Configure your web server to reject requests made directly to your IP:
Nginx:
server {
listen 443 ssl http2 default_server;
server_name _;
ssl_certificate /etc/ssl/cloudflare/cert.pem;
ssl_certificate_key /etc/ssl/cloudflare/key.pem;
return 444;
}
Apache:
<VirtualHost *:443>
ServerName _default_
SSLEngine on
SSLCertificateFile /etc/ssl/cloudflare/cert.pem
SSLCertificateKeyFile /etc/ssl/cloudflare/key.pem
<Location />
Require all denied
</Location>
</VirtualHost>
Validate Cloudflare Headers
Cloudflare adds headers to requests. You can add additional validation in your application:
- Check for
CF-Connecting-IPheader - Validate
CF-Rayheader exists - Log and alert on requests without Cloudflare headers that somehow passed firewall rules
Monitor Access Logs
Regularly check web server logs for connection attempts that bypassed Cloudflare:
sudo grep -v "CF-" /var/log/nginx/access.log | tail -50
Any successful connection without Cloudflare headers indicates a gap in your protection.
Verification and Testing
Test Through Cloudflare
Visit your site normally. Everything should work:
curl -I https://example.com
Look for CF-Ray and other Cloudflare headers.
Test Direct Connection
Attempt to connect directly to your origin IP:
curl -vI https://YOUR_ORIGIN_IP
This should fail with a connection timeout or TLS error. If it succeeds, review your firewall rules and Authenticated Origin Pulls configuration.
Test from External Network
Use a VPS or VPN outside your network to verify firewall rules work correctly:
telnet YOUR_ORIGIN_IP 443
The connection should hang or be rejected.
Check DNS Leaks
Use online tools to verify your origin IP isn't exposed:
- Historical DNS lookup tools
- SSL certificate transparency logs (check SANs don't reference origin IP)
- Search your domain in Shodan or Censys to see what IPs are associated
Troubleshooting Common Issues
Site returns 525 or 526 errors: Your origin certificate is invalid or Authenticated Origin Pulls misconfigured. Verify certificate paths and that SSL mode is Full (strict).
Site loads but some requests fail: Check that all subdomains used by your site are proxied through Cloudflare or excluded from origin pull verification.
Cannot SSH to server: If you locked yourself out with firewall rules, access your server through your hosting provider's console and review rules. Always keep SSH access separate from web traffic restrictions.
Cloudflare shows offline status: Your origin is rejecting Cloudflare's health checks. Verify firewall rules include all Cloudflare IP ranges and Authenticated Origin Pulls is properly configured.
Certificate warnings on origin: Ensure you're using a Cloudflare Origin Certificate, not a standard CA certificate. Set Cloudflare SSL mode to Full (strict), not Flexible or Full only.
Ongoing Maintenance
- Update Cloudflare IPs: Automate this check monthly
- Monitor certificate expiration: Origin certificates last up to 15 years but check expiry dates annually
- Review firewall logs: Weekly checks for bypass attempts
- Audit DNS records: Quarterly review for new records that might expose origin
- Test failover: Periodically disable Cloudflare proxy to ensure you can access origin directly when needed for maintenance
Conclusion
Private Origins configuration significantly hardens your infrastructure by ensuring all traffic flows through Cloudflare's security stack. The combination of Authenticated Origin Pulls, IP-restricted firewall rules, and proper SSL configuration makes direct-to-origin attacks extremely difficult.
Implementation takes an hour or two but provides ongoing protection against reconnaissance, DDoS bypass attempts, and direct exploitation of origin vulnerabilities. Schedule regular maintenance checks and automate IP list updates to maintain your security posture over time.
The effort is worthwhile for any production site where availability and security matter—especially high-traffic sites, those handling sensitive data, or targets of frequent attacks.
