• src/sbbs3/ftpsrvr.cpp mailsrvr.cpp main.cpp mqtt.c sbbs_ini.c src/sbbs

    From Rob Swindell (on Windows 11)@VERT to Git commit to main/sbbs/master on Sat May 2 17:27:15 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/1c591f2b638c7fa7a6b2abc5
    Modified Files:
    src/sbbs3/ftpsrvr.cpp mailsrvr.cpp main.cpp mqtt.c sbbs_ini.c src/sbbs3/scfg/scfgsrvr.c src/sbbs3/services.cpp startup.h websrvr.cpp
    Log Message:
    sbbs3 terminal server: auto-filter IPs hitting max-concurrent limit

    When a client repeatedly hits the per-IP max concurrent (unauthenticated) connection limit, optionally add the IP to text/ip.can for a configurable duration. Threshold and duration are tunable in SCFG via a new submenu
    ("Max Concurrent Connections...") and via two new sbbs.ini keys in [BBS]: MaxConConnFilterThreshold and MaxConConnFilterDuration. A threshold of 0
    (the default) disables the auto-filter and preserves prior behavior.

    This is a useful mitigation (when enabled by setting the threshold to a non-zero value) against the recent spate of terminal server bot attacks
    (likely looking for CVE-2026-31431: Copy Fail vulnerability on Linux
    hosts), which tend to tie up a BBS's terminal server nodes just sitting
    at a login prompt, causing a denial-of-service.

    The strike counter for an IP is held in memory and is cleared on: a
    successful login from that IP, terminal server recycle/restart, the
    clear*.term semaphore file, or the new MQTT "clear" topic. Bans are
    written to ip.can with the existing e=<expiry> field, so they expire
    naturally without any cleanup pass. A failed filter_ip() call leaves
    the strike count in place so we don't reset on transient errors.

    Also added: an MQTT "clear" topic (under both <host> and <server>
    scopes) that signals the corresponding server to clear its login-attempt
    list. The polling hook is wired into all five servers (terminal, FTP,
    mail, web, services) via a new clear_attempts_now flag in STARTUP_COMMON_ELEMENTS. The auto-filter on max-concurrent itself is terminal-only by design, since "nodes" are a scarce resource.

    Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

    ---
    þ Synchronet þ Vertrauen þ Home of Synchronet þ [vert/cvs/bbs].synchro.net