Lan Tian @ Blog

nginx 配置 LDAP 认证

我的各台服务器上安装了各种不同的服务,都有各自的用户名密码体系,难以统一管理。假设未来某天我的密码泄露了,一个个修改就会非常累人。因此,我希望用一个服务来专门管理用户名密码,其它服务都从它上面获取认证信息。

LDAP 是常用的认证协议之一,不仅有许多软件原生支持它的认证(包括 Jenkins,pfSense 等),而且通过插件可以使得 nginx 支持它,为任何基于网页的服务加上统一管理的认证。

添加插件

如果你的 nginx 已经是源代码编译的,添加 nginx 的 LDAP 插件只需要三步:

  1. apk add openldap-dev
  2. git clone https://github.com/kvspb/nginx-auth-ldap.git
  3. ./configure --add-module=/path/to/nginx-auth-ldap

我依然使用 Docker 部署 nginx,Dockerfile 可以在 https://github.com/xddxdd/dockerfiles/blob/master/nginx/Dockerfile.amd64 找到,其中的编译参数可以参考。

配置认证

安装插件后,先在 nginx.conf 的 http 配置块中添加 ldap_server 配置块。为了防止我的单台服务器出问题导致认证服务全挂,我暂时先用了 JumpCloud 的 LDAP 服务,配置如下:

ldap_server jumpcloud {
    url ldap://ldap.jumpcloud.com/ou=Users,o=[你的 JumpCloud LDAP 编号],dc=jumpcloud,dc=com?uid?sub?(objectClass=posixAccount);
    binddn "uid=[LDAP 认证专用用户名],ou=Users,o=[你的 JumpCloud LDAP 编号],dc=jumpcloud,dc=com";
    binddn_passwd "[LDAP 认证专用用户密码]";
    group_attribute "memberOf";
    group_attribute_is_dn on;

    max_down_retries 3;
    connections 1;
    referral off;

    require valid_user;
    satisfy any;
}

然后在要保护的 server 块或 location 块中添加如下内容:

location /private {
    auth_ldap "Forbidden";
    auth_ldap_servers jumpcloud;
}

即可使用指定的 LDAP 服务器进行认证。

不过要注意的是,LDAP 认证插件会和 http_addition 插件产生冲突,具体表现是如果同一个 location 里开启了 auth_ldap 和 add_after_body,在输入用户名密码认证通过后,nginx 似乎不会发送网页数据,体现为浏览器一直转圈直到超时。暂时的解决办法只能是禁用 add_after_body:

# LDAP auth doesn't work well with http_addition, disable it
add_after_body "";

如上操作之后,指定的地址就启用了 LDAP 认证。如果将 nginx 作为反向代理代理其它内部服务,并屏蔽外网直接访问这些内部服务,就可以用 LDAP 统一保护认证这些服务。

nginx:TLS 1.3 多版本草案和 HPACK

距离我之前给 nginx 启用 TLS 1.3 已经过了 11 个月了。快一年过后,许多与 nginx 相关的程序、补丁都有了很大的变化:

  1. OpenSSL 已经在发布 1.1.1 的测试版,写本文时最新版本是 1.1.1-pre8(也就是 Beta 6)。
  2. nginx 已经更新到 1.15.1。
  3. nginx 的 HPACK 补丁(HTTP 头压缩补丁)的 bug 已经有另外的补丁的补丁修复,使用原先的 HPACK 补丁会导致网站访问不正常,体现为每个网站只能打开一个页面,第二个页面开始就出现协议错误。
  4. 有大佬发布了 OpenSSL 的补丁,可以让最新版 OpenSSL 同时支持 TLS 1.3 的 draft 23,26,28 三个版本。
  5. Lets Encrypt 证书已经自带 Certificate Transparency 信息了,不需要 nginx-ct 了。
  6. 2018 年 7 月 1 日起,TLS 1.0 不再被建议使用。

因此我重新调整了 nginx 的编译和运行配置,以适应 8102 年的需要。

Dockerfile

我依然使用 Docker 部署 nginx。与之前的 Dockerfile 相比,新的 Dockerfile 只是改了下版本号,添加了几个补丁,整体并没有大的变化。

为了节省篇幅,我将 Dockerfile 上传到了 https://github.com/xddxdd/dockerfiles/blob/master/nginx/Dockerfile.amd64。你也可以直接 docker pull xddxdd/nginx 来使用。

这个 Dockerfile 包含了如下内容:

  • nginx 1.15.1
  • OpenSSL 1.1.1-pre8
  • kn007 大佬的 SPDY、HPACK、Dynamic TLS Record 三合一补丁,他的项目地址在此访问
  • kn007 大佬的 HPACK 补丁的修复补丁
  • Brotli 压缩算法
  • hakasenyang 大佬的 TLS 1.3 三版本草案补丁,他的项目地址在此访问
  • nginx headers-more 模块

配置改变

首先禁用 TLS 1.0。

#ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;

然后,因为 OpenSSL 修改了一大堆加密算法的名称,因此如果直接沿用之前的 ssl_ciphers 会出现 ERR_SSL_VERSION_OR_CIPHER_MISMATCH 错误,意思是没有服务器和客户端同时支持的加密算法。因此修改 ssl_ciphers:

#ssl_ciphers 'TLS13-AES-256-GCM-SHA384:TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES-128-GCM-SHA256:TLS13-AES-128-CCM-8-SHA256:TLS13-AES-128-CCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:!DSS';
ssl_ciphers '[TLS13+AESGCM+AES128|TLS13+CHACHA20]:TLS13+AESGCM+AES256:[EECDH+ECDSA+AESGCM+AES128|EECDH+ECDSA+CHACHA20]:EECDH+ECDSA+AESGCM+AES256:EECDH+ECDSA+AES128+SHA:EECDH+ECDSA+AES256+SHA:[EECDH+aRSA+AESGCM+AES128|EECDH+aRSA+CHACHA20]:EECDH+aRSA+AESGCM+AES256:EECDH+aRSA+AES128+SHA:EECDH+aRSA+AES256+SHA:RSA+AES128+SHA:RSA+AES256+SHA';

然后?

重新启动 nginx,用最新稳定版的 Chrome 和 Firefox 就可以以 TLS 1.3 draft 23 访问了,用最新开发版的 Chrome 和 Firefox 就可以以 TLS 1.3 draft 28 访问了。

