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.
-
classmethod
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
orNone
depending on whetherblock
wasTrue
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 ofexit
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!"