7.4 KiB
XRCON Protocol Specification
Overview
XRCON is a TCP-based remote console protocol implemented as a server within the engine. It provides an alternative to the legacy RCON (which operates over UDP as out-of-band packets). XRCON uses a framed binary protocol over a single persistent TCP connection, accepting at most one client at a time.
Key characteristics:
- Based on TCP (stream-oriented, reliable)
- Default port is 27000
- Maximum only one concurrent client
- Binary framed protocol with a 12-byte header + variable-length payload
Configuration
The XRCON server is controlled by two configuration variables, both restricted to privileged users:
| Variable | Default | Description |
|---|---|---|
xrcon_enable |
0 (disabled) |
Master switch; when enabled, the server starts listening for connections |
xrcon_address |
127.0.0.1:27000 |
Bind address and port; supports both IPv4 and IPv6. Changing this at runtime triggers a XRCON server restart (stop + rebind) |
By default, XRCON binds only to localhost (127.0.0.1), providing a degree of access control. The server will not start listening until explicitly enabled.
Frame Format
All XRCON messages are encapsulated in a framed binary format. Each frame consists of a fixed 12-byte header followed by a variable-length payload.
Header (12 bytes)
| Offset | Size | Field | Description |
|---|---|---|---|
| 0 | 4 | Type | 4-character message type string (null-terminated, occupies 5 bytes in the structure but the 5th byte is padding) |
| 4 | 4 | Version | Protocol version (32-bit unsigned integer, network byte order) |
| 8 | 2 | Length | Total frame length in bytes, including the header (16-bit unsigned integer, network byte order) |
| 10 | 2 | Handle | Handle or sequence number (16-bit unsigned integer, network byte order; currently always zero) |
Protocol Version
The current protocol version is 0x000000D4 (212 decimal). The server also accepts 0x00D40000 for compatibility with certain third-party clients (e.g., CS2RemoteConsole).
Maximum Frame Size
- Maximum payload per frame: 4096 bytes
- Maximum total packet size (header + payload): approximately 4136 bytes
- Receive buffer size: 4096 + 64 bytes
- Transmit buffer size: 16384 bytes (4 × maximum frame size)
Byte Order
Multi-byte integer fields (version, length, handle) are transmitted in network byte order (big-endian).
Message Types
| Type | Direction | Description |
|---|---|---|
CMND |
Client → Server | Execute a console command |
PRNT |
Server → Client | Console output / print message |
CHAN |
Server → Client | Channel list (channel metadata) |
AINF |
Server → Client | Application / server info |
ADON |
Server → Client | Additional info / server name |
CMND — Client Command
Direction: Client → Server
Sent by the client to execute a console command on the server.
| Section | Size | Description |
|---|---|---|
| Header | 12 bytes | Type = "CMND", version, length, handle |
| Payload | Variable | Raw command string (null-terminated) |
The command string is injected into the engine's command buffer for execution. There is no authentication — any connected client may execute arbitrary commands.
PRNT — Server Print
Direction: Server → Client
Sent by the server to stream console output to the connected client.
| Section | Size | Description |
|---|---|---|
| Header | 12 bytes | Type = "PRNT", version, length, handle |
| Channel ID | 4 bytes | Channel identifier (unsigned 32-bit integer; always 0 for "Console") |
| Padding | 20 bytes | Reserved (5 × 32-bit unsigned integers, all zero) |
| Red | 1 byte | Red color component (always 255) |
| Green | 1 byte | Green color component (always 255) |
| Blue | 1 byte | Blue color component (always 255) |
| Alpha | 1 byte | Alpha / opacity component (always 255) |
| Text | Variable | The console output text (up to 4096 bytes) |
CHAN — Channel List
Direction: Server → Client
Sent by the server during the initial handshake (and potentially later) to describe the available console output channels.
| Section | Size | Description |
|---|---|---|
| Header | 12 bytes | Type = "CHAN", version, length, handle |
| Channel Count | 2 bytes | Number of channel records (unsigned 16-bit integer; always 1) |
Each channel record (58 bytes):
| Field | Size | Description |
|---|---|---|
| Channel ID | 4 bytes | Unique channel identifier (unsigned 32-bit integer; always 0) |
| Unknown 1 | 4 bytes | Reserved (unsigned 32-bit integer; always 0) |
| Unknown 2 | 4 bytes | Reserved (unsigned 32-bit integer; always 0) |
| Default Verbosity | 4 bytes | Default verbosity level (unsigned 32-bit integer; always 5) |
| Current Verbosity | 4 bytes | Current verbosity level (unsigned 32-bit integer; always 5) |
| Red | 1 byte | Red color component for the channel (always 255) |
| Green | 1 byte | Green color component (always 255) |
| Blue | 1 byte | Blue color component (always 255) |
| Alpha | 1 byte | Alpha component (always 255) |
| Name | 34 bytes | Channel name string, null-padded (always "Console") |
Total payload size for this frame: 2 + 58 = 60 bytes.
AINF — Application Info
Direction: Server → Client
Sent by the server immediately after a client connects, before ADON and CHAN.
| Section | Size | Description |
|---|---|---|
| Header | 12 bytes | Type = "AINF", version, length, handle |
| Payload | 77 bytes | All zeros (placeholder / reserved for structured application information) |
This packet currently serves as a placeholder and contains no meaningful data. It may be extended in future versions to carry structured metadata about the server application.
ADON — Additional Info
Direction: Server → Client
Sent by the server immediately after AINF during the connection handshake.
| Section | Size | Description |
|---|---|---|
| Header | 12 bytes | Type = "ADON", version, length, handle |
| Unknown | 2 bytes | Reserved (unsigned 16-bit integer; always 0) |
| Name Length | 2 bytes | Length of the name string (unsigned 16-bit integer) |
| Name | Variable | Server name / identifier string (e.g., "HLDS") |
This packet carries the server application name, which is a short string identifying the server type (e.g., "HLDS" for Half-Life Dedicated Server).
Security
XRCON has no built-in authentication or encryption. There is no password validation or transport-layer security. Any client that can establish a TCP connection to the XRCON port has full command execution access to the engine console.
The only security measures are:
- Default localhost binding: The server binds to
127.0.0.1by default, accepting connections only from the local machine. - Disabled by default: The
xrcon_enablevariable defaults to0, so the server does not listen unless explicitly enabled. - Privileged variables: Both configuration variables are restricted to privileged users and cannot be modified through unprivileged console commands or external access.
Comparison with Legacy RCON
| Feature | XRCON | Legacy RCON |
|---|---|---|
| Transport | TCP (stream) | UDP (datagram, out-of-band) |
| Port | Configurable, default 27000 | Game port (default 27015) |
| Framing | Binary frame header | Plain text over UDP |
| Authentication | None | Password-based |
| Max clients | 1 | Multiple |
| Interaction format | Full console access | Request-response only for submitted command |
| Supported environments | Client and server | Server only |