-
-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Orthrus: Remote Socket Proxy Agent
1. Overview
Orthrus is a lightweight, standalone agent designed to run on remote servers. Named after the brother of Cerberus, its job is to guard the remote resource and securely transport it back to Charon.
It eliminates the need for SSH tunneling or complex port forwarding by utilizing the tunneling protocols managed by Hecate.
2. Operational Logic
Orthrus operates in Reverse Mode. It does not listen on a public port. Instead, it dials out to the tunneling network to connect with Charon.
++-
2.1 Core Functions
- Docker Socket Proxy: Securely proxies the remote server's
/var/run/docker.sockso Charon can auto-discover containers on the remote host. - Service Proxy: Proxies specific localhost ports (e.g., a database on port 5432) over the tunnel.
3. Technical Implementation
3.1 Tech Stack
- Language: Go (Golang)
- Base Image:
scratchoralpine(Goal: < 20MB image size)
3.2 Configuration (Environment Variables)
Orthrus is configured entirely via Environment Variables for easy Docker Compose deployment.
| Variable | Description |
|---|---|
ORTHRUS_NAME |
Unique identifier for this agent (e.g., vps-london-01) |
ORTHRUS_MODE |
socket (Docker Socket) or port (Specific Port) |
CHARON_LINK |
The IP/DNS of the main Charon server (e.g., 100.x.y.z:8080 or charon.example.com) |
AUTH_KEY |
A shared secret or JWT generated by Charon to authorize this agent |
3.3 External Connectivity
Orthrus does NOT manage VPNs or network tunnels internally.
It relies entirely on the host operating system for network connectivity.
- User Responsibility: The user must ensure the host running Orthrus can reach the
CHARON_LINKaddress. - VPNs: If you are using Tailscale, WireGuard, or ZeroTier, you must install and configure the VPN client on the Host OS (or a sidecar container). Orthrus simply dials the IP provided in
CHARON_LINK. - Reverse Mode: Orthrus initiates the connection. Charon waits for the incoming handshake. This means you do not need to open inbound ports on the Orthrus side, but Charon must be reachable.
3.4 The "Leash" Protocol (Communication)
Orthrus communicates with Charon via a custom gRPC stream or WebSocket called "The Leash."
- Handshake: Orthrus connects to
Charon:InternalIP. - Auth: Orthrus presents the
AUTH_KEY. - Registration: Orthrus tells Charon: "I have access to Docker Network X and Port Y."
- Tunneling: Charon requests a resource; Orthrus pipes the data securely over "The Leash."
4. Deployment Example (Docker Compose)
services:
orthrus:
image: wikid82/orthrus:latest
container_name: orthrus-agent
restart: always
environment:
- ORTHRUS_NAME=remote-media-server
- CHARON_LINK=100.x.y.z:8080
- AUTH_KEY=ch_xxxxx_secret
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
# No ports required!5. Security Considerations
- Read-Only Socket: By default, Orthrus mounts the Docker socket as Read-Only to prevent Charon (or a compromised Charon) from destroying the remote server.
- Mutual TLS (mTLS): All communication between Charon and Orthrus should be encrypted via mTLS if not running inside an encrypted VPN (like Tailscale).
6. Implementation Details
6.1 Communication Architecture
Orthrus uses a Reverse Tunnel architecture established via WebSockets with Yamux multiplexing.
- Transport: Secure WebSocket (
wss://) initiates the connection from Orthrus to Charon. This bypasses inbound firewall rules on the remote network. - Multiplexing: Yamux is used over the WebSocket stream to create multiple logical channels.
- Control Channel (Stream ID 0): Handles heartbeats, configuration updates, and command signals.
- Data Channels (Stream ID > 0): Ephemeral streams created for each proxied request (e.g., a single HTTP request to the Docker socket or a TCP connection to a database).
6.2 Authentication & Security
- Token-Based Handshake: The
AUTH_KEYis passed in theAuthorizationheader during the WebSocket Upgrade request. - mTLS (Mutual TLS):
- Charon as CA: Charon maintains an internal Certificate Authority.
- Enrollment: On first connect with a valid
AUTH_KEY, Orthrus generates a private key and sends a CSR. Charon signs it and returns the certificate. - Rotation: Orthrus monitors certificate expiry and initiates a renewal request over the Control Channel 24 hours before expiration.
- Encryption: All traffic is TLS 1.3 encrypted.
6.3 Docker Socket Proxying (The "Muzzle")
To prevent security risks, Orthrus does not blindly pipe traffic to /var/run/docker.sock. It implements an application-level filter (The "Muzzle"):
- Parser: Intercepts HTTP requests destined for the socket.
- Allowlist: Only permits safe methods/endpoints (e.g.,
GET /v1.xx/containers/json,GET /v1.xx/info). - Blocking: Rejects
POST,DELETE,PUTrequests (unless explicitly configured to allow specific actions like "Restart Container") with a403 Forbidden.
6.4 Heartbeat & Health
- Mechanism: Orthrus sends a custom "Ping" packet over the Control Channel every 5 seconds.
- Timeout: Charon expects a "Ping" within 10 seconds. If missed, the agent is marked
Offline. - Reconnection: Orthrus implements exponential backoff (1s, 2s, 4s... max 30s) to reconnect if the link is severed.
7. Protocol Specification ("The Leash")
7.1 Handshake
GET /api/v1/orthrus/connect HTTP/1.1
Host: charon.example.com
Upgrade: websocket
Connection: Upgrade
Authorization: Bearer <AUTH_KEY>
X-Orthrus-Version: 1.0.0
X-Orthrus-ID: <ORTHRUS_NAME>7.2 Message Types (Control Channel)
Messages are Protobuf-encoded for efficiency.
HEARTBEAT:{ timestamp: int64, load_avg: float, memory_usage: int }PROXY_REQUEST: Sent by Charon to request a new stream.{ stream_id: int, target_type: "docker"|"tcp", target_addr: "localhost:5432" }CONFIG_UPDATE: Sent by Charon to update allowlists or rotation policies.
7.3 Data Flow
- Charon receives a request for a remote container (e.g., user views logs).
- Charon sends
PROXY_REQUESTon Control Channel. - Orthrus accepts, opens a new Yamux stream.
- Orthrus dials the local Docker socket.
- Orthrus pipes the stream, applying "The Muzzle" filter in real-time.
8. Repository Structure (Monorepo)
Orthrus resides in the same repository as Charon to ensure protocol synchronization and simplified CI/CD.
8.1 Directory Layout
To maintain a lightweight footprint (< 20MB), Orthrus uses a separate Go module within the agent/ directory. This prevents it from inheriting Charon's heavy backend dependencies (GORM, SQLite, etc.).
/projects/Charon
├── go.work # Manages the workspace (includes ./backend and ./agent)
├── backend/ # The Main Server (Heavy)
│ ├── go.mod
│ └── ...
├── agent/ # Orthrus (Lightweight)
│ ├── go.mod # Separate dependencies (Standard Lib + Yamux)
│ ├── main.go
│ └── Dockerfile # Separate build process
└── protocol/ # Shared Definitions (Protobufs)
├── go.mod
└── leash.proto
8.2 Build Strategy
- Charon: Built from
backend/Dockerfile. - Orthrus: Built from
agent/Dockerfile. - CI/CD: A single GitHub Action workflow builds and pushes both images (
charon:latestandorthrus:latest) synchronously.
9. Packaging & Install Options
Orthrus should be distributed in multiple formats so users can choose one that fits their environment and security posture.
9.1 Supported Distribution Formats
- Docker / Docker Compose: easiest for container-based hosts.
- Standalone static binary (recommended): small, copy to
/usr/local/bin, run viasystemd. - Deb / RPM packages: for managed installs via
apt/yum. - Homebrew formula: for macOS / Linuxbrew users.
- Tarball with installer: for offline or custom installs.
- Kubernetes DaemonSet: for fleet deployment inside clusters.
9.2 Quick Install Snippets (copyable)
- Docker Compose
version: "3.8"
services:
orthrus:
image: wikid82/orthrus:latest
restart: always
environment:
- ORTHRUS_NAME=remote-media-server
- CHARON_LINK=100.x.y.z:8080
- AUTH_KEY=REPLACE_WITH_AUTH_KEY
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro- Standalone binary +
systemd(Linux)
# download and install
curl -L https://example.com/orthrus/latest/orthrus-linux-amd64 -o /usr/local/bin/orthrus
chmod +x /usr/local/bin/orthrus
# systemd unit (/etc/systemd/system/orthrus.service)
cat > /etc/systemd/system/orthrus.service <<'EOF'
[Unit]
Description=Orthrus agent
After=network.target
[Service]
Environment=ORTHRUS_NAME=remote-media-server
Environment=CHARON_LINK=100.x.y.z:8080
Environment=AUTH_KEY=REPLACE_WITH_AUTH_KEY
ExecStart=/usr/local/bin/orthrus
Restart=on-failure
User=root
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now orthrus- Tarball + install script
curl -L -o orthrus.tar.gz https://example.com/orthrus/vX.Y.Z/orthrus-linux-amd64.tar.gz
sha256sum orthrus.tar.gz # compare with UI-provided hash
tar -xzf orthrus.tar.gz -C /usr/local/bin
chmod +x /usr/local/bin/orthrus
# then use the systemd unit above- Homebrew (macOS / Linuxbrew)
brew tap wikid82/charon
brew install orthrus
- Kubernetes DaemonSet
Provide a DaemonSet YAML referencing the orthrus image and the required env vars (AUTH_KEY, CHARON_LINK), optionally mounting the Docker socket or using hostNetworking.
9.3 Security & UX Notes
- Provide SHA256 checksums and GPG signatures for binary downloads.
- Avoid recommending
curl | sh; prefer explicit steps and checksum verification. - The Hecate UI should present each snippet as a selectable tab with a copy button and an inline checksum.
- Offer a one-click
AUTH_KEYregenerate action in the UI and mark old keys revoked.
Auto-created from orthrus.md
Metadata
Metadata
Assignees
Labels
Projects
Status