Files
proxmox/docs/04-configuration/CLOUDFLARE_TUNNEL_RPC_SETUP.md

14 KiB

Cloudflare Tunnel Setup for RPC Endpoints

Last Updated: 2025-12-21
Status: Configuration Guide


Overview

This guide explains how to set up Cloudflare Tunnel for the RPC endpoints with Nginx SSL termination. This provides additional security, DDoS protection, and hides your origin server IPs.


Architecture Options

Internet → Cloudflare → Tunnel → cloudflared → Nginx (443) → Besu RPC (8545/8546)

Benefits:

  • Direct connection to Nginx on each RPC container
  • SSL termination at Nginx level
  • Simpler architecture
  • Better performance (fewer hops)

Option 2: Tunnel via nginx-proxy-manager

Internet → Cloudflare → Tunnel → cloudflared → nginx-proxy-manager → Nginx → Besu RPC

Benefits:

  • Centralized management
  • Additional routing layer
  • Useful if you have many services

This guide focuses on Option 1 (Direct Tunnel to Nginx).


Prerequisites

  1. Nginx installed on RPC containers (2501, 2502) - Already done
  2. SSL certificates configured - Already done
  3. Cloudflare account with Zero Trust enabled
  4. Domain d-bis.org managed by Cloudflare
  5. cloudflared container (VMID 102 or create new one)

Step 1: Create Cloudflare Tunnel

1.1 Create Tunnel in Cloudflare Dashboard

  1. Access Cloudflare Zero Trust:

  2. Create Tunnel:

    • Go to Zero TrustNetworksTunnels
    • Click Create a tunnel
    • Select Cloudflared
    • Enter tunnel name: rpc-tunnel (or proxmox-rpc)
    • Click Save tunnel
  3. Copy Tunnel Token:

    • After creation, you'll see installation instructions
    • Copy the tunnel token (starts with eyJ...)
    • Save it securely - you'll need it in Step 2

Step 2: Deploy/Configure cloudflared

2.1 Check Existing cloudflared Container

# Check if cloudflared container exists (VMID 102)
ssh root@192.168.11.10 "pct status 102"
ssh root@192.168.11.10 "pct exec 102 -- which cloudflared"

2.2 Install cloudflared (if needed)

If cloudflared is not installed:

# Install cloudflared on VMID 102
ssh root@192.168.11.10 "pct exec 102 -- bash -c '
  wget -q https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb
  dpkg -i cloudflared-linux-amd64.deb || apt-get install -f -y
  cloudflared --version
'"

2.3 Configure Tunnel

Option A: Using Tunnel Token (Easiest)

# Install tunnel with token
ssh root@192.168.11.10 "pct exec 102 -- cloudflared service install <YOUR_TUNNEL_TOKEN>"

# Start service
ssh root@192.168.11.10 "pct exec 102 -- systemctl enable cloudflared"
ssh root@192.168.11.10 "pct exec 102 -- systemctl start cloudflared"

Option B: Using Config File (More Control)

Create tunnel configuration file:

ssh root@192.168.11.10 "pct exec 102 -- bash" <<'EOF'
cat > /etc/cloudflared/config.yml <<'CONFIG'
tunnel: <YOUR_TUNNEL_ID>
credentials-file: /etc/cloudflared/credentials.json

ingress:
  # Public HTTP RPC
  - hostname: rpc-http-pub.d-bis.org
    service: https://192.168.11.251:443
    originRequest:
      noHappyEyeballs: true
      connectTimeout: 30s
      tcpKeepAlive: 30s
      keepAliveConnections: 100
      keepAliveTimeout: 90s

  # Public WebSocket RPC
  - hostname: rpc-ws-pub.d-bis.org
    service: https://192.168.11.251:443
    originRequest:
      noHappyEyeballs: true
      connectTimeout: 30s
      tcpKeepAlive: 30s
      keepAliveConnections: 100
      keepAliveTimeout: 90s

  # Private HTTP RPC
  - hostname: rpc-http-prv.d-bis.org
    service: https://192.168.11.252:443
    originRequest:
      noHappyEyeballs: true
      connectTimeout: 30s
      tcpKeepAlive: 30s
      keepAliveConnections: 100
      keepAliveTimeout: 90s

  # Private WebSocket RPC
  - hostname: rpc-ws-prv.d-bis.org
    service: https://192.168.11.252:443
    originRequest:
      noHappyEyeballs: true
      connectTimeout: 30s
      tcpKeepAlive: 30s
      keepAliveConnections: 100
      keepAliveTimeout: 90s

  # Catch-all (must be last)
  - service: http_status:404
CONFIG

# Set permissions
chmod 600 /etc/cloudflared/config.yml
EOF

Important Notes:

  • Use https:// (not http://) because Nginx is listening on port 443 with SSL
  • The tunnel will handle SSL termination at Cloudflare edge
  • Nginx will still receive HTTPS traffic (or you can configure it to accept HTTP from tunnel)