Kimsufi 独服安装升级 ESXi 并设置软路由

Kimsufi 是法国 OVH 公司的一个廉价品牌,专门出租性价比极高的服务器。我自己租的是 KS-4C 型号,i5-2400 处理器,16GB 内存,2TB 硬盘,百兆带宽无限流量,只需要 13欧元/月,性价比极高,非常适合开虚拟机做实验。

VMware ESXi(现在也叫 vSphere Hypervisor)和 Proxmox VE 是两个非常流行的专门用来开虚拟机的操作系统,且两者都是免费的。最重要的是,Kimsufi 的控制面板中都有两款系统的一键安装。但我在使用过程中发现 Proxmox VE 在网络条件不佳的情况下远程控制虚拟机经常连接不上(VNC 黑屏)或者丢键(输密码时尤其要命),因此还是换装了 ESXi。

这里又产生了一个问题:ESXi 不是完整的 Linux、FreeBSD 等系统,它不具有 Linux 等所有的 NAT 功能,也就是不能一个 IP 地址开好几台虚拟机然后做端口转发。不过,由于 Kimsufi 同时提供 IPv4 和 IPv6 地址,可以把 IPv4 给一台虚拟机用,让 ESXi 用 IPv6;再设置这台虚拟机做 NAT 就可以了。

这就是本文中要做的事。

为什么要写这篇文章

因为我在配置的过程中遇到了一堆问题:

  1. ESXi 5.0 从命令行下在线升级的方法已经不能用了,会报错;
  2. ESXi 6 系列带的网页面板虽然平时管理虚拟机很好用,不需要装客户端,但是一设置 ESXi 的网络就会出现 bug。

安装 ESXi

Kimsufi 提供的 ESXi 版本极其古老,是 5.0 版本,而本文写成时最新版本已经到了 6.7。因此,安装完 ESXi 后就需要立即升级系统。但是由于 VMware 官方的一些操作,下面这种在线升级的方法已经行不通了:

esxcli software profile update -p ESXi-6.5.0-20170702001-standard -d https://hostupdate.vmware.com/software/VUM/PRODUCTION/main/vmw-depot-index.xml

ESXi 5.0 运行上述命令会提示 XML 格式错误等等。所以必须下载离线安装包,本地升级。但是 ESXi 的 wget 居然不支持 HTTPS,因此还需要另一台 VPS 中转。

具体步骤如下:

1: 挂上中转 VPS 的 SS,因为 VMware 下载网站会验证下载的 IP。

2: 访问 https://my.vmware.com/group/vmware/patch#search,选择 ESXi 6.0.0(5.0 不能直接升级 6.5),点击搜索,出现补丁列表:

插图

3: 向下翻,找到任何文件名类似于 update-from-esxi6.0-6.0_update03 的补丁:

插图

4: 点击下载,然后把下载链接复制到 VPS 上去 wget。在 VPS 上 wget 完后,开一个 HTTP 服务器,再从 ESXi 上 wget 一遍。

5: 点击第三栏的 KBxxxxxx 链接,在上图中就是 KB2148155。

6: 在新开的页面向下翻,找到 Image Profiles 段:

插图

这里的类似 ESXi-6.0.0-20170202001-standard 的这一段名称就是更新的版本名称。

7: 在 ESXi 的 SSH 中输入:

esxcli software profile update -d [下载的补丁 ZIP 的绝对路径] -p [版本名称]

例如:

esxcli software profile update -d /vmfs/volumes/datastore1/update-from-esxi6.0-6.0_update03.zip -p ESXi-6.0.0-20170202001-standard

回车执行升级,重启。

8: 回到第二步,选择 6.5.0 版本(本文写成时还没有 6.7 的升级文件),重复以上流程。

如上操作完成后,我们就有了一个 6.5 版本的 ESXi。

设置 IPv6

我们的目标是把 IPv6 给 ESXi 用,把 IPv4 分给虚拟机,因此需要先给 ESXi 配置 IPv6。但是这里 ESXi 的网页界面配置会出现无法成功保存设置的问题,因此需要命令行操作,步骤如下:

1: 登录 ESXi,执行如下命令开启 IPv6,然后重启:

esxcli network ip set -e true

2: 执行如下命令开启默认网卡的 IPv6:

esxcli network ip interface ipv6 set -e true -r false -i vmk0

3: 假设你的服务器分到的 IPv6 是 2001:41d0:1:234::1,那么你的 IPv6 网关是 2001:41d0:1:2ff:ff:ff:ff:ff,具体可以参照 Kimsufi 其它系统上的 IPv6 设置教程。我们需要添加两个 IPv6 地址,一个是我们自己的 IPv6,另一个则是在和网关同一个 /64 里随便取一个,以让 ESXi 承认这个网关:

esxcli network ip interface ipv6 address add -i vmk0 -I 2001:41d0:1:234::1
esxcli network ip interface ipv6 address add -i vmk0 -I 2001:41d0:1:2ff:12:34:56:78

4: 接下来就是设置默认网关:

esxcli network ip route ipv6 add -g 2001:41d0:1:2ff:ff:ff:ff:ff -n default

5: 从其它支持 IPv6 的 VPS 等 ping 一下,确认可以 ping 通再继续下一步。

6: 如果本地没有 IPv6,可以考虑使用 Cloudflare 反代服务器的 IPv6 地址,方便之后的操作。

安装软路由

我使用的软路由系统是 pfSense。首先把 pfSense 的 ISO 下载到 ESXi 服务器上。因为 pfSense 的下载服务器支持 HTTP,所以不必再中转了:

cd /vmfs/volumes/datastore1
wget http://frafiles.pfsense.org/mirror/downloads/pfSense-CE-2.4.3-RELEASE-amd64.iso.gz
gunzip pfSense-CE-2.4.3-RELEASE-amd64.iso.gz

然后在网页面板上点 Networking - Virtual Switches,创建一个虚拟交换机,并在 Port groups 页面创建一个端口组,连接到这个交换机,这将是之后虚拟机之间的内网。

插图

如果你想要让 ESXi 连接进入虚拟机的内网,需要先做一些准备操作:再创建一个端口组,连接到这个交换机,如图:

插图

