π― Purpose & Use Cases
Primary Purpose
Securely expose internal web applications to the internet without opening firewall ports, providing secure access through Cloudflare's global edge network.
Top 3 Use Cases
- Public Web Application Hosting
Securely expose internal web applications to the internet without opening firewall ports - Development Environment Access
Provide external access to development servers and staging environments - Internal Tool Distribution
Share internal dashboards, monitoring tools, and administrative interfaces with authorized users
Key Benefits
- Zero-trust security model
- No inbound firewall rules required
- Global edge network performance
- Built-in DDoS protection
- SSL/TLS termination at edge
π Prerequisites
Required Accounts & Services
- Cloudflare Account with domain management
- Cloudflare Zero Trust subscription (free tier available)
- AWS Account with EC2 instance running Ubuntu
- Domain registered and managed through Cloudflare
- WARP Client installed on devices requiring Infrastructure Access
Server Requirements
- Ubuntu 20.04+ (other Linux distributions supported)
- cloudflared binary (latest version)
- OpenSSH Server
- Web application (nginx, apache, or custom app)
- sudo access on target server
Network Requirements
- Server outbound connectivity on port 443 (for tunnel establishment)
- Web application running on designated port (default: 80)
- SSH service running on port 22
- No inbound firewall rules required (all access through tunnels)
ποΈ Architecture Overview
System Architecture Diagram
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β CLIENT DEVICES β
β βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββββββββββββββββββ β
β β Web Browser β β Web Browser β β WARP + SSH Client β β
β β (Any Device) β β (Any Device) β β (Admin Device) β β
β βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β β β
β HTTPS β HTTPS β WARP Tunnel
β β β
βββββββββββββΌβββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββΌββββββββββββββ
β CLOUDFLARE EDGE NETWORK β
β βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββββββββββββββββββ β
β β Web App β β SSH Browser β β SSH Infrastructure β β
β β DNS Route β β DNS Route β β IP Route β β
β βwebapp.ztn.*****.comβ βssh.ztn.*****.com β β172.31.***.***/31 β β
β βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββββββββββββββββββ β
β βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββββββββββββββββββ β
β βSelf-hosted App β βSelf-hosted App β βInfrastructure App β β
β βAccess Policy β βAccess Policy β βAccess Policy β β
β βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β β β
β Tunnel 1 β Tunnel 2 β Tunnel 3
β β β
βββββββββββββΌβββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββΌββββββββββββββ
β AWS UBUNTU SERVER β
β 172.31.***.*** β
β βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββββββββββββββββββ β
β β Tunnel 1 β β Tunnel 2 β β Tunnel 3 β β
β β Port 8080 β β Port 8081 β β Port 8082 β β
β β Web App β β SSH Browser β β SSH Infrastructure β β
β βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββββββββββββββββββ β
β β β β β
β βΌ βΌ βΌ β
β βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββββββββββββββββββ β
β β Web Server β β SSH Daemon β β SSH Daemon β β
β β Port 80 β β Port 22 β β Port 22 β β
β β (nginx/app) β β (Browser CA) β β (Infrastructure CA) β β
β βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Service Interaction Matrix
| Component | Web App Tunnel | SSH Browser Tunnel | SSH Infrastructure |
|---|---|---|---|
| Cloudflared Process | β Separate | β Separate | β Separate |
| DNS Route | webapp.ztn.*****.com | ssh.ztn.*****.com | None |
| IP Route | None | None | 172.31.***.***/31 |
| Access Policy | Self-hosted | Self-hosted | Infrastructure |
| Target Service | HTTP:80 | SSH:22 | SSH:22 |
| Authentication | Email-based | Email + SSH Cert | WARP + SSH Cert |
| Client Requirement | Browser | Browser | WARP + SSH Client |
π¦ Detailed Traffic Flow
Web Application Access Flow
Step 1: User Request
- User opens browser
- Navigates to https://webapp.ztn.*****.com
- DNS resolution via Cloudflare
Step 2: Cloudflare Edge Processing
- DNS resolves to Cloudflare edge IP
- Request hits Cloudflare proxy
- Edge identifies associated tunnel (web-app-tunnel)
- Checks for self-hosted Access application
Step 3: Authentication Flow
- Self-hosted Access policy evaluation
- If not authenticated: redirect to login page
- User enters email: ubuntu@*****.com
- Email verification (OTP or SSO)
- Access token issued
Step 4: Request Forwarding
- Authenticated request forwarded to tunnel
- Tunnel receives request on web-app-tunnel
- Tunnel forwards to service: http://localhost:80
- Web server (nginx/app) processes request
Step 5: Response Flow
- Web server generates response
- Response travels back through tunnel
- Cloudflare edge adds security headers
- Response cached (if applicable)
- Browser receives final response
Timeline: ~500ms for authenticated users, ~3-5s for new authentication
βοΈ Configuration
Tunnel Configuration
Tunnel Config (~/.cloudflared/tunnels/web-app/config.yml):
tunnel: <web-tunnel-id>
credentials-file: /home/ubuntu/.cloudflared/<web-tunnel-id>.json
logfile: /home/ubuntu/.cloudflared/logs/web-app.log
loglevel: info
ingress:
- hostname: webapp.ztn.*****.com
service: http://localhost:80
- service: http_status:404
Systemd Service
Service File (/etc/systemd/system/cloudflared-web.service):
[Unit]
Description=Cloudflare Tunnel - Web Application
After=network.target
Wants=network.target
[Service]
Type=simple
User=ubuntu
Group=ubuntu
ExecStart=/usr/local/bin/cloudflared tunnel --config /home/ubuntu/.cloudflared/tunnels/web-app/config.yml run
Restart=always
RestartSec=5
TimeoutStartSec=0
KillMode=mixed
StandardOutput=journal
StandardError=journal
SyslogIdentifier=cloudflared-web
[Install]
WantedBy=multi-user.target
Web Server Configuration
Nginx Configuration (/etc/nginx/sites-available/default):
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name _;
location / {
try_files $uri $uri/ =404;
}
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
}
π File Structure
Cloudflared Tunnel Files
/home/ubuntu/.cloudflared/
βββ logs/
β βββ web-app.log # Web application tunnel logs
β βββ ssh-browser.log # SSH browser tunnel logs
β βββ ssh-infra.log # SSH infrastructure tunnel logs
βββ tunnels/
β βββ web-app/
β β βββ config.yml # Web app tunnel configuration
β βββ ssh-browser/
β β βββ config.yml # SSH browser tunnel configuration
β βββ ssh-infra/
β βββ config.yml # SSH infrastructure tunnel configuration
βββ <web-tunnel-id>.json # Web tunnel credentials
βββ <ssh-browser-tunnel-id>.json # SSH browser tunnel credentials
βββ <ssh-infra-tunnel-id>.json # SSH infrastructure tunnel credentials
Web Project Files
/var/www/html/ # Default nginx/apache document root
βββ index.html # Main web application
βββ assets/ # Static assets (CSS, JS, images)
βββ api/ # API endpoints (if applicable)
βββ config/ # Application configuration
# Alternative locations:
/home/ubuntu/web-app/ # Custom application directory
/opt/webapp/ # System-wide application directory
Systemd Service Files
/etc/systemd/system/
βββ cloudflared-web.service # Web tunnel service
βββ cloudflared-ssh-browser.service # SSH browser tunnel service
βββ cloudflared-ssh-infra.service # SSH infrastructure tunnel service
π Scaling & Management
Adding a New Tunnel to Current Server
Step 1: Plan the New Service
# Example: Adding a database management tunnel
NEW_SERVICE="db-admin"
NEW_HOSTNAME="db.ztn.oskarcode.com"
NEW_PORT="8080" # phpMyAdmin or similar
Step 2: Create and Configure Tunnel
# Create new tunnel
cloudflared tunnel create ${NEW_SERVICE}-tunnel
NEW_TUNNEL_ID=$(cloudflared tunnel list | grep "${NEW_SERVICE}-tunnel" | awk '{print $1}')
# Create directory structure
mkdir -p ~/.cloudflared/tunnels/${NEW_SERVICE}
# Create configuration
cat > ~/.cloudflared/tunnels/${NEW_SERVICE}/config.yml << EOF
tunnel: $NEW_TUNNEL_ID
credentials-file: /home/ubuntu/.cloudflared/${NEW_TUNNEL_ID}.json
logfile: /home/ubuntu/.cloudflared/logs/${NEW_SERVICE}.log
loglevel: info
ingress:
- hostname: ${NEW_HOSTNAME}
service: http://localhost:${NEW_PORT}
- service: http_status:404
EOF
# Configure DNS route
cloudflared tunnel route dns $NEW_TUNNEL_ID $NEW_HOSTNAME
Step 3: Create Systemd Service
# Create service file
sudo tee /etc/systemd/system/cloudflared-${NEW_SERVICE}.service > /dev/null << EOF
[Unit]
Description=Cloudflare Tunnel - ${NEW_SERVICE}
After=network.target
[Service]
Type=simple
User=ubuntu
Group=ubuntu
ExecStart=/usr/local/bin/cloudflared tunnel --config /home/ubuntu/.cloudflared/tunnels/${NEW_SERVICE}/config.yml run
Restart=always
RestartSec=5
StandardOutput=journal
StandardError=journal
SyslogIdentifier=cloudflared-${NEW_SERVICE}
[Install]
WantedBy=multi-user.target
EOF
# Enable and start service
sudo systemctl daemon-reload
sudo systemctl enable cloudflared-${NEW_SERVICE}
sudo systemctl start cloudflared-${NEW_SERVICE}
Horizontal Scaling Best Practices
Load Balancing Multiple Servers
# Use multiple tunnels with same hostname for load balancing
# Example: Multiple web servers behind same domain
# Server 1
cloudflared tunnel route dns web-tunnel-1 webapp.ztn.oskarcode.com
# Server 2
cloudflared tunnel route dns web-tunnel-2 webapp.ztn.oskarcode.com
# Cloudflare will automatically load balance between tunnels
Resource Management
# Monitor resource usage per tunnel
systemctl status cloudflared-*
htop -p $(pgrep cloudflared)
# Implement resource limits
# Add to systemd service files:
[Service]
MemoryLimit=256M
CPUQuota=50%
π Future Plans
Phase 1: Cloudflare Zero Trust Gateway Integration
Objective
Enhance security monitoring and control by implementing advanced Gateway features for comprehensive traffic inspection and policy enforcement.
Implementation Strategy
- Gateway Proxy: Enable TCP proxy for SSH traffic and HTTPS proxy for web traffic
- SSH Command Logging: Full command capture with optional session recording
- Advanced Network Policies: Time-based, location-based, and device posture restrictions
- Web Traffic Inspection: Malware detection, data loss prevention, content filtering
Timeline: 8 weeks implementation with enhanced security monitoring
Phase 2: Google Cloud Identity Integration
Objective
Replace email-based authentication with enterprise-grade Google Cloud Identity integration for improved security and user management.
Key Features
- Centralized User Management: Google Admin Console integration
- Enterprise MFA: Google Authenticator integration
- Automated Provisioning: SCIM-based user synchronization
- Group-based Access: Dynamic group membership
Timeline: 10 weeks with enterprise identity standards
Phase 3: Advanced Security and Monitoring
Objective
Implement comprehensive security monitoring, alerting, and incident response capabilities.
Features to Implement
- Behavioral Analytics: User behavior analysis and anomaly detection
- SIEM Integration: Splunk, ELK Stack, or Azure Sentinel
- Incident Response: Automated and manual response procedures
- System Monitoring: Resource utilization and performance metrics
Phase 4: Infrastructure as Code (IaC)
Objective
Automate the entire infrastructure deployment and management using Terraform and configuration management tools.
Implementation Components
- Terraform Infrastructure: Version-controlled infrastructure deployment
- Ansible Configuration: Automated configuration management
- Disaster Recovery: Infrastructure recreation capabilities
- Standardized Configurations: Consistent setups across all servers
π§ Common Issues & Solutions
Issue 1: Empty SSH Certificate Public Key
Problem:
curl -X GET "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/access/apps/$APP_ID/ca"
# Returns: "public_key": ""
Solution:
# Delete existing certificate
curl -X DELETE "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/access/apps/$APP_ID/ca"
# Regenerate certificate
curl -X POST "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/access/apps/$APP_ID/ca"
# Verify public key is populated
curl -X GET "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/access/apps/$APP_ID/ca"
Issue 2: Tunnel Name/ID Mismatch
Problem:
cloudflared tunnel info ssh-ec2
# Returns info for different tunnel (aws-tunnel)
Solution:
# List all tunnels to identify correct names and IDs
cloudflared tunnel list
# Use tunnel ID instead of name for reliability
cloudflared tunnel info <tunnel-id>
# Clean up orphaned tunnels
cloudflared tunnel delete <unused-tunnel-id>
Issue 3: Service Start Failures
Problem:
sudo systemctl start cloudflared-web
# Job failed. See "systemctl status cloudflared-web" for details.
Solution:
# Check service status and logs
sudo systemctl status cloudflared-web
sudo journalctl -u cloudflared-web -n 50
# Validate configuration
cloudflared tunnel --config ~/.cloudflared/tunnels/web-app/config.yml validate
# Check file permissions
ls -la ~/.cloudflared/tunnels/web-app/config.yml
ls -la ~/.cloudflared/*.json
# Fix permissions if needed
chmod 600 ~/.cloudflared/*.json
chmod 644 ~/.cloudflared/tunnels/*/config.yml
π References
Official Documentation
- Cloudflare Tunnel Documentation
- Zero Trust Access Documentation
- SSH with Access for Infrastructure
- Short-lived Certificates
Technical Specifications
- RFC 4253 - SSH Transport Layer Protocol
- RFC 4252 - SSH Authentication Protocol
- OpenSSH Certificate Documentation