kevin
|
6ee2dd8184
|
fix(security): 修复 P4 封禁记录数据错位 + P5 枚举爆破宽限(方案 A)
P4 #17 手动封禁 Create 非 upsert 导致数据错位:
- BanStore 新增 BanIP(ip, reason, duration):事务内清理该 IP 全部
既有记录(兼容历史脏数据)后插入单条封禁记录,计数清零;
DisconnectConnection 改用(原裸 Create 为全仓库唯一调用点)
- BanEntry.IPAddress 升级 uniqueIndex;InitDB 在 AutoMigrate 前
dedupeBanEntries 清理历史重复行(MySQL 1093 兼容写法)
- IncrementFail 原子化:SQL 侧 fail_count+1,miss 时 OnConflict
DoNothing 插入兜底并发竞态,回读计数
P5 #18 方案 A(按失败性质区分宽限):
- RecordAuthFailure 新增 knownUser 参数:用户名不存在(枚举型
爆破)跳过 3 次宽限、首次触发即封第 1 档;用户名存在(真实
用户输错)保留宽限防误封
- 新增 UserStore.LoginExists(邮箱/裸用户名);五个失败调用点
接线(Web 登录查存在性;SMTP/IMAP/POP3 用登录名;LDAP 侧
存在性不可判定,保守按已知用户处理)
- 封禁原因注明「未知用户名,跳过宽限」便于后台审计
新增 8 个测试(-race 通过):BanIP 单行 upsert、唯一索引约束、
16 协程并发计数精确、dedupe 清理/表不存在静默、未知用户即时
封禁、已知用户宽限回归、LoginExists 矩阵。
|
2026-08-20 11:25:10 +08:00 |
|
dsh
|
f48776e89b
|
fix(auth): 协议登录(IMAP/SMTP/POP3)成功时清零失败计数 + 支持裸用户名
问题:ResetFail 只在 Web 登录调用,协议层失败计数只增不减。
合法用户的客户端(手机 APP 用裸用户名重试、配置向导探测、输错
密码等)失败次数持续累积,每达到阈值就触发一次封禁档位,从第 4
次触发起真实封禁 30 分钟+——用户被反复误封,手机端表现为一直
卡在"正在接收邮件"。
修复:
- IMAP/SMTP/POP3 认证成功路径调用 Bans.ResetFail(与 Web 一致)
- 新增 UserStore.AuthenticateLogin:支持裸用户名(如 "kevin"),
唯一归属时自动解析到其域名;跨域名同名歧义时要求完整邮箱
- 新增 TestAuthenticateLoginBareUsername 单元测试
|
2026-08-19 10:12:28 -04:00 |
|
kevin
|
6a9dcd0285
|
feat(imap): 多客户端状态实时同步 + 当前连接「断开并封禁」
- 推送扩展:IMAP STORE(已读/星标/\Deleted)推送 FETCH 标志更新、
EXPUNGE 推送 ExpungeUpdate(删除前序号)、APPEND/COPY/MOVE 推送
新邮件;POP3 QUIT 删除、Web 标已读/删除同样实时同步到 IMAP 客户端
- Pusher 接口统一 SMTP/POP3/Web 的推送入口,IMAP 内部操作经会话
通道直接入队(非阻塞,满则丢弃)
- 当前连接页新增「断开并封禁」:connhub 支持断开回调,SMTP/POP3
关底层连接、IMAP 经 ForEachConn 按地址断开;一键封禁 180 天并
断开该 IP 全部在线连接,黑名单页可随时解封
- 修复:POP3 PASS 成功后保留完整邮箱(此前被裸用户名覆盖)
- 新增测试:断开/按 IP 断开、flags/expunge 推送内容、POP3 删除推送、
Web 断开封禁处理器;全量 -race 通过
|
2026-08-19 19:56:04 +08:00 |
|
kevin
|
ede85e0698
|
feat(imap): 新邮件实时推送(IDLE)+ 后台当前连接监控
- IMAP 推送:imapBackend 实现 backend.BackendUpdater,SMTP 本地投递
与 Web 写信投递成功后 NotifyNewMessage,挂起 IDLE 的客户端即时收到
新邮件 FETCH 通知(按用户名+INBOX 过滤广播,通道满非阻塞丢弃)
- 当前连接:新增 internal/connhub 连接注册中心,SMTP/IMAP/POP3 三协议
注册/注销/用户名/TLS/活跃时间追踪;后台新增「当前连接」页
(/admin/connections,统计卡片+连接表格,每 5 秒自动刷新)
- 新增测试:connhub 并发安全、推送内容/非阻塞/nil 安全、
后台页面渲染;全量 -race 通过
|
2026-08-19 19:40:05 +08:00 |
|
kevin
|
f2493da03e
|
feat(security): IP 阶段性封禁,前3次触发不封禁、第4次起按档位递增
- 封禁规则:达到失败阈值记为一次触发,前 3 次只计数不封禁;
第 4 次起封禁并按档位递增:30分钟(ban_duration_min)→ 3小时
→ 3个月 → 半年(上限);封禁过期后保留记录作为升档依据,
成功登录或管理员解封清零
- BanEntry 新增 BanCount(累计触发次数),每 IP 一条记录 upsert,
不再重复建行;RecordAuthFailure 统一 Web/LDAP/SMTP/IMAP/POP3
五处封禁逻辑,原因带档位(如"第1次封禁:登录失败次数过多
(第4次触发,失败5次)")
- 黑名单页修复:列表仅显示已封禁或曾封禁记录(原因/到期时间必填),
新增封禁次数列与封禁中/已过期状态徽章,移除清理过期按钮
- 用户封禁页显示第 N 次封禁档位;新增档位升级与列表过滤单测
|
2026-08-19 19:07:25 +08:00 |
|
kevin
|
353bfa88f2
|
feat: 新增 SMTP/IMAP/POP3 协议调用日志(含攻击分析筛选)
- 每个连接记录一条日志:协议、端口、来源 IP、用户名、成功/失败、
失败原因(密码错误/IP封禁/中继被拒/发件人伪造/未认证发信等)、
操作摘要、消息数与会话时长
- 管理后台新增「协议日志」页:按协议/状态/IP/用户名/时间筛选,
今日与历史成功/失败统计卡片,分页查看,可手动清理
- 后台每 6 小时自动清理超出 protocol_log_keep_days(默认30天)
的日志;新增 [web] protocol_log_keep_days 配置项
- 修复 POP3 认证既有 bug:handleUSER 丢弃邮箱域名导致 PASS 永远失败
- 新增 store 单测、SMTP/POP3 端到端测试与模板渲染测试
|
2026-08-19 18:49:29 +08:00 |
|
kevin
|
3f28ec20f4
|
fix(security): 修复 P2 中危项(cookie/协议限速/路径遍历/默认口令/中继TLS/安全头/信息泄露)
- 会话 cookie 增加 Secure 标志;新增 [web].cookie_secure 配置
(默认 true,仅本地 HTTP 调试关闭;缺失字段按安全默认处理)
- SMTP/IMAP/POP3 认证接入封禁体系(store.RecordAuthFailure 与 Web
共用 ban_entries):失败计数达 ban.max_fail_attempts 即封禁 IP,
已封禁 IP 拒绝认证,堵住协议层暴力破解
- 附件存储路径遍历防护重写:FullPath 白名单校验(UUID 文件名格式)
+ baseDir 前缀兜底,非法路径返回错误;Save 扩展名白名单化
- 初始管理员不再使用 admin/admin:密码取 MAILGO_ADMIN_PASSWORD 或
随机生成并打印一次;新增 MustChangePassword 首登强制改密
(管理员重置密码同样触发)
- 外发中继默认验证 TLS 证书(保护 AUTH 凭据,防 MITM),直投 MX
保持机会式 TLS;新增 outbound.relay_tls_insecure 开关(默认 false)
- 新增安全响应头中间件:HSTS、X-Frame-Options DENY、nosniff、
Referrer-Policy、基础 CSP(frame-ancestors 'none' 防点击劫持,
connect-src/form-action 'self' 防数据外泄)
- LDAP/OAuth 登录错误统一为通用文案,原始错误只写日志,
不再回显邮箱/内部细节(防用户枚举与信息泄露)
- 新增 25 个回归测试:cookie 标志、封禁阈值、路径遍历用例、
中继 TLS 验证(自签证书 STARTTLS 集成)、安全头、OAuth 文案
部署注意:升级后所有会话失效需重新登录;若直接以 HTTP 提供
服务需显式配置 cookie_secure = false。
|
2026-08-19 16:45:21 +08:00 |
|
dsh
|
f0b9ad3e6f
|
feat: 管理后台一键从 Caddy 获取证书 + TLS 证书热加载
- 域名编辑页新增“从 Caddy 获取证书”按钮:一键把本机 Caddy 已签发的
证书与私钥导入该域名的 TLS 目录并自动启用 TLS,支持通配符证书
(如 *.example.com 可匹配 mail.example.com),成功/失败均回显横幅
- 新增 internal/caddycert:搜索 Caddy 证书存储(同步镜像目录优先、
caddy.data_dir 与常见位置兜底),校验密钥对/有效期/SAN,并给出
可操作的中文错误提示(未找到/证书无效/权限不足)
- install.sh 新增 setup-caddy-cert:安装 root 权限的 systemd
path+timer 同步任务(mailgo-caddy-sync),把 Caddy 证书树镜像到
/srv/mail_go/tls/caddy(证书续期后自动更新、每日兜底),另授予
ACL 作为直接读取兜底;install 时自动检测并配置
- 新增 [caddy] data_dir 配置节,支持自定义 Caddy 数据目录
- 新增 internal/tlsutil:TLS 证书热加载器,每次握手按需重载证书
文件(mtime 检测),重载失败继续使用旧证书兜底并节流重试;
应用于 SMTPS 465/IMAPS 993/POP3S 995 与 STARTTLS,导入或上传
新证书后无需重启服务即生效
- 证书来源动态切换:协议显式配置优先,否则取首个启用 TLS 且有证书
的域名(10 秒缓存),新域名一键导入证书后自动切换
- 更新 README 与界面文案(去掉“重启服务生效”提示)
|
2026-08-16 23:39:43 -04:00 |
|
dsh
|
31e5f94be6
|
fix: SMTP 收件邮件的附件未保存(Web 邮箱看不到附件)
- parseSMTPMessage 之前只提取附件元数据、丢弃内容;现在保留原始字节
- saveMessage 创建邮件后落盘附件文件(storage.Save)、写 attachments 记录
并计入用户配额 used_bytes,Web 邮箱可正常列表/下载
- 新增单元测试:附件字节提取 + 附件落盘/记录/配额校验
- 已在生产环境实测:带附件邮件经 :25 入站后,附件文件、记录、配额、
Web 下载(/attachment/:id)全部正确
|
2026-08-15 23:53:50 -04:00 |
|
dsh
|
5eb9bc2c71
|
feat: 实现对外邮件投递(外发队列 + MX 直投 + DKIM + 退信 + 管理后台)
- 新增 internal/outbound 模块:MX 查询、SMTP 出站客户端(EHLO/STARTTLS/
MAIL/RCPT/DATA/QUIT)、4xx 临时失败与 5xx 永久失败分类、8BITMIME 支持
- 新增 outbound_messages 队列表与 OutboundStore,后台 worker 指数退避重试
- 永久失败/超限退信到发件人收件箱,包含原因与目标收件人
- 外发邮件使用域名 DKIM 私钥签名(go-msgauth)
- SMTP 提交集成:认证用户可发外部收件人,MAIL FROM 必须等于登录用户邮箱,
未认证外部投递明确拒绝(防开放中继)
- Web 发信集成:外部收件人自动入队,附件以 multipart/mixed + base64 编码
加入邮件正文
- 每用户每分钟/每日发送限速(max_per_day=0 可禁用外部投递)
- 管理后台新增外发队列页面:状态统计、失败原因、手动重试/取消
- 新增 [outbound] 配置段并更新 README / todo.md
|
2026-08-15 17:18:54 -04:00 |
|
kevin
|
59719586a1
|
修复部分功能
|
2026-06-02 20:33:08 +08:00 |
|
kevin
|
3dcc3f9a35
|
up
|
2026-06-01 20:43:01 +08:00 |
|
kevin
|
4e233c82b4
|
二阶段差不多
|
2026-06-01 19:46:51 +08:00 |
|
kevin
|
9e50d05e71
|
一阶段ok
|
2026-06-01 18:59:55 +08:00 |
|