然后在 VMkernel NICs 创建一个虚拟网卡,连接到这个端口组,选择 Services 中的 Management,如图:

插图

然后在 Physical NIC 页面中复制下物理网卡的 MAC 地址。由于机房有 IP 和 MAC 的绑定,我们要让这台虚拟机伪装成主服务器的 MAC 地址,才能正常获取 IP 地址。

然后按照正常步骤创建虚拟机、安装系统。此处注意虚拟机的第一张网卡的 MAC 地址要改的和物理网卡相同,并将这张网卡连接到“VM Network”,也就是和外网相通。如果你现在通过 IPv4 连接服务器,那么在软路由系统启动后,到 ESXi 管理面板的连接会突然中断一下,这是正常的,因为 ESXi 和软路由在同时抢占这个地址。因为相同的原因,现在软路由里已经可以 ping 通外网了,但是 TCP 连接会被 reset。接下来就要关闭 ESXi 的 IPv4,解决这个冲突。

关闭 IPv4

这一步是危险操作,因为如果你 IPv6 没有设置好,又关闭了 IPv4,那么就没有人可以访问这台服务器了,只能重装!因此请务必确认服务器的 IPv6 已经正常工作!

从支持 IPv6 的 VPS ssh 到服务器上,运行如下命令即可:

esxcli network ip interface ipv4 set -i vmk0 -t none

此时软路由应该已经可以正常上网了。

如果你之前想让 ESXi 连接到内网,只要在网页面板 VMkernel NICs 页面上修改之前手动创建的虚拟网卡的 IP 地址,符合内网的设置:

插图

然后在 ESXi SSH 中运行:

esxcli network ip route ipv4 add -g [内网网关 IP] -n default

例如:

esxcli network ip route ipv4 add -g 172.18.254.1 -n default

然后 ESXi 就也能通过软路由访问 IPv4 的网站了。

编写配置文件,让 Thunderbird 自动配置域名邮箱

许多人在自己的网站域名上设置了邮箱系统,我也在主站 lantian.pub 的域名上使用了 Zoho 的域名邮箱。不过使用域名邮箱的一大缺点是,你很难记住邮件系统的 POP3、IMAP、SMTP 等服务器地址,一旦出现重装系统、重装邮件客户端等情况,需要重新配置时,就不得不再登上邮件系统去查看服务器地址,非常麻烦。

不过,如果你用的是 Thunderbird 邮件客户端,在设置账户时,你可能注意到,Thunderbird 在添加账户时,会有一个“从邮件服务商获取设置”的过程。这个过程实质上就是从这个域名的网站服务器上请求一份 XML 文档,其中记录了邮件服务器的设置。因此,只要手动编写这份配置文件,并将它放在网站服务器上,就可以实现 Thunderbird 下的自动配置了。

创建配置文件

配置文件中保存了 POP3、IMAP、SMTP 服务器的地址、端口号、用户名等信息。对于本站使用的 Zoho 邮件系统,配置文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<clientConfig version="1.1">
  <emailProvider id="lantian.pub">
    <domain>lantian.pub</domain>
    <displayName>Lan Tian @ Mail</displayName>
    <displayShortName>Lan Tian Mail</displayShortName>
    <incomingServer type="imap">
      <hostname>imappro.zoho.com</hostname>
      <port>993</port>
      <socketType>SSL</socketType>
      <authentication>password-cleartext</authentication>
      <username>%EMAILADDRESS%</username>
    </incomingServer>
    <incomingServer type="pop3">
      <hostname>poppro.zoho.com</hostname>
      <port>995</port>
      <socketType>SSL</socketType>
      <authentication>password-cleartext</authentication>
      <username>%EMAILADDRESS%</username>
    </incomingServer>
    <outgoingServer type="smtp">
      <hostname>smtp.zoho.com</hostname>
      <port>465</port>
      <socketType>SSL</socketType>
      <authentication>password-cleartext</authentication>
      <username>%EMAILADDRESS%</username>
    </outgoingServer>
  </emailProvider>
</clientConfig>

可以看到,这个 XML 文件记录了 IMAP、POP3、SMTP 三个服务器的域名、端口、加密方式、认证方式。如果你也使用 Zoho 系统,把上面的 lantian.pub 替换成你自己的域名,就可以直接拿去用了。

如果你使用的是其它邮件系统,就要把对应的邮件服务器地址替换进去。但是,替换后也可能会遇到问题,提示“用户名密码错误”。这是因为邮件客户端在发送用户名密码的时候,可能以明文方式发送,也可能进行 MD5 加密后再发送。如果服务器不支持某种方式,就会出问题。

那么如何知道邮件服务器支持的认证方式呢?打开 Thunderbird,在添加账户界面选择“手动配置”,填入服务器配置,然后在“认证 / Authentication”一栏全部选择“自动检测 / Autodetect”,如图:

插图

然后点击下面的“重新测试 / Re-test”,稍等片刻:

插图

认证方式一栏就会发生变化。“普通密码 / Normal password” 就是明文方式发送密码,对应 XML 文件 authentication 字段的 password-cleartext 值;“加密密码 / Encrypted password” 就是 MD5 加密,对应 password-encrypted。

如果你需要更复杂的配置,请参考 Mozilla 官方的 Autoconfiguration in ThunderbirdAutoconfig: How to create a configuration file 两篇文章。

上传配置文件

Thunderbird 获取配置文件时,会尝试两个地址:

  1. http://autoconfig.[你的域名]/mail/config-v1.1.xml?emailaddress=[你的邮箱]
  2. http://[你的域名]/.well-known/autoconfig/mail/config-v1.1.xml

因此将配置文件放在上述任选一处的位置即可。正确配置完成后的效果如下:(注意 Thunderbird 的提示“从邮件服务商获得配置 / Configuration found at email provider”)

插图

在 DN42 中设置 IPv6 反向解析

DN42 全称 Decentralized Network 42(42 号去中心网络),是一个大型的 VPN 网络。但是与其它传统 VPN 不同的是,DN42 使用了大量在互联网骨干上应用的技术(例如 BGP),可以很好的模拟一个真实的网络环境。

我在先前的一篇文章中加入了 DN42 网络,并在另一篇文章中注册了自己的域名,设置了自己的 DNS 服务器。然后,我在这一篇文章设置了 IPv4 的反向解析。当时由于 DN42 Wiki 上的信息有点问题,导致我当时认为不能设置 IPv6 反向解析,但经过我尝试后发现是可以的。

