Connection flow
The agent separates orchestration (control) from operational traffic (data):
- Control socket: A Socket.IO component, which is used to transmit agent metadata and receive control instructions from the server (reset/kill, etc.)
- Data socket: An SSH channel, which may be encapsulated depending on egress filtering restrictions, which is used to tunnel operational traffic (proxies, SSH access, pivoting services, etc.)
If a connection is lost, the agent automatically attempts to reconnect to both channels using an exponential backoff strategy.
Control socket
The control socket is a Socket.IO client/server. It works on:
- WebSocket (via HTTP Upgrade)
- HTTP long polling
- Encapsulated over DNS – in this mode, the WebSocket transport is tunneled through DNS queries and responses, allowing the control channel to operate in environments where only DNS egress is allowed.
All control messages are encrypted, except for the agent identifier, which is transmitted in cleartext to allow the server to associate the connection with the correct agent instance.
The initial message is encrypted using the server’s age public key, which is embedded in the agent binary.
During this step, the agent generates and transmits a symmetric session key.
All subsequent control messages are encrypted using this symmetric key.
Data socket
The data socket is an outbound SSH connection initiated by the agent to the server, allowing the connection to traverse NAT and restrictive firewalls.
This SSH connection may be encapsulated over tunnels (see agent/tunnels and server/services)
Through SSH remote port forwarding, the agent exposes several services to the server, including:
- SSH access to the agent host
- SOCKS and HTTP proxy services
- a WireGuard endpoint for network pivoting
SSH authentication uses an ephemeral public key generated by the server for each agent connection.
