Smail/docs/远程服务器测试记录.md
smail bf1e69f480
Some checks are pending
Security Checks / security (push) Waiting to run
修复生产审查凭据泄露风险并增加持久投递队列
2026-09-17 10:17:09 +08:00

22 KiB
Raw Blame History

远程服务器测试记录

范围

2026 年 9 月 16 日,用户指定在 47.108.78.12 测试,并授权清理测试数据库。远程部署目录为 /opt/smail,服务为 smail.service,网页为 https://mail.solit.cn/。

本轮应用运行、自动测试二进制执行和业务验收均针对远程服务器。本机只进行源码操作、编译、SSH 连接和远程网页浏览;没有启动本机 Smail 或本机开发服务器。此前《清库部署测试记录》的本机结果属于历史记录,不作为本轮远程通过依据。

任务状态

  • [✓] 批量已读事务原子性修复已编译为 Linux amd64,并部署到 47 服务器;服务版本指纹和二进制摘要核对通过。
  • [✓] 批量已读部署前完成主程序及两份 SQLite 备份,备份数据库完整性校验通过;部署过程中未清理账号、配置或历史邮件。
  • [!] 批量已读网页实机登录受测试账号密码已失效阻塞;未通过数据库改密或其他方式绕过登录边界。代码自动测试已覆盖混合归属拒绝、更新失败回滚、重复 ID 和非法 ID。
  • [✓] 新部署版本在远程 127.0.0.1:25 完成内部 SMTP 回归,五项用例均完成真实 SQLite 归属核对。
  • [✓] 核实仅使用两份 SQLite,备份校验后清空数据库对象,保留数据库文件及 inode。
  • [✓] 清库后通过独立浏览器上下文完成首次安装、超级管理员登录与安全引导确认。
  • [✓] 修复首次安装完成后未生成分区配置,实际生成五份配置文件,配置管理页面可正常读取。
  • [✓] 重启远程服务后,无缓存刷新仍保持登录,已确认的安全引导不重复出现。
  • [✓] 浏览器创建普通用户,普通用户可登录;密码长度不符时返回中文错误。
  • [✓] 修复收件人、抄送、密送输入后直接回车未选中候选的问题,远程浏览器逐项复测通过。
  • [✓] 主界面使用中文组件语言,空列表、关闭对话框、关闭标签、数值按钮均有实际页面证据。
  • [✓] 配置、安装及管理员恢复相关 Linux 测试包在远程执行通过。
  • [✓] 恢复 socket 为 smail:smail 0600;非授权服务账号直接运行恢复工具被拒绝。
  • [✓] 内部 25 端口真实收信、中文正文、多收件人、中文附件及下载内容通过。
  • [✓] 普通用户不能读取管理员专属邮件或下载其真实附件。
  • [!] 网页按 MX 路由的实际投递未通过:网络连接与证书信任阻塞,未绕过校验;按最新要求不再要求公网 25 端口连通。
  • [✓] 修复异步发信提前显示成功:网页提交显示正在投递,列表先显示待投递,手动刷新后显示实际失败。
  • [✓] 修复 587 端口误用隐式 TLS,远程 STARTTLS 已进入证书校验阶段。
  • [!] 当前仍使用原有定时与手动刷新机制;快速状态轮询、进程中断后的待投递恢复未验收。
  • [!] 正式 systemctl start smail-admin 密码代理交互、新密码登录及旧会话失效闭环未完成。
  • [!] 外部邮箱验证码恢复未完成,需要确定实际可接收验证码的测试邮箱。
  • [!] 受信任 TLS、移动端及全部业务模块验收未完成。

已部署修复

3ae8ecb 修复批量已读事务原子性:批量 ID 去重并校验,事务内先确认全部邮件属于当前用户,任一邮件不属于当前用户或任一更新失败时整批拒绝并回滚;新增混合归属、更新失败回滚、重复 ID 和非法 ID 自动测试。

2026 年 9 月 17 日 00:34,47 服务器部署该提交对应的 Linux amd64 主程序。源码指纹为 fd6737820921cb382743ab2537fe7de72a1c47084e974368a47fde966fff0447,版本日志为 remote-fd6737820921,远程 /opt/smail/smail SHA-256 为 5422129011db2fa9faaef5fd65bb022628e084dd6c0e0f1f5cbed4fea35f3696。部署后 smail.service 为 active,主进程退出状态为 0,25、80、443 正常监听;两份 SQLite 的 PRAGMA integrity_check 均为 ok。