因为设置的是大体相同的东西,所以本文会和之前 IPv4 的文章有比较多的内容重复(复制粘贴)。

设置 IP 段的解析服务器

第一步是将自己所有的 IP 段解析到自己的 DNS 服务器上,我的服务器是 ns[1-2].lantian.dn42,可以全填。

在 IPv4 文中我直接用了原先的设置,但是因为我 IPv6 的 DNS 设置有问题,不得不改,因此只能发一次 Pull Request 修改 IPv6 的 DNS 服务器,并顺手把 IPv4 的也改了。

在 git clone 下 DN42 的数据文件后,在自己的 IP 段文件中添加这样一句话:

nserver:            ns1.lantian.dn42
nserver:            ns2.lantian.dn42

整个文件就看起来像这个样子:

inet6num:           fdbc:f9dc:67ad:0000:0000:0000:0000:0000 - fdbc:f9dc:67ad:ffff:ffff:ffff:ffff:ffff
netname:            LANTIAN-IPV6
descr:              Peer with me at b980120@hotmail.com
country:            CN
admin-c:            LANTIAN-DN42
tech-c:             LANTIAN-DN42
mnt-by:             LANTIAN-MNT
nserver:            ns1.lantian.dn42
nserver:            ns2.lantian.dn42
status:             ASSIGNED
cidr:               fdbc:f9dc:67ad::/48
source:             DN42

接下来 git add,git commit,发 Pull Request 等待合并,等待递归 DNS 生效等等。

设置 PowerDNS

在等待的同时,就可以把解析服务器先搭起来。首先按照这篇文章,我们已经有了一个 PowerDNS 的服务器。而解析 IP,其实类似于解析一个特殊的域名。

因为 IPv6 地址够多,DN42 中人手一个 /48 块,因此不存在像 IPv4 一样,需要根据 IP 段的大小加上“/29”等内容。IPv6 的特殊域名就是 “[IP 顺序反过来].ip6.arpa”。例如我的 fdbc:f9dc:67ad::/48 对应的就是 d.a.7.6.c.d.9.f.c.b.d.f.ip6.arpa。

将这个域名添加到 PowerDNS 中,如图:

插图

然后就是为每个 IP 设置自己的反向解析记录,即 PTR 记录。例如 fdbc:f9dc:67ad::8b:c606:ba01 的就是 1.0.a.b.6.0.6.c.b.8.0.0.0.0.0.0.0.0.0.0.d.a.7.6.c.d.9.f.c.b.d.f.ip6.arpa,如图填写:

插图

但是这样手动转换很容易少 0,出现问题。偷懒的办法是找一台 Linux 或 Mac 机器运行 dig -x fdbc:f9dc:67ad::8b:c606:ba01,出现如图输出:

插图

其中 QUESTION SECTION 下面就会出现 IPv6 地址对应的 PTR 记录名:

;; QUESTION SECTION:
;1.0.a.b.6.0.6.c.b.8.0.0.0.0.0.0.0.0.0.0.d.a.7.6.c.d.9.f.c.b.d.f.ip6.arpa. IN PTR

此例中即为 1.0.a.b.6.0.6.c.b.8.0.0.0.0.0.0.0.0.0.0.d.a.7.6.c.d.9.f.c.b.d.f.ip6.arpa。

等待 DN42 的递归 DNS 生效之后,就可以用 dig -x [IP 地址] @172.23.0.53 的命令查询反向记录了。

在 DN42 中设置 IP 反向解析

DN42 全称 Decentralized Network 42(42 号去中心网络),是一个大型的 VPN 网络。但是与其它传统 VPN 不同的是,DN42 使用了大量在互联网骨干上应用的技术(例如 BGP),可以很好的模拟一个真实的网络环境。

我在先前的一篇文章中加入了 DN42 网络,并在另一篇文章中注册了自己的域名,设置了自己的 DNS 服务器。有了 DNS 服务器,我们就可以给自己的 IP 也设置上反向解析记录。反向解析记录的主要用途是反垃圾邮件,以及在 ping、traceroute 等网络工具中或许能好看一点。

设置 IP 段的解析服务器

第一步是将自己所有的 IP 段解析到自己的 DNS 服务器上,我的服务器是 ns[1-3].lantian.dn42,理论上可以全填,但是由于 DN42 现在修改配置需要发 Pull Request,流程比较长,我就保留了最初注册这个 IP 时设置的 DNS 服务器,只有 ns1.lantian.dn42。

在 git clone 下 DN42 的数据文件后,在自己的 IP 段文件中添加这样一句话:

nserver:            ns1.lantian.dn42

整个文件就看起来像这个样子:

inetnum:            172.22.76.184 - 172.22.76.191
netname:            LANTIAN-IPV4
remarks:            Peer with me at b980120@hotmail.com
descr:              Peer with me at b980120@hotmail.com
country:            CN
admin-c:            LANTIAN-DN42
tech-c:             LANTIAN-DN42
mnt-by:             LANTIAN-MNT
nserver:            ns1.lantian.dn42
status:             ASSIGNED
cidr:               172.22.76.184/29
source:             DN42

接下来 git add,git commit,发 Pull Request 等待合并,等待递归 DNS 生效等等。

设置 PowerDNS

在等待的同时,就可以把解析服务器先搭起来。首先按照这篇文章,我们已经有了一个 PowerDNS 的服务器。而解析 IP,其实类似于解析一个特殊的域名。

对于 /24 的 IP 段,这个特殊的域名就是 [IP 顺序反过来].in-addr.arpa,例如 192.168.0.0/24 的就是 0.168.192.in-addr.arpa。但多数 DN42 用户用不到 /24,只注册了 /26 至 /29 的 IP 段,就需要把 IP 最后一位连上“/26”等一起处理。以我的 IP 段 172.22.76.184/29 为例,对应域名就是 184/29.76.22.172.in-addr.arpa。

将这个域名添加到 PowerDNS 中,如图:

插图

然后就是为每个 IP 设置自己的反向解析记录,即 PTR 记录。例如 172.22.76.185 的就是 185.184/29.76.22.172.in-addr.arpa,如图填写:

插图

