Remote console is how you administer a running Call of Duty server without restarting it. It is a single UDP request/response with the password in cleartext, which tells you most of what you need to know about how much to trust it.
The cvar name differs per game
| Game | Cvar |
|---|---|
| Call of Duty 1 | rconpassword |
| Call of Duty: United Offensive | rconpassword |
| Call of Duty 2 | rcon_password |
| Call of Duty 4 | rcon_password |
| Call of Duty: World at War | rcon_password |
Setting the wrong one leaves rcon disabled with no error at startup. A config copied from a CoD1 server to a CoD2 server is the most common cause of "rcon does not work".
Using it from the game console
Connect to the server, open the console and set the password once:
/rconpassword mysecret // CoD1 / UO
/rcon_password mysecret // CoD2 / CoD4 / WaW
/rcon status
/rcon map mp_carentan
Useful commands
| Command | Effect |
|---|---|
status |
Player list with slot number, score, ping, GUID, IP |
serverinfo |
Current cvar snapshot |
map <name> |
Change map immediately |
map_rotate |
Advance to the next entry in sv_mapRotation |
map_restart |
Restart current map, keeps scores |
fast_restart |
Restart the round without reloading the map |
kick <name> |
Kick by name |
clientkick <slot> |
Kick by slot number from status |
banclient <slot> |
Ban by slot |
tempbanclient <slot> |
Temporary ban |
say <text> |
Server message in chat |
set <cvar> <value> |
Change any cvar |
<cvar> |
Read a cvar back |
Reading a cvar back returns the current and default value:
"sv_maxclients" is:"20^7" default:"8^7"
That echo is the basis of the verification pattern below.
The wire protocol
Quake3-derived, so it is four 0xFF bytes followed by a plain-text command:
\xff\xff\xff\xffrcon <password> <command>
The reply is:
\xff\xff\xff\xffprint\n<output>
Which means you never need a client library:
import socket
def rcon(host, port, password, command, timeout=2.0):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.settimeout(timeout)
s.sendto(b'\xff\xff\xff\xffrcon %s %s' % (password.encode(), command.encode()),
(host, port))
out = b''
try:
while True:
out += s.recv(8192)
except socket.timeout:
pass
return out.decode('latin-1', 'replace').replace('\xff\xff\xff\xffprint\n', '')
print(rcon('127.0.0.1', 28960, 'mysecret', 'status'))
The same trick gives you a server query without rcon at all, which is how server browsers work:
printf '\xff\xff\xff\xffgetstatus' | nc -u -w2 YOUR.IP 28960 | head -c 400
If that returns configstrings, your server is reachable from the outside and any "not in the browser" problem is master-side. See server not in the browser.
Flood protection: the trap that eats automation
CoD applies sv_floodProtect to rcon. Two rcon commands within roughly 500 ms collapse,
and the second one comes back as Bad rconpassword. or an empty reply.
That response is indistinguishable from a genuinely wrong password or a dropped UDP packet.
It gets worse: a set <cvar> <value> returns an empty reply even on success. So there
is no way to distinguish a landed set from a lost one by looking at the response.
The consequences for anything scripted:
- Space rcon commands at least 600 ms apart.
- Treat an empty reply or
Bad rconpasswordas probably flood, and retry, rather than concluding your password is wrong. - Never trust a one-shot
set.
Set-and-verify
The reliable pattern is to set, read back, compare, and retry with jitter:
import time, random
def set_cvar_verified(host, port, password, cvar, value, attempts=5):
for i in range(attempts):
rcon(host, port, password, f'set {cvar} "{value}"')
time.sleep(0.7)
echo = rcon(host, port, password, cvar)
if f'"{cvar}" is:"{value}' in echo:
return True
time.sleep(1 + random.random() * 2)
return False
This is not theoretical. A scheduled job that flipped a gameplay cvar once, had the packet dropped by flood protection, and never verified it, left a public server stuck in the wrong mode for hours. One read-back would have caught it.
Log noise you can ignore
Two lines appear constantly in server logs and mean nothing is wrong:
Rcon from <ip>:<negative port>
cmdCount > MAX_PACKET_USERCMDS
The first is NAT artefacts in the port field, the second is a client sending user commands faster than the server samples them. Filter both out before reading logs:
grep -v 'cmdCount\|MAX_PACKET\|Rcon from' server.log | tail -50
Security
The password travels in cleartext in a UDP datagram, and there is no rate limit on authentication attempts beyond flood protection. Therefore:
- Use a long random password, not a word.
- Use a different password per server.
- Do not reuse it anywhere else.
- Where possible, firewall the game port to accept rcon only from your admin addresses.
Tools
The CoD RCON Tool on war24.net is a Windows GUI client for the classic titles. For anything scripted, the twenty lines of Python above are usually a better fit than a GUI.
For a persistent admin layer with bans, roles and chat commands, look at B3 (BigBrotherBot), which parses the server log and drives rcon.
