
通用BBS软件
SSH-Chatter 源于对 Go 语言 ssh-chat 服务的 C 语言重实现。它镜像/扩展了原始行为,同时使用现代 C 语言模式和小巧可测试的核心。该服务监听 SSH/TELNET 连接,并将每个经过身份验证的用户放入一个共享聊天室,该聊天室暴露与 Go 参考实现相同的命令界面。
你知道为什么理解 C 语言需要那么长时间吗?因为这是一种本能。
/rss list、/rss read <tag> 以及 /rss add <url> <tag> 和 /rss del <tag>(仅操作员可用)让聊天室共同浏览头条新闻。/delete-msg 用于有针对性的聊天历史清理。/bbs 命令解锁沉浸式复古公告板系统,支持标签、评论、顶帖和多行编辑器。
list [hot|top|new|bumped|all] 按 bumped(最近活动)、hot(根据评分和评论的趋势)、top(最高净赞数)或 new(创建日期)查看帖子排序。search <query> 对帖子标题、正文、作者或标签进行不区分大小写的即时搜索。▲ 12 💬 5)直接显示净赞数和评论数。/bbs 前缀。/asciiart 实时编辑器,设有 640 行限制、每个 IP 十分钟冷却时间、多行输出,以及通过 Ctrl+A 取消、Ctrl+S 或区域感知 >/__ARTWORK_END> 默认快捷键提交。/birthday 注册生日,/grant <ip> 使 LAN 操作员可以按 IP 地址委托权限,/revoke <ip> 使高级 LAN 管理员可以收回权限。/ban 升级,允许使用原始 IP 地址以及用户名。/weather <city> 快速获取全球预报。

代码库有意保持紧凑,以便新贡献者快速导航:

