Reverse Tunnels Infrastructure
Overview
Infrastructure components for enabling public URL access to device web services via AWS IoT Secure Tunneling. Public URL Format:https://device-{dsn}.fleet.roboticks.io
CDK Stack Components
All components are integrated into the mainRoboticksStack in lib/roboticks-stack.ts (lines 1165-1430).
1. DynamoDB Cache Table
Resource:ReverseTunnelCache
Purpose: Fast lookup of tunnel configurations for proxy Lambda
Schema:
tunnel-id-index on tunnel_id for reverse lookups
TTL: Automatic deletion when tunnels expire
Billing: PAY_PER_REQUEST (serverless)
2. Reverse Tunnel Proxy Lambda
Resource:ReverseTunnelProxy
Runtime: Node.js 20.x
Purpose: Route HTTP/WebSocket traffic to AWS IoT Secure Tunnels
Code Location: lambda/reverse-tunnel-proxy/
Handler: index.handler
Timeout: 30 seconds
Memory: 512 MB
VPC: Connected to private subnets with database access
Environment Variables:
TUNNEL_CACHE_TABLE- DynamoDB table nameDB_HOST,DB_PORT,DB_NAME,DB_USER,DB_PASSWORD- PostgreSQLAWS_IOT_REGION- Region for IoT Secure Tunneling
dynamodb:GetItem,dynamodb:PutItemon tunnel cache tablesecretsmanager:GetSecretValuefor database credentialsiotsecuretunneling:DescribeTunnel,iotsecuretunneling:OpenTunnel
- ✅ DSN extraction from subdomain
- ✅ DynamoDB cache lookup with PostgreSQL fallback
- ✅ AWS IoT tunnel status verification
- ⏳ WebSocket proxy implementation (TODO)
3. Tunnel Cache Warmer Lambda
Resource:TunnelCacheWarmer
Runtime: Python 3.11
Purpose: Sync tunnel configs from PostgreSQL to DynamoDB every 5 minutes
Code Location: lambda/tunnel-cache-warmer/
Handler: index.lambda_handler
Timeout: 2 minutes
Memory: 256 MB (default)
VPC: Connected to private subnets with database access
Environment Variables:
TUNNEL_CACHE_TABLE- DynamoDB table nameDB_HOST,DB_PORT,DB_NAME,DB_USER,DB_PASSWORD- PostgreSQL
dynamodb:PutItemon tunnel cache tablesecretsmanager:GetSecretValuefor database credentials
4. EventBridge Schedule
Resource:TunnelCacheWarmerRule
Schedule: Rate(5 minutes)
Target: TunnelCacheWarmer Lambda
Purpose: Keep DynamoDB cache in sync with PostgreSQL
5. Backend IAM Permissions
Added to:backendTaskDefinition.taskRole
Permissions:
6. Backend Environment Variables
Added to:backendContainer
Variable: TUNNEL_CACHE_TABLE = roboticks-reverse-tunnel-cache
Purpose: Backend can read/write tunnel cache for real-time updates
7. API Gateway HTTP API
Resource:ReverseTunnelApi
Purpose: HTTP endpoint for Lambda proxy integration
Type: HTTP API (supports HTTP/1.1, HTTP/2, and WebSocket)
Routes:
/{proxy+}- Catch-all route for all paths/- Root route
ReverseTunnelProxy
CORS: Configured for wildcard origins
URL Format: https://{api-id}.execute-api.{region}.amazonaws.com
8. ACM Certificate
Resource:FleetCertificate
Domain: *.fleet.roboticks.io (wildcard)
Validation: DNS validation via Route53
Purpose: TLS certificate for CloudFront distribution
Region: Same as stack (us-east-1 required for CloudFront)
9. CloudFront Distribution
Resource:TunnelDistribution
Purpose: TLS termination, caching, and DDoS protection
Origin: API Gateway HTTP API
Custom Domains: *.fleet.roboticks.io
Certificate: FleetCertificate (ACM)
Behavior:
- Viewer Protocol: Redirect HTTP to HTTPS
- Allowed Methods: ALL (GET, POST, PUT, DELETE, PATCH, OPTIONS, HEAD)
- Cache Policy: CACHING_DISABLED (proxy traffic, no caching)
- Origin Request Policy: ALL_VIEWER (forward all headers/cookies)
cloudfront-tunnel-logs/ prefix)
Price Class: PRICE_CLASS_100 (North America + Europe only)
10. Route53 DNS Records
Resources:FleetWildcardARecord, FleetWildcardAAAARecord
Domain: *.fleet.roboticks.io
Type: A (IPv4) and AAAA (IPv6) alias records
Target: CloudFront distribution
Purpose: Route all device subdomains to CloudFront
Examples:
device-abc123.fleet.roboticks.io→ CloudFront → API Gateway → Lambdadevice-rpi001.fleet.roboticks.io→ CloudFront → API Gateway → Lambda
Data Flow
Tunnel Creation (Backend → AWS)
- User creates reverse tunnel via frontend UI
- Backend API calls
IoTSecureTunnelService.create_reverse_tunnel() - Service creates AWS IoT Secure Tunnel
- Service stores tunnel_id + tokens in PostgreSQL
reverse_tunnelstable - Backend writes to DynamoDB cache immediately
- Cache warmer syncs to DynamoDB every 5 minutes (redundancy)
Traffic Proxying (Browser → Device)
- Browser navigates to
https://device-abc123.fleet.roboticks.io - Route53 DNS resolves
*.fleet.roboticks.ioto CloudFront distribution - CloudFront terminates TLS using ACM certificate
- CloudFront forwards request to API Gateway HTTP API origin
- API Gateway invokes
ReverseTunnelProxyLambda - Lambda extracts DSN from subdomain (
device-abc123) - Lambda queries DynamoDB cache for tunnel configuration
- Lambda falls back to PostgreSQL if cache miss
- Lambda verifies tunnel is OPEN in AWS IoT Secure Tunneling
- Lambda forwards traffic to IoT Secure Tunnel using
source_access_token(TODO) - Device local proxy agent receives traffic via
destination_access_token - Device forwards to local service (localhost:8080)
Cache Synchronization (PostgreSQL → DynamoDB)
- EventBridge triggers
TunnelCacheWarmerevery 5 minutes - Lambda queries PostgreSQL for active tunnels
- Lambda writes each tunnel to DynamoDB with TTL
- DynamoDB auto-deletes expired entries based on TTL
Stack Outputs
CDK Outputs (added to stack):Deployment
Testing
Test Lambda Functions Locally
Reverse Tunnel Proxy:Invoke Lambda via AWS CLI
Query DynamoDB Cache
Monitoring
CloudWatch Logs
Proxy Lambda:CloudWatch Metrics
Key Metrics:ReverseTunnelProxy.Invocations- Proxy request countReverseTunnelProxy.Errors- Proxy error rateReverseTunnelProxy.Duration- Proxy latencyTunnelCacheWarmer.Invocations- Cache sync frequencyDynamoDB.ConsumedReadCapacityUnits- Cache read loadDynamoDB.ConsumedWriteCapacityUnits- Cache write load
Alarms (Recommended)
Cost Estimation
DynamoDB
- Capacity: PAY_PER_REQUEST (serverless)
- Storage: First 25 GB free
- Reads: $0.25 per million requests
- Writes: $1.25 per million requests
Lambda
Proxy Lambda:- Requests: 100 devices × 1000 req/day × 30 days = 3M requests/month
- Duration: 500ms average
- Cost: ~$10/month (request charges + compute time)
- Requests: 12 invocations/hour × 24 hours × 30 days = 8,640 invocations/month
- Duration: 2-5 seconds
- Cost: ~$0.10/month (negligible)
Total Estimated Cost
100 Devices: ~100-150/monthNext Steps
Infrastructure: ✅ Complete Remaining Implementation:-
Lambda Proxy Logic (~12-16 hours):
- Implement WebSocket-to-WebSocket bidirectional forwarding
- Implement HTTP-to-IoT-Tunnel request proxying
- Add AWS IoT Secure Tunneling Local Proxy protocol support
- Handle connection lifecycle, errors, and retries
-
Device SDK (~4 hours):
- Add reverse tunnel manager to roboticks-sdk
- Fetch tunnel config on device startup
- Start AWS IoT local proxy agents
-
Monitoring (~2 hours):
- Add CloudWatch alarms for proxy errors
- Add CloudWatch alarms for cache warmer failures
- Create dashboard for tunnel metrics
-
Testing (~4 hours):
- End-to-end testing with real devices
- Load testing for concurrent tunnels
- Failover testing (expired tunnels, rotation)
- Cloudflare proxy (currently optional, CloudFront provides DDoS protection)
- Custom CloudWatch metrics for tunnel usage
- X-Ray tracing for Lambda proxy
- API Gateway throttling limits per device