等待 DN42 的递归 DNS 生效之后,就可以用 dig -x [IP 地址] @172.23.0.53 的命令查询反向记录了,类似下图:

插图

另外 DN42 的 IPv6 反向解析可以在这篇文章看到。

在 DN42 中注册自己的域名

DN42 全称 Decentralized Network 42(42 号去中心网络),是一个大型的 VPN 网络。但是与其它传统 VPN 不同的是,DN42 使用了大量在互联网骨干上应用的技术(例如 BGP),可以很好的模拟一个真实的网络环境。

我在先前的一篇文章中加入了 DN42 网络,并连接了大部分自己拥有的 VPS。(剩下几台是没有 Tun/Tap 的 OpenVZ VPS,无法加入)之前我就知道 DN42 拥有自己的域名体系,例如 DN42 的 Wiki 站(https://wiki.dn42.us/Home)就可以在 DN42 中以 https://internal.dn42 的域名访问,但是之前没有时间去完成域名注册,并且当时对 DN42 的了解还不够。这个月我完成了域名注册,就来分享一下过程。

搭建权威 DNS 服务器

权威 DNS 服务器,就是指管理某个域名记录的服务器。例如本站主域名 lantian.pub 的权威服务器是 lv3ns[1-4].ffdns.net,就是 CloudXNS。在互联网上注册域名时,我们可以用现成的 CloudXNS、Cloudflare 等免费 DNS 服务,但是在 DN42 中,虽然有人提供这样的服务,但是需要在 IRC 上与他们交流申请,我觉得太麻烦,就干脆自建了。

Linux 下自建 DNS 一般使用 Bind 或 PowerDNS 两款软件。Bind 以文件形式保存 DNS 记录,跨服务器同步有些麻烦,而 PowerDNS 不仅可以用文件保存,还可以用 MySQL 等数据库形式保存,同时自己也提供记录同步功能。

由于我配置 PowerDNS 自带的记录同步功能总是失败,查不出原因,我就干脆设置了 MySQL 主从复制来进行同步。

搭建 DNS:设置 MySQL 主从同步

首先,在每台服务器中安装一个 MySQL,并且在 my.cnf 设置上这些内容:

# 每台服务器的编号,随便设置,但不能重复
server-id=1
# 每台服务器的名称,设置后可以在 phpMyAdmin 中看到从服务器的名字
report-host=Master
# MySQL 日志文件的位置,主从复制的核心文件
log_bin=mysql-bin
log_error=mysql-bin.err

然后用 phpMyAdmin 登录主 MySQL 服务器,在“Replication / 主从复制”页面将这台服务器设置为 Master / 主服务器,并创建一个用于主从复制的用户(拥有 REPLICATION SLAVE 和 REPLICATION CLIENT 权限)。由于这一步我已经做过了,所以我没法截图。

设置完后你应该可以看到类似这样的状态:

插图

其中的“File / 文件名”就是日志文件名,“Position / 位置”就是当前记录的行数。记下这两个值。

然后,关闭所有服务器上的 MySQL,用 rsync 之类方法把数据库复制到从服务器上,覆盖掉各自的数据目录,再打开所有的 MySQL。如果是没什么数据库写入操作的站,例如个人小博客,可以尝试不关主服务器 MySQL,但是可能会造成复制出去的数据损坏。

然后,用 phpMyAdmin 登录从 MySQL 服务器。因为 phpMyAdmin 在设置从服务器时有奇怪的 bug,所以我没用它的向导来设置,而是直接执行 SQL:

change master to master_host='服务器 IP',
master_user='主从复制用户名',
master_password='主从复制用户密码',
master_log_file='主服务器日志文件名',
master_log_pos=主服务器记录行数;
start slave;

然后进入“Replication / 主从复制”页面,点击“See slave status table / 查看从服务器状态表”,确认 Slave_IO_Running 和 Slave_SQL_Running 均为 Yes,主从同步就已经开始了。

插图

搭建 DNS:设置 PowerDNS

设置完数据库,我们就可以设置 PowerDNS 了。先在 MySQL 给 PowerDNS 建立一个用户和数据库。因为我是 Docker 用户,所以在主服务器上,直接用 docker-compose 下载镜像并启动:

powerdns:

image: psitrax/powerdns
container_name: powerdns
restart: always
entrypoint: "/entrypoint.sh --cache-ttl=120 --master=yes --slave=yes"
environment:
  - MYSQL_HOST=数据库服务器地址
  - MYSQL_USER=数据库用户名
  - MYSQL_PASS=数据库密码
  - MYSQL_DB=数据库名字
ports:
  - "DN42 内的 IP 地址:53:53"
  - "DN42 内的 IP 地址:53:53/udp"

然后 PowerDNS 可能会启动失败,提示在创建 comments 表时某些列过长。这是因为 MySQL 的一些配置被修改了,导致数据表的行为发生了变化,而这些列最长可达 64000 Bytes,修改后的数据表存不下。

解决这个问题不需要再改数据库配置,只需要把 64000 改小,例如 16000,然后手动创建表即可:

CREATE TABLE domains (
  id                    INT AUTO_INCREMENT,
  name                  VARCHAR(255) NOT NULL,
  master                VARCHAR(128) DEFAULT NULL,
  last_check            INT DEFAULT NULL,
  type                  VARCHAR(6) NOT NULL,
  notified_serial       INT DEFAULT NULL,
  account               VARCHAR(40) DEFAULT NULL,
  PRIMARY KEY (id)
) Engine=InnoDB;

CREATE UNIQUE INDEX name_index ON domains(name);

CREATE TABLE records (
  id                    INT AUTO_INCREMENT,
  domain_id             INT DEFAULT NULL,
  name                  VARCHAR(255) DEFAULT NULL,
  type                  VARCHAR(10) DEFAULT NULL,
  content               VARCHAR(64000) DEFAULT NULL,
  ttl                   INT DEFAULT NULL,
  prio                  INT DEFAULT NULL,
  change_date           INT DEFAULT NULL,
  disabled              TINYINT(1) DEFAULT 0,
  ordername             VARCHAR(255) BINARY DEFAULT NULL,
  auth                  TINYINT(1) DEFAULT 1,
  PRIMARY KEY (id)
) Engine=InnoDB;

CREATE INDEX nametype_index ON records(name,type);
CREATE INDEX domain_id ON records(domain_id);
CREATE INDEX recordorder ON records (domain_id, ordername);

CREATE TABLE supermasters (
  ip                    VARCHAR(64) NOT NULL,
  nameserver            VARCHAR(255) NOT NULL,
  account               VARCHAR(40) NOT NULL,
  PRIMARY KEY (ip, nameserver)
) Engine=InnoDB;

CREATE TABLE comments (
  id                    INT AUTO_INCREMENT,
  domain_id             INT NOT NULL,
  name                  VARCHAR(255) NOT NULL,
  type                  VARCHAR(10) NOT NULL,
  modified_at           INT NOT NULL,
  account               VARCHAR(40) NOT NULL,
  comment               VARCHAR(16000) NOT NULL,
  PRIMARY KEY (id)
) Engine=InnoDB;

CREATE INDEX comments_domain_id_idx ON comments (domain_id);
CREATE INDEX comments_name_type_idx ON comments (name, type);
CREATE INDEX comments_order_idx ON comments (domain_id, modified_at);

CREATE TABLE domainmetadata (
  id                    INT AUTO_INCREMENT,
  domain_id             INT NOT NULL,
  kind                  VARCHAR(32),
  content               TEXT,
  PRIMARY KEY (id)
) Engine=InnoDB;

CREATE INDEX domainmetadata_idx ON domainmetadata (domain_id, kind);

CREATE TABLE cryptokeys (
  id                    INT AUTO_INCREMENT,
  domain_id             INT NOT NULL,
  flags                 INT NOT NULL,
  active                BOOL,
  content               TEXT,
  PRIMARY KEY(id)
) Engine=InnoDB;

CREATE INDEX domainidindex ON cryptokeys(domain_id);

CREATE TABLE tsigkeys (
  id                    INT AUTO_INCREMENT,
  name                  VARCHAR(255),
  algorithm             VARCHAR(50),
  secret                VARCHAR(255),
  PRIMARY KEY (id)
) Engine=InnoDB;

CREATE UNIQUE INDEX namealgoindex ON tsigkeys(name, algorithm);

这下 PowerDNS 就能成功启动了,但是它还没有任何记录。

搭建 DNS:安装 PowerAdmin

PowerAdmin 是一个 PowerDNS 的控制面板,可以去 https://github.com/poweradmin/poweradmin 下载安装。安装过程只需要跟着向导走即可,在此略过。

安装完后,进入主界面:

插图

点“Add Master Zone / 添加主区域”,这里是添加你要解析的域名的地方。在“Zone Name / 域名”中填入域名,然后直接确定。

返回主界面,点“List Zones / 域名列表”,点击域名左边的编辑按钮进行管理,进入如下界面,这里以我的 DN42 域名 lantian.dn42 为例:

插图

最开始装完 PowerAdmin 之后,创建的 SOA 记录开头可能是没有类似 ns1.lantian.dn42 一类的内容的,这样的 SOA 记录就不符合规范。我的 SOA 记录是“ns1.lantian.dn42 lantian.lantian.dn42 0 28800 7200 604800 60”,解释如下:

  • ns1.lantian.dn42:主要 DNS 服务器的名字,一般就是你现在在操作的服务器之后要取的域名。
  • lantian.lantian.dn42:DNS 服务器管理者的邮箱,但是 @ 符号被句点代替了,例如这里就是 lantian@lantian.dn42。在 DN42 中不一定需要真实地址。
  • 0:记录编号,如果使用 AXFR 等进行 DNS 记录同步,从 DNS 服务器可能会根据这个编号判断记录有没有更改。我们使用 MySQL 主从复制,所以这里不重要。这里设置为 0 代表 PowerDNS 会自动管理这一项,无需人工操作。
  • 28800:刷新时间,AXFR 从服务器两次拉取的间隔,同样不重要。
  • 7200:重试时间,AXFR 从服务器拉取失败后,再次拉取的时间,同样不重要。
  • 604800:过期时间,AXFR 从服务器拉取失败后,最多用先前最后一次拉取成功的记录继续提供服务这么长时间,之后停止应答。同样不重要。
  • 60:最小 TTL,所有记录的最小刷新时间,至少过了这么长时间才会刷新。

点击 SOA 记录左边的编辑按钮,对应着设置好,保存。

接下来要设置 NS 记录,指明你的域名由这几台 DNS 服务器提供服务。我这次设置 3 台服务器,分别是 ns[1-3].lantian.dn42,需要分别创建相应的 NS 记录,这样填写即可:

插图

一一提交即可。

最后设置 A 记录 指明域名指向某台服务器,这样填写即可:

插图

主 PowerDNS 服务器到此设置完成。因为设置了 MySQL 主从同步,所以你的配置也已经同步到了其它服务器上,在相应的服务器上安装 PowerDNS 即可。

最后 dig 一下自己的服务器测试:

插图

在 DN42 注册域名

DN42 最近进行了一次升级,弃用了原来的 Monotone 管理界面,改用 Git 管理。首先去 https://git.dn42.us/explore/repos 上面注册一个账号,Fork dn42/registry,Clone 到本地。

首先,DN42 要求 Git Commit 经过 GPG 数字签名。我在 Mac 上使用的软件是 GPG Keychain,Windows / Linux 下使用什么软件我并不了解。大致流程是:创建密钥,将公钥提交到 SKS 等公开 GPG 服务器上供查询,然后复制下 Fingerprint。

然后设置 git,打开自动签名每次 commit 的功能:

git config --global user.signingKey [你的 Fingerprint]
git config --global commit.gpgSign true

因为我是 DN42 老用户,已经有了自己的 MNT Handle,就打开 data/mntner/LANTIAN-MNT,加入相应的指纹信息,类似如下:

mntner:             LANTIAN-MNT
admin-c:            LANTIAN-DN42
tech-c:             LANTIAN-DN42
mnt-by:             LANTIAN-MNT
source:             DN42
auth:               pgp-fingerprint 23067C13B6AEBDD7C0BB567327F31700E751EC22

然后创建 data/dns/lantian.dn42:

domain:             lantian.dn42
admin-c:            LANTIAN-DN42
tech-c:             LANTIAN-DN42
mnt-by:             LANTIAN-MNT
nserver:            ns1.lantian.dn42 172.22.76.186
nserver:            ns1.lantian.dn42 fdbc:f9dc:67ad::8b:c606:ba01
nserver:            ns2.lantian.dn42 172.22.76.185
nserver:            ns2.lantian.dn42 fdbc:f9dc:67ad::dd:c85a:8a93
nserver:            ns3.lantian.dn42 172.22.76.187
nserver:            ns3.lantian.dn42 fdbc:f9dc:67ad::18:ca0f:741d
status:             CONNECT
source:             DN42

然后 git add,git commit,git push,然后发 Pull Request 等待合并,并根据管理员的提示修改可能出现的错误。

插图

因为 DN42 中采用 Anycast DNS,每个人都能建立递归 DNS 服务器,而每个人从中心库拉取配置的频率不一,因此可能要等最长一个星期的时间,你的域名才能生效。

插图

到此 DN42 域名就注册成功了,接下来就可以在上面配置网站、邮件、IRC、游戏服务器等等了。

抢到了 50KVM 家一台 0.1 折的 VPS

TG 最大主机商 50KVM 倒闭啦!原价 100 多,200 多的 VPS,现在通通 2 块钱!通通 2 块钱!(并不

起始

  • 4 月 1 号星期天凌晨,正躺在床上看最新一集的国家队
  • Telegram 弹出消息,50KVM 发了一个愚人节优惠:

插图

插图

  • 反正国家队看完了,那就试试看输这排 emoji 吧

第一轮尝试

  • 尝试用 macOS 的输入法输入 emoji,然而发现并不好用,因为根本不知道这些 emoji 是什么东西
  • Google “emoji 列表”
  • 找到了一个 emoji 的列表网站 表情符号列表
  • 等等,macOS 的 emoji 和图上的根本不是一个风格
  • 先猜猜看吧
  • (尝试 5 次之后)
  • 还是得知道是什么 emoji 字体啊,虽然凌晨 2 点人不多,但是再慢一点说不定会被别的大佬抢走

第二轮尝试

  • 思考屌鸡(50KVM 老板)用的什么系统
  • macOS(以及 iOS)已经被排除了
  • 拿起边上的 Android 手机,打开输入法,emoji 长得不一样,排除
  • 另外主机商应该不会拿手机截图发优惠吧
  • 在 TG 群里翻了一下,翻到了 50VZ 的优惠码照片(这两家老板是一个人)

插图

  • 明显的 ClearType 痕迹,应该是 Windows 10
  • 下床拿 Windows 10 系统的游戏本,打开 emoji 列表网站,发现长得一样
  • 一个个对应输进去,提交优惠码
  • “您输入的优惠码不存在”
  • 仔细看看优惠码输入框,再看看前面两张截图,好像哪里有点不对?
  • (输入框的截图是后来在 macOS 下截的,请自行脑补替换字体)

插图

插图

  • 50KVM 截图上 emoji 之间两两间距怎么这么大?
  • 加了空格?
  • 输入“⛵️ ⛴ ⛅️ ⛈ ⛱ ⛄️ ⚽️ ⚾️ ⛳️ ⛸ ⛏ ⛓ ⛔️ ⭕️”
  • emoji 间两两加上空格,提交
  • “已应用优惠码”

插图

去 Telegram 晒

  • 提交,登录,结账,拍照,打开 TG,看到大佬们正在不停的试
  • “50kvm 的 99off 我已经拿走了”

插图
插图
插图

  • 某大佬“发出来发出来”

插图
插图
插图

  • 翻了一下聊天记录

插图
插图

  • “前面有个大佬 emoji 都输对了,但是他没发现 emoji 之间都有空格”

插图
插图
插图
插图
插图

后记

  • 今天这台 VPS 开通了,我才把文章放出来,所以并没有翻车(滑稽
  • 我当时选的是香港沙田流量型的第三档,4G 内存 6 核心,原价 217.6 人民币每月,优惠后只要 2.18 元
  • 不过老板说第三档没货了,给我降到了第二档,2G 内存 4 核心,原价 108.8 每月
  • 虽然价格没改(仍然是 2.18/月),不过仍然极其超值(相当于白送)
  • 直接向账户充值 100 元并续费 32 个月到 2021 年元旦
  • 传家宝 get✓

大幅优化了博客主题性能

今晚修改了一下主题,删掉了好几个不必要的正则匹配,把页面加载时间(HTTP 头中的 LT-Latency)从 0.25 左右降到了 0.1 左右。

正则表达式功能虽强,但为了性能考虑,还是要谨慎使用。

如何在 SSLLabs 测试中冲满分

Qualys SSL Labs 是一个测试服务器 SSL 功能的网站,我们在配置服务器时经常用它作为参考。一般来说我们只参考它的评级(A+,A,B,C,D,E,F,T)等,达到 A+ 就认为服务器的配置足够优秀。不过,SSLLabs 也在评级右侧给出了分项分数,而我的主站并没有把它们全部冲到满分。如果把 SSLLabs 的各项分项分数全部达到满分,会是什么效果,有什么实际意义吗?我用一台不运行网站的 VPS 安装了 nginx 并进行了一些配置,成功刷到了全满分,如图或者这里所示

插图

作为对比,这是本站的评分,除看图外也可在此处看到

插图

本文有关 SSLLabs 评分标准全部来自于 SSLLabs 官方的评分标准文档 在本文写成之日的版本。

准备工作

我们要先安装好 nginx。因为这台 VPS 是 OpenVZ 的,没法装 Docker,所以没法像我的其它 VPS 一样一键部署。不过因为我的 VPS 和镜像都是 Debian,所以我就把之前写过的 Dockerfile 里的指令直接复制过来用了。

证书要求

SSL Labs 要求证书不能有以下情况:

  • 域名不匹配
  • 证书还未生效或者已到期
  • 使用自签名证书等不被信任的证书
  • 使用被注销(Revoked)的证书
  • 不安全的证书签名或者密钥

基本上,只要你的证书是近期申请的,并且浏览器能正常打开你的网站,那么就没问题。

协议支持

协议支持在评级中占 30% 的比重,算法是根据服务器支持的协议打分,取最高分和最低分的平均数。

各个协议评分如下:

  • SSL 2.0: 0 分
  • SSL 3.0: 80 分
  • TLS 1.0: 90 分
  • TLS 1.1: 95 分
  • TLS 1.2: 100 分
  • TLS 1.3: 100 分

(注:TLS 1.3 的得分在评分标准中未给出,但是实际按 100 分计)(此处指 TLS 1.3 草案 18(draft 18))

SSL 2.0 现在看来是个筛子,必须严格禁止使用。SSL 3.0 也没好到哪去,但是有些网站需要它来支持老旧的浏览器(对,我说的就是 IE6)。

TLS 1.0 也有点问题,不过在各大浏览器厂商的合作下,这个问题可以当成已经解决。TLS 1.1、1.2 和 1.3 目前来看没有问题。

为了在此项得到满分,必须关闭除 TLS 1.2 以外的全部协议(包括 TLS 1.3,原因等会讲),在 nginx 中如此配置:

ssl_protocols TLSv1.2;

密钥交换

密钥交换是服务器和客户端验证彼此身份,并且产生用于当前会话的对称加密密钥的方式。其评分标准同样是最高和最低的平均数。详细分数如下:

  • 匿名密钥交换:0 分(因为无法验证身份,极易被中间人攻击)
  • 密钥强度 0 到 511 bit: 20 分
  • 出口密钥交换:40 分(这些是早期美国限制出口密钥交换算法时的产物,都很弱,容易破解)
  • 密钥强度 512 到 1023 bit:40 分
  • 密钥强度 1024 到 2047 bit:80 分
  • 密钥强度 2048 到 4095 bit:90 分
  • 密钥强度 4096 bit 及以上:100分

此处的强度是指 RSA 的等效强度。如果你用的是 RSA 证书(一般都是这种),要将密钥强度调成 4096 bit。如果你用的是 ECC 证书(比较新的证书格式),只需要 384 bit 就能有 4096 bit 的 RSA 等效强度。

如果你用的是 Let's Encrypt 以及其官方客户端 Certbot,用以下命令生成密钥即可:

certbot certonly --webroot -w /var/www/ -d vmbox.lantian.pub --rsa-key-size 4096

生成 ECC 证书需要第三方客户端,这里先不展开。(我比较懒就跳过了)

但是安装上 4096 bit 证书后,你这项的评分仍然可能没满。这就取决于 nginx 配置文件中的密钥交换算法了。先来看下这张图,这是本站的加密算法列表:

插图

算法后面有一些标记,其意义如下:

  • ECDH secp256r1 (eq. 3072 bits RSA):ECDH 256 bit 算法,等效 3072 bit RSA
  • ECDH secp384r1 (eq. 7680 bits RSA):ECDH 384 bit 算法,等效 7680 bit RSA
  • DH 4096 bit:RSA 4096 bit 算法

密钥交换算法的强度取决于密钥本身和交换算法两者中的较弱者。为了满分,就只好把所有小于 4096 bit RSA 的算法都关了。

再看一下 TLS 1.3 的算法们,它们都是等效 3072 bit RSA 的,只能把它们全禁了。全禁了之后,TLS 1.3 也就没用了,因此我刚刚不保留开启 TLS 1.3。

等等,还没完。ECDH 系列交换算法依赖一个叫 DHparams 的文件,需要运行这条命令生成:

openssl dhparam -out dhparam.pem 4096

这条命令运行奇慢,在我的 i5-3210M 的笔记本上运行了快 1 个小时。生成完后在 nginx 里如下配置:

ssl_dhparam /etc/dhparam.pem;

密钥强度

最后,就是双方交换得到的密钥本身的强度。评分同样是最大和最小的平均值,细则如下:

  • 0 bit(无加密):0 分
  • 1-127 bit:20 分
  • 128-255 bit:80 分
  • 256 bit 及以上:100 分

密钥强度由密钥交换算法确定,因此只留 256 bit 密钥强度的交换算法即可。符合条件的算法是 CHACHA20-POLY1305 和 AES-256。我的配置如下:

ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA:!DSS';

其它调整

另外还要打开 HSTS(强制浏览器走 SSL)。最好还要打开 HPKP(要求浏览器只认某几家的证书)。配置如下:

add_header Strict-Transport-Security 'max-age=15768000;includeSubDomains;preload';

(HSTS,注意会对子域名生效,并且允许你的网站提交到 HSTS Preload 列表,也就是浏览器永远走 SSL,即使没访问过你的网站)

add_header Public-Key-Pins 'pin-sha256="9uthMA8OzB/wVGSR3w5bzlt6jAFLWEI533bM+vNDkts=";pin-sha256="YLh1dUR9y6Kja30RrAn7JKnbQG/uEtLMkBgFF2Fuihg=";pin-sha256="sRHdihwgkaib1P1gxX8HFszlD+7/gTfNvuAybgLPNis=";pin-sha256="58qRu/uxh4gFezqAcERupSkRYBlBAvfcw7mEjGPLnNU=";max-age=2592000';

(放行了 Let's Encrypt 的两张中级证书,另两张貌似是 TrustAsia 和 Comodo 的,记不清了)

完成以上这些后,SSL Labs 就会显示你的 SSL 满分了。

实用性?

满分固然好看,但是其提供的意义又有多少?在这个过程中,我们使用了明显更慢的 4096 bit 密钥和交换算法,而 2048 bit 对于现在的算力来说已经足够。这就造成了额外的 CPU 开销(加密解密)和网络开销(传输密钥)。同时,我们放弃了很多旧客户端的支持,其中有些我们一般不考虑支持了(例如 IE8),但是根据 SSLLabs 显示的测试结果,有些客户端却很重要:

  • Android 4.3 及之前版本的设备(旧手机,旧智能电视及盒子)
  • 百度搜索索引机器人(根据 SSL Labs 页面上显示,2015 年 1 月的版本)
  • IE 10 及之前的浏览器(一些还没升上级的 Windows 7,以及 Windows Phone 8.0)
  • Java 6、7(不支持 TLS 1.2)
  • Java 8(不支持留下的这些密钥交换算法)
  • Safari 6 及之前版本

其中以 Java 8 最为重要。绝大多数网站完全不需要这么注重安全的配置,大可以允许一些稍微弱一些的算法来提高兼容性。

最后,满分演示站在此:http://vmbox.lantian.pub/

满分报告地址:https://www.ssllabs.com/ssltest/analyze.html?d=vmbox.lantian.pub