Some checks failed
Deploy to Phoenix / deploy (push) Has been cancelled
Co-authored-by: Cursor <cursoragent@cursor.com>
520 lines
14 KiB
Markdown
520 lines
14 KiB
Markdown
# 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
|
|
|
|
### Option 1: Direct Tunnel to Nginx (Recommended)
|
|
|
|
```
|
|
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:**
|
|
- Navigate to: https://one.dash.cloudflare.com
|
|
- Sign in with your Cloudflare account
|
|
|
|
2. **Create Tunnel:**
|
|
- Go to **Zero Trust** → **Networks** → **Tunnels**
|
|
- 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
|
|
|
|
```bash
|
|
# 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:
|
|
|
|
```bash
|
|
# 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)**
|
|
|
|
```bash
|
|
# 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:
|
|
|
|
```bash
|
|
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)
|
|
|
|
### 5.1 Option A: Keep HTTPS (Recommended)
|
|
|
|
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:**
|
|
|
|
```bash
|
|
# 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:**
|
|
```yaml
|
|
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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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:**
|
|
```bash
|
|
# 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:**
|
|
```bash
|
|
# 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. **Client** → `https://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:**
|
|
```yaml
|
|
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)
|
|
```
|
|
|
|
---
|
|
|
|
## Related Documentation
|
|
|
|
- [RPC_DNS_CONFIGURATION.md](../RPC_DNS_CONFIGURATION.md) - Direct DNS configuration
|
|
- [CLOUDFLARE_DNS_TO_CONTAINERS.md](CLOUDFLARE_DNS_TO_CONTAINERS.md) - General tunnel setup
|
|
- [CLOUDFLARE_NGINX_INTEGRATION.md](../../05-network/CLOUDFLARE_NGINX_INTEGRATION.md) - Nginx integration
|
|
|