Romania XPlayZM.CSBlackDevil.COM # Zombie Plague UltimateX [ Respawn + FDL + VIP 22-12PM + POINTS] ® 22/32
Unknown ❤ RESPAWN.ZAFEST.RO | VIP FREE | FREE FOR ALL ❤ 0/32
France EMIRATES.KiNGS 亗 GAMEAREA ||͇̿P͇̿U͇̿B͇̿L͇̿I͇̿C͇̿| ✪ 32/32
Prodvigat server
77 lines 5.6 KiB Markdown Source Rendered Raw Permalink History
---
title: "Sending RCON Commands from the Linux Command Line"
excerpt: "How the GoldSrc RCON challenge-response protocol works over UDP, and a self-contained Python script to run rcon commands against a CS 1.6 server from a shell."
category: "administration"
tags: "rcon, cli"
image: ""
read_time: "9 min read"
---
<p>Being able to fire an RCON command at your CS 1.6 server from a shell — <code>changelevel</code>, <code>amx_ban</code>, a config reload — is enormously handy for scripts, cron jobs and quick fixes without launching the game. But GoldSrc RCON is not the TCP protocol that Source-era tools like <code>mcrcon</code> speak; it is a UDP challenge-response scheme, and using the wrong tool just times out. This explains the protocol and gives you a working client.</p>

<h2>1. Know the protocol (why generic tools fail)</h2>
<p>GoldSrc RCON runs over the same UDP game port (default 27015) and works in two steps:</p>
<ol>
<li>The client sends a <code>getchallenge</code> request. The server replies with a one-time challenge number.</li>
<li>The client sends <code>rcon &lt;challenge&gt; "&lt;password&gt;" &lt;command&gt;</code>. The server runs it and returns the console output.</li>
</ol>
<p>Every packet is prefixed with four <code>0xFF</code> bytes. Because it is UDP with a challenge, TCP-based RCON tools (built for Source or Minecraft) cannot talk to it — that is the number-one reason people think "RCON is broken."</p>

<h2>2. Set it up on the server</h2>
<p>RCON must be enabled with a password in <a href="/tutorials/setup-server-cfg-cs16">server.cfg</a>:</p>
<pre>rcon_password "USE-A-LONG-RANDOM-STRING"</pre>
<p>Because RCON is brute-forceable over the network, make the password long and random, and never expose the game port to the whole internet if you can restrict it — see <a href="/tutorials/cs16-server-firewall-ports">which ports to open</a>. On ReHLDS you also get failed-attempt limits worth enabling.</p>

<h2>3. A self-contained Python RCON client</h2>
<p>This implements the two-step handshake with only the standard library:</p>
<pre>#!/usr/bin/env python3
import socket, sys

def rcon(host, port, password, command):
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    s.settimeout(4)
    s.connect((host, port))

    # 1) get a challenge
    s.send(b"\xFF\xFF\xFF\xFFgetchallenge\n")
    reply = s.recv(1400).decode("latin-1", "ignore")
    # reply looks like: \xFF\xFF\xFF\xFFchallenge rcon 1234567890
    challenge = reply.split("rcon")[1].strip()

    # 2) send the command
    pkt = 'rcon %s "%s" %s' % (challenge, password, command)
    s.send(b"\xFF\xFF\xFF\xFF" + pkt.encode("latin-1") + b"\n")
    return s.recv(4096).decode("latin-1", "ignore")

if __name__ == "__main__":
    host, port, pw = sys.argv[1], int(sys.argv[2]), sys.argv[3]
    cmd = " ".join(sys.argv[4:])
    print(rcon(host, port, pw, cmd).lstrip("\xFF").lstrip("l"))</pre>
<p>Save it as <code>rcon.py</code>, make it executable, and call it:</p>
<pre>chmod +x rcon.py
./rcon.py 127.0.0.1 27015 "your-rcon-password" status
./rcon.py 127.0.0.1 27015 "your-rcon-password" changelevel de_inferno</pre>
<p>The reply is prefixed with <code>0xFF 0xFF 0xFF 0xFF l</code>; the script strips that so you get clean console text.</p>

<h2>4. Useful things to run</h2>
<pre>./rcon.py HOST 27015 PW "status"              // players, map, uptime
./rcon.py HOST 27015 PW "amx_map de_nuke"     // change map via AMXX
./rcon.py HOST 27015 PW "exec server.cfg"     // reload config
./rcon.py HOST 27015 PW "amx_reloadadmins"    // re-read users.ini</pre>
<p>Quote a command with arguments as one shell argument if it contains spaces you want kept together, e.g. <code>"say hello everyone"</code>. This is the backbone of remote admin scripting — pair it with the <a href="/tutorials/monitor-server-uptime-alerts">uptime monitor</a> to auto-<code>changelevel</code> off a stuck map, or with the <a href="/tutorials/parse-cs16-server-logs">log parser</a> to react to events.</p>

<h2>5. Keep the password out of your shell history</h2>
<p>A password on the command line lands in <code>~/.bash_history</code> and in <code>ps</code> output. For anything recurring, read it from an environment variable or a mode-600 file instead of typing it inline, and restrict who can run the script.</p>

<h2>Troubleshooting</h2>
<ul>
<li><strong>Timeout / no reply</strong> — the UDP port is firewalled, the server is on a different port, or you are using a TCP RCON tool. Confirm the port answers a normal query first.</li>
<li><strong><code>Bad rcon_password</code></strong> — the password is wrong or was rotated. It must match <code>rcon_password</code> exactly, including case.</li>
<li><strong><code>Bad challenge</code></strong> — you reused an old challenge; each command needs a fresh <code>getchallenge</code>. The script does this every call.</li>
<li><strong>Command runs but returns nothing</strong> — many commands (like <code>changelevel</code>) produce no console text; that is normal. Run <code>status</code> to confirm the channel works.</li>
<li><strong>RCON locked out</strong> — on ReHLDS, repeated bad passwords trip the failure limit and temporarily block your IP. Wait it out and fix the password.</li>
</ul>

<h2>Verification</h2>
<p>Run <code>status</code> against the server and confirm you get the player list and current map back:</p>
<pre>./rcon.py 127.0.0.1 27015 "your-rcon-password" status</pre>
<p>A clean <code>hostname</code>, <code>map</code> and player table means the handshake and password are correct. Then run a harmless state change like <code>exec server.cfg</code> and confirm from the game console that it took. Once the script works locally, you can safely wire it into cron and monitoring.</p>