Exponential backoff up to 300s made no sense with rotating Tor exits where each reconnect gets a fresh IP. Single 1s delay is sufficient. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
279 lines
8.0 KiB
Markdown
279 lines
8.0 KiB
Markdown
# 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 <password> # 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.<name>] # 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
|
|
```
|