部署前备份保留于 /var/backups/smail-before-batch-read-20260917-003225,包含原主程序、smail.db 和 smail-state.db。首次错误格式产物曾短暂触发 systemd Exec format error,已立即用备份恢复并确认服务 active,随后使用明确 GOOS=linux GOARCH=amd64 CGO_ENABLED=0 的 ELF 产物重新部署;错误格式文件未继续运行,数据库和配置未受影响。

3d5c94e 修复首次安装完成后未启用分区配置管理。首次完成安装时通过现有迁移校验发布分区配置,失败不直接标记初始化完成;不强制迁移已经正常运行的旧版实例。

b93ea9d 修复收件人回车选择并统一主界面组件中文。地址选择器启用默认候选,主应用通过组件配置提供中文语言。

49ab24b 修复异步邮件投递状态与 587 端口加密协议。邮件与用户关联先以既有待投递状态入库;列表接口返回真实状态,页面不再将错误文本为空当作成功;587 使用 STARTTLS,保留证书校验及禁止明文回退的边界。

416b849 修复标准 MIME 中文附件名称解析。原正则无法识别 RFC 2231 的 filename*=,导致真实收信附件名变成 no_name_file;改为使用现有 go-message 参数解析器,保留 Content-Type name 优先级,新增普通名称、带分号名称、UTF-8 扩展参数、分段参数、编码词、旧式名称、优先级、缺省及非法参数共九个用例。

两次清库安装后,前端修复及邮件状态修复均采用备份后保留数据库的升级部署,用于同轮故障回归和验证会话、配置保持,不宣称这些版本又进行了一轮全新清库安装。

最终 Smail 二进制 SHA-256:

e0455f8156f4bc0ff25136ffb39e42566b0b154165eb3ce8eb4fb937ba6fe1f6

远程服务在部署后保持 active,HTTP 80、HTTPS 443 正常监听。config.json、email.json、plugins.json、smtp.json、ssl.json 均为 smail:smail 0600。

邮件与证书证据

从超级管理员网页向新建普通用户发送中文测试邮件。发件页面提交后返回列表,最初显示发送成功,但收件账号的收件箱和广告箱均未见该邮件。服务器 20:44 日志记录:

  1. 连接 47.108.78.12:25 超时。
  2. 587 回退使用隐式 TLS,返回 first record does not look like a TLS handshake;代码与当前 STARTTLS 端口语义不一致,需要单独整改。
  3. 465 投递被 x509: certificate signed by unknown authority 拒绝。

发件箱手动刷新后显示发送失败,说明最终错误已落库;最初成功提示来自异步投递前的状态,不能作为投递成功依据。

21:05 对 49ab24b 进行真实网页回归:向同一测试用户提交“投递状态远程回归 2104”,页面提示“邮件已提交,正在投递”,发件箱立即显示“待投递”。21:05:32 日志记录 25 端口超时后,587 STARTTLS 因证书不受信任终止,不再出现原来的 TLS 协议错误。21:06 手动刷新后,列表仅显示“发送失败”,无横向溢出。没有宣称自动刷新时效已经通过验证。

从 47 服务器执行 openssl s_client -starttls smtp -connect mail.solit.cn:587 -servername mail.solit.cn -verify_return_error -brief,已进入证书验证并返回 self-signed certificate,未关闭证书校验、未发送邮件内容。

原证书仅覆盖 *.solit.cn,安装校验因不覆盖主域名 solit.cn 而拒绝。测试改用服务器已有的 custom.crt、custom.key,覆盖主域名和通配域名,但属于自签名证书。当前公网服务仍使用该测试证书,浏览器提示证书不受信任。需要提供覆盖所需域名的受信任证书,不能将本轮功能检查当作生产 TLS 验收。

安装向导公网 IP 检测未成功;远程访问 api.ipify.org:443 失败,未修改外部 DNS,也未使用网页 DNS 解析结果冒充探测结果。

