Source Remote Console (RCON)

Source remote console (or RCON) provides a way for server operators to administer and interact with their servers remotely in the same manner as the console provided by srcds. The valve.rcon module provides an implementation of the RCON protocol.

RCON is a simple, TCP-based request-response protocol with support for basic authentication. The RCON client initiates a connection to a server and attempts to authenticate by submitting a password. If authentication succeeds then the client is free to send further requests. These subsequent requests are interpreted the same way as if you were to type them into the srcds console.

Warning

Passwords and console commands are sent in plain text. Tunneling the connection through a secure channel may be advisable where possible.

Note

Multiple RCON authentication failures in a row from a single host will result in the Source server automatically banning that IP, preventing any subsequent connection attempts.

High-level API

The valve.rcon module provides a number of ways to interact with RCON servers. The simplest is the execute() function which executes a single command on the server and returns the response as a string.

In many cases this may be sufficient but it’s important to consider that execute() will create a new, temporary connection for every command. If order to reuse a connection the RCON class should be used directly.

Also note that execute() only returns Unicode strings which may prove problematic in some cases. See Unicode and String Encoding.

valve.rcon.execute(address, password, command)

Execute a command on an RCON server.

This is a very high-level interface which connects to the given RCON server using the provided credentials and executes a command.

Parameters:
  • address – the address of the server to connect to as a tuple containing the host as a string and the port as an integer.
  • password (str) – the password to use to authenticate the connection.
  • command (str) – the command to execute on the server.
Raises:
  • UnicodeDecodeError – if the response could not be decoded into Unicode.
  • RCONCommunicationError – if a connection to the RCON server could not be made.
  • RCONAuthenticationError – if authentication failed, either due to being banned or providing the wrong password.
  • RCONMessageError – if the response body couldn’t be decoded into a Unicode string.
Returns:

the response to the command as a Unicode string.

Core API

The core API for the RCON implementation is split encapsulated by two distinct classes: RCONMessage and RCON.

Representing RCON Messages

Each RCON message, whether a request or a response, is represented by an instance of the RCONMessage class. Each message has three fields: the message ID, type and contents or body. The message ID of a request is reflected back to the client when the server returns a response but is otherwise unsued by this implementation. The type is one of four constants (represented by three distinct values) which signifies the semantics of the message’s ID and body. The body it self is an opaque string; its value depends on the type of message.

class valve.rcon.RCONMessage(id_, type_, body_or_text)

Represents a RCON request or response.

classmethod decode(buffer_)

Decode a message from a bytestring.

This will attempt to decode a single message from the start of the given buffer. If the buffer contains more than a single message then this must be called multiple times.

Raises:MessageError – if the buffer doesn’t contain a valid message.
Returns:a tuple containing the decoded RCONMessage and the remnants of the buffer. If the buffer contained exactly one message then the remaning buffer will be empty.
encode()

Encode message to a bytestring.

text

Get the body of the message as Unicode.

Raises:UnicodeDecodeError – if the body cannot be decoded as ASCII.
Returns:the body of the message as a Unicode string.

Note

It has been reported that some servers may not return valid ASCII as they’re documented to do so. Therefore you should always handle the potential UnicodeDecodeError.

If the correct encoding is known you can manually decode body for your self.

Unicode and String Encoding

The type of the body field of RCON messages is documented as being a double null-terminated, ASCII-encoded string. At the Python level though both Unicode strings and raw byte string interfaces are provided by RCONMessage.text and RCONMessage.body respectively.

In Python you are encouraged to deal with text (a.k.a. Unicode strings) in preference to raw byte strings unless strictly neccessary. However, it has been reported that under some conditions RCON servers may return invalid ASCII sequences in the response body. Therefore it is possible that the textual representation of the body cannot be determined and attempts to access RCONMessage.text will fail with a UnicodeDecodeError being raised.

It appears – but is not conclusively determined – that RCON servers in fact return UTF-8-encoded message bodies, hence why ASCII seems to to work in most cases. Until this can be categorically proven as the behaviour that should be expected Python-valve will continue to attempt to process ASCII strings.

If you come across UnicodeDecodeError whilst accessing response bodies you will instead have to make-do and handle the raw byte strings manually. For example:

response = rcon.execute("command")
response_text = response.body.decode("utf-8")

If this is undesirable it is also possible to globally set the encoding used by RCONMessage but this not particularly encouraged:

import valve.rcon

valve.rcon.RCONMessage.ENCODING = "utf-8"

Creating RCON Connections

class valve.rcon.RCON(address, password, timeout=None)

Represents an RCON connection.

__call__(command)

Invoke a command.

This is a higher-level version of execute() that always blocks and only returns the response body.

Raises:RCONMessageError – if the response body couldn’t be decoded into a Unicode string.
Returns:the response to the command as a Unicode string.
authenticate(timeout=None)

Authenticate with the server.

This sends an authentication message to the connected server containing the password. If the password is correct the server sends back an acknowledgement and will allow all subsequent commands to be executed.

