-
Notifications
You must be signed in to change notification settings - Fork 1
Protocol
This page describes the message protocol used between the server and agents, including transport, authentication, encryption, framing, and message types.
Rosemary supports two agent transport modes:
| Mode | Transport | Direction | Use case |
|---|---|---|---|
agent |
QUIC/UDP on the server agent port, default 2048
|
Agent connects to server | Normal outbound agent mode |
agent-bind |
Encrypted TCP frames | Server connects to agent | Environments where the server can reach the agent but the agent cannot reach the server |
The HTTP dashboard and REST API stay on the HTTP port, default 1024. The dashboard WebSocket is only for browser updates and is not the agent transport.
Outbound Go agents connect to the server with QUIC using the rosemary-quic/1 ALPN. The server listens on -agent-port, default 2048/udp.
After the QUIC connection is established:
- The agent opens the control stream.
- The agent sends an HMAC authentication token derived from the shared key.
- The server verifies the token before accepting registration.
- Control messages and data envelopes flow over QUIC streams.
The certificate material is deterministic from the shared key, and the client verifies the expected server certificate. This binds the QUIC session to the configured Rosemary key.
Bind mode uses a TCP listener on the agent. The server connects with:
connect <agent-ip>:9001
Frames are length-prefixed and contain AES-GCM encrypted Rosemary messages. This mode is useful when the agent is reachable from the server but cannot initiate outbound UDP to the server.
Control messages are JSON objects carried inside transport envelopes. Bind-mode frames use:
+-------------------+-----------------------------+
| 4 bytes (big-end) | N bytes (encrypted payload) |
+-------------------+-----------------------------+
length prefix AES-256-GCM ciphertext
The 4-byte length prefix is a big-endian uint32 indicating the byte length of the payload that follows.
Rosemary message payloads use AES-256-GCM.
| Parameter | Value |
|---|---|
| Algorithm | AES-256-GCM |
| Key size | 32 bytes |
| Key encoding | Base64url |
| Nonce | Random, 12 bytes, prepended to ciphertext |
| Scope | Independent nonce per encrypted message |
The shared key is configured on both server and agent. There is no key exchange; the key must be distributed out of band.
Data payloads may optionally be compressed with DEFLATE before encryption:
- Only applied when payload size exceeds 256 bytes
- Only applied when compression reduces the payload size
- The receiver detects compression from the message flag
All control messages are JSON objects. Common fields:
| Field | Description |
|---|---|
type |
Message type string |
conn_id |
Connection identifier for routing data |
original_agent_id |
Source agent for multi-hop relaying |
target_agent_id |
Destination agent for multi-hop relaying |
| Type | Direction | Description |
|---|---|---|
register |
Agent to Server | Agent sends subnets, OS, hostname, username, internet status |
register_ok |
Server to Agent | Server confirms registration and returns assigned agent ID |
| Type | Direction | Description |
|---|---|---|
heartbeat |
Agent to Server | Sent every 10 seconds |
| Type | Direction | Description |
|---|---|---|
connect |
Server to Agent | Open a TCP or UDP connection to a target host and port |
connect_response |
Agent to Server | Success or failure of the connect request |
data |
Bidirectional | Raw payload for an open connection, optionally DEFLATE compressed |
| Type | Direction | Description |
|---|---|---|
icmp-request |
Server to Agent | Ping a target host via the agent |
icmp-response |
Agent to Server | Result of the ping including RTT and success status |
icmp_proxy |
Server to Agent | Transparently proxy an ICMP echo request |
icmp_proxy_response |
Agent to Server | Result of the proxied ICMP echo |
| Type | Direction | Description |
|---|---|---|
dns_request |
Server to Agent | DNS query to resolve via the agent's resolver |
dns_response |
Agent to Server | DNS answer records |
| Type | Direction | Description |
|---|---|---|
ping-sweep-request |
Server to Agent | Discover live hosts in a subnet using concurrent TCP probing |
ping-sweep-response |
Agent to Server | List of live hosts found |
port-scan-request |
Server to Agent | TCP or UDP port scan on a target |
port-scan-response |
Agent to Server | List of open ports found |
| Type | Direction | Description |
|---|---|---|
start-agent-listener |
Server to Agent | Open a local TCP or UDP port forward on the agent |
start-agent-listener-response |
Agent to Server | Result of listener startup |
stop-agent-listener |
Server to Agent | Close a port forward |
| Type | Direction | Description |
|---|---|---|
agent_fwd_open |
Agent to Server | Agent requests to open a reverse forward |
agent_fwd_ack |
Server to Agent | Server acknowledges the reverse forward |
agent_fwd_data |
Bidirectional | Data relay for an active reverse forward |
| Type | Direction | Description |
|---|---|---|
reconnect |
Server to Agent | Tell the agent to disconnect and reconnect |
disconnect |
Server to Agent | Tell the agent to exit |
Messages include original_agent_id and target_agent_id fields. When the server receives a message addressed to a different agent than the sender, it relays it to the target agent. This enables multi-hop pivoting where traffic can be routed through a chain of agents.
Use only on systems you own or have explicit written permission to test. Unauthorized use is prohibited.