main 保持同步work 分支会定期与上游开发分叉,以便较大功能在不中断生产流量的情况下孵化。当需要与 main 同步时,先拉取最新树并在本地合并,然后打开拉取请求:```bash
git fetch origin main
git checkout work
git merge --no-ff origin/main
在本地解决所有冲突(`src/host_aggregate.c` 帮助函数已经镜像了 `main` 分支的布局,因此合并通常很直接),然后运行 `make` 确认构建仍然成功,之后再推送结果。
## 自动化钩子
- `host_snapshot_last_captcha` 暴露最近生成的验证码提示和答案以及时间戳,以便外部客户端可以代表无人值守的自动化通过挑战。
## 安全加固
- `scripts/safe_permission.sh` 收紧运行时数据文件(BBS 状态、投票状态、冷却快照和通用聊天状态)的所有权和权限。部署后运行它以将数据目录限制为 `ssh-chatter` 并确保每个文件设置为 `0600`。通过传递显式路径或导出 `STATE_ROOT` 或相应的 `CHATTER_*_FILE` 环境变量来覆盖目标。
- 后台 BBS 监视器定期将帖子和评论通过 AI 审核管道(主要使用 Gemini,后备使用 Ollama)处理。被标记的帖子会自动移除,并向房间广播通知。
- 聊天消息、ASCII 艺术和 BBS 帖子/评论流经 AI 审核管道。用 `CHATTER_SECURITY_AI=on` 启用(设置 `GEMINI_API_KEY` 使用 Gemini;守护进程自动回退到本地 Ollama 端点 `http://127.0.0.1:11434`)。用 `CHATTER_SECURITY_FILTER=off` 禁用一切。如果所有提供商都失败,过滤器会自动禁用自身以保持对话进行,而不是静默丢弃内容。
- SSH 传输被固定为现代密钥交换、加密算法和 MAC,每个桥接负载被包装在三层 AES-256-GCM 洋葱中,因此中继只看到密文。
- 触发分层过滤器的可疑提交现在按 IP 跟踪;重复命中会自动触发踢出和封禁(当启用时),而快速重连检测器允许更长的恢复窗口,使不稳定的网络会话可以重新加入而不受惩罚。自动封禁条目默认**关闭**;设置 `CHATTER_AUTO_BAN=on`(或 `true`/`1`)启用,或保持变量未设置以保留警告和节流而不写入自动封禁条目。
- 操作员可以用 `CHATTER_PROTECTED_IPS`(逗号分隔,默认为 `127.0.0.1,::1,192.168.0.1`)标记受信任的入口点(VPN 出口、反向代理、localhost),以便紧急封禁不会将守护进程锁定在其控制平面之外。
## 文件存储与传输
- 所有用户管理的文件现在位于 `/etc/ssh-chatter/user-files` 下(使用 `CHATTER_FILESTORE_PATH` 覆盖,旧版回退:`CHATTER_FILE_STORAGE_ROOT`)。守护进程在需要时创建该目录,并将上传限制在该目录内。
- SSH 客户端使用标准 `scp`,无需自定义包装器。将 `/name.ext` 视为存储树的根:`scp my.zip user@host:/demos/my.zip` 写入 `/etc/ssh-chatter/user-files/demos/my.zip`,而 `scp user@host:/readme.txt ./` 下载 `/etc/ssh-chatter/user-files/readme.txt`。
- TELNET 客户端使用新的 `/filestore` 命令。`/filestore` 列出可用文件,`/filestore-upload` 启动一个 `rz` 会话,`/filestore-download <name>` 启动一个 `sz` 会话。在服务器上安装 `lrzsz`(或任何提供 `rz`/`sz` 的包),以便 ZMODEM 后端可以生成这些帮助程序。
- `/filestore-upload` 接受可选的目标路径(例如 `/filestore-upload /kitten/meow.png`)。SSH-Chatter 自动创建 `/kitten` 目录并将上传的文件放置在那里,模拟 SCP 使用路径如 `user@host:/kitten/meow.png` 的方式。
- 两种传输方式可以混合使用:SSH 用于无人值守的脚本化传输,TELNET 用于带有内置 ZMODEM 工具的怀旧 BBS 客户端。
## Morse 中继
SSH-Chatter 支持业余无线电中继。
显示全球摩尔斯电码信号。
`/morse on` 查看,`/morse-reply` 发送。
### 协议细节
实现遵循 Binkp 协议规范:
- 标准 Binkp 帧结构,2 字节头部
- 会话密码认证 (CMD\_PWD/CMD\_OK)
- 每 60 秒的心跳机制 (CMD\_NUL)
- 自定义 CHAT 命令 (CMD\_CHAT 扩展) 用于消息同步
## 先决条件
构建项目需要 POSIX 环境,包含:
- C23 兼容编译器(例如 `gcc` 或 `clang`)
- `make`
- `libssh` 开发头文件和库(Debian/Ubuntu 上为 `libssh-dev`)
- `libcurl` 开发头文件和库(Debian/Ubuntu 上为 `libcurl4-openssl-dev`)
- `uchardet` 开发头文件和库(Debian/Ubuntu 上为 `libuchardet-dev`)
- `icu`(Unicode 国际化组件)开发头文件和库(Debian/Ubuntu 上为 `libicu-dev`)
- `lz4` 压缩库和开发头文件(Debian/Ubuntu 上为 `liblz4-dev`)
- POSIX 线程(通常由系统 `libpthread` 提供)
- `python3-pygments`(为俄罗斯方块伪装屏幕提供 `pygmentize` 高亮器)
在 Debian/Ubuntu 上可以使用以下命令安装依赖:```bash
sudo apt-get update
sudo apt-get install build-essential libssh-dev libcurl4-openssl-dev libuchardet-dev libicu-dev liblz4-dev
克隆仓库并使用提供的 Makefile:```bash
make
这会生成位于仓库根目录下的 `ssh-chatter` 二进制文件,以及一个暴露翻译助手的共享对象 `libssh_chatter_backend.so`,供其他应用复用。使用 `make clean` 清理中间构件。
### 使用共享翻译后端
共享对象复用了服务器端的 C 语言翻译管道(包括 ANSI 占位符的保留),因此其他进程可以在不启动完整 SSH 主机的情况下获取翻译。链接到 `libssh_chatter_backend.so` 并包含 `include/ssh_chatter/ssh_chatter_backend.h`:```c
#include "ssh_chatter/ssh_chatter_backend.h"
int main(void) {
char translated[4096];
char detected[64];
if (ssh_chatter_backend_translate_line("Hello, world!", "ko", translated, sizeof(translated), detected, sizeof(detected))) {
printf("Detected %s -> %s\n", detected, translated);
}
}
在环境中设置 GEMINI_API_KEY(以及可选的 GEMINI_API_BASE 或 GEMINI_MODEL),以便助手能够访问 Google Generative Language API,这与主守护进程的运行要求一致。在启动聊天服务器之前,你可以运行 ./scripts/test_gemini_connection.sh 来验证凭据是否允许出站调用;该脚本会直接输出 Gemini 原始响应,以便查看请求是否成功。
服务器默认监听 0.0.0.0:2222。你可以使用以下可用标志调整运行时参数:```
Usage: ./ssh-chatter [-a address] [-p port] [-m motd_file] [-k host_key_dir] [-T telnet_port|off] [-J json_port|off]
./ssh-chatter [-h]
./ssh-chatter [-V]
当提供时,`-m` 从指定的文件路径读取每日消息。
常见示例:```bash
# Start the chat server on port 2022, loading host keys from /etc/ssh
./ssh-chatter -p 2022 -k /etc/ssh
# Enable telnet access on 0.0.0.0:4242 alongside SSH
./ssh-chatter -T 0.0.0.0:4242
# Serve a custom MOTD from a file and bind to localhost
./ssh-chatter -a 127.0.0.1 -m /etc/ssh-chatter/motd
主机密钥目录必须包含一个 ssh_host_rsa_key 文件(以及可选的 .pub 文件)。如果您不想重用系统 SSH 主机密钥,请使用 ssh-keygen -t rsa -b 4096 -f /path/to/dir/ssh_host_rsa_key 生成一个。名为 ssh_host_ed25519_key 和 ssh_host_ecdsa_key 的其他主机密钥在存在时会自动加载,以便服务器在密钥交换期间提供现代算法。
运行后,使用任何 SSH 客户端连接:```bash ssh -p 2222 user@server-address
公共服务器可在 `bbs.chatter.pw` 的默认SSH端口上访问:```bash
ssh -p 2222 [email protected]
在SSH提示符下输入的用户名将用作您的聊天昵称。
Telnet客户端可以使用相同的功能集加入。Telnet监听默认在端口2323上启用,可以通过-T标志调整或禁用。提供-T address:port来覆盖绑定地址(省略时继承SSH绑定;使用空主机如-T :4242来监听所有接口)。例如,通过复古终端使用Telnet加入:```bash
telnet server-address 2323
传递 `-T off`(或 `-T disable`)以完全关闭telnet监听器。
### JSON行API
服务器还通过TCP暴露了一个JSON行协议,用于自动化和外部集成。它默认监听端口 `34567`,可以通过 `-J` 禁用或重新配置:```bash
# Disable the JSON API
./ssh-chatter -J off
# Bind JSON API on a custom port
./ssh-chatter -J 0.0.0.0:45678
每个请求都是一个单独的JSON对象,以\n终止。响应和聊天事件也是JSON对象,同样以换行符分隔。该API支持一般聊天以及/poll、/vote、/image、/video、/audio、/files和/asciiart流程。
事件负载(服务器→客户端)```json {"type":"event","event":"message","payload":{"id":123,"username":"alice","message":"hello","created_at":1710000000,"system":false,"preserve_whitespace":false,"attachment":{"type":"none","target":"","caption":""}}}
**请求示例(客户端 → 服务器)**```json
{"type":"chat","id":1,"username":"alice","message":"안녕하세요"}
{"type":"image","id":2,"username":"alice","url":"https://example.com/cat.png","caption":"cat"}
{"type":"asciiart","id":3,"username":"alice","message":" /\\_/\\\\n( o.o )\\\\n > ^ <"}
{"type":"poll","id":4,"username":"op","is_operator":true,"question":"Favorite color?","options":["red","blue","green"]}
{"type":"poll","id":5,"username":"bob","action":"vote","choice":2}
{"type":"vote","id":6,"username":"op","label":"weekend","question":"Plan?","options":["hike","rest"],"allow_multiple":true}
{"type":"vote","id":7,"username":"bob","label":"weekend","action":"vote","choice":1}
Responses echo the id and include status, message, and optional result objects:```json
{"type":"response","id":4,"status":"ok","message":"poll started","result":{"poll":{"active":true,"allow_multiple":false,"id":10,"question":"Favorite color?","options":[{"index":1,"text":"red","votes":0},{"index":2,"text":"blue","votes":0}]}}}
如需可运行示例,请参见 `scripts/json_api_example.py`:```bash
python3 scripts/json_api_example.py --url tcp://127.0.0.1:34567 --save /tmp/json_api_output.txt
提供了一个辅助脚本,用于在使用systemd的系统上自动安装:```bash
sudo ./scripts/install_chatter_service.sh
脚本的作用:
1. 编译项目(`make`)。
2. 将生成的二进制文件安装到 `/usr/local/bin/ssh-chatter`。
3. 创建专门的 `ssh-chatter` 系统用户和组(如果尚不存在)。
4. 为运行时状态(包括 SSH 主机密钥)创建 `/var/lib/ssh-chatter`,为配置文件创建 `/etc/ssh-chatter`。
5. 在缺失时,在 `/var/lib/ssh-chatter/ssh_host_rsa_key` 下生成默认的 RSA 主机密钥。
6. 在 `/etc/ssh-chatter/motd` 创建默认 MOTD,并创建覆盖文件 `/etc/ssh-chatter/chatter.env` 用于基于环境的调整。
7. 写入 `/etc/systemd/system/chatter.service`,重新加载 `systemd`,启用服务,并立即启动该服务。
生成的 `chatter.service` 单元以合理的默认值启动服务器,并授予 `CAP_NET_BIND_SERVICE` 能力,以便非 root 服务帐户在需要时可以绑定到特权端口。
### 自定义服务
您可以通过编辑 `/etc/ssh-chatter/chatter.env` 并重启服务来调整默认值:```bash
sudo systemctl edit chatter.service # or edit the environment file directly
sudo systemctl restart chatter.service
支持的环境变量包括:
CHATTER_BIND_ADDRESS – 绑定的IP地址(默认 0.0.0.0)。CHATTER_PORT – 向客户端暴露的TCP端口(默认 2222)。CHATTER_MOTD_FILE – 每日消息文件的路径(默认 /etc/ssh-chatter/motd)。CHATTER_HOST_KEY_DIR – 包含 ssh_host_rsa_key 的目录(默认 /var/lib/ssh-chatter)。CHATTER_EXTRA_ARGS – 附加到 ssh-chatter 调用的额外参数。CHATTER_VOTE_FILE – 投票状态文件的路径(默认 vote_state.dat)。CHATTER_GEMINI_COOLDOWN_FILE – Gemini 冷却状态文件的路径(默认 )。伪装代码片段:
对于俄罗斯方块伪装功能,运行时期望代码片段文件位于 /var/lib/ssh-chatter/。
此仓库现在包含 ./camouflage/ 下的现成示例(c.txt、cpp.txt、java.txt、go.txt、js.txt、ts.txt、rust.txt)。
在设置时将它们复制到运行时目录:```bash
sudo install -d /var/lib/ssh-chatter
sudo cp camouflage/*.txt /var/lib/ssh-chatter/
您可以编辑任何已复制的文件,自定义伪装屏幕激活时显示的内容。
翻译支持现在依赖于 Google Gemini API。在 `chatter.env`(或环境变量)中设置以下内容以启用它:
- `GEMINI_API_KEY` – 用于验证翻译请求的密钥 API 密钥。
- `GEMINI_API_BASE` – API 基本 URL 的可选覆盖(默认为 `https://generativelanguage.googleapis.com/v1beta`)。
- `GEMINI_MODEL` – Gemini 模型名称的可选覆盖(默认为 `gemini-2.5-flash`)。
当翻译激活时,聊天会立即以原始语言发送每条消息,并在 Gemini 响应到达后,以缩进标题的形式提供翻译文本。反应摘要使用相同的标题样式,因此更新直接显示在引用的消息下方。
如果内联标题插入显得突兀,您可以提前用 `/chat-spacing <0-5>` 保留少量空白行缓冲区。此设置仅影响实时聊天线程——公告板内容继续无保留地翻译——因此您可以为自己的会话调整间距而不影响长帖。
您的翻译切换和语言选择保存在 `chatter_state.dat` 中,因此以后重新连接时会自动恢复相同的配置。
如果您希望安装但不立即启动服务,请使用 `SKIP_START=1` 运行脚本。
服务管理命令:```bash
sudo systemctl status chatter.service
sudo systemctl restart chatter.service
sudo systemctl disable --now chatter.service
-m 标志或服务管理的配置文件传递 MOTD。/help 命令。/ban、/poke)。/weather/vote 投票和单选 /vote-single 投票选项,包括 /elect <label> <choice> 作为文本友好的投票快捷方式。/bbs 访问的复古公告板系统,支持标签、评论、提升以及交互式编辑器,以支持本地化的终止符结束(默认 >/__BBS_END>)。/asciiart 编辑器,支持 640 行草稿、每个 IP 每十分钟发帖冷却时间、多行发送以及 Ctrl+A/Ctrl+S 快捷键。/game 中心内置 (从原苏联时期 C 实现转码而来)和 ,均可通过 或 Ctrl+Z 暂停。欢迎提交问题(Issues)和拉取请求(Pull Requests)。请包含错误的复现步骤,并确保在提交更改前 make 命令成功执行。
| 路径 | 描述 |
|---|
src/main.c | 命令行解析和进程引导(绑定地址、端口、MOTD、主机密钥目录)。 |
src/host_aggregate.c, include/ssh_chatter/host.h | 聊天主机实现——会话生命周期、MOTD 处理以及未来消息广播逻辑的钩子。 |
src/host | 模块化主机子系统,通过 src/host_aggregate.c 编译为单个翻译单元。 |
include/ssh_chatter | 守护进程、压力工具和翻译后端的共享头文件。 |
include/ssh_chatter/contexts | session_ctx_t 及相关结构的定义,封装每个连接的状态。 |
data/banner/banner | 示例欢迎横幅,可通过 CHATTER_WELCOME_BANNER 指向。 |
scripts/install_chatter_service.sh | 便捷安装脚本,构建二进制文件,安装到 /usr/local/bin,并配置 systemd 单元(chatter.service)。 |
scripts/install_dependencies.sh | 适用于 Debian/Ubuntu 系统的最小构建依赖包安装脚本。 |
gemini_cooldown.datCHATTER_SECURITY_FILTER – 设置为 off/false/0 以禁用层级安全过滤器(默认启用)。CHATTER_SECURITY_AI – 设置为 on/true/1 以启用AI审核(默认禁用)。CHATTER_FILESTORE_PATH – 覆盖托管的文件存储路径(默认 /etc/ssh-chatter/user-files)。CHATTER_FILE_STORAGE_ROOT – 托管文件存储路径的旧版回退。CHATTER_MAX_ALLOC_BYTES – 内部内存管理器中单次连续分配尝试的上限。默认 无上限(SIZE_MAX)。仅当您想对一次分配施加硬性限制时才设置此项。设置为 0、unlimited、inf 或 infinity 以明确移除任何上限。tetrisliargame/suspend!