修复 freeshell ”move“ 功能

4月17日以来,freeshell “move” 操作所加的锁会跟着数据库条目一起移动,也就是新生成的条目就处于锁定状态,加锁失败而给用户返回错误信息。这个问题造成 4 个用户的 freeshell 从控制面板中消失,多出了一条事实上不存在的条目。原有 freeshell 的运行没有受影响,已经修复数据库并将给这些用户发邮件通知。非常抱歉。

LUG Wiki添加CAPTCHA插件

LUG Wiki上有数千个疑似机器人注册用户,为了防止恶意的机器人注册,我安装了dokuwiki的CAPTCHA插件,目前的验证方式是算术题。

Wiki的管理员可以通过“配置设置”来设置验证出现的位置和验证形式。

GitLab升级至6.8.1

4月27日凌晨,GitLab 由6.7.pre 升级至 6.8.1,服务共中断23分钟。

新版本主要特性:

  • 允许在issue和“合并请求”时@用户
  • 搜索功能改进
  • 受保护的分支不允许git push –force
  • 若干安全漏洞修复
  • 其他一些bug修正

Freeshell HTTP Proxy 加入 X-Forwarded-For 字段

Freeshell HTTP Proxy 的用户 IP 是通过 X-Real-IP 字段传递的。而一些 Web 框架认为 X-Forwarded-For 才是正统,因此现在 HTTP Proxy 同时添加了 X-Forwarded-For 和 X-Real-IP 头,内容相同,都是 HTTP Proxy 服务器看到的用户 IP(freeshell 看到的源 IP 都是 202.141.160.99,即 HTTP Proxy 服务器的 IP,因此要获取真实用户 IP 就要通过 HTTP 头中另加的字段)。

USTC Blog WordPress 升级

4月19日早上 05:30,USTC Blog WordPress 升级到 4.0-alpha,这是 WordPress 官方发布的最新版本,大家可以尝尝鲜。

第一次登录博客后台时,会提示对数据库进行升级,点击“升级”,在升级完成后“继续”就行。

这是一次例行升级。如果升级后您的 blog 不能正常工作,或者有插件提示错误,请先尝试升级插件,如果还是有问题,请联系 support@blog.ustc.edu.cn

To USTC Blog Developers: 可以按照 部署说明 所述的步骤对 WordPress 进行升级。

Freeshell 支持绑定多个自定义域名

为方便更换自定义域名的过渡期,freeshell 现在支持绑定多个自定义域名了,可以在控制面板的 “HTTP Proxy” 区域添加和删除自定义域名,如下图所示。

Capture

对所设置域名的子域名的 HTTP / HTTPS 访问也会被代理到你 freeshell 的 IPv4 80 端口,因此不需要为每个子域名单独设置自定义域名。

Freeshell 控制面板 502 错误报告

4月16日 14:52,freeshell 控制面板访问超时,几分钟后转变成 502 错误。直到 17 日 12:47,zsj 重启 php5-fpm,问题才解决。非常抱歉一天来无法访问 freeshell 控制面板。Freeshell 虚拟机没有受到影响。

问题触发的过程是这样的:

  1. 4月16日 14:48,某用户安装 Fedora 20,而 Fedora 20 安装脚本的最后一步 yum localinstall 忘了加 -y 选项(这是4月11日引入的 bug),导致安装脚本停在让用户选择 y/n 的位置。
  2. PHP session 在 session_start() 后会被锁住,在脚本退出或者调用 session_write_close() 之前,如果另一个相同 session 的 HTTP 请求也调用了 session_start(),则会等待这个锁。由于 PHP 脚本一般执行时间很短,我一直没发现这个坑爹的特性。之前也发现在重装等操作过程中,刷新页面没有响应,不过一直以为是 OpenVZ 的锁,没有引起重视。
  3. 此用户多次刷新页面,每个 HTTP 请求都是相同的 session 在等待锁,占满了 php5-fpm 的 50 个 worker 进程,导致 freeshell 控制面板的所有访问被阻塞。

这两个 bug 的修复:

问题持续了整整一天,Freeshell 的报警系统怎么没有工作呢?

  1. DNSPod 报警通过邮件和短信发送,报警邮件进了 Gmail 的垃圾邮件箱,报警短信没有收到。
  2. Blog 服务器上部署的 URL 监控系统,报警邮件是发到 servmon@blog.ustc.edu.cn,LUG 邮件服务器里这个 Email 的转发是匹配的默认规则,不知什么时候这条默认规则被去掉了。由于核心服务都配置了 DNSPod 监控,每次出问题时 blog 上监控系统的失语并未被发现。
  3. Freeshell 某虚拟机里部署的 URL 监控系统,由于监控了一些不太稳定的 URL,报警邮件被分类到一个标签里,我很长时间才去看一次。
  4. Freeshell 控制服务器上本来每 5 分钟检查一次 freeshell 物理节点上是否有运行时间过长的虚拟机管理进程,如果发现就发邮件报警,但上个月 freeshell 出现大量僵死进程之后,收到大量报警邮件,就把这个 crontab 关掉了。freeshell 换内核后僵死进程问题修复了,但忘了重新打开 crontab 监控。

从理论上说,这个问题应该被上述 4 个监控系统同时发现,但事实上只有 DNSPod 一个监控渠道是工作的。DNSPod 确实尽职尽责地发现了问题,但邮件进垃圾箱、短信没收到同时发生,还是挺巧合的。

我给 freeshell 脆弱的代码加了一些防护措施:

  • Freeshell 管理操作加乐观锁,如果加锁失败,给用户返回错误。
  • Freeshell 锁定期间,在控制面板上提示用户 “另一个操作正在进行”。
  • SSH 操作开始前,就把 command line 写进日志备查(之前是操作结束后才将 command line 和 SSH output 一并写入日志)。
  • SSH 操作结束后,在日志里记录操作耗时,以便排查长时间锁住的问题。
  • SSH 操作失败(返回码非零)时,发邮件给管理员。
  • 每小时检查是否有处于锁定状态超过一小时的 freeshell,如果有,邮件通知管理员。
  • 封装 mysql_query,数据库访问失败时将错误信息发邮件给管理员。
  • 给 freeshell 管理脚本中的 HTTP 操作(从 mirrors 源更新)设置 60 秒的超时。

SSH 操作失败的邮件报警机制很快就派上了用场:3月23日由于批量替换变量名出错(错误发生在一个比较少见的代码执行路径上),导致 7 号节点创建虚拟机失败。经查,这个 bug 共导致 4 个用户创建虚拟机失败,已经恢复这些用户的 freeshell 并发送了邮件。

今天提交了 24 个 commit,sigh……

blog, gitlab 等服务器凌晨 IPv6 中断 20 分钟

今天凌晨 03:30 至 03:50,blog、gitlab 等 2001:da8:d800:f001::/64 网段的服务器 IPv6 中断,表现为这些机器能 ping 通默认网关 2001:da8:d800:f001::1,但 ping 其他 IPv6 地址都是 network unreachable (no route)。这些机器之间互相 ping6 是正常的。从其他地方 ping6 这些机器表现为超时。我正在 ustcnet 版上发帖,突然就恢复了,因此这事就算过去了。