CDN 似乎工作不正常

由于大家都懂的原因,这几天发生了不少事情,本站所使用的 CDN 也受到了一定程度的影响。这几天已有至少两位用户表示图片打不开或加载缓慢。

对于这种情况,暂时的解决方案是:

  1. 在你的浏览器中清空本站的 Cookie,这样可以触发 CDN 探测,如果 CDN 访问不了,则会切回源站;
  2. 升级你的浏览器至最新版本,如 Chrome 45、IE 11 / Edge、Firefox 40 等。

另外我还在考察国内的 CDN 服务,如果有合适的,过段时间会切换到国内 CDN。

写于博客密码泄露之后

很不幸我的博客密码被盗了,一个不名黑客在半夜入侵了我的主机,植入了菜刀,远程控制了机器。然后他窃取了一些重要资料(比如一些羞羞照),并且把主机变成了一个台肉机。我发现的时候,肉机已经偷跑了超过 5000 美元的流量......

在电脑手机前偷笑的各位可以稍微停一下了。以上只是我被害妄想症的一种表现,它实际上并没有发生。

由于对安全的偏执,我假想了各种安全漏洞的情形,然后加以防御。之前讨论过 WordPress 的密码安全性插件安全性,这次来探讨一下密码失窃之后,有哪些亡羊补牢的方法。

假设一名黑客偷取了本博客的管理员密码,(先假设只是博客的密码,而不是主机的管理员权限),那么他能做哪些事情?

一,很明显,他可以操作博客的数据库,新建用户、新建文章、删除文章等。

二,黑客可以在后台直接挂马,然后进行更强大的远程操作。

对于第一条,似乎没有特别好的方法,一旦密码被盗,数据库就只能放弃了。当然,如果你的博客没有任何加密的内容,数据库被盗也没什么好怕的,本来就都是公开的东西。

接下来重点说一下第二条。

PHP 有一个很好用也很危险的特性,就是源代码可以直接执行;而 WordPress 也有一个很好的特性,即可以在后台直接修改插件代码。于是一旦黑客控制了后台,他可以在源代码里嵌入一行如下的语句,然后就可以远程控制了。对,PHP 就是那么强大。

要防止这种情况,最有效的方法是在把所有源代码设置为只读,即 Linux 文件属性 400(或 444),这样可以避免任何人对文件进行修改。但这样做之后,自己真想要修改文件的时候,却是非常麻烦,先要 SSH 登录,把文件属性设为可写(如 755),然后再回到后台改文件。另外,这样做也阻止了 WordPress 的自动更新,一定程度上降低了安全性。

对此, WordPress 提供了一个简单的防御方式,可以 wp-config.php 中添加一行:

这样可以禁用掉 WordPress 中修改源代码的界面,包括插件和主题,同时也禁止了安装新的插件和主题。当然这样同样会有上述的问题,即每次修改文件之前,需要先修改 wp-config.php。为了避免对 wp-config.php 的频繁修改,我们可以加一点小小的逻辑,如下:

它的含义是在不是运行 WP Cron 并且 Session 中没有定义 enable_edit 的时候,才禁用对主题和插件的修改。开启 WP Cron 的原因是它会定期检查并更新 WordPress,而 Session 的定义则可以按需开启修改的界面。

手动启用修改界面,还需要一段代码,写在 functions.php 中:

然后访问 http://你的博客地址/wp-admin/admin-ajax.php?action=temp_enable_edit 即可临时开启对插件和主题的修改,有效期到 Session 过期为止。需要注意的是,并不所有的主机都启用了 Session。如果你的主机把 Session 关了,你可以改成使用 Cookie,效果类似。

这种方法是安全和易用的一个折中,它假设了 WordPress 不会有 Bug,比如 DISALLOW_FILE_MODS 工作正常,并且没有安装可以直接运行 PHP 代码的插件

另外还有一些其它的方法仅供参考:

  • 给 wp-admin/ 文件夹加一个密码,比如 Apache 的 Basic Authentication。我觉得每次登录都需要多输一个密码,实在太麻烦了。
  • 重命名 wp-admin/ 文件夹让别人找不到。根据前几年的讨论贴,这种方法并不能完美工作,也就说是 WordPress 的代码某种程度上依赖于 wp-admin 而不能改名。
  • 创建一个新的域名,只用来访问 wp-admin,而原先的域名供访客浏览。这种方法的前提是你愿意支付双倍的 SSL 证书费用。

这个世界上没有绝对的安全,只不持之以恒的防御。

