rs-short 3.3.1 配置参数详解
rs-short 3.3.1 双配置文件全量详解:config.toml 16 参数语义与启动红线(panic 级校验)、lists.toml 名单语法与 _category 陷阱、names 黑名单 Missing translation 缺陷、可疑监测按去重 IP 计数纠偏,theme/verbose_console/名单四项改参→重启→验证闭环实录。
rs-short 3.3.1 配置参数详解
覆盖 rs-short 3.3.1 的全部两个配置文件:
config.toml(16 个参数)与lists.toml(策略名单)。所有参数语义取自源码(src/init.rs、src/structs.rs、src/spam.rs)与样例文件注释,关键行为均经"改参→重启→验证"闭环实测(取证:/opt/data/quzuo/tmp/rs-short/evidence.md)。
一、配置文件总览
| 文件 | 作用 | 生效方式 | 镜像内位置 |
|---|---|---|---|
config.toml | 主配置(监听、数据库、站点身份、验证码、反钓鱼) | 启动时一次性读取,改后必须重启 | 不含,必须挂载到 /run_dir/config.toml |
lists.toml | 名单策略(names/urls 的 allow/blocklist) | 同上,无热加载 | 内置默认版,建议挂载覆盖 |
lang.json | 界面文案(en/fr/hr/oc) | 编译期嵌入模板逻辑,一般不改 | 内置 |
assets/themes/* | light/dark/custom 主题 CSS 与背景 | 重启生效 | 内置 |
启动红线(源码 check() 实测):以下任一情况进程直接 panic 退出,容器表现为重启循环——
config_version≠ 3(提示 "Your configuration file is obsolete!");instance_hostname/cookie_key/phishing_password仍是样例默认值(前两者中 instance_hostname 为阻断级);cookie_key长度 < 88;lists.toml解析失败(含 §3 的_category陷阱)。
二、config.toml 参数详解
2.1 [general] 站点与网络(10 项)
| 参数 | 默认(样例) | 语义与实测要点 |
|---|---|---|
listening_address | 0.0.0.0:8080 | 监听地址:端口。容器内保持 8080,宿主映射自选(本部署 8164) |
database_path | ./db/db.sqlite | 三形态:SQLite 相对/绝对路径;postgres://user:pass@host:port/db;mysql://...。必须与二进制编译 feature 匹配:官方 Dockerfile 产物只认 postgres://(PG 实测 ✅);SQLite 官方注明有库锁风险(有缓存层兜底) |
instance_hostname | s.example.com | 对外 (子)域名含协议、无尾斜杠。用于生成管理链接/钓鱼标记链接展示与自链接防护比对。⚠️ 实测:填 http://127.0.0.1:8164 这类带端口值时,自链接防护失效(比对用 uri.host() 不含端口);生产填无端口域名即正常 |
hoster_name | ExampleSoft | 站点名,出现在 <title>(实测 "Link shortener – QuzuoLab")、页脚与政策文案 |
hoster_hostname | example.com | 提供方主站链接(展示用,非默认值不阻断) |
hoster_tos | https://example.com/ToS | 服务条款链接(展示用) |
contact | mailto:... | 举报联系通道(反钓鱼必需入口,支持任意 scheme) |
theme | light | light / dark / custom(custom 需自建 assets/themes/custom/base.css)。实测闭环:light→dark 重启后首页资源路径即变 themes/dark ✅ |
cookie_key | CHANGE ME | 会话 Cookie 加密密钥(存验证码答案)。生成:openssl rand -base64 64 | tr -d '\n';长度 <88 panic。改动会使所有未完成创建的会话失效(无害) |
captcha_difficulty | 3 | 验证码强度 0–5,逐级叠加 Noise/Wave/Grid 滤镜。0–5 均强制启用,无法关闭(README 把"可关开关"列为待办)。实测难度 3 下 6 字符图像人工/视觉识别均可稳定通过 |
2.2 [phishing] 反钓鱼与日志(6 项)
| 参数 | 默认(样例) | 语义与实测要点 |
|---|---|---|
verbose_console | false | true 时每次建链向 stdout 打印 NOTE: New link created: … / Redirects to / Admin link / Flag as phishing。便于治理但牺牲建链者隐私(样例注释原话)。实测闭环:false→true 重启后新建 verbose-test 即见四行打印 ✅ |
verbose_suspicious | true | 启用 RAM 内可疑访问监视器(临时存 IP+时间戳,重启即清,不落库) |
verbose_level | notice | 日志级别 info|notice|warn|crit |
suspicious_click_count | 25 | 告警阈值。⚠️ 源码实测语义是时间窗内去重 IP 数(spam.rs 对相同 IP 不重复计数),与样例注释"how many clicks"不符——单机刷点击不会触发,分布式访问才会。这正是"活跃钓鱼需立即处置"的设计本意 |
suspicious_click_timeframe | 12 | 窗口小时数;达到阈值打印 WARN: suspicious activity detected. 并清空该链接计数 |
phishing_password | CHANGE ME | 服务端管理密码,构成标记 URL /<short>/phishing/<此值>。要求 URL 安全字符、>16 字符。⚠️ 该密码出现在 URL 中,反代日志会留痕——生产建议反代层屏蔽该路径日志并定期轮换 |
三、lists.toml 策略名单详解
结构:[names] 与 [urls] 两个域,各含 allowlist / blocklist。
3.1 语义
- allowlist(仅
{ expr = '<regex>' }):命中项永不进入 verbose_console / verbose_suspicious 的日志与监视(治理豁免,如自家活动链接); - blocklist:建链时命中即 403 拒绝。
[urls]条目{ expr, category, matching },category ∈ shortener | freehost | spam(决定用户端提示文案),matching ∈ host(默认) | full-uri | port | authority | path | query(基于 http::Uri 组件匹配,大小写不敏感); - 默认版内置 100+ 条短链域名黑名单(bit.ly/t.co/tinyurl/linkvertise/iplogger 等)——实测缩短
https://bit.ly/fake返回 403「Please do not chain shortened links with another link shortener.」✅
3.2 ⚠️ 实测最大的坑:names 的 _category
文件头注释写条目格式是 { expr, category },但源码 BlockEntryName 结构体字段为 _category(serde 按字段原名解析):
[names]
allowlist = []
blocklist = [
{ expr = '^blocked-name$', _category = 'spam' }, # ✅ 正确(注意下划线)
]
写成 category 的实测后果——启动即 panic,容器重启循环:
thread 'main' panicked at src/spam.rs:89:34:
called `Result::unwrap()` on an `Err` value: Error { message: "missing field `_category`", ... }
[urls] blocklist 则正常用 category(无下划线),两域不一致,属上游文档/代码缺陷。
3.3 命中 names 黑名单的已知显示缺陷
_category='spam' 命中后用户端提示区显示 「Missing translation」(HTTP 403 正常返回)。源码定位:spam.rs 抛 ErrorKind::WarnBlockedName,而 lang.json 只有 WarnBlockedNameSpam 键,键名不匹配,日志伴随 FATAL: Missing translation for key WarnBlockedName。功能不受影响(仍拦截),文案待上游修复;急需可读提示可自行给 lang.json 补键(需重建镜像)。
四、改参→重启→验证闭环实录
以本部署(compose 挂载两个文件,docker compose restart rs-short 约 2 秒)为例:
| # | 改动 | 验证命令 | 实测结果 |
|---|---|---|---|
| 1 | theme = "light"→"dark" | curl -s http://127.0.0.1:8164/ | grep -o 'themes/[a-z]*' | themes/dark ✅ |
| 2 | verbose_console = false→true | 创建任一链接后 docker logs rs-short-3.3.1-app | 出现 NOTE: New link created: http://127.0.0.1:8164/verbose-test … 四行 ✅ |
| 3 | lists.toml 增 blocked-name 规则(先误写 category) | restart 后 curl http://127.0.0.1:8164/ | 连接空响应;docker ps 见 Restarting (101);日志 panic missing field '_category' ❌→改 _category 后 ✅ |
| 4 | 修正后创建 blocked-name | POST /(表单) | 403 拦截生效(文案 "Missing translation",见 §3.3)✅ |
| 5 | cookie_key 改新值 | restart | 正常启动;旧会话 Cookie 解析失败 → 建链需重新 GET 首页拿验证码(400 NoticeCookieParseFail 路径)✅ |
对照实验(负向):把 config_version 改 2 → panic "configuration file is obsolete";phishing_password 留 CHANGE ME → panic "You must change it in order to proceed"。校验前置、宁崩不裸奔,是该项目值得称道的安全默认。
五、生产配置建议清单
instance_hostname用真实 HTTPS 域名(不带端口、不带尾斜杠);- 两个密钥按 §2.1 命令现场生成,纳入备份(cookie_key 丢失仅影响进行中会话;phishing_password 泄露=治理权旁落);
- 公开实例建议
verbose_console = true+ 反代日志 + fail2ban(README 官方推荐组合);captcha_difficulty保持 ≥3; - 用 allowlist 豁免自家高频链接,避免日志噪音;
- 名单变更纳入发布流程(无热加载,重启秒级但会清空 RAM 监视器);
- 反代层对
/phishing/路径加访问日志脱敏或来源限制。