Unknown ❤ RESPAWN.ZAFEST.RO | VIP FREE | FREE FOR ALL ❤ 0/32
Romania XPlayZM.CSBlackDevil.COM # Zombie Plague UltimateX [ Respawn + FDL + VIP 22-12PM + POINTS] ® 16/32
Prodvigat server

Add 6 tutorials (6 files)

Browse Source
Daemon666 committed parent 39d4316022 commit 79551703e440f8a6d96b77e204a00ef89cc3126a
6 changed files with 329 additions and 0 deletions
+81 -0 auto-restart-on-crash/en.md A
@@ -0,0 +1,81 @@
1 +---
2 +title: "Auto-Restart on Crash (hlds_run and Wrapper Scripts)"
3 +excerpt: "Keep a CS 1.6 server up 24/7: how hlds_run already restarts on crash, the -pingboost and -norestart flags, and a systemd unit or screen loop that survives a hard fault."
4 +category: "administration"
5 +tags: "uptime, crash"
6 +image: ""
7 +read_time: "8 min read"
8 +---
9 +<p>A CS 1.6 server process will eventually die on its own &mdash; a bad plugin, a malformed packet, an out-of-memory kill, or the classic <code>SegV</code>. If nothing is watching, it stays down until you notice, and on a public server that is empty slots and lost regulars. The good news is that the stock launcher already restarts a crashed server; the job is to understand what it does and layer a supervisor on top for the cases it cannot cover.</p>
10 +
11 +<h2>1. Understand what hlds_run already does</h2>
12 +<p>On Linux you do not launch the game binary directly &mdash; you launch <code>hlds_run</code>, a shell wrapper that <code>exec</code>s the real <code>hlds_linux</code> engine and then loops. When the engine exits with a non-zero status (a crash), <code>hlds_run</code> restarts it automatically. When it exits cleanly (you typed <code>quit</code>), it stays down. That single behavior handles the majority of crashes for free:</p>
13 +<pre>./hlds_run -game cstrike +ip 0.0.0.0 -port 27015 \
14 + +map de_dust2 +maxplayers 20 -pingboost 1</pre>
15 +<p>The relevant flags:</p>
16 +<ul>
17 +<li><code>-pingboost 1|2|3</code> &mdash; alternate timing loops; <code>1</code> is the safe default, higher values reduce latency at a CPU cost.</li>
18 +<li><code>-norestart</code> &mdash; <strong>disables</strong> the auto-restart loop. If your server dies and stays dead, check that this flag is not present.</li>
19 +<li><code>-autoupdate</code> &mdash; runs the updater between restarts. Leave it off unless you actually want that on every crash, because it slows recovery.</li>
20 +</ul>
21 +
22 +<h2>2. Why hlds_run is not enough by itself</h2>
23 +<p>The wrapper restarts a crashed <em>engine</em>, but it cannot help if the whole <code>hlds_run</code> process is killed &mdash; an OOM kill, an admin closing the terminal, a reboot. If you started the server over SSH without a persistent session, closing the connection takes the server with it. You need something that keeps <code>hlds_run</code> itself alive and detached from your login.</p>
24 +
25 +<h2>3. Option A: a screen or tmux loop</h2>
26 +<p>The lightweight approach is a detached <code>screen</code> session running a small restart loop, so both the engine and the wrapper are supervised:</p>
27 +<pre>#!/bin/bash
28 +# start.sh
29 +cd /home/steam/hlds
30 +while true; do
31 + ./hlds_run -game cstrike +ip 0.0.0.0 -port 27015 \
32 + +map de_dust2 +maxplayers 20 -pingboost 1
33 + echo "server exited at $(date), restarting in 3s" &gt;&gt; restart.log
34 + sleep 3
35 +done</pre>
36 +<pre>screen -dmS cs ./start.sh # start detached
37 +screen -r cs # re-attach later (Ctrl-A D to detach)</pre>
38 +<p>The <code>sleep 3</code> matters: without a small delay, a server that crashes instantly on load will spin in a tight loop and hammer the CPU. This survives SSH disconnects, but not a machine reboot &mdash; for that you need a service manager.</p>
39 +
40 +<h2>4. Option B: a systemd unit (recommended)</h2>
41 +<p>On a modern Linux box, let systemd be the supervisor. It restarts on crash, starts on boot, throttles restart storms, and captures logs. Create <code>/etc/systemd/system/cs16.service</code>:</p>
42 +<pre>[Unit]
43 +Description=CS 1.6 Server
44 +After=network.target
45 +
46 +[Service]
47 +Type=simple
48 +User=steam
49 +WorkingDirectory=/home/steam/hlds
50 +ExecStart=/home/steam/hlds/hlds_run -game cstrike \
51 + +ip 0.0.0.0 -port 27015 +map de_dust2 +maxplayers 20 -pingboost 1
52 +Restart=always
53 +RestartSec=3
54 +StartLimitIntervalSec=60
55 +StartLimitBurst=5
56 +
57 +[Install]
58 +WantedBy=multi-user.target</pre>
59 +<pre>systemctl daemon-reload
60 +systemctl enable --now cs16
61 +systemctl status cs16
62 +journalctl -u cs16 -f # live server console output</pre>
63 +<p><code>Restart=always</code> covers clean exits and crashes alike; <code>RestartSec=3</code> is the same anti-spin delay as the shell loop. The <code>StartLimitBurst=5</code> means that if the server dies five times in 60 seconds it gives up and stops &mdash; that is a feature, because a server crashing on load will otherwise loop forever and you want it to fail loudly so you go read the logs.</p>
64 +
65 +<h2>5. Log the crash so you can fix the cause</h2>
66 +<p>Restarting hides the symptom; find the cause in the crash log. GoldSrc writes a <code>core</code> dump and often a <code>debug.log</code> in the game directory listing the faulting module. A plugin that crashes the server repeatedly shows up there. Enable AMXX per-map logs and run the suspect plugin with the <code>debug</code> flag &mdash; see <a href="/tutorials/plugins-ini-load-order">plugins.ini load order</a> and <a href="/tutorials/find-crashing-plugin">finding a crashing plugin</a>.</p>
67 +
68 +<h2>Common errors</h2>
69 +<ul>
70 +<li><strong>Server dies and stays down</strong> &mdash; <code>-norestart</code> is in your command line, or you ran the engine binary directly instead of <code>hlds_run</code>. Use the wrapper.</li>
71 +<li><strong>Restart loop pegs one CPU core at 100%</strong> &mdash; the server crashes on load and restarts with no delay. Add <code>RestartSec</code>/<code>sleep</code> and read the crash log; do not paper over it.</li>
72 +<li><strong>Server dies when I log out of SSH</strong> &mdash; you launched it in your login shell. Use <code>screen</code>/<code>tmux</code> or, better, a systemd unit.</li>
73 +<li><strong>systemd keeps saying <code>start request repeated too quickly</code></strong> &mdash; it hit <code>StartLimitBurst</code>. The server is failing on startup; fix the underlying fault, then <code>systemctl reset-failed cs16</code>.</li>
74 +<li><strong>Comes back on crash but not after a reboot</strong> &mdash; you did not <code>systemctl enable</code> the unit, or your screen loop was never wired to boot.</li>
75 +</ul>
76 +
77 +<h2>Verification</h2>
78 +<p>Prove the supervisor works by killing the server and watching it return:</p>
79 +<pre>pkill -f hlds_linux # simulate a crash
80 +journalctl -u cs16 -f # watch it restart within RestartSec</pre>
81 +<p>The engine should come back within a few seconds and the server reappear in the browser. Reboot the machine once and confirm it starts unattended. For scheduled restarts (a nightly clean bounce rather than crash recovery) pair this with <a href="/tutorials/cron-restart-cs16-server">cron-based restarts</a>, and make sure your <a href="/tutorials/backup-configs-bans-stats">configs and bans are backed up</a> before you rely on any of it.</p>
+69 -0 cs16-buy-binds/en.md A
@@ -0,0 +1,69 @@
1 +---
2 +title: "Making Buy Binds in CS 1.6 (buy m4a1; buy primammo)"
3 +excerpt: "Bind full weapon-and-armor loadouts to single keys using the built-in buy aliases, chain purchases with semicolons, and fix binds that only buy the first item."
4 +category: "client"
5 +tags: "binds, buy"
6 +image: ""
7 +read_time: "7 min read"
8 +---
9 +<p>The buy menu costs you three or four keypresses and a second of standing still in the open during freezetime. Buy binds collapse a full loadout onto one key: press it in a buy zone and you have the rifle, the armor, and the grenades in an instant. CS 1.6 exposes a set of console <em>aliases</em> for every purchasable item, and you chain them with semicolons. This walks through the alias names, how to bind a loadout, and why a bind sometimes buys only the first item.</p>
10 +
11 +<h2>1. Understand the buy aliases</h2>
12 +<p>You do not open the menu from a bind. Instead the game defines a standalone console alias for each item, and typing that alias while you stand in a buy zone purchases it directly. The armor and grenade aliases are the ones people forget:</p>
13 +<table>
14 +<thead><tr><th>Alias</th><th>Buys</th></tr></thead>
15 +<tbody>
16 +<tr><td><code>ak47</code>, <code>m4a1</code>, <code>awp</code>, <code>deagle</code>, <code>mp5</code>, <code>usp</code>, <code>glock</code></td><td>The named weapon (mp5 = MP5 Navy).</td></tr>
17 +<tr><td><code>primammo</code></td><td>Primary ammo (one clip). Same as <code>buyammo1</code>.</td></tr>
18 +<tr><td><code>secammo</code></td><td>Secondary ammo. Same as <code>buyammo2</code>.</td></tr>
19 +<tr><td><code>vest</code> / <code>vesthelm</code></td><td>Kevlar / kevlar + helmet.</td></tr>
20 +<tr><td><code>hegren</code> / <code>flash</code> / <code>sgren</code></td><td>HE grenade / flashbang / smoke grenade.</td></tr>
21 +<tr><td><code>defuser</code> / <code>nvgs</code></td><td>Defuse kit (CT) / night-vision.</td></tr>
22 +</tbody>
23 +</table>
24 +<p>These are aliases, so <code>m4a1</code> on its own works. You will also see them written as <code>buy m4a1</code> in old configs; both resolve to the same purchase because the alias name is what the engine matches.</p>
25 +
26 +<h2>2. Bind a single item</h2>
27 +<p>Open the console (see <a href="/tutorials/cs16-enable-console">how to enable the console</a>) and bind one key to one alias:</p>
28 +<pre>bind "f4" "vesthelm"</pre>
29 +<p>Press F4 in a buy zone during buytime and you get full armor. Bindable keys include the function keys, the numpad (<code>kp_end</code>, <code>kp_downarrow</code>, …), and letters not already bound to movement.</p>
30 +
31 +<h2>3. Chain a full loadout with semicolons</h2>
32 +<p>A semicolon runs several commands from one press. Put the whole buy on one line:</p>
33 +<pre>// full CT rifle buy
34 +bind "f1" "m4a1; primammo; primammo; vesthelm; defuser; flash; flash; hegren"
35 +
36 +// full T rifle buy
37 +bind "f2" "ak47; primammo; primammo; vesthelm; flash; flash; hegren; sgren"
38 +
39 +// eco / pistol round
40 +bind "f3" "deagle; secammo; vest"</pre>
41 +<p>Repeat <code>primammo</code> to buy more clips, and repeat <code>flash</code> to buy two flashbangs. The engine processes the line left to right, so order the expensive item first — if you run out of money the leftovers simply fail rather than skipping the rifle.</p>
42 +
43 +<h2>4. Make the binds permanent</h2>
44 +<p>Binds typed in console last only for the session. Put them in <code>cstrike/userconfig.cfg</code> (or your own config that <code>autoexec.cfg</code> execs) so they load every launch:</p>
45 +<pre>// userconfig.cfg
46 +bind "f1" "m4a1; primammo; primammo; vesthelm; defuser; hegren; flash; flash"
47 +bind "f2" "ak47; primammo; primammo; vesthelm; hegren; flash; flash; sgren"
48 +hud_fastswitch 1</pre>
49 +<p>Do not edit <code>config.cfg</code> by hand — the game rewrites it on exit and can clobber your changes. A separate config that you exec is the safe home for binds, the same discipline covered in the <a href="/tutorials/cs16-competitive-video-config">competitive video config</a> guide. <code>hud_fastswitch 1</code> is worth adding alongside so weapon switches after the buy are instant.</p>
50 +
51 +<h2>5. Add a fast weapon switch</h2>
52 +<p>A loadout bind pairs naturally with quick-switch keys so you are not scrolling the mouse wheel mid-fight:</p>
53 +<pre>bind "q" "lastinv"
54 +bind "mouse4" "+quickthrow; slot4" // grenade on a thumb button</pre>
55 +<p>Keep grenade throws on a spare key so you never fumble the weapon menu when you need to pop a flash.</p>
56 +
57 +<h2>Common errors</h2>
58 +<ul>
59 +<li><strong>The bind buys only the first item</strong> — you separated commands with something other than a semicolon, or wrapped each in its own quotes. The whole chain lives inside one pair of quotes: <code>bind "f1" "ak47; vesthelm"</code>, not <code>bind "f1" "ak47"; "vesthelm"</code>.</li>
60 +<li><strong>Nothing is bought at all</strong> — you were outside the buy zone or past buytime. Buytime is short and set server-side by <code>mp_buytime</code> (in minutes); see the <a href="/tutorials/mp-cvars-reference">mp_ cvars reference</a>.</li>
61 +<li><strong>Binds vanish after restart</strong> — you typed them in console only, or you put them in <code>config.cfg</code> and the game overwrote it. Use <code>userconfig.cfg</code> or an execed config.</li>
62 +<li><strong>A weapon alias does nothing</strong> — that weapon is not available to your team (an AWP alias on an eco you cannot afford, or a CT-only item on T). The purchase silently fails.</li>
63 +<li><strong>Key does nothing in menus</strong> — the key you chose is already bound to a movement or menu action; pick a free one or accept the override.</li>
64 +</ul>
65 +
66 +<h2>Verification</h2>
67 +<p>Join any server, enter a buy zone during freezetime, and press your key once. Check the money counter drops by the full loadout cost in a single tick and that armor, ammo, and grenades all appear. Read a bind back in console to confirm it stuck:</p>
68 +<pre>bind f1</pre>
69 +<p>The console echoes the command string currently bound to F1. If it shows the right chain but nothing buys, you are outside the buy zone; if it shows the wrong string, your config did not load and you are back on the session default.</p>
+52 -0 fix-leak-in-hull-pointfile/en.md A
@@ -0,0 +1,52 @@
1 +---
2 +title: "Fix 'LEAK in hull 0': Reading the Pointfile in CS 1.6 Maps"
3 +excerpt: "What a leak actually is, why hlbsp aborts VIS, and how to load the generated .pts/.lin pointfile in your editor and in-game to walk straight to the hole."
4 +category: "mapping"
5 +tags: "leak, compiling"
6 +image: ""
7 +read_time: "7 min read"
8 +---
9 +<p>You hit compile, the console scrolls, and near the end you see <code>LEAK in hull 0</code> followed by a warning that VIS and RAD were skipped. Your map still runs, but it is fullbright, unlit and renders the entire level at once because visibility was never calculated. A leak is not a cosmetic bug — it stops the toolchain dead. The good news is that the compiler hands you an exact line to the hole; you just have to know how to read it.</p>
10 +
11 +<h2>1. Understand what a leak is</h2>
12 +<p>The HLDS engine needs the playable space to be completely sealed from the "void" — the empty outside of the map. During the <code>hlbsp</code> stage the compiler floods the void with a fill and checks whether that fill can reach any entity. If it can, there is a gap connecting the inside to the outside, and you get:</p>
13 +<pre>Warning: === LEAK in hull 0 ===
14 +Entity info_player_start @ ( -320, 512, -32)
15 +A LEAK is a hole in the map, where the inside of it is exposed to the
16 +(unwanted) outside region.</pre>
17 +<p>The critical detail people miss: <strong>only world brushes seal a map.</strong> A brush that has been tied to an entity — <code>func_wall</code>, <code>func_detail</code>, <code>func_door</code>, a trigger — is invisible to the sealing pass. If your outer shell is a <code>func_</code> anything, the map leaks no matter how solid it looks.</p>
18 +
19 +<h2>2. Read the entity in the error</h2>
20 +<p>The leak line always starts at an entity, because the fill reached that entity through the hole. The compiler names it and gives its coordinates. That entity is not the problem — it is simply the closest thing the void could touch. Note the name (<code>info_player_start</code>, a <code>light</code>, an <code>armoury_entity</code>) so you can find it in the editor, then follow the trail from there.</p>
21 +
22 +<h2>3. Load the pointfile in the editor</h2>
23 +<p>Every leaked compile writes two files next to your <code>.map</code>: a plain-text <code>mapname.pts</code> and a <code>mapname.lin</code> for modern editors. The line traces the shortest path from the leaked entity, through the hole, out into the void. In <a href="/tutorials/jack-editor-setup-cs16">J.A.C.K.</a> or Hammer, open the map, then use <strong>Map &rarr; Load Pointfile</strong>. A red (or white) line appears in the 2D and 3D views.</p>
24 +<pre>mymap.pts &lt;- text list of XYZ points, one per line
25 +mymap.lin &lt;- binary line file J.A.C.K./Hammer load automatically</pre>
26 +<p>Follow the line from the entity until it passes through a wall, floor or corner and exits into empty space. Where it crosses the shell is your hole. Zoom the 2D grid there and look for the gap.</p>
27 +
28 +<h2>4. Load the pointfile in-game</h2>
29 +<p>If the leak is subtle, run the (fullbright) map on your test server and use the client command to draw the same line inside the engine:</p>
30 +<pre>developer 1
31 +pointfile</pre>
32 +<p>The engine loads <code>maps/mapname.pts</code> and draws the trail as a string of dots you can physically walk along until you reach the wall it passes through. This is often faster than eyeballing the 2D grid, because you see the exact brush at eye level.</p>
33 +
34 +<h2>5. Common causes and fixes</h2>
35 +<ul>
36 +<li><strong>An entity is outside the map.</strong> A stray light or spawn dragged into the void will always "leak" because it is literally in the outside. Delete or move it back in.</li>
37 +<li><strong>The outer shell is an entity.</strong> A wall you tied to <code>func_wall</code> to make it non-solid-seal. Un-tie outer brushes back to world (<em>To World</em>), or wrap the level in a world-brush box.</li>
38 +<li><strong>A gap between brushes.</strong> Two walls that look flush but have a hairline gap from off-grid vertices. Snap everything to a sane grid (8 or 16 units) and rebuild the corner.</li>
39 +<li><strong>Carve/clip damage.</strong> The carve tool leaves micro-gaps. Avoid carve for structural geometry; build walls as explicit brushes.</li>
40 +</ul>
41 +<blockquote>Do not "fix" a leak by dropping a giant box around the whole level (the "skybox hug"). It seals the error but fills the void with playable space, which cripples VIS and tanks your FPS. Seal the actual hole.</blockquote>
42 +
43 +<h2>Troubleshooting</h2>
44 +<ul>
45 +<li><strong>No pointfile appears.</strong> You loaded the <code>.map</code> from a different folder than the one that compiled. The <code>.pts</code>/<code>.lin</code> sit beside the compiled output; point the editor at that directory.</li>
46 +<li><strong><code>pointfile</code> does nothing in-game.</strong> The <code>.pts</code> is not in <code>cstrike/maps/</code> next to the <code>.bsp</code>, or you are on a different map. Copy it in and reload the map.</li>
47 +<li><strong>Fixed one leak, now a second appears.</strong> Normal — hlbsp reports the first hole it finds. Seal it, recompile, repeat until the leak warning is gone.</li>
48 +<li><strong>Map still fullbright after sealing.</strong> The leak is gone but you recompiled without VIS/RAD, or you have no <code>light</code> entities at all. Re-run the full toolchain — see the <a href="/tutorials/zhlt-vhlt-compile-parameters">compile parameters guide</a>.</li>
49 +</ul>
50 +
51 +<h2>Verification</h2>
52 +<p>Recompile and watch the console. A sealed map runs <code>hlvis</code> and <code>hlrad</code> to completion with no leak warning, and the run ends with a chart of clusters and light data rather than "VIS skipped". Load the map, confirm it is lit and that only nearby geometry renders. Once it seals cleanly, tune your final compile with the <a href="/tutorials/zhlt-vhlt-compile-parameters">VHLT parameter reference</a>, and if you are still learning the layout side, start from <a href="/tutorials/make-your-first-cs16-map">making your first CS 1.6 map</a>.</p>
+62 -0 ip-bans-vs-steamid-bans/en.md A
@@ -0,0 +1,62 @@
1 +---
2 +title: "IP Bans vs SteamID Bans (What Works Against Non-Steam)"
3 +excerpt: "The difference between SteamID and IP bans on CS 1.6, the engine and AMX Mod X commands behind each, and which one actually holds against non-Steam abusers."
4 +category: "administration"
5 +tags: "bans, non-steam"
6 +image: ""
7 +read_time: "8 min read"
8 +---
9 +<p>Banning a rule-breaker sounds simple until the same player is back five minutes later under a new name. Whether a ban actually holds depends on <em>what</em> you banned — the player's SteamID or their IP — and on whether your server runs Steam or non-Steam clients through Reunion or dproto. This walks through both ban types, the engine and AMX Mod X commands behind them, and which to reach for against non-Steam abusers.</p>
10 +
11 +<h2>1. Understand the two identities</h2>
12 +<p>Every connecting client presents two things the server can ban on:</p>
13 +<ul>
14 +<li><strong>The authid (SteamID)</strong> — like <code>STEAM_0:1:12345</code>. On a legitimate Steam client this is tied to the Steam account and is expensive to change.</li>
15 +<li><strong>The IP address</strong> — the network address the packets arrive from.</li>
16 +</ul>
17 +<p>SteamID bans follow the account regardless of IP; IP bans follow the connection regardless of account. Which is stronger depends entirely on how trustworthy the SteamID is on your server.</p>
18 +
19 +<h2>2. Ban by SteamID (engine and AMXX)</h2>
20 +<p>The engine command is <code>banid</code>, and you must persist it with <code>writeid</code> or the ban evaporates on restart:</p>
21 +<pre>banid 0 STEAM_0:1:12345 kick // 0 minutes = permanent
22 +writeid // save to banned.cfg</pre>
23 +<p>Through AMX Mod X the same thing is one command, and it handles the write for you:</p>
24 +<pre>amx_ban 0 STEAM_0:1:12345 "cheating" // 0 = permanent
25 +amx_addban STEAM_0:1:12345 0 // ban an offline authid
26 +amx_unban STEAM_0:1:12345</pre>
27 +<p>SteamID bans are stored in <code>cstrike/banned.cfg</code>, which the engine loads at startup. This is the right default for a Steam-only server: it is precise and survives an IP change.</p>
28 +
29 +<h2>3. Ban by IP (engine and AMXX)</h2>
30 +<p>The engine command is <code>addip</code>, persisted with <code>writeip</code> into <code>listip.cfg</code>:</p>
31 +<pre>addip 0 203.0.113.45 // 0 minutes = permanent
32 +writeip // save to listip.cfg</pre>
33 +<p>In AMXX the equivalent is:</p>
34 +<pre>amx_banip 0 &lt;name or #userid&gt; "reason"</pre>
35 +<p>For the IP ban filter to actually reject connections, <code>sv_filterban</code> must be <code>1</code> (its default) — see the <a href="/tutorials/essential-server-cvars">essential server cvars</a> list. IP bans also stop the player before they even authenticate, which matters against a client that spoofs its SteamID.</p>
36 +
37 +<h2>4. The non-Steam problem</h2>
38 +<p>Here is where it matters. On a non-Steam server running <a href="/tutorials/install-rehlds-on-linux">ReHLDS</a> with <strong>Reunion</strong> (or original HLDS with <strong>dproto</strong>), the SteamID a client presents is not backed by Steam. Depending on configuration, non-Steam clients may all share a generic id like <code>STEAM_ID_LAN</code>, may be handed a generated id derived from their client identity, or may set their own. A self-assigned SteamID is far easier to change than a real one, which makes a pure SteamID ban weak on a badly configured non-Steam box.</p>
39 +<p>Configure Reunion (via <code>reunion.cfg</code>) so it hands out stable, per-client SteamIDs rather than lumping everyone under one id. Reunion also requires a <code>SteamIdHashSalt</code> of at least 16 characters or it refuses to load, so if the module is not even coming up, start there. If every non-Steam player looks like <code>STEAM_ID_LAN</code> to your server, a SteamID ban will either miss the target or ban the entire non-Steam population — verify what ids you are actually seeing before you rely on them.</p>
40 +
41 +<h2>5. Which to use, when</h2>
42 +<ul>
43 +<li><strong>Steam-only server</strong> — ban by SteamID. It is precise and follows the account across IP changes.</li>
44 +<li><strong>Non-Steam with stable Reunion ids</strong> — SteamID first, IP as a backup for stubborn repeat offenders.</li>
45 +<li><strong>Non-Steam with shared or weak ids</strong> — IP bans are your real tool, with the caveats below.</li>
46 +</ul>
47 +<p>Keeping bans consistent is easier from a menu; if you run a managed admin workflow, pair this with the <a href="/plugins/csb-admin-menu">CSB Admin Menu</a> and keep the human side honest with <a href="/tutorials/prevent-admin-abuse">admin-abuse logging</a>.</p>
48 +
49 +<h2>Troubleshooting</h2>
50 +<ul>
51 +<li><strong>Ban did not survive a restart</strong> — you ran <code>banid</code>/<code>addip</code> but never <code>writeid</code>/<code>writeip</code>. The in-memory ban is gone after a reload. Always write.</li>
52 +<li><strong>IP ban catches innocent players</strong> — the target shares an IP with others (household NAT, mobile carrier-grade NAT). Prefer a SteamID ban, or use a short timed IP ban rather than a permanent one.</li>
53 +<li><strong>Banned player keeps returning</strong> — a dynamic IP (they reconnect and get a new one) evades IP bans; a self-set SteamID evades SteamID bans. On non-Steam, fix Reunion id assignment first.</li>
54 +<li><strong>SteamID ban bans everyone / nobody</strong> — all clients report the same id. Reunion is misconfigured; check <code>reunion.cfg</code>.</li>
55 +<li><strong>Ban ignored entirely</strong> — <code>sv_filterban 0</code>, or the id/ip is in the wrong list file. <code>banned.cfg</code> is for SteamIDs, <code>listip.cfg</code> for IPs.</li>
56 +</ul>
57 +
58 +<h2>Verification</h2>
59 +<p>List the active bans from the server console to confirm they are loaded:</p>
60 +<pre>listid // shows banned SteamIDs (banned.cfg)
61 +listip // shows banned IPs (listip.cfg)</pre>
62 +<p>Then have a test client reconnect from the banned identity and confirm it is rejected. For SteamID bans on non-Steam, connect a second non-Steam client and confirm it is <em>not</em> caught — if it is, your ids are not unique and you need to revisit Reunion before trusting SteamID bans at all.</p>
+12 -0 server-side-demo-recording/en.md A
@@ -0,0 +1,12 @@
1 +---
2 +title: "Recording Server-Side Demos and Reviewing Them"
3 +excerpt: "Why CS 1.6 has no native server-side demo, how to record with the client console, use HLTV as a recorder, force clients to record with a plugin, and review the files."
4 +category: "administration"
5 +tags: "demos, admin"
6 +image: ""
7 +read_time: "8 min read"
8 +---
9 +<p>Admins ask for "server-side demos" to catch cheaters after the fact, and the first thing to understand is that GoldSrc CS 1.6 has <strong>no built-in server-side demo</strong>. The engine records demos on the <em>client</em> that runs <code>record</code>. What people mean in practice is one of three things: recording on your own client while spectating, running an HLTV proxy that captures the match, or forcing suspects to record their own client with a plugin. This walks through all three and how to play the files back.</p><h2>1. The client-side record command</h2><p>Any player, including you while spectating, records their own view with two console commands:</p><pre>record mymatch
10 +stop</pre><p>This writes <code>mymatch.dem</code> into the <code>cstrike/</code> folder of the machine that ran <code>record</code>. It captures only what that client received from the server &mdash; you cannot record a player's screen from the server. If you connect as a spectator and follow a suspect, you record what the server sent about them, which is enough to review positioning and obvious wall/aim tells but not their raw inputs.</p><h2>2. Play a demo back</h2><p>Put the <code>.dem</code> file in <code>cstrike/</code> and run either command from the console:</p><pre>playdemo mymatch
11 +viewdemo mymatch</pre><p><code>playdemo</code> plays it inline; <code>viewdemo</code> opens the demo player overlay with a timeline, pause, and free-look camera. During <code>viewdemo</code> playback you can detach the camera and orbit the recorded player, which is exactly what you want when reviewing a suspected wallhack &mdash; watch whether their aim tracks enemies through geometry before line of sight exists.</p><h2>3. Use HLTV as a dedicated recorder</h2><p>HLTV (the standalone <code>hltv</code> proxy that ships with the dedicated server tools) connects to your server as a spectator client and can record the whole match to a demo on the HLTV machine. Started from the HLTV console:</p><pre>connect 127.0.0.1:27015
12 +record match_2026_07_15</pre><p>Because HLTV sees every player with a configurable delay, its demo is the closest thing to a true "server" recording: one file, all players, reviewable with <code>viewdemo</code> afterwards. The cost is that HLTV is a second process consuming a player slot and bandwidth, and its <code>delay</code> and <code>maxrate</code> must be tuned so it does not choke. Run it on the same box or a nearby one to keep the feed clean.</p><h2>4. Force a suspect to record with a plugin</h2><p>The genuinely "server-driven" option is an AMX Mod X plugin that issues the <code>record</code> command on a target client and later pulls the file up via the upload channel or asks the player to send it. The engine lets the server run client commands through the standard client-command forward, so a plugin can start and stop a recording on a chosen SteamID. This is how anti-cheat admin suites implement "demo a player": they are scripting the client's own <code>record</code>, not capturing frames on the server. If you go this route, a maintained admin suite such as the <a href="/plugins/csb-admin-menu">CSB Admin Menu</a> is safer than a raw one-off plugin, and you still need the player's cooperation to retrieve the resulting <code>.dem</code>.</p><h2>5. Keep demos small and named sanely</h2><p>Demos grow fast &mdash; a busy 30-minute round can be tens of megabytes. Record only when you have a reason, name files with the date and the suspect (<code>2026-07-15_nova.dem</code>), and delete them once reviewed. Cross-reference the demo with the server logs so you can tie a moment in the demo to a kill line and a <a href="/tutorials/find-player-steamid">SteamID</a>; the log gives you the identity, the demo gives you the evidence.</p><h2>Common errors</h2><ul><li><strong><code>record</code> does nothing / no file appears</strong> &mdash; you were already in a demo, or the name collided. Run <code>stop</code> first, then <code>record</code> with a fresh name, and check <code>cstrike/</code> on the recording machine, not the server.</li><li><strong>"Can't record during multiplayer games"</strong> &mdash; on some builds recording is blocked unless you start it before the map fully loads; reconnect and issue <code>record</code> right after connect, or use HLTV instead.</li><li><strong>Demo plays but the camera is stuck to the recorder</strong> &mdash; use <code>viewdemo</code>, not <code>playdemo</code>, and detach the camera from the overlay to free-look.</li><li><strong>HLTV shows nothing / times out</strong> &mdash; <code>sv_lan</code> or a password is blocking it, or its <code>maxrate</code> is too low. HLTV connects like any client and obeys the same rules; see <a href="/tutorials/essential-server-cvars">the essential cvars</a>.</li><li><strong>Expecting to record a cheater's raw aim from the server</strong> &mdash; impossible in GoldSrc. You only ever have what the server sent about them; interpret demos accordingly.</li></ul><h2>Verification</h2><p>Record a short clip while spectating, run <code>stop</code>, confirm the <code>.dem</code> exists in <code>cstrike/</code>, then <code>viewdemo</code> it and detach the camera to orbit a player. If that works, your review workflow is sound. For a whole-match capture, stand up HLTV, record one map, and confirm the single demo contains every player &mdash; that is the file you keep when you need to justify a ban.</p>
+53 -0 stop-a2s-query-flood/en.md A
@@ -0,0 +1,53 @@
1 +---
2 +title: "Stopping A2S Query Floods (Rate-Limiting Port 27015)"
3 +excerpt: "Why A2S_INFO query floods knock a CS 1.6 server offline, how to spot them with tcpdump, and how to rate-limit connectionless queries on UDP 27015 with iptables."
4 +category: "security"
5 +tags: "a2s, ddos"
6 +image: ""
7 +read_time: "8 min read"
8 +---
9 +<p>A CS 1.6 server answers every <code>A2S_INFO</code> query it receives on UDP 27015 — that is how it appears in the master list and in server browsers. Attackers abuse this: they blast thousands of spoofed query packets per second, the server dutifully builds and sends a reply to each, and the main game thread spends all its time answering queries instead of simulating the round. Players see rubber-banding, then mass timeouts. This is a query flood, and unlike a raw bandwidth DDoS you can blunt most of it on the host itself.</p>
10 +
11 +<h2>1. Understand what the flood looks like</h2>
12 +<p>Query packets are <em>connectionless</em>: they start with the four bytes <code>0xFF 0xFF 0xFF 0xFF</code> followed by a request byte such as <code>T</code> (A2S_INFO), <code>U</code> (A2S_PLAYER) or <code>W</code>. They are tiny and cheap to send but force the server to assemble a larger reply, which is why the attack also works as a reflection/amplification vector against third parties. The key fact: a real player sends a handful of queries when browsing, then switches to a full connection. A flood sends the same query byte from many spoofed source addresses, hundreds of times a second each.</p>
13 +
14 +<h2>2. Confirm it with tcpdump</h2>
15 +<p>Before you block anything, verify the traffic is really query spam and not legitimate load. On the host:</p>
16 +<pre>tcpdump -ni any udp port 27015 -c 200</pre>
17 +<p>A flood shows a torrent of small inbound packets from many source IPs, often with implausible source ports or obviously spoofed ranges. Compare the packet rate to your player count — a 20-slot server does not generate thousands of packets per second of inbound queries under normal play. If CPU is pinned at the same time, cross-check with <a href="/tutorials/fix-hlds-100-cpu">the HLDS 100% CPU guide</a>.</p>
18 +
19 +<h2>3. Rate-limit queries with iptables hashlimit</h2>
20 +<p>The most effective host-level defence is to cap how many packets any single source IP may send to the game port per second, using the <code>hashlimit</code> module. This lets real browsers and players through while throttling a source that hammers the port:</p>
21 +<pre>iptables -A INPUT -p udp --dport 27015 \
22 + -m hashlimit \
23 + --hashlimit-name cs_queries \
24 + --hashlimit-mode srcip \
25 + --hashlimit-above 30/sec \
26 + --hashlimit-burst 60 \
27 + -j DROP</pre>
28 +<p>This drops packets from any single IP that exceeds 30 per second (with a short burst allowance of 60). Tune the numbers to your traffic — a busy server with a live feed of joins may need a higher ceiling. Because it keys on source IP, a distributed flood from thousands of hosts each staying under the limit will slip through, which is the boundary where host rules end and <a href="/tutorials/ddos-protected-hosting">DDoS-protected hosting</a> begins.</p>
29 +
30 +<h2>4. Drop malformed and oversized query packets</h2>
31 +<p>Legitimate A2S queries are short. You can discard obviously abusive connectionless packets by length before they reach the game process:</p>
32 +<pre>iptables -A INPUT -p udp --dport 27015 -m length --length 1:32 \
33 + -m hashlimit --hashlimit-name cs_small \
34 + --hashlimit-mode srcip --hashlimit-above 15/sec -j DROP</pre>
35 +<p>Apply the tighter limit to the small connectionless packets while leaving normal in-game traffic (which is larger and belongs to established clients) alone. Keep the rules in the right order and make sure your firewall still permits the port at all — see <a href="/tutorials/cs16-server-firewall-ports">which ports a CS 1.6 server needs open</a>.</p>
36 +
37 +<h2>5. Persist the rules</h2>
38 +<p>iptables rules vanish on reboot. Save them so a restart does not leave you exposed:</p>
39 +<pre>iptables-save &gt; /etc/iptables/rules.v4</pre>
40 +<p>On a systemd host, install <code>iptables-persistent</code> (or your distro's equivalent) so the rules reload at boot alongside your <a href="/tutorials/hlds-systemd-service">HLDS systemd service</a>.</p>
41 +
42 +<h2>Common errors</h2>
43 +<ul>
44 +<li><strong>Server drops off the master list after adding rules</strong> — your limit is too aggressive and it is throttling the master server's own queries, or you accidentally blocked outbound. Loosen <code>--hashlimit-above</code> and confirm the port is still reachable. See <a href="/tutorials/fix-server-not-in-master-list">server not in the master list</a>.</li>
45 +<li><strong>Real players still time out during a flood</strong> — the attack is distributed and each source stays under your per-IP cap. Host rules cannot fully stop that; you need upstream filtering.</li>
46 +<li><strong>CPU still pinned after blocking</strong> — the flood may be hitting a different port, or it is a connection flood rather than a query flood. Re-run <code>tcpdump</code> to see the real target port.</li>
47 +<li><strong>Legitimate server-list refreshes look like an attack</strong> — a popular server receives a lot of queries normally. Do not set the ceiling below what your genuine browse traffic needs, or you will hide yourself.</li>
48 +</ul>
49 +
50 +<h2>Verification</h2>
51 +<p>With the rules loaded, watch the counters climb only during an actual flood:</p>
52 +<pre>iptables -L INPUT -v -n --line-numbers</pre>
53 +<p>The DROP rule's packet counter should stay near zero in normal operation and spike when a flood hits. During an attack, confirm the server FPS holds and players stop timing out. If the counter never moves but the server still lags, the traffic is not a simple per-IP query flood and the fight moves upstream to your host or a scrubbing provider. A separate <a href="/plugins/csb-high-ping-kicker">high-ping kicker</a> will not help here — that is for individual laggy players, not query floods.</p>
0 54