5.5 KiB
Hecate: Tunnel & Pathway Manager
1. Overview
Hecate is the internal module within Charon responsible for managing third-party tunneling services. It serves as the "Goddess of Pathways," allowing Charon to route traffic not just to local ports, but through encrypted tunnels to remote networks without exposing ports on the public internet.
2. Architecture
Hecate is not a separate binary; it is a Go package (internal/hecate) running within the main Charon daemon.
2.1 The Provider Interface
To support multiple services (Tailscale, Cloudflare, Netbird), Hecate uses a strict Interface pattern.
type TunnelProvider interface {
// Name returns the unique ID of the provider (e.g., "tailscale-01")
Name() string
// Status returns the current health (Connected, Connecting, Error)
Status() TunnelState
// Start initiates the tunnel daemon
Start(ctx context.Context) error
// Stop gracefully terminates the connection
Stop() error
// GetAddress returns the internal IP/DNS routed through the tunnel
GetAddress() string
}
2.2 Supported Integrations (Phase 1)
Cloudflare Tunnels (cloudflared)
- Mechanism: Charon manages the
cloudflaredbinary viaos/exec. - Config: User provides the Token via the UI.
- Outcome: Exposes Charon directly to the edge without opening port 80/443 on the router.
Tailscale / Headscale
- Mechanism: Uses
tsnet(Tailscale's Go library) to embed the node directly into Charon, OR manages thetailscaledsocket. - Outcome: Charon becomes a node on the Mesh VPN.
3. Dashboard Implementation (Frontend)
A new tab "Hecate / Tunnels" will be added to the Charon Dashboard.
- Tunnel Cards: Display status of connected services.
- Auth Manager: Input fields for API Keys/Auth Tokens.
- Routing Table: A visual map showing which external domains map to which tunnel.
4. API Endpoints
GET /api/hecate/status- Returns health of all tunnels.POST /api/hecate/configure- Accepts auth tokens and provider types.POST /api/hecate/logs- Streams logs from the underlying tunnel binary (e.g., cloudflared logs) for debugging.
5. Security (Cerberus Integration)
Traffic entering through Hecate must still pass through Cerberus.
- Tunnels terminate before the middleware chain.
- Requests from a Cloudflare Tunnel are tagged
source:tunneland subjected to the same WAF rules as standard traffic.
6. Implementation Details
6.1 Process Supervision
Hecate will act as a process supervisor for external binaries like cloudflared.
- Supervisor Pattern: A
TunnelManagerstruct will maintain a map of activeTunnelProviderinstances. - Lifecycle:
- On startup,
TunnelManagerloads enabled configs from the DB. - It launches the binary using
os/exec. - It monitors the process state. If the process exits unexpectedly, it triggers a Restart Policy (Exponential Backoff: 5s, 10s, 30s, 1m).
- On startup,
- Graceful Shutdown: When Charon shuts down, Hecate must send
SIGTERMto all child processes and wait (with timeout) for them to exit.
6.2 Secrets Management
API tokens and sensitive credentials must not be stored in plaintext.
- Encryption: Sensitive fields (like Cloudflare Tokens) will be encrypted at rest in the SQLite database using AES-GCM.
- Key Management: An encryption key will be generated on first run and stored in
data/keys/hecate.key(secured with 600 permissions), or provided viaCHARON_SECRET_KEYenv var.
6.3 Logging & Observability
- Capture: The
TunnelProviderimplementation will attach to theStdoutandStderrpipes of the child process. - Storage:
- Hot Logs: A circular buffer (Ring Buffer) in memory (last 1000 lines) for real-time dashboard viewing.
- Cold Logs: Rotated log files stored in
data/logs/tunnels/<provider>.log.
- Streaming: The frontend will consume logs via a WebSocket endpoint (
/api/ws/hecate/logs/:id) or Server-Sent Events (SSE) to display real-time output.
6.4 Frontend Components
- TunnelStatusBadge: Visual indicator (Green=Connected, Yellow=Starting, Red=Error/Stopped).
- LogViewer: A terminal-like component (using
xterm.jsor a virtualized list) to display the log stream. - ConfigForm: A dynamic form that renders fields based on the selected provider (e.g., "Token" for Cloudflare, "Auth Key" for Tailscale).
7. Database Schema
We will introduce a new GORM model TunnelConfig in internal/models.
package models
import (
"time"
"github.com/google/uuid"
"gorm.io/datatypes"
)
type TunnelProviderType string
const (
ProviderCloudflare TunnelProviderType = "cloudflare"
ProviderTailscale TunnelProviderType = "tailscale"
)
type TunnelConfig struct {
ID uuid.UUID `gorm:"type:uuid;primaryKey" json:"id"`
Name string `gorm:"not null" json:"name"` // User-friendly name (e.g., "Home Lab Tunnel")
Provider TunnelProviderType `gorm:"not null" json:"provider"`
// EncryptedCredentials stores the API token or Auth Key.
// It is encrypted at rest and decrypted only when starting the process.
EncryptedCredentials []byte `gorm:"not null" json:"-"`
// Configuration stores provider-specific settings (JSON).
// e.g., Cloudflare specific flags, region settings, etc.
Configuration datatypes.JSON `json:"configuration"`
IsActive bool `gorm:"default:false" json:"is_active"` // User's desired state
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}