Network control (CONNECT, DISCONNECT, RECONNECT, NICK, RAW), visibility (CHANNELS, CLIENTS, BACKLOG, VERSION), config management (REHASH, ADDNETWORK, DELNETWORK, AUTOJOIN), and NickServ operations (IDENTIFY, REGISTER, DROPCREDS). Total command count: 22. Adds stats()/db_size() to Backlog, add_network()/remove_network() to Router, and _connected_at timestamp to Client. 74 command tests. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
304 lines
8.6 KiB
Markdown
304 lines
8.6 KiB
Markdown
# Usage
|
|
|
|
## Starting the Bouncer
|
|
|
|
```bash
|
|
bouncer -c config/bouncer.toml -v
|
|
```
|
|
|
|
| Flag | Description |
|
|
|------|-------------|
|
|
| `-c, --config PATH` | Config file (default: `config/bouncer.toml`) |
|
|
| `-v, --verbose` | Debug logging |
|
|
| `--version` | Show version |
|
|
|
|
## Connection Lifecycle
|
|
|
|
The bouncer goes through several states when connecting to an IRC server:
|
|
|
|
```
|
|
DISCONNECTED -> CONNECTING -> REGISTERING -> PROBATION -> READY
|
|
| | |
|
|
`--------------+--------------'
|
|
(failure = reconnect)
|
|
```
|
|
|
|
### 1. Stealth Registration
|
|
|
|
On connect, the bouncer registers with a **random identity**:
|
|
|
|
- **Nick**: pronounceable markov-generated word (e.g., `heliagu`, `crewo`, `midon`)
|
|
- **User/Ident**: random pronounceable word
|
|
- **Realname**: random capitalized word
|
|
|
|
No fixed prefix or pattern -- each attempt looks like a different person.
|
|
|
|
### 2. Probation (15 seconds)
|
|
|
|
After registration succeeds (001 RPL_WELCOME), the bouncer enters a 15-second
|
|
probation window. During this time it watches for:
|
|
|
|
- `ERROR` messages (K-line, ban)
|
|
- Server closing the connection
|
|
|
|
If the connection drops during probation, the bouncer reconnects with a fresh
|
|
random identity and tries again.
|
|
|
|
### 3. Ready
|
|
|
|
Once probation passes without incident:
|
|
|
|
1. Bouncer switches to your configured nick (`NICK mynick`)
|
|
2. Joins configured channels (if `autojoin = true`)
|
|
3. Begins relaying messages to/from connected clients
|
|
|
|
### 4. Reconnection
|
|
|
|
On any disconnection, the bouncer reconnects with exponential backoff:
|
|
|
|
| Attempt | Delay |
|
|
|---------|-------|
|
|
| 1 | 5s |
|
|
| 2 | 10s |
|
|
| 3 | 30s |
|
|
| 4 | 60s |
|
|
| 5 | 120s |
|
|
| 6+ | 300s |
|
|
|
|
Each reconnection uses a fresh random identity.
|
|
|
|
## DNS Resolution
|
|
|
|
Hostnames are resolved locally before being passed to the SOCKS5 proxy. If a
|
|
hostname resolves to multiple IPs, the bouncer tries each one until a connection
|
|
succeeds. This handles proxies that don't support remote DNS and avoids IPs
|
|
that are unreachable through the proxy.
|
|
|
|
## Connecting with an IRC Client
|
|
|
|
Configure your IRC client to connect to the bouncer:
|
|
|
|
| Setting | Value |
|
|
|---------|-------|
|
|
| Server | `127.0.0.1` |
|
|
| Port | `6667` (or as configured) |
|
|
| Password | `yourpassword` |
|
|
|
|
### Password Format
|
|
|
|
```
|
|
PASS <password>
|
|
```
|
|
|
|
The password is the `bouncer.password` value from config. A single connection
|
|
automatically attaches to **all** configured networks.
|
|
|
|
### Client Examples
|
|
|
|
**irssi:**
|
|
```
|
|
/connect -password mypassword 127.0.0.1 6667
|
|
```
|
|
|
|
**weechat:**
|
|
```
|
|
/server add bouncer 127.0.0.1/6667 -password=mypassword
|
|
/connect bouncer
|
|
```
|
|
|
|
**hexchat:**
|
|
|
|
Set server password to `mypassword` in the network settings.
|
|
|
|
## Multi-Network Namespacing
|
|
|
|
All configured networks are multiplexed onto a single client connection. Channels
|
|
and nicks carry a `/network` suffix so you can tell which network they belong to:
|
|
|
|
```
|
|
Client sees: Server wire:
|
|
#libera/libera <-> #libera (on libera network)
|
|
#debian/oftc <-> #debian (on oftc network)
|
|
user123/libera <-> user123 (on libera network)
|
|
```
|
|
|
|
### Rules
|
|
|
|
- **Channels**: `#channel/network` in client, `#channel` on wire
|
|
- **Foreign nicks**: `nick/network` in client, `nick` on wire
|
|
- **Own nicks**: shown without suffix (prevents client confusion)
|
|
- **Sending messages**: include the `/network` suffix in the target
|
|
|
|
```
|
|
/msg #libera/libera hello -> sends "hello" to #libera on libera network
|
|
/join #test/oftc -> joins #test on oftc network
|
|
/msg user123/libera hi -> private message to user123 on libera
|
|
```
|
|
|
|
### Comma-Separated JOIN/PART
|
|
|
|
Targets can span networks:
|
|
|
|
```
|
|
/join #a/libera,#b/oftc -> joins #a on libera AND #b on oftc
|
|
```
|
|
|
|
Multiple clients can attach simultaneously. All receive the same namespaced
|
|
messages in real time.
|
|
|
|
## What Clients Receive on Connect
|
|
|
|
When a client authenticates:
|
|
|
|
1. **Backlog replay** -- missed messages (namespaced) from all networks
|
|
2. **Synthetic welcome** -- 001-004 numeric replies listing all networks
|
|
3. **Channel state** -- synthetic JOIN, TOPIC, and NAMES for every joined
|
|
channel across all networks (all namespaced with `/network` suffix)
|
|
|
|
## Backlog
|
|
|
|
Messages are stored in `bouncer.db` (SQLite) next to the config file. When
|
|
you reconnect, missed messages are automatically replayed.
|
|
|
|
Configure in `bouncer.toml`:
|
|
|
|
```toml
|
|
[bouncer.backlog]
|
|
max_messages = 10000 # per network, 0 = unlimited
|
|
replay_on_connect = true # set false to disable replay
|
|
```
|
|
|
|
Stored commands: `PRIVMSG`, `NOTICE`, `TOPIC`, `KICK`, `MODE`.
|
|
|
|
## Configuration Reference
|
|
|
|
```toml
|
|
[bouncer]
|
|
bind = "127.0.0.1" # listen address
|
|
port = 6667 # listen port
|
|
password = "changeme" # client authentication password
|
|
|
|
[bouncer.backlog]
|
|
max_messages = 10000 # per network, 0 = unlimited
|
|
replay_on_connect = true # replay missed messages on client connect
|
|
|
|
[proxy]
|
|
host = "127.0.0.1" # SOCKS5 proxy address
|
|
port = 1080 # SOCKS5 proxy port
|
|
|
|
[networks.libera]
|
|
host = "irc.libera.chat" # IRC server hostname
|
|
port = 6697 # server port (default: 6697 if tls, 6667 otherwise)
|
|
tls = true # use TLS for server connection
|
|
nick = "mynick" # desired IRC nick (set after probation)
|
|
channels = ["#test"] # channels to join (after probation)
|
|
autojoin = true # auto-join channels on ready (default: true)
|
|
password = "" # IRC server password (optional, for PASS command)
|
|
```
|
|
|
|
## Bouncer Commands
|
|
|
|
Send a PRIVMSG to `*bouncer` (or `bouncer`) from your IRC client to inspect
|
|
and control the bouncer. All commands are case-insensitive.
|
|
|
|
Responses arrive as NOTICE messages from `*bouncer`.
|
|
|
|
### Inspection
|
|
|
|
| Command | Description |
|
|
|---------|-------------|
|
|
| `HELP` | List available commands |
|
|
| `STATUS` | Overview: state, nick, host per network |
|
|
| `INFO <network>` | Detailed info for one network (state, server, channels, creds) |
|
|
| `UPTIME` | Bouncer uptime since process start |
|
|
| `NETWORKS` | List all configured networks with state |
|
|
| `CREDS [network]` | NickServ credential status (all or per-network) |
|
|
| `CHANNELS [network]` | List joined channels with topics (all or per-network) |
|
|
| `CLIENTS` | List connected bouncer clients |
|
|
| `BACKLOG [network]` | Message counts per network and database size |
|
|
| `VERSION` | Bouncer and Python version |
|
|
|
|
### Network Control
|
|
|
|
| Command | Description |
|
|
|---------|-------------|
|
|
| `CONNECT <network>` | Start a disconnected network |
|
|
| `DISCONNECT <network>` | Stop a network |
|
|
| `RECONNECT <network>` | Stop and restart with a fresh identity |
|
|
| `NICK <network> <nick>` | Change nick on a network |
|
|
| `RAW <network> <command>` | Send a raw IRC command to a network |
|
|
|
|
### Config Management
|
|
|
|
| Command | Description |
|
|
|---------|-------------|
|
|
| `REHASH` | Reload config file, add/remove/reconnect networks |
|
|
| `ADDNETWORK <name> key=val ...` | Create a network at runtime |
|
|
| `DELNETWORK <name>` | Stop and remove a network |
|
|
| `AUTOJOIN <network> +/-#channel` | Add or remove channel from autojoin list |
|
|
|
|
**ADDNETWORK keys:** `host` (required), `port`, `tls` (yes/no), `nick`,
|
|
`channels` (comma-separated), `password`.
|
|
|
|
### NickServ
|
|
|
|
| Command | Description |
|
|
|---------|-------------|
|
|
| `IDENTIFY <network>` | Force NickServ IDENTIFY with stored credentials |
|
|
| `REGISTER <network>` | Trigger NickServ registration attempt |
|
|
| `DROPCREDS <network> [nick]` | Delete stored NickServ credentials |
|
|
|
|
### Examples
|
|
|
|
```
|
|
/msg *bouncer HELP
|
|
/msg *bouncer STATUS
|
|
/msg *bouncer INFO libera
|
|
/msg *bouncer CHANNELS
|
|
/msg *bouncer CLIENTS
|
|
/msg *bouncer BACKLOG
|
|
/msg *bouncer VERSION
|
|
/msg *bouncer CONNECT libera
|
|
/msg *bouncer DISCONNECT libera
|
|
/msg *bouncer RECONNECT libera
|
|
/msg *bouncer NICK libera newnick
|
|
/msg *bouncer RAW libera WHOIS someuser
|
|
/msg *bouncer REHASH
|
|
/msg *bouncer ADDNETWORK oftc host=irc.oftc.net port=6697 tls=yes channels=#test
|
|
/msg *bouncer DELNETWORK oftc
|
|
/msg *bouncer AUTOJOIN libera +#newchannel
|
|
/msg *bouncer AUTOJOIN libera -#oldchannel
|
|
/msg *bouncer IDENTIFY libera
|
|
/msg *bouncer REGISTER libera
|
|
/msg *bouncer DROPCREDS libera
|
|
/msg *bouncer DROPCREDS libera oldnick
|
|
```
|
|
|
|
### Example Output
|
|
|
|
```
|
|
[STATUS]
|
|
libera ready fabesune user/fabesune
|
|
oftc ready ceraty cloaked.user
|
|
hackint connecting (attempt 3)
|
|
quakenet ready spetyo --
|
|
|
|
[CHANNELS]
|
|
libera #test Welcome to the test channel
|
|
libera #dev
|
|
oftc #debian Debian support
|
|
|
|
[CLIENTS]
|
|
myuser 127.0.0.1:54321 connected 2h 15m 3s
|
|
|
|
[BACKLOG]
|
|
libera 1,500 messages
|
|
oftc 842 messages
|
|
DB size: 2.1 MB
|
|
```
|
|
|
|
## Stopping
|
|
|
|
Press `Ctrl+C` or send `SIGTERM`. The bouncer shuts down gracefully, closing
|
|
all network connections and the backlog database.
|