From e41b55ca4ff7d4f7478df61d2caefcb28f2ebc41 Mon Sep 17 00:00:00 2001 From: pipistrello Date: Wed, 9 Sep 2026 22:33:30 +0300 Subject: [PATCH] tailscale-proxy: pin Telemt's nofile limit and abort dead pre-auth sockets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mirrors what is now running on the client-02 docker host, so a "pull and redeploy" from this repo can no longer silently revert it. On 2026-09-09 a connection flood against the public :1080 (peak 4,301 connections/minute, ~100% failing the Fake-TLS handshake) exhausted the Telemt container's file-descriptor table, which sat at Docker's default soft limit of 1024. accept() then failed for every caller — real Telegram clients and the monitoring collector alike — until the burst drained. Steady state needs only 45-73 descriptors, so the ceiling was ~7% used in normal operation. ulimits: nofile 65536/524288 on the telemt service The host was mitigated at runtime with prlimit on the day, but that is lost on any recreate, and this compose is exactly what a redeploy would restore. The proxy (3proxy) service deliberately does NOT get the block in this commit — it is still on the runtime limit only and is scheduled for its own window, so adding it here would make the repo claim something that is not yet true. rst_on_close = "errors" in telemt.toml.example Scanners and DPI probes that never complete the handshake leave orphaned sockets in FIN-WAIT-1. "errors" sets SO_LINGER(0) at accept() and clears it once a client authenticates, so real sessions still close gracefully with FIN and only pre-auth closes are aborted. Verified on the wire on the host: a failed handshake now ends FIN then RST, while authenticated sessions in the same capture closed FIN-only. Applied on the host at 22:17 MSK via telemt-safe-restart: healthy in 10s, container IP unchanged, bad-handshake delta 0 over a 5-minute recheck, no EMFILE since. NOTE for whoever deploys this stack from this repo: it is still missing the ts-vpn + ts-lan-ikev2 services that have been running on the client-02 host since 2026-09-05. Deploying this file as-is would take the IKEv2 VPN front down. That drift is untouched here and needs its own commit. --- tailscale-proxy/docker-compose.yaml | 7 +++++++ tailscale-proxy/telemt/telemt.toml.example | 6 ++++++ 2 files changed, 13 insertions(+) diff --git a/tailscale-proxy/docker-compose.yaml b/tailscale-proxy/docker-compose.yaml index 1b9c971..293c7da 100644 --- a/tailscale-proxy/docker-compose.yaml +++ b/tailscale-proxy/docker-compose.yaml @@ -47,6 +47,13 @@ services: image: ghcr.io/telemt/telemt:3.4.25 container_name: ts-lan-telemt restart: unless-stopped + # Docker default soft nofile is 1024. A connection flood on the public :1080 + # exhausted it on 2026-09-09 and accept() then failed for EVERY caller, for + # ~8 minutes. Steady state needs only ~45-73 descriptors. + ulimits: + nofile: + soft: 65536 + hard: 524288 depends_on: [ts-proxy] environment: NO_COLOR: "1" # cleaner `docker logs` (no ANSI escapes) diff --git a/tailscale-proxy/telemt/telemt.toml.example b/tailscale-proxy/telemt/telemt.toml.example index 1645eea..d87d7c1 100644 --- a/tailscale-proxy/telemt/telemt.toml.example +++ b/tailscale-proxy/telemt/telemt.toml.example @@ -15,6 +15,12 @@ [general] use_middle_proxy = false +# Scanners/DPI probes that never complete the Fake-TLS handshake leave orphaned +# sockets in FIN-WAIT-1. "errors" sets SO_LINGER(0) at accept() and CLEARS it once +# a client authenticates, so real sessions still close gracefully with FIN and only +# pre-auth closes get an RST. Applied at 02-tekhnohim 2026-09-09. +rst_on_close = "errors" + [general.modes] classic = false secure = false