From f5bce30a4a8d7e440dacf50cd0c5afbd66bdebfe Mon Sep 17 00:00:00 2001 From: CroneKorkN Date: Fri, 15 May 2026 16:30:00 +0200 Subject: [PATCH] fix(left4me): srcds binds RCON to all interfaces + close external TCP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two changes to fix web's "No data / Connection refused" symptoms: 1. ExecStart adds +ip 0.0.0.0 so srcds_linux binds both UDP and TCP to all interfaces (incl. loopback). Default Source auto-IP picks the primary host IP (141.95.32.8 here), so TCP RCON was only on the public IP; web's 127.0.0.1 connect got ECONNREFUSED. 2. nftables/input drops the TCP accept on the game port range. UDP stays open for players. Loopback (127.0.0.1) bypasses the input chain via the existing 'iifname lo accept' rule in bundles/nftables/files/nftables.conf, so web→RCON via loopback still works. Net effect: web's live-state polling + console RCON work via loopback; RCON is no longer reachable from the public internet. Co-Authored-By: Claude Opus 4.7 (1M context) --- bundles/left4me/metadata.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/bundles/left4me/metadata.py b/bundles/left4me/metadata.py index f4df47c..b723783 100644 --- a/bundles/left4me/metadata.py +++ b/bundles/left4me/metadata.py @@ -248,8 +248,13 @@ def nftables_input(metadata): return { 'nftables': { 'input': { + # Players connect via UDP. TCP on the same port range is RCON + # — only the local web app should reach it. Loopback bypasses + # the input chain (iifname lo accept in bundles/nftables/...), + # so 127.0.0.1 RCON works without an explicit TCP accept here. + # External TCP on these ports stays blocked by the default + # input-chain drop. f'udp dport {port_start}-{port_end} accept', - f'tcp dport {port_start}-{port_end} accept', }, }, } @@ -352,7 +357,11 @@ def systemd_units(metadata): ), 'WorkingDirectory': '-/var/lib/left4me/runtime/%i/merged/left4dead2', 'ExecStartPre': '+/usr/bin/nsenter --mount=/proc/1/ns/mnt -- /usr/local/libexec/left4me/left4me-overlay mount %i', - 'ExecStart': '/var/lib/left4me/runtime/%i/merged/srcds_run -game left4dead2 +hostport ${L4D2_PORT} $L4D2_ARGS', + # +ip 0.0.0.0 binds RCON (TCP) to all interfaces incl. loopback; + # without this, Source auto-selects the primary IP and the web + # app's 127.0.0.1 RCON connect gets ECONNREFUSED. External TCP + # on the game port range is firewall-blocked in nftables_input. + 'ExecStart': '/var/lib/left4me/runtime/%i/merged/srcds_run -game left4dead2 +ip 0.0.0.0 +hostport ${L4D2_PORT} $L4D2_ARGS', 'ExecStopPost': '+/usr/bin/nsenter --mount=/proc/1/ns/mnt -- /usr/local/libexec/left4me/left4me-overlay umount %i', 'Restart': 'on-failure', 'RestartSec': '5',