However, if the password is wrong the server will either notify the client or immediately drop the connection depending on whether the client IP has been banned or not. In either case, the client connection will be closed and an exception raised.

Note

Client banning IP banning happens automatically after a few failed attempts at authentication. Assuming you can direct access to the server’s console you can unban the client IP using the removeip command:

Banning xxx.xxx.xxx.xx for rcon hacking attempts
] removeip xxx.xxx.xxx.xxx
removeip:  filter removed for xxx.xxx.xxx.xxx
param timeout:the number of seconds to wait for a response. If not given the connection-global timeout is used.
raises RCONAuthenticationError:
 if authentication failed, either due to being banned or providing the wrong password.
raises RCONTimeoutError:
 if the server takes too long to respond. The connection will be closed in this case as well.
Raises:
  • RCONError – if closed.
  • RCONError – if not connected.
authenticated

Determine if the connection is authenticated.

close()

Close connection to a server.

closed

Determine if the connection has been closed.

connect()

Create a connection to a server.

Raises:
  • RCONError – if closed.
  • RCONError – if connected.
connected

Determine if a connection has been made.

Note

Strictly speaking this does not guarantee that any subsequent attempt to execute a command will succeed as the underlying socket may be closed by the server at any time. It merely indicates that a previous call to connect() was successful.

cvarlist()

Get all ConVars for an RCON connection.

This will issue a cvarlist command to it in order to enumerate all available ConVars.

Returns:an iterator of :class:`ConVar`s which may be empty.
execute(command, block=True, timeout=None)

Invoke a command.

Invokes the given command on the conncted server. By default this will block (up to the timeout) for a response. This can be disabled if you don’t care about the response.

param str command:
 the command to execute.
param bool block:
 whether or not to wait for a response.
param timeout:the number of seconds to wait for a response. If not given the connection-global timeout is used.
raises RCONCommunicationError:
 if the socket is closed or in any other erroneous state whilst issuing the request or receiving the response.
raises RCONTimeoutError:
 if the timeout is reached waiting for a response. This doesn’t close the connection but the response is lost.
returns:the response to the command as a RCONMessage or None depending on whether block was True or not.
Raises:
  • RCONError – if not authenticated.
  • RCONError – if not connected.

Example

import valve.rcon

address = ("rcon.example.com", 27015)
password = "top-secrect-password"
with valve.rcon.RCON(address, password) as rcon:
    response = rcon.execute("echo Hello, world!")
    print(response.text)

Command-line Client

As well as providing means to programatically interact with RCON servers, the valve.rcon module also provides an interactive, command-line client. A client shell can be started by calling shell() or running the valve.rcon module.

valve.rcon.shell(address=None, password=None)

A simple interactive RCON shell.

This will connect to the server identified by the given address using the given password. If a password is not given then the shell will prompt for it. If no address is given, then no connection will be made automatically and the user will have to do it manually using !connect.

Once connected the shell simply dispatches commands and prints the response to stdout.

Parameters:
  • address – a network address tuple containing the host and port of the RCON server.
  • password (str) – the password for the server. This is ignored if address is not given.

Using the RCON Shell

When shell() is executed, an interactive RCON shell is created. This shell reads commands from stdin, passes them to a connected RCON server then prints the response to stdout in a conventional read-eval-print pattern.

By default, commands are treated as plain RCON commmands and are passed directly to the connected server for evaluation. However, commands prefixed with an exclamation mark are interpreted by the shell it self:

!connect

Connect to an RCON server. This command accepts two space-separated arguments: the address of the server and the corresponding password; the latter is optional. If the password is not given the user is prompted for it.

If the shell is already connected to a server then it will disconnect first before connecting to the new one.

!disconnect
Disconnect from the current RCON server.
!shutdown
Shutdown the RCON server. This actually just sends an exit command to the server. This must be used instead of exit as its behaviour could prove confusing with !exit otherwise.
!exit
Exit the shell. This does not shutdown the RCON server.

Help is available via the help command. When connected, an optional argument can be provided which is the RCON command to show help for.

When connected to a server, command completions are provided via the tab key.

Command-line Invocation

The valve.rcon module is runnable. When ran with no arguments its the same as calling shell() with defaults. As with shell(), the address and password can be provided as a part of the invoking command:

$ python -m valve.rcon
$ python -m valve.rcon rcon.example.com:27015
$ python -m valve.rcon rcon.example.com:27015 --password TOP-SECRET

Warning

Passing sensitive information via command-line arguments, such as your RCON password, can be dangerous. For example, it can show up in ps output.

Executing a Single Command

When ran, the module has two modes of execution: the default, which will spawn an interactive RCON shell and the single command execution mode. When passed the --execute argument, python -m valve.rcon will run the given command and exit with a status code of zero upon completion. The command response is printed to stdout.

This can be useful for simple scripting of RCON commands outside of a Python environment, such as in a shell script.

$ python -m valve.rcon rcon.example.com:27015 \
    --password TOP-SECRET --execute "echo Hello, world!"

Usage