问题描述
公网访问密码目前采用 8 位纯数字方案,但代理层完全没有对多次尝试的阻拦,导致密码容易被暴力破解。建议立刻修复。
技术细节
密码强度分析
- 8 位纯数字 = 10^8 种组合 (1 亿)
- 假设每次尝试 100ms 响应:
- 10,000 次尝试 = 16.7 分钟
- 100,000 次尝试 = 2.78 小时
- 穷举全部 = 1.16 天
代码缺陷位置:lib/proxy.mjs 第 155-173 行
- 密码校验后直接返回登录页,无任何延迟或锁定
- 没有记录客户端 IP 的尝试次数
- 没有临时锁定机制
- 没有验证码或二次验证
当前代码问题
if (submitted === token) {
// 成功:种 cookie
res.writeHead(302, { ... });
} else {
// 失败:直接返回登录页,无限重试 ❌
res.writeHead(200, { ... });
res.end(loginPageHtml(true, isPublic));
}
影响范围
- 🔴 公网场景(cloudflare 隧道):高风险,DNS 可被任意客户端扫描
- 🟡 局域网场景:中低风险,但仍可被同网段用户破解
建议方案
方案 A:速率限制(推荐,立即可行)
在代理层实现简单的 IP-based 速率限制:
- 记录客户端 IP 的失败次数(内存 Map)
- 失败 5 次后,60 秒内拒绝新尝试(返回 429)
- 成功登录后清空该 IP 的计数
优点:快速实现、防止暴力破解
缺点:公网隧道环境下 IP 都来自 cloudflare 边缘节点,可能需要用 X-Forwarded-For 区分
方案 B:公网自定义密码
允许用户在开启公网时自己指定密码:
- 支持更长、更强的密码(数字 + 字母)
- 更新设置页 UI,公网开启时提示输入自定义密码
- 如果不输入,降级到自动生成的 8 位数字
方案 C:强密码自动生成(长期方案)
- 改为生成更强的密码:如 12-16 字符,含大小写字母 + 数字 + 符号
- 保持 8 位数字用于局域网快速输入(手机小屏输入体验)
- 公网/隧道模式用强密码
其他安全建议
- 添加尝试日志:记录失败的登录尝试(便于事后审计)
- 密码过期:公网密码每小时自动轮换(现在是重启时轮换)
- CAPTCHA:多次失败后要求验证码(防止自动化破解)
- 限制并发:限制单个客户端的同时连接数
相关代码文件
lib/proxy.mjs - 密码校验逻辑
lib/index.js - 密码生成与管理
client/ - 设置页 UI(若要支持自定义密码)
问题描述
公网访问密码目前采用 8 位纯数字方案,但代理层完全没有对多次尝试的阻拦,导致密码容易被暴力破解。建议立刻修复。
技术细节
密码强度分析
代码缺陷位置:
lib/proxy.mjs第 155-173 行当前代码问题
影响范围
建议方案
方案 A:速率限制(推荐,立即可行)
在代理层实现简单的 IP-based 速率限制:
优点:快速实现、防止暴力破解
缺点:公网隧道环境下 IP 都来自 cloudflare 边缘节点,可能需要用
X-Forwarded-For区分方案 B:公网自定义密码
允许用户在开启公网时自己指定密码:
方案 C:强密码自动生成(长期方案)
其他安全建议
相关代码文件
lib/proxy.mjs- 密码校验逻辑lib/index.js- 密码生成与管理client/- 设置页 UI(若要支持自定义密码)