自动验证与限制

  • setup.test、config.test 在远程以 smail 身份执行通过。
  • adminreset.test 在远程以 smail 身份执行全部通过,覆盖调用身份、一次性挑战、防重放、过期、socket 权限、重置事务与凭据撤销。
  • email.test、send.test、smtp.test 在远程以 smail 身份执行全部通过,新增实际持久化函数待投递状态、关联写入失败回滚、列表接口三种状态回归。测试使用隔离内存数据库,不写部署业务库。
  • parsemail.test 在远程以 smail 身份执行全部通过,包含九个新增附件名称用例以及既有正文、隐私和 XSS 用例。
  • 配置测试曾因从 /root 继承工作目录而失败,改在服务账号可访问的测试目录执行后通过,没有放宽权限。
  • 前端生产构建与 Linux Go 编译通过;构建有编辑器块超过 500 kB 的提示。
  • 本次没有重新执行全部后端包、竞态测试或前端自动测试,不能沿用此前本机全量测试作为远程全量结论。
  • 桌面浏览器已检查页面快照、截图和发件页控制台,所查控制台没有错误;未进行移动端检查。
  • 键盘选择回归仅检查表单行为,未向不存在的选择测试地址发送邮件。

内部 25 端口验收

2026 年 9 月 17 日部署后回归

在最新 3ae8ecb 部署版本上,从 47 服务器本机连接 127.0.0.1:25,没有使用公网 25 端口。运行号为 20260917-003640,结果和本轮双库备份保留于 /var/backups/smail-internal-smtp-20260917-003640/result.json。五项测试均使用 TLS 1.3,SMTP DATA 返回 250,并以真实 SQLite 记录核对结果:

用例 邮件 ID 实际结果
中文纯文本 20 仅普通用户 remotecheck 关联,正文核对一致
HTML 与中文附件、多收件人 21 管理员和普通用户均关联,附件及字节核对通过
管理员专属附件 22 仅管理员关联
未知本域收件人 23 当前过滤级别 0,转管理员收件箱
未认证外域收件人 24 当前策略转管理员收件箱,无发信记录

本轮内部 SMTP 结果只证明远程本机接收链路和实际持久化正常,不代表公网 SMTP 投递、受信任 TLS 或网页发信闭环已通过。

根据用户最新要求,仅从 47 服务器连接 127.0.0.1:25,不要求公网 25 端口连通。测试脚本为 test/tools/internal_smtp_check.py,本机没有执行该脚本。测试客户端显式信任服务器现有测试证书,仍校验 mail.solit.cn 主机名、证书有效期和证书链;没有修改应用证书校验、系统 CA、DNS 或中继配置。

21:26:17 最终一轮五项测试全部完成,全部使用 TLS 1.3,SMTP DATA 返回 250,随后核对真实 SQLite 数据与用户关联,并非仅以协议返回码判定成功:

用例 邮件 ID 实际结果
中文纯文本 15 仅普通用户收件,正文一致
HTML 与中文附件、多收件人 16 管理员和普通用户均关联,正文、附件名及附件字节一致
管理员专属附件 17 仅管理员关联,用于附件越权对照
未知本域收件人 18 当前过滤级别 0,转管理员收件箱
未认证外域收件人 19 当前策略转管理员收件箱,仅有收信记录,没有发信记录

TLS 前未公布 AUTH,主动尝试明文 AUTH 返回 523。未认证外域邮件走收信分支,不调用发信路径;本轮没有公网抓包,不将该检查描述为所有中继场景的完整安全验收。当前未知地址和外域地址均不是在 RCPT 阶段拒绝,管理员兜底行为保持原样。

早期脚本误以为未知收件人必定丢弃,实际只读诊断确认当前过滤级别为 0、SPF 状态为通过、DKIM 状态为未通过,且邮件仅属于管理员。修订脚本显式要求当前过滤级别为 0,再验证准确归属,没有为让测试通过而修改业务策略。

桌面浏览器无缓存刷新后保持普通用户登录,列表可见中文邮件,详情显示中文 HTML 和“中文验收附件.txt”。附件 12 的下载内容与发送字节一致。管理员专属附件 17 在管理员会话中返回正确内容,在普通用户会话中返回业务错误“附件不可用”,没有附件数据。普通用户访问管理员邮件详情 13 返回“读取邮件失败”,自己的详情 12 正常返回。权限对照使用正常 CSRF 请求头;首次缺少该头的来源校验拒绝不作为用户隔离证据。

以上拒绝接口当前 HTTP 状态仍为 200,应依据业务错误码和无数据结果判断,不能仅看 HTTP 状态。详情页面未发现横向溢出。本轮未进行移动端验收,也未重新执行完整清库安装:保留同轮故障邮件和会话,完成备份后升级回归。

本轮内部 SMTP 结果及双库备份保留于 /var/backups/smail-internal-smtp-20260916-212617,目录内 result.json 可复核。本轮通过的是内部接收链路,不代表网页按 MX 路由发信闭环或公网受信任 TLS 已通过。

