pyCluster uses layered security controls rather than a single mechanism.
- per-user passwords
- first-login password creation for human telnet users
- per-user channel access
- per-user posting permissions
- callsign blocking
- block reason tracking
- durable failed-password lock state shared by telnet and public web login
- account-lock recovery notices from both telnet and public web when SMTP and a verified account email are configured
- durable five-attempt MFA lock state scoped to the exact callsign-SSID
- verified-email password reset through the public web when SMTP is configured
- authenticator MFA fallback to email OTP after repeated failed TOTP attempts
- recent audit activity
- recent auth failures
- current fail2ban bans
pyCluster ships auth-failure patterns for fail2ban.
Included filters:
deploy/fail2ban/filter.d/pycluster-auth-core.confdeploy/fail2ban/filter.d/pycluster-auth-web.confdeploy/fail2ban/filter.d/pycluster-auth-telnet.confdeploy/fail2ban/filter.d/pycluster-auth-scanner.conf
Included optional actions:
deploy/fail2ban/action.d/pycluster-lock-account.conf
Included jails:
deploy/fail2ban/jail.d/pycluster-core.localdeploy/fail2ban/jail.d/pycluster-web.localdeploy/fail2ban/jail.d/pycluster-telnet.localdeploy/fail2ban/jail.d/pycluster-scanner.local
Installed jail names:
pycluster-core-authpycluster-telnet-authpycluster-web-authpycluster-telnet-scanner
The SysOp-web and telnet authentication jails each use five failed attempts, but they ban only their own service ports. Password failures for an exact account with verified email and configured recovery mail are handled by pyCluster's durable account lock and are excluded from the public-web and telnet IP bans, allowing immediate reset and reconnection. Malformed, unverified, and mail-unrecoverable attempts remain eligible for IP bans. Password and MFA recovery each require the exact callsign/SSID, matching verified email, and a purpose-bound one-time code, so records sharing an email address cannot reset one another. MFA recovery does not change the password, clear unrelated locks, or bypass node-wide MFA policy. Failed-password and failed-MFA locks are recorded against the exact callsign-SSID; a failure for one SSID does not lock its base call or siblings. The scanner jail matches malformed callsigns only, and installation leaves any existing SSH jail enabled.
pyCluster emits structured auth-failure lines suitable for fail2ban.
Example:
AUTHFAIL channel=sysop-web ip=198.51.100.24 call=N0CALL reason=bad_password
Common reasons:
bad_passwordinvalid_credentialsinvalid_callsignblocked_loginweb_login_not_allowedtelnet_login_not_allowed
Operational checks:
sudo fail2ban-client status
sudo fail2ban-client status pycluster-core-auth
sudo fail2ban-client status pycluster-telnet-auth
sudo fail2ban-client status pycluster-web-auth
sudo fail2ban-client status pycluster-telnet-scanner
sudo tail -n 50 /var/log/pycluster/authfail.logThe default jails ban IP addresses. To also lock the user account named in a structured auth-failure line, enable the optional pycluster-lock-account action in a local jail override and point pycluster_db at the active SQLite database. The action writes the same durable lock keys that the SysOp Unlock Account control clears. The helper can also be run directly on the host:
sudo /home/pycluster/pyCluster/scripts/lock_user_account.py --db /home/pycluster/pyCluster/data/pycluster.db --call AI3I-90
sudo /home/pycluster/pyCluster/scripts/lock_user_account.py --db /home/pycluster/pyCluster/data/pycluster.db --call AI3I-90 --unlock- keep sysop and public web behind a reverse proxy
- use HTTPS externally
- a reverse proxy may run on the pyCluster host or a separate trusted host; for an external proxy, bind backend listeners explicitly and allow their ports only from the proxy or management network
- dual-stack listeners require both IPv4 and IPv6 firewall review; do not assume an IPv4-only ACL also protects a wildcard IPv6 socket
- never expose the System Operator listener on
8080broadly or send its credentials over an untrusted plain-HTTP network - enable the shipped
fail2banjails - keep telnet exposed only as needed
- back up config and SQLite data regularly
CTY data is operational data, not a security boundary. Keep it current, but do not treat entity mapping as access control.