Step 3: Configure Tunnel in Cloudflare Dashboard

3.1 Add Public Hostnames

In Cloudflare Zero Trust → Networks → Tunnels → Your Tunnel → Configure:

Add each hostname:

  1. rpc-http-pub.d-bis.org

    • Subdomain: rpc-http-pub
    • Domain: d-bis.org
    • Service: https://192.168.11.251:443
    • Type: HTTP
    • Click Save hostname
  2. rpc-ws-pub.d-bis.org

    • Subdomain: rpc-ws-pub
    • Domain: d-bis.org
    • Service: https://192.168.11.251:443
    • Type: HTTP
    • WebSocket: Enable (if available)
    • Click Save hostname
  3. rpc-http-prv.d-bis.org

    • Subdomain: rpc-http-prv
    • Domain: d-bis.org
    • Service: https://192.168.11.252:443
    • Type: HTTP
    • Click Save hostname
  4. rpc-ws-prv.d-bis.org

    • Subdomain: rpc-ws-prv
    • Domain: d-bis.org
    • Service: https://192.168.11.252:443
    • Type: HTTP
    • WebSocket: Enable (if available)
    • Click Save hostname

Step 4: Configure DNS Records

4.1 Update DNS Records to Use Tunnel

Change from A records to CNAME records pointing to tunnel:

In Cloudflare DNS Dashboard:

  1. Delete existing A records (if any):

    • rpc-http-pub.d-bis.org → A → 192.168.11.251
    • rpc-ws-pub.d-bis.org → A → 192.168.11.251
    • rpc-http-prv.d-bis.org → A → 192.168.11.252
    • rpc-ws-prv.d-bis.org → A → 192.168.11.252
  2. Create CNAME records:

Type Name Target Proxy TTL
CNAME rpc-http-pub <tunnel-id>.cfargotunnel.com 🟠 Proxied Auto
CNAME rpc-ws-pub <tunnel-id>.cfargotunnel.com 🟠 Proxied Auto
CNAME rpc-http-prv <tunnel-id>.cfargotunnel.com 🟠 Proxied Auto
CNAME rpc-ws-prv <tunnel-id>.cfargotunnel.com 🟠 Proxied Auto

Where <tunnel-id> is your tunnel ID (e.g., abc123def456).

Example:

Type: CNAME
Name: rpc-http-pub
Target: abc123def456.cfargotunnel.com
Proxy: 🟠 Proxied (orange cloud)
TTL: Auto

Important:

  • Proxy must be enabled (orange cloud) for tunnel to work
  • Use CNAME records (not A records) when using tunnels
  • Target format: <tunnel-id>.cfargotunnel.com

Step 5: Update Nginx Configuration (Optional)

Nginx continues to use HTTPS. The tunnel will:

  • Terminate SSL at Cloudflare edge
  • Forward HTTPS to Nginx
  • Nginx handles SSL again (double SSL - acceptable but not optimal)

5.2 Option B: Use HTTP from Tunnel (More Efficient)

If you want to avoid double SSL, configure Nginx to accept HTTP from the tunnel:

Update Nginx config on each container:

# On VMID 2501 and 2502
ssh root@192.168.11.10 "pct exec 2501 -- bash" <<'EOF'
# Add HTTP server block for tunnel traffic
cat >> /etc/nginx/sites-available/rpc <<'NGINX_HTTP'
# HTTP server for Cloudflare Tunnel (no SSL needed)
server {
    listen 80;
    listen [::]:80;
    server_name rpc-http-pub.d-bis.org rpc-ws-pub.d-bis.org;

    # Trust Cloudflare IPs
    set_real_ip_from 173.245.48.0/20;
    set_real_ip_from 103.21.244.0/22;
    set_real_ip_from 103.22.200.0/22;
    set_real_ip_from 103.31.4.0/22;
    set_real_ip_from 141.101.64.0/18;
    set_real_ip_from 108.162.192.0/18;
    set_real_ip_from 190.93.240.0/20;
    set_real_ip_from 188.114.96.0/20;
    set_real_ip_from 197.234.240.0/22;
    set_real_ip_from 198.41.128.0/17;
    set_real_ip_from 162.158.0.0/15;
    set_real_ip_from 104.16.0.0/13;
    set_real_ip_from 104.24.0.0/14;
    set_real_ip_from 172.64.0.0/13;
    set_real_ip_from 131.0.72.0/22;
    real_ip_header CF-Connecting-IP;

    access_log /var/log/nginx/rpc-tunnel-access.log;
    error_log /var/log/nginx/rpc-tunnel-error.log;

    # HTTP RPC endpoint
    location / {
        if ($host = rpc-http-pub.d-bis.org) {
            proxy_pass http://127.0.0.1:8545;
        }
        if ($host = rpc-ws-pub.d-bis.org) {
            proxy_pass http://127.0.0.1:8546;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
        }
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_buffering off;
    }
}
NGINX_HTTP

nginx -t && systemctl reload nginx
EOF

