# Cheatsheet ## Run ```bash bouncer -c config/bouncer.toml # start bouncer -c config/bouncer.toml -v # start (debug) bouncer --version # version bouncer --help # help ``` ## Systemd ```bash systemctl --user enable bouncer # enable at boot systemctl --user start bouncer # start systemctl --user stop bouncer # stop systemctl --user restart bouncer # restart systemctl --user reload bouncer # hot reload (SIGHUP) systemctl --user status bouncer # status journalctl --user -u bouncer -f # follow logs ``` ## Podman ```bash make build # build container image make up # podman-compose up -d make down # podman-compose down make logs # podman logs -f bouncer ``` ```bash podman logs bouncer 2>&1 | grep -E 'INFO|WARN' # filtered logs podman exec -it bouncer bash # shell into container podman ps --filter name=bouncer # status ``` ## Develop ```bash make dev # install with dev deps into .venv make test # pytest make lint # ruff check make fmt # black + ruff --fix make run # run with config/bouncer.toml make clean # rm .venv, build artifacts ``` ## Client Auth ``` PASS # authenticate (all networks) ``` ## Bouncer Commands ### Inspection ``` /msg *bouncer HELP # list commands /msg *bouncer STATUS # all network states /msg *bouncer INFO libera # detailed network info /msg *bouncer UPTIME # process uptime /msg *bouncer NETWORKS # list networks /msg *bouncer CREDS [network] # NickServ creds /msg *bouncer CHANNELS [network] # joined channels + topics /msg *bouncer CLIENTS # connected clients /msg *bouncer BACKLOG [network] # message counts + DB size /msg *bouncer VERSION # bouncer + Python version ``` ### Network Control ``` /msg *bouncer CONNECT libera # start disconnected network /msg *bouncer DISCONNECT libera # stop network /msg *bouncer RECONNECT libera # restart with fresh identity /msg *bouncer NICK libera newnick # change nick /msg *bouncer RAW libera WHOIS user # send raw IRC command ``` ### Config Management ``` /msg *bouncer REHASH # reload config file /msg *bouncer ADDNETWORK name host=h port=N tls=yes nick=n channels=#a,#b /msg *bouncer DELNETWORK name # remove network /msg *bouncer AUTOJOIN net +#chan # add to autojoin /msg *bouncer AUTOJOIN net +#chan key # add with channel key /msg *bouncer AUTOJOIN net -#chan # remove from autojoin ``` ### NickServ ``` /msg *bouncer IDENTIFY libera # force IDENTIFY /msg *bouncer REGISTER libera # trigger registration /msg *bouncer DROPCREDS libera # delete all creds /msg *bouncer DROPCREDS libera nick # delete one nick's creds ``` ### CertFP ``` /msg *bouncer GENCERT libera # generate cert (current nick) /msg *bouncer GENCERT libera nick # generate cert (specific nick) /msg *bouncer CERTFP # list all cert fingerprints /msg *bouncer CERTFP libera # list certs for one network /msg *bouncer DELCERT libera # delete cert (current nick) /msg *bouncer DELCERT libera nick # delete cert (specific nick) ``` ### Account Farming ``` /msg *bouncer FARM # global farming status /msg *bouncer FARM libera # network stats + trigger attempt /msg *bouncer ACCOUNTS # list all stored accounts /msg *bouncer ACCOUNTS libera # accounts for one network ``` ## Namespacing ``` #channel/network # channel on a specific network nick/network # foreign nick on a specific network own-nick # own nicks shown without suffix ``` ``` /msg #libera/libera hello # send to #libera on libera network /join #test/oftc # join #test on oftc /join #a/libera,#b/oftc # comma-separated, different networks ``` ## Connection States ``` DISCONNECTED -> CONNECTING -> REGISTERING -> PROBATION (45s) -> READY ``` | State | What happens | |-------|-------------| | CONNECTING | TCP + SOCKS5 + TLS handshake | | REGISTERING | Random nick/user/realname sent to server | | PROBATION | 45s wait (configurable), watching for K-line | | READY | Switch to configured nick, join channels | ## Auth Cascade ``` SASL EXTERNAL (cert + creds) > SASL PLAIN (creds) > NickServ IDENTIFY ``` ## Reconnect Backoff ``` 1s (flat, no escalation) ``` ## PING Watchdog Detects stale connections where TCP stays open but server stops responding. ```toml ping_interval = 120 # silence before PING (seconds) ping_timeout = 30 # wait for PONG (seconds) ``` Total detection time: `ping_interval + ping_timeout` (default 150s). ## server-time (IRCv3) Automatic -- no config needed. Timestamps injected on all messages. Backlog replay includes original timestamps. ## Push Notifications ```toml notify_url = "https://ntfy.sh/my-topic" # ntfy or generic webhook notify_on_highlight = true # channel mentions notify_on_privmsg = true # private messages notify_cooldown = 60 # rate limit (seconds) notify_proxy = false # use SOCKS5 for notifications ``` Only fires when no clients are attached. ## Security - DCC/CTCP stripped both directions (prevents IP leaks). ACTION preserved. - All server connections routed through SOCKS5 proxy. - Stealth connect: random nick/user/realname on every connection. ## Hot Reload ```bash kill -HUP $(pidof bouncer) # reload config via signal /msg *bouncer REHASH # reload config via command ``` ## Config Skeleton ```toml [bouncer] bind / port / password client_tls / client_tls_cert # client-side TLS client_tls_key # separate key file (optional) captcha_api_key # NoCaptchaAI key (optional) captcha_poll_interval / captcha_poll_timeout probation_seconds / nick_timeout / rejoin_delay backoff_steps / http_timeout email_poll_interval / email_max_polls / email_request_timeout cert_validity_days ping_interval / ping_timeout # PING watchdog notify_url / notify_on_highlight / notify_on_privmsg notify_cooldown / notify_proxy # push notifications farm_enabled / farm_interval # background account farming farm_max_accounts [bouncer.backlog] max_messages / replay_on_connect [proxy] host / port [networks.] # repeatable host / port / tls nick / channels / autojoin channel_keys # keys for +k channels password # optional, IRC server PASS ``` ## Files | Path | Purpose | |------|---------| | `config/bouncer.toml` | Active config (gitignored) | | `config/bouncer.example.toml` | Example template | | `config/bouncer.service` | Systemd user service unit | | `config/bouncer.db` | SQLite backlog (auto-created) | | `{data_dir}/bouncer.pem` | Listener TLS cert (auto-created) | | `{data_dir}/certs/{net}/{nick}.pem` | Client certificates (auto-created) | ## Backlog Queries ```sql -- recent messages SELECT * FROM messages ORDER BY id DESC LIMIT 20; -- per-network counts SELECT network, COUNT(*) FROM messages GROUP BY network; -- last seen state SELECT * FROM client_state; ``` ## Source Layout ``` src/bouncer/ __main__.py # entry point, event loop cli.py # argparse config.py # TOML loader irc.py # IRC message parse/format namespace.py # /network encode/decode for multiplexing proxy.py # SOCKS5 connector (local DNS, multi-IP, CertFP) network.py # server connection + state machine + SASL client.py # client session handler cert.py # client certificate generation + management captcha.py # hCaptcha solver via NoCaptchaAI farm.py # background account farming commands.py # bouncer control commands (/msg *bouncer) notify.py # push notifications (ntfy/webhook) router.py # message routing + backlog trigger + server-time server.py # TCP listener backlog.py # SQLite store/replay/prune ```