PureVPN 夏日优惠:买一年送一年

刚收到 PureVPN 的邮件说是有优惠,看上去还不错的样子,买一年送一年。也就是说,两年的 VPN 只需要 49.95 美元,平均每月只需 2 美元左右。点这里注册

顺带提一下 PureVPN 的好处:

  • 超过 100 个国家的 VPN 出口,套餐中不限制出口节点,随意使用;
  • 有 PC、Mac、iOS 和 Android 的客户端,方便配置 VPN 连接;
  • 一个帐号可以使用五台设备同时连接 VPN。

更多介绍可见之前的文章

把 Google Cloud Storage 加载到文件系统

主机移到 Google Cloud 之后,博客的图片都存放于 Google Cloud Storage (GCS) 中。

GCS 是一个独立的储存系统,可以通过 HTTP 访问,用来当作 CDN 使用。但问题是,GCS 无法绑定一个 SSL 的域名,HTTPS 访问成问题,并且经常被墙。于是我采用的方法是定期把 GCS 的文件用 GSUtil 同步到主机上,这个方法很灵活,不必开放整个 GCS 的 Bucket,而且可以限制文件一定要从博客中访问。唯一一点不爽的是,我设置的同步周期是五分钟,也就是在 GCS 上添加一个新文件之后,要等五分钟才可以从博客中看到,有时候等得比较累。而且我也不经常向 GCS 传文件,每五分钟都同步一下,80% 的同步是浪费掉的。

后来我就看到了 GCSFuse 这个工具。

Fuse (Filesystem in Userspace)是 Linux 中的一个概念,它向用户提供了一种虚拟磁盘的访问方式,即把一个不在本地的磁盘,当成本地磁盘一样来访问。这一技术经常被用来映射网络磁盘。

GCSFuse 是 Google Cloud 的一个 Fuse 实现,它可以把 GCS 的 Bucket 映射到本地,然后就可以通过文件系统的方式来访问 GCS 上的文件。

安装 GCSFuse 的方法用下(Ubuntu):

然后就可以通过以下命令行映射一个 Bucket(其中路径和 Bucket 名称按需修改):

GCSFuse 暂时还处于 Beta 状态,没有提供后台运行的方式,如果要在后台运行,还需要依赖 daemon 工具,完整的命令行大概是这个样子的:

这样运行了之后,/path/to/mount/point 就会成为 my-bucket 的映射,可以直接进行文件操作。其中 -o allow_other 表示允许所有用户访问,GCSFuse 默认只允许运行该命令行的用户访问映射的文件(比如 root),要给其它用户开放权限,我发现 -o allow_other 是最简简单的方法,另外你还可以通过 --uid $UID 和 --gid $GID 指定用户,但我尝试了没有成功。

daemon 不会在开机的时候自动运行,如果要在开机的时候就创建映射,需要添加一个 systemd 或者 upstart 的启动项,代码还在调试中,稍后放出。另外 GCSFuse 来提供了一种 mount 的方式加载,但我死活没有成功运行出来,还搞挂了主机,如果你成功了,请知会一声。

恢复 GCE 上无法启动的 Instance

两年前我搞坏过一台 EC2 的机器,而今天一早,我又搞坏了一台 GCE 的机器。这次的起因是 gcsfuse 和 fstab。

先吐槽一下 Ubuntu,在 fstab 加载不成功的时候,居然没有任何恢复的方法,它也不会自己把无法加载的项给禁用了。在 GCE 中,Ubuntu 的表现是无法连上 SSH,没有任何错误信息,连日志文件都看不到。

于是和上次一样,我能做的便是:

  1. 对当前磁盘创建一个 Snapshot;
  2. 创建一台新的临时机器,以 Additional Disk 的方式加载之前创建的 Snapshot;
  3. 修改磁盘上的内容;
  4. 删除临时机器,再创建一台新机器,以 Boot Disk 方式加载修复的磁盘。

GCE 上的 Addition Disk 会出现在 /dev/disk/by-id/ 下,可以使用以下命令查看:

我发现我的磁盘有两个分区,即:

  • /dev/disk/by-id/google-leonax-1
  • /dev/disk/by-id/google-leonax-1-part1

part1 中存放的是主要内容,通过下列命令把它加载出来:

然后在 /leonax-1 中修改相应文件即可。

顺便说一句,GCE 提供了一个 safe_format_and_mount 工具,不知道什么原因,这个工具在这种情况下没有效果,它不认为我的磁盘是一个有效磁盘,拒绝加载。于是我只好用了 Linux 自带的 mount。