Skip to content

Cloudflare Setup

CloakProbe is designed to run behind Cloudflare. This guide covers the recommended setup.

Internet → Cloudflare → Nginx → CloakProbe (localhost:8080)

Or without Nginx:

Internet → Cloudflare → CloakProbe (0.0.0.0:8080, firewall restricted)
  1. Add your domain to Cloudflare

    Add your domain (e.g., ip.example.com) to Cloudflare and update your nameservers.

  2. Create DNS record

    Add an A or AAAA record pointing to your server:

    TypeNameContentProxy
    Aipyour.server.ipProxied (orange cloud)
  3. SSL/TLS settings

    In SSL/TLSOverview, set encryption mode to:

    • Full (strict) - Recommended if you have a valid certificate on your origin
    • Full - If using a self-signed certificate
  4. Enable useful features (optional)

    • SpeedOptimization → Enable Brotli compression
    • SecuritySettings → Set security level to Medium or High
    • CachingConfiguration → Disable caching or set to “Bypass” for API routes

When proxied through Cloudflare, these headers are automatically added:

HeaderDescriptionUsed for
CF-Connecting-IPReal client IPPrimary IP detection
CF-RayRequest IDDebugging, shown in UI
CF-IPCountryClient countryDisplay (2-letter code)
CF-VisitorConnection protocolTLS detection
CDN-LoopLoop detection-

CloakProbe reads CF-Connecting-IP first to get the real client IP, not Cloudflare’s IP.

To get extended Cloudflare data (geo location, network info, security scores, etc.), you can use a Cloudflare Worker to forward request.cf data to your origin server as custom headers.

The standard Cloudflare proxy provides basic headers like CF-Connecting-IP and CF-Ray. However, Cloudflare Workers have access to the request.cf object, which contains much more detailed information:

  • Geo Location: Country, city, region, latitude/longitude, timezone
  • Network: ASN, AS organization, colo (datacenter)
  • Connection: HTTP protocol, TLS version, TLS cipher
  • Security: Trust score, bot score, verified bot status

By forwarding this data as custom headers (X-CF-*), CloakProbe can display all this information in both the HTML UI and API responses.

  1. Create a new Worker application

    In the Cloudflare dashboard, go to Workers & PagesCreate applicationCreate Worker.

  2. Use the Hello World template

    Click Start with Hello World! to create a basic Worker.

  3. Replace with the example script

    Replace the default code with the example Worker script below.

  4. Deploy the Worker

    Click Deploy to save and deploy your Worker.

  5. Create a Worker Route

    Go to Workers & Pages → Your Worker → TriggersRoutesAdd route.

    • Route: your-domain.com/* (or ip.your-domain.com/*)
    • Zone: Select your domain
    • Click Add route
  6. Configure DNS records

    Ensure your DNS records are set to Proxied (orange cloud) so the Worker can intercept requests.

Here’s a complete example Worker that extracts data from request.cf and forwards it to your origin server:

/**
* Cloudflare data forwarder for CloakProbe
*
* This Worker extracts information from the request.cf object and forwards
* it to the origin server as custom headers (X-CF-*). CloakProbe will
* automatically parse and display these headers.
*/
export default {
async fetch(request, env, ctx) {
// Preserve the original URL
const url = new URL(request.url);
// Extract information from the request.cf object
// This object contains detailed Cloudflare data about the request
const cf = request.cf || {};
// Create new headers by copying the original request headers
const newHeaders = new Headers(request.headers);
// Add Geo Location headers from request.cf
if (cf.country) newHeaders.set('X-CF-Country', cf.country);
if (cf.city) newHeaders.set('X-CF-City', cf.city);
if (cf.region) newHeaders.set('X-CF-Region', cf.region);
if (cf.regionCode) newHeaders.set('X-CF-Region-Code', cf.regionCode);
if (cf.continent) newHeaders.set('X-CF-Continent', cf.continent);
if (cf.latitude) newHeaders.set('X-CF-Latitude', cf.latitude);
if (cf.longitude) newHeaders.set('X-CF-Longitude', cf.longitude);
if (cf.postalCode) newHeaders.set('X-CF-Postal-Code', cf.postalCode);
if (cf.timezone) newHeaders.set('X-CF-Timezone', cf.timezone);
// Add Network headers from request.cf
if (cf.asn) newHeaders.set('X-CF-ASN', cf.asn.toString());
if (cf.asOrganization) newHeaders.set('X-CF-AS-Organization', cf.asOrganization);
if (cf.colo) newHeaders.set('X-CF-Colo', cf.colo);
// Add Connection headers from request.cf
if (cf.httpProtocol) newHeaders.set('X-CF-HTTP-Protocol', cf.httpProtocol);
if (cf.tlsVersion) newHeaders.set('X-CF-TLS-Version', cf.tlsVersion);
if (cf.tlsCipher) newHeaders.set('X-CF-TLS-Cipher', cf.tlsCipher);
// Add Security headers from request.cf
if (cf.clientTrustScore !== undefined) {
newHeaders.set('X-CF-Trust-Score', cf.clientTrustScore.toString());
}
// Add Bot Management headers (if Bot Management is enabled)
if (cf.botManagement) {
if (cf.botManagement.score !== undefined) {
newHeaders.set('X-CF-Bot-Score', cf.botManagement.score.toString());
}
if (cf.botManagement.verifiedBot !== undefined) {
newHeaders.set('X-CF-Verified-Bot', cf.botManagement.verifiedBot.toString());
}
}
// Create a new request with the modified headers
// This preserves the original request method, body, etc.
const modifiedRequest = new Request(request, {
headers: newHeaders
});
// Forward the modified request to the origin server
return fetch(modifiedRequest);
}
};
  1. Request interception: The Worker intercepts all requests to your domain (via the Worker Route).

  2. Data extraction: The Worker reads data from request.cf, which contains Cloudflare’s detailed information about the request.

  3. Header forwarding: The Worker adds custom headers (X-CF-*) containing this data and forwards the request to your origin server.

  4. CloakProbe processing: CloakProbe receives these headers, sanitizes them, and displays them in:

    • HTML UI: Organized into sections (Geo Location, Network, Connection, Security)
    • JSON API: Under the cloudflare field
    • Plain text API: In organized sections