备份与保留

以下目录均位于远程服务器,包含敏感运行数据,不提交仓库:

  • /var/backups/smail-before-reset-20260916-201834:第一轮清库前备份。
  • /var/backups/smail-before-reset-20260916-202943:第二轮清库前备份。
  • /var/backups/smail-before-reset-20260916-205033:前端修复升级前备份,本次未执行清库。
  • /var/backups/smail-before-reset-20260916-210318:邮件状态及 STARTTLS 修复升级前备份,本次未执行清库。
  • /var/backups/smail-before-reset-20260916-212132:中文附件解析修复升级前完整备份,本次未执行清库。

备份均对完整归档进行比较与 SHA 校验。两份数据库 inode 保持为 smail.db=915735、smail-state.db=915727。旧配置及迁移源已归档,没有删除其他项目文件,没有操作同机 Scert、MySQL 或 PostgreSQL 数据。

最新备份归档 SHA-256:

9f712cb881db6acdcdefb1c20c5244524107529409196be810f8bb4d4c832c58

测试用户与失败邮件保留用于后续复核,密码、密钥及会话凭据不写入记录。

2026 年 9 月 17 日后续批量已读验收审查

本轮继续只在 47.108.78.12 执行远程验收,没有启动本机 Smail 服务,也没有修改远程账号密码、伪造会话或清理数据库。远程环境复核结果如下:

  • smail.service 为 active,主进程退出状态为 0;远程 /opt/smail/smail SHA-256 仍为 5422129011db2fa9faaef5fd65bb022628e084dd6c0e0f1f5cbed4fea35f3696。
  • 远程运行文件确认为 Linux x86-64 ELF;25、80、443 及邮件协议端口均保持监听。
  • smail.db 与 smail-state.db 的 PRAGMA integrity_check 均返回 ok,已有批量已读部署前备份及内部 SMTP 测试备份仍保留。
  • 从 47 服务器本机通过 HTTPS 回环访问登录页返回 200;未认证访问 /api/v1/user/info 和 /api/v1/email/list 均返回业务错误码 403“登录已过期”。
  • 未认证调用 POST /api/v1/email/read,请求 ID 为 [20,21],返回业务错误码 403;调用前后相关 user_email.is_read 值均为 2:20:0,1:21:0,2:21:0,没有越权修改。
  • 继续尝试了当前数据库中的 admin、remotecheck 账号和已有候选密码,均返回“账号或密码错误”;没有可用的授权网页测试会话。
  • Chrome DevTools 访问远程站点时被现有自签名证书拦截,停留在证书错误页;这与此前记录的受信任 TLS 阻塞一致,不能据此宣称网页渲染或真实点击验收通过。

因此,本轮审查确认服务、部署产物、数据库完整性及未认证接口边界正常;批量已读的真实网页登录、选择邮件、点击“标记为已读”、刷新页面和混合归属网页请求仍保持阻塞,待提供有效测试账号及受信任测试证书后继续。数据库没有执行清理,历史测试邮件和备份继续保留。

2026 年 9 月 17 日生产整改升级回归

本节记录后续生产整改版本,不覆盖前文历史证据。本轮应用及测试二进制仍只在 47.108.78.12 运行;本机仅进行源码检查、前端构建、Linux 交叉编译和 SSH 操作。本轮采用备份后保留双库升级,没有清库,不作为重新安装验收。

整改内容

  • 测试及部署脚本统一读取环境变量中的 SSH 凭据,校验已知主机密钥,不再自动信任未知主机。网页安装及 SMTP 示例密码也改为环境变量输入。
  • 网页发信在同一事务内保存邮件、用户关联及每收件人的持久投递任务。进程重启后,尚未尝试的任务可以继续;已在途任务及旧版无队列的待投递邮件标记为“投递结果待核对”,不盲目重投。
  • 临时网络、DNS 或 SMTP 4xx 失败最多尝试五次,间隔为 1、2、4、8 分钟。明确拒绝、证书错误、私网目标和 DATA 结果不确定均不自动重试。
  • MX 按优先级排序并去重,支持备用 MX、无 MX 时使用域名自身及 Null MX 拒绝;保留既有安全端口回退。邮件头保留完整收件信息,队列任务只投递当前收件人的 SMTP 信封。
  • SMTP DATA 最终 250 后的 QUIT 异常不再误判失败;发送 DATA 后失去明确结果的任务暂停核对。结果写库失败只重试数据库写入,不重复调用 SMTP。
  • 后台投递接入在线数据库迁移排空边界;停机等待投递结束,不提前关闭仍在使用的数据库。投递状态更新不恢复已放入回收站的用户关联。