Then update tunnel config to use HTTP:

ingress:
  - hostname: rpc-http-pub.d-bis.org
    service: http://192.168.11.251:80  # Changed from https://443

Recommendation: Keep HTTPS (Option A) for simplicity and security.


Step 6: Verify Configuration

6.1 Check Tunnel Status

# Check cloudflared service
ssh root@192.168.11.10 "pct exec 102 -- systemctl status cloudflared"

# View tunnel logs
ssh root@192.168.11.10 "pct exec 102 -- journalctl -u cloudflared -f"

In Cloudflare Dashboard:

  • Go to Zero Trust → Networks → Tunnels
  • Tunnel status should show "Healthy" (green)

6.2 Test DNS Resolution

# Test DNS resolution
dig rpc-http-pub.d-bis.org
nslookup rpc-http-pub.d-bis.org

# Should resolve to Cloudflare IPs (if proxied)

6.3 Test Endpoints

# Test HTTP RPC endpoint
curl https://rpc-http-pub.d-bis.org/health
curl -X POST https://rpc-http-pub.d-bis.org \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'

# Test WebSocket RPC endpoint
wscat -c wss://rpc-ws-pub.d-bis.org

Benefits of Using Cloudflare Tunnel

  1. 🔒 Security:

    • Origin IPs hidden from public
    • No need to expose ports on firewall
    • DDoS protection at Cloudflare edge
  2. Performance:

    • Global CDN (though RPC responses shouldn't be cached)
    • Reduced latency for global users
    • Automatic SSL/TLS at edge
  3. 🛡️ DDoS Protection:

    • Cloudflare automatically mitigates attacks
    • Rate limiting available
    • Bot protection
  4. 📊 Analytics:

    • Traffic analytics in Cloudflare dashboard
    • Request logs
    • Security events
  5. 🔧 Management:

    • Centralized tunnel management
    • Easy to add/remove routes
    • No firewall changes needed

Troubleshooting

Tunnel Not Connecting

Symptoms: Tunnel shows "Unhealthy" in dashboard

Solutions:

# Check cloudflared service
pct exec 102 -- systemctl status cloudflared

# View logs
pct exec 102 -- journalctl -u cloudflared -n 50

# Verify credentials
pct exec 102 -- cat /etc/cloudflared/credentials.json

# Test tunnel connection
pct exec 102 -- cloudflared tunnel info

DNS Not Resolving

Symptoms: Domain doesn't resolve or resolves incorrectly

Solutions:

  1. Verify DNS record type is CNAME (not A)
  2. Verify proxy is enabled (orange cloud)
  3. Verify target is correct: <tunnel-id>.cfargotunnel.com
  4. Wait for DNS propagation (up to 5 minutes)

Connection Timeout

Symptoms: DNS resolves but connection times out

Solutions:

# Check if Nginx is running
pct exec 2501 -- systemctl status nginx

# Check if port 443 is listening
pct exec 2501 -- ss -tuln | grep 443

# Test direct connection (bypassing tunnel)
curl -k https://192.168.11.251/health

# Check tunnel config
pct exec 102 -- cat /etc/cloudflared/config.yml

SSL Certificate Errors

Symptoms: SSL certificate warnings

Solutions:

  1. If using self-signed certs, clients will see warnings (expected)
  2. Consider using Let's Encrypt certificates
  3. Or rely on Cloudflare SSL (terminate at edge, use HTTP internally)

Architecture Summary

Request Flow with Tunnel

  1. Clienthttps://rpc-http-pub.d-bis.org
  2. DNS → Resolves to Cloudflare IPs (via CNAME to tunnel)
  3. Cloudflare Edge → SSL termination, DDoS protection
  4. Cloudflare Tunnel → Encrypted connection to cloudflared
  5. cloudflared (VMID 102) → Forwards to https://192.168.11.251:443
  6. Nginx (VMID 2501) → Receives HTTPS, routes to 127.0.0.1:8545
  7. Besu RPC → Processes request, returns response
  8. Response → Reverse path back to client

Quick Reference

Tunnel Configuration:

ingress:
  - hostname: rpc-http-pub.d-bis.org
    service: https://192.168.11.251:443
  - hostname: rpc-ws-pub.d-bis.org
    service: https://192.168.11.251:443
  - hostname: rpc-http-prv.d-bis.org
    service: https://192.168.11.252:443
  - hostname: rpc-ws-prv.d-bis.org
    service: https://192.168.11.252:443
  - service: http_status:404

DNS Records:

rpc-http-pub.d-bis.org → CNAME → <tunnel-id>.cfargotunnel.com (🟠 Proxied)
rpc-ws-pub.d-bis.org → CNAME → <tunnel-id>.cfargotunnel.com (🟠 Proxied)
rpc-http-prv.d-bis.org → CNAME → <tunnel-id>.cfargotunnel.com (🟠 Proxied)
rpc-ws-prv.d-bis.org → CNAME → <tunnel-id>.cfargotunnel.com (🟠 Proxied)