Files
ping_service/manager/GATEWAY.md
2026-01-08 12:11:26 +02:00

348 lines
9.1 KiB
Markdown

# Gateway Mode - External Worker Support
The manager can act as a **gateway/proxy** for external ping_service instances that cannot directly access your internal input/output services. This simplifies deployment for workers running outside your WireGuard network.
## Architecture
```
External Ping Service (Internet)
|
| HTTPS + API Key
v
Manager (Public Internet)
|
+---> Input Services (Private WireGuard)
|
+---> Output Services (Private WireGuard)
```
## Benefits
**Simple Deployment**: External workers only need manager URL + API key
**Single Public Endpoint**: Only manager exposed to internet
**Load Balancing**: Automatic round-robin across healthy backends
**Centralized Auth**: API key management from dashboard
**Monitoring**: Track usage per API key
**Revocable Access**: Instantly disable compromised keys
## Enabling Gateway Mode
Start the manager with the `--enable-gateway` flag:
```bash
sudo ./manager --port=443 --domain=example.dy.fi --enable-gateway
```
## API Key Management
### 1. Generate API Key (Admin)
After logging into the dashboard with TOTP, generate an API key:
```bash
curl -X POST https://example.dy.fi/api/apikeys/generate \
-H "Cookie: auth_session=YOUR_SESSION" \
-H "Content-Type: application/json" \
-d '{
"name": "External Ping Worker #1",
"worker_type": "ping"
}'
```
**Response:**
```json
{
"key": "xLmKj9fR3pQ2vH8nY7tW1sZ4bC6dF5gN0aE3uI2oP7kM9jL8hG4fD1qS6rT5yV3w==",
"name": "External Ping Worker #1",
"worker_type": "ping",
"note": "⚠️ Save this key! It won't be shown again."
}
```
**⚠️ IMPORTANT**: Save the API key immediately - it won't be displayed again!
### 2. List API Keys
```bash
curl https://example.dy.fi/api/apikeys/list \
-H "Cookie: auth_session=YOUR_SESSION"
```
**Response:**
```json
[
{
"key_preview": "xLmKj9fR...yV3w==",
"name": "External Ping Worker #1",
"worker_type": "ping",
"created_at": "2026-01-07 14:23:10",
"last_used_at": "2026-01-07 15:45:33",
"request_count": 1523,
"enabled": true
}
]
```
### 3. Revoke API Key
```bash
curl -X DELETE "https://example.dy.fi/api/apikeys/revoke?key=FULL_API_KEY_HERE" \
-H "Cookie: auth_session=YOUR_SESSION"
```
## Gateway Endpoints
### GET /api/gateway/target
Get next IP address to ping (proxies to input service).
**Authentication**: API Key (Bearer token)
**Request:**
```bash
curl https://example.dy.fi/api/gateway/target \
-H "Authorization: Bearer YOUR_API_KEY"
```
**Response:**
```
203.0.113.42
```
### POST /api/gateway/result
Submit ping/traceroute result (proxies to output service).
**Authentication**: API Key (Bearer token)
**Request:**
```bash
curl -X POST https://example.dy.fi/api/gateway/result \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"source": "203.0.113.1",
"target": "203.0.113.42",
"ping": {
"sent": 4,
"received": 4,
"loss_percent": 0,
"min_rtt": 12.3,
"avg_rtt": 13.1,
"max_rtt": 14.2,
"stddev_rtt": 0.8
},
"traceroute": {
"hops": [
{"hop": 1, "ip": "192.168.1.1", "rtt": 1.2, "timeout": false},
{"hop": 2, "ip": "10.0.0.1", "rtt": 5.3, "timeout": false},
{"hop": 3, "ip": "203.0.113.42", "rtt": 12.3, "timeout": false}
]
}
}'
```
**Response:**
```json
{"status": "ok"}
```
## Configuring External Ping Service
For an external ping service to use the gateway, configure it with:
```bash
export MANAGER_URL="https://example.dy.fi"
export WORKER_API_KEY="xLmKj9fR3pQ2vH8nY7tW1sZ4bC6dF5gN0aE3uI2oP7kM9jL8hG4fD1qS6rT5yV3w=="
export GATEWAY_MODE="true"
```
**Modified ping service main loop:**
```go
// Get target from gateway
req, _ := http.NewRequest("GET", os.Getenv("MANAGER_URL")+"/api/gateway/target", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("WORKER_API_KEY"))
resp, err := client.Do(req)
// ... read target IP
// Perform ping/traceroute
result := performPing(target)
// Submit result to gateway
resultJSON, _ := json.Marshal(result)
req, _ = http.NewRequest("POST", os.Getenv("MANAGER_URL")+"/api/gateway/result",
bytes.NewBuffer(resultJSON))
req.Header.Set("Authorization", "Bearer "+os.Getenv("WORKER_API_KEY"))
req.Header.Set("Content-Type", "application/json")
resp, err = client.Do(req)
```
## Load Balancing
The gateway automatically load balances across healthy backend services:
- **Input Services**: Round-robin across all healthy input workers
- **Output Services**: Round-robin across all healthy output workers
- **Health Awareness**: Only routes to workers marked as healthy by the health poller
If a backend becomes unhealthy, it's automatically removed from the rotation until it recovers.
## Security
### API Key Security
- **256-bit keys**: Cryptographically secure random generation
- **Encrypted storage**: API keys stored with AES-256-GCM encryption
- **Bearer token auth**: Standard OAuth 2.0 bearer token format
- **Usage tracking**: Monitor request count and last used time
- **Instant revocation**: Disable keys immediately if compromised
### Rate Limiting
Gateway endpoints inherit the same rate limiting as other API endpoints:
- **100 requests/minute per IP**
- Logs `API_KEY_INVALID` attempts
- Compatible with fail2ban for IP blocking
### Logging
All gateway activity is logged:
```
API_KEY_AUTH: External Ping Worker #1 (type: ping) from IP 203.0.113.100
```
Failed authentication attempts:
```
API_KEY_MISSING: Request from IP 203.0.113.100
API_KEY_INVALID: Failed auth from IP 203.0.113.100
```
## Monitoring
### Gateway Statistics
Get current gateway pool statistics (admin only):
```bash
curl https://example.dy.fi/api/gateway/stats \
-H "Cookie: auth_session=YOUR_SESSION"
```
**Response:**
```json
{
"input_backends": 3,
"output_backends": 2,
"total_backends": 5
}
```
### Health Checks
The gateway uses the existing worker health poller to track backend availability:
- Polls every 60 seconds
- Only routes to healthy backends
- Automatic failover on backend failure
## Deployment Example
### 1. Start Manager with Gateway
```bash
# On your public server
sudo ./manager --port=443 --domain=example.dy.fi --enable-gateway
```
### 2. Register Internal Workers
From the dashboard, register your internal services:
- Input Service #1: `http://10.0.0.5:8080` (WireGuard)
- Output Service #1: `http://10.0.0.10:9090` (WireGuard)
### 3. Generate API Key
Generate an API key for your external ping worker.
### 4. Deploy External Ping Service
```bash
# On external server (e.g., AWS, DigitalOcean)
export MANAGER_URL="https://example.dy.fi"
export WORKER_API_KEY="your-api-key-here"
export GATEWAY_MODE="true"
./ping_service
```
The external ping service will:
1. Request targets from the manager gateway
2. Perform pings/traceroutes
3. Submit results back through the gateway
4. Manager forwards requests to internal services
## Troubleshooting
### "No healthy backends available"
**Problem**: Gateway returns error when requesting target or submitting results.
**Solution**:
1. Check if input/output services are registered in the dashboard
2. Verify services are marked as "Healthy" (green dot)
3. Check health poller logs: `grep "Health check" /var/log/twostepauth.log`
4. Ensure internal services are reachable from manager
### "Invalid API key"
**Problem**: Gateway rejects API key.
**Solution**:
1. Verify API key hasn't been revoked (check `/api/apikeys/list`)
2. Check key is enabled (`"enabled": true`)
3. Ensure key is sent correctly: `Authorization: Bearer <key>`
4. Check for typos or truncation in environment variable
### High Latency
**Problem**: Gateway adds latency to requests.
**Solution**:
- Gateway adds minimal overhead (~5-10ms for proxy)
- Most latency comes from: External worker → Manager → Internal service
- Consider deploying manager closer to internal services
- Use WireGuard for lower latency between manager and internal services
## Best Practices
1. **Key Rotation**: Rotate API keys periodically (e.g., every 90 days)
2. **One Key Per Worker**: Generate separate keys for each external instance
3. **Descriptive Names**: Use clear names like "AWS-US-East-1-Ping-Worker"
4. **Monitor Usage**: Review `request_count` and `last_used_at` regularly
5. **Revoke Unused Keys**: Remove keys for decommissioned workers
6. **Secure Storage**: Store API keys in environment variables, not in code
7. **Backup Keys**: Keep secure backup of active API keys
## Performance
Gateway performance characteristics:
- **Latency overhead**: ~5-10ms per request
- **Throughput**: Handles 100+ req/s per backend easily
- **Connection pooling**: Maintains persistent connections to backends
- **Concurrent requests**: Go's concurrency handles many simultaneous workers
## Future Enhancements
Potential improvements (not yet implemented):
- [ ] WebSocket support for persistent connections
- [ ] Request caching for frequently accessed targets
- [ ] Metrics endpoint (Prometheus format)
- [ ] Geographic routing (route to closest backend)
- [ ] Custom routing rules (pin worker to specific backend)
- [ ] API key scopes (restrict to specific endpoints)
---
**Last Updated**: 2026-01-07
**Version**: 1.0