自动测试

七个相关 Linux 测试包在远程以 smail 账号执行,使用隔离内存或临时数据库,不改部署业务库。共 132 个顶层测试用例通过,日志保留在 /var/tmp/smail-review-20260917/*.result.log。

测试包 顶层用例数 结果
outbox 10 通过
utils-send 11 通过
utils-smtp 8 通过
controllers-email 12 通过
db-migration 26 通过
res_init 14 通过
services-dbmigration 51 通过

新增覆盖包括部分投递成功、防重复领取、退避及重试上限、DATA 不确定结果、结果写库故障、读取失败、旧待投递记录、重启恢复、停机超时、回收站状态、队列插入失败整事务回滚和迁移等待后台投递。这里的测试通过不等于真实网页登录发信闭环已通过。

前端生产构建和 Linux amd64 编译通过,仍有编辑器分块超过 500 kB 的构建提示。没有重新执行全部后端包、竞态检测、移动端、真实 MySQL 或 PostgreSQL 验证。

部署证据

2026 年 9 月 17 日 10:06 完成双程序升级,版本为 remote-13bcad90e832,源码指纹为 13bcad90e832a9be78604854a1c91f72cfaf2a21770481c627e50ac361ce3b70。

项目 结果
/opt/smail/smail SHA-256 a3b4a0b0e75213bb7997fa55f789d98bca027e879c9dbfe986f7b1ee8c8230d9
/opt/smail/smail-admin SHA-256 16e48a16d3f47ab78b42fb1aa854dfc32ec2ccd3a95694c6ccb93fc1da075e34
数据库迁移版本 23
两份 SQLite 完整性 均为 ok
服务状态 active/running,NRestarts=0,ExecMainStatus=0
本地恢复 socket /run/smail/admin-control.sock,smail:smail 0600
HTTPS 首页 显式测试 CA、主机名校验下返回 200
未认证用户信息、邮件列表接口 均返回业务码 403,无业务数据
本次检查时段日志 25 条 journal 记录,未发现 error、fatal 或 panic 标记

完整停服备份为 /var/backups/smail-before-outbox-20260917-100608,归档 SHA-256 为 a2ed56666e9e691a63dfc6734ebe2a1e9c7bf2fe4ceb81cb55028e66ea52d016;包含原主程序、管理员工具、双库及完整部署归档。归档比对和数据库备份完整性检查通过,没有删除历史文件。此次部署成功,未实际演练失败回滚或异机恢复。

内部 SMTP 回归

运行号 20260917-100912,仅从远程连接 127.0.0.1:25。五项均使用 TLS 1.3,DATA 返回 250,并核对真实数据库归属、正文和附件字节:

用例 邮件 ID 结果
中文纯文本 27 仅普通用户关联,正文一致
HTML、中文附件及多收件人 28 管理员和普通用户关联,附件一致
管理员专属附件 29 仅管理员关联
未知本域收件人 30 过滤级别 0 下转管理员收件箱
未认证外域收件人 31 转管理员收件箱,无发信记录

结果及测试前双库备份位于 /var/backups/smail-internal-smtp-20260917-100912。没有修改过滤策略、系统 CA、证书验证或 DNS;客户端仅显式信任已有测试证书。内部接收链路通过,不代表网页发信、外部投递或生产 TLS 验收通过。

结论与限制

  • [✓] 本轮指定的七包测试、部署产物核对、双库完整性、内部 SMTP 和未认证接口边界复审通过。
  • 凭据硬编码清理完成;工作区已知旧 SSH 密码扫描零命中,但旧密码仍有效,Git 历史仍含旧凭据,不能视为泄露处置完成。
  • [!] 新队列尚未完成真实网页登录发信闭环;部署后的队列表为空,不能用入站 SMTP 回归代替出站队列业务验收。
  • [!] 当前队列按单实例、单工作器运行,未压测。结果落库持续失败时保留在途任务,需要告警和受控重启后转为待核对;不得人工直接改回排队状态。
  • [!] 受信任 TLS、凭据轮换、正式管理员恢复交互、新密码登录与旧会话撤销、灾备恢复及全量兼容性验证仍未完成。

当前结论仍为:适合继续受控远程验收,不建议直接用于正式生产。后续门槛见《生产整改验收清单》。