After setting up the Worker, verify it’s working:

Terminal window
# Check that custom headers are being received
curl -v https://your-domain.com/api/v1/info 2>&1 | grep -i "x-cf-"
# Check JSON response for cloudflare field
curl -s https://your-domain.com/api/v1/info | jq '.cloudflare'

You should see:

  • Custom X-CF-* headers in the request
  • cloudflare field in the JSON response with geo, network, connection, and security data
  • Enhanced information displayed in the HTML UI

Worker not intercepting requests:

  • Ensure the Worker Route matches your domain pattern (e.g., your-domain.com/*)
  • Verify DNS records are proxied (orange cloud)
  • Check that the Worker is deployed and active

Headers not appearing:

  • Verify the Worker code is correctly extracting from request.cf
  • Check that the origin server is receiving the X-CF-* headers
  • Ensure CloakProbe version is 0.1.1 or later

Missing data:

  • Some fields in request.cf may be undefined for certain requests
  • Bot Management data requires Bot Management to be enabled in Cloudflare
  • Geo location accuracy depends on Cloudflare’s data

Allow only Cloudflare IPs to reach your server:

Terminal window
# Cloudflare IPv4 ranges
for ip in 173.245.48.0/20 103.21.244.0/22 103.22.200.0/22 103.31.4.0/22 \
141.101.64.0/18 108.162.192.0/18 190.93.240.0/20 188.114.96.0/20 \
197.234.240.0/22 198.41.128.0/17 162.158.0.0/15 104.16.0.0/13 \
104.24.0.0/14 172.64.0.0/13 131.0.72.0/22; do
sudo ufw allow from $ip to any port 443
done
# Block direct access
sudo ufw deny 443
Terminal window
# Allow Cloudflare IPs (example)
iptables -A INPUT -p tcp --dport 443 -s 173.245.48.0/20 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -s 103.21.244.0/22 -j ACCEPT
# ... add all Cloudflare ranges
# Drop other traffic to 443
iptables -A INPUT -p tcp --dport 443 -j DROP

Configure rate limiting in Cloudflare:

  1. Go to SecurityWAFRate limiting rules

  2. Create a rule:

    • If: URI Path contains /api/
    • Then: Block for 1 minute
    • When rate exceeds: 100 requests per 10 seconds

Create page rules for specific behaviors:

  • URL: ip.example.com/api/*
  • Setting: Cache Level = Bypass
  • URL: ip.example.com/*
  • Setting: Always Use HTTPS

Check that Cloudflare headers are being received:

Terminal window
curl -v https://ip.example.com/api/v1/info 2>&1 | grep -i "cf-"

In the JSON response, you should see:

  • connection.cf_ray - Cloudflare Ray ID
  • connection.datacenter - Cloudflare datacenter code

IP shows Cloudflare’s IP instead of client

Section titled “IP shows Cloudflare’s IP instead of client”

Ensure CloakProbe is reading CF-Connecting-IP. Check:

  • The domain is proxied (orange cloud) in DNS
  • You’re accessing via the domain, not directly by IP
  • 520: CloakProbe returned an empty or invalid response
  • 521: CloakProbe is not running or port is blocked
  • 522: Connection timed out - check firewall rules

For Full (strict) mode, ensure your origin has a valid certificate. Options:

  • Use Cloudflare Origin CA certificate
  • Use Let’s Encrypt certificate
  • Use Cloudflare Tunnel instead