# 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

1. **Docker Socket Proxy:** Securely proxies the remote server's `/var/run/docker.sock` so Charon can auto-discover containers on the remote host.
2. **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:** `scratch` or `alpine` (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.

1. **User Responsibility**: The user must ensure the host running Orthrus can reach the `CHARON_LINK` address.
2. **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`.
3. **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."

1. **Handshake**: Orthrus connects to `Charon:InternalIP`.
2. **Auth**: Orthrus presents the `AUTH_KEY`.
3. **Registration**: Orthrus tells Charon: *"I have access to Docker Network X and Port Y."*
4. **Tunneling**: Charon requests a resource; Orthrus pipes the data securely over "The Leash."

## 4. Deployment Example (Docker Compose)

```yaml
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.

1. **Transport**: Secure WebSocket (`wss://`) initiates the connection from Orthrus to Charon. This bypasses inbound firewall rules on the remote network.
2. **Multiplexing**: [Yamux](https://github.com/hashicorp/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_KEY` is passed in the `Authorization` header 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"):

1. **Parser**: Intercepts HTTP requests destined for the socket.
2. **Allowlist**: Only permits safe methods/endpoints (e.g., `GET /v1.xx/containers/json`, `GET /v1.xx/info`).
3. **Blocking**: Rejects `POST`, `DELETE`, `PUT` requests (unless explicitly configured to allow specific actions like "Restart Container") with a `403 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

```http
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

1. **Charon** receives a request for a remote container (e.g., user views logs).
2. **Charon** sends `PROXY_REQUEST` on Control Channel.
3. **Orthrus** accepts, opens a new Yamux stream.
4. **Orthrus** dials the local Docker socket.
5. **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.).

```text
/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:latest` and `orthrus: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 via `systemd`.
* **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)

1) Docker Compose

```yaml
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
```

1) Standalone binary + `systemd` (Linux)

```bash
# 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
```

1) Tarball + install script

```bash
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
```

1) Homebrew (macOS / Linuxbrew)

```
brew tap wikid82/charon
brew install orthrus
```

1) 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_KEY` regenerate action in the UI and mark old keys revoked.
