Reverse Tunnels - Public URL Access to Devices
Overview
Reverse Tunnels enable exposing device web services (dashboards, cameras, APIs) via public URLs using AWS IoT Secure Tunneling + Cloudflare. This provides secure, authenticated access to devices without requiring them to have public IPs or open inbound firewall ports. Example Use Cases:- Access robot web dashboard at
https://device-abc123.fleet.roboticks.io - View camera feed at
https://device-camera01.fleet.roboticks.io - Monitor sensor data via device API
Architecture
Components
- Database:
reverse_tunnelstable tracks tunnel configurations - Backend API: CRUD endpoints for managing tunnels
- IoT Tunneling Service: Creates/manages AWS IoT Secure Tunnels
- Device Agent: Fetches config on startup, establishes tunnels
- Cloudflare: DNS routing and TLS termination
- Proxy Service: Routes traffic from Cloudflare to IoT tunnels
Database Schema
API Endpoints
Management Endpoints (for users)
List device reverse tunnels:Device Configuration Endpoint
Get tunnel config (called by device on startup):AWS IoT Secure Tunneling
Service Methods
TheIoTSecureTunnelService provides methods for managing reverse tunnels:
Tunnel Lifecycle
- Creation: When user creates reverse tunnel, AWS IoT Secure Tunnel is created immediately
- Device Fetch: Device calls
/reverse-tunnels-configon startup - Activation: Endpoint ensures tunnel is active (rotates if expired/expiring)
- Expiration: Tunnels expire after 12 hours (AWS max)
- Rotation: Celery task rotates tunnels expiring within 1 hour
- Cleanup: Celery task closes expired tunnels
Automatic Maintenance
Two Celery Beat tasks handle tunnel maintenance: 1. Cleanup Expired Tunnels (runs hourly):Device Agent Implementation
The device agent should fetch tunnel config on startup and establish connections.Example Device Agent Code
Device Requirements
-
AWS IoT Secure Tunneling Local Proxy installed:
- Device registration with valid IoT certificate
-
Systemd service to run tunnel manager on startup:
Frontend UI
The Reverse Tunnels page (/reverse-tunnels) provides:
- Device Selector: Choose device to create tunnel for
- Create Tunnel Dialog:
- Name
- Description
- Local Port (default: 8080)
- Protocol (http/https/ws/wss)
- Require Authentication
- Tunnels Table:
- Public URL with copy button
- Target (protocol://localhost:port)
- Enable/Disable toggle
- Usage metrics
- Delete action
- Info Banner: Notifies that config applies on next device startup
Security Considerations
-
Authentication:
require_auth=true: Public URL requires user JWT tokenallowed_user_ids: Restrict access to specific users- Future: Per-tunnel API keys
-
TLS Encryption:
- Cloudflare provides TLS termination
- AWS IoT Secure Tunnel encrypts data in transit
- End-to-end encryption browser → device
-
Access Control:
- Users can only create tunnels for devices in their projects
- Devices authenticate with IoT certificates
- Proxy validates source access tokens
-
Rate Limiting:
- Cloudflare provides DDoS protection
- Future: Per-tunnel rate limits
-
Audit Trail:
total_requeststracks usagelast_accessed_atfor monitoring- Future: Detailed access logs
Production Deployment
Required Infrastructure
-
Cloudflare:
- DNS: Configure
*.fleet.roboticks.io→ API Gateway - SSL/TLS: Full (strict) mode
- Firewall: WAF rules for protection
- DNS: Configure
-
API Gateway / Proxy Service:
- WebSocket support for IoT tunnels
- Lambda or EC2 instance running proxy
- Validate source access tokens
- Forward traffic to AWS IoT endpoints
-
AWS IoT Core:
- Device certificates provisioned
- IoT Secure Tunneling enabled
- Policies configured for tunneling
-
Celery Beat:
- Schedule tunnel cleanup tasks
- Monitor task execution logs
Environment Variables
Troubleshooting
Tunnel Not Working
-
Check tunnel status:
- Check device logs: Verify device fetched config and started local proxy
-
Check tunnel expiration: Tunnels expire after 12 hours
-
Manually rotate tunnel:
Device Not Fetching Config
- Check device registration: Verify device has valid IoT certificate
- Check API authentication: Device should use certificate auth, not JWT
- Check network connectivity: Device must reach backend API
- Check device agent logs: Look for HTTP errors or exceptions
Proxy Errors
- Invalid source access token: Tunnel may have been rotated, fetch new config
- Tunnel closed: Check if tunnel expired or was manually closed
- Connection refused: Verify local service is running on configured port
Future Enhancements
- Per-Tunnel API Keys: Alternative to JWT authentication
- Custom Domains: Allow users to map their own domains
- WebSocket Support: Full duplex communication
- Traffic Analytics: Detailed request logs and metrics
- Bandwidth Limiting: Per-tunnel data caps
- Auto-Scaling: Multiple proxy instances behind load balancer
- Geographic Routing: Route to nearest proxy for lower latency
- Tunnel Sharing: Share public URLs with external users (time-limited)