DN11 是受 DN42 启发而搭建的一个实验性网络,目前用于杭电范围内,对网络感兴趣的同学学习使用,DN11和DN42非常相似,他们之间的经验都有广泛借鉴意义。

在真实的互联网中,我们常常会通过校验 SSL 证书的方式创建加密 socket 来访问互联网上的资源,这能够有效阻止他人看到通信的内容。而在 DN11 中,由于每个人都相当于是 ISP,流量可能途径每一个人,随时可能被人抓取,因此使用 SSL 证书这件事就更为重要了。

本文将在使用 PDNS 搭建好实验性网络 DNS 的基础上使用 step-ca 搭建 ACME Server 并使用 acme.sh 签发证书。

0. 实验环境介绍

  1. DNS服务器自建已经完成了,通过 anycast IP172.16.255.53可以解析顶级域名dn11
  2. acme.dn11域名已经解析到172.16.255.2,并且实验机已经宣告了这个 IP。
  3. 已经获取到根证书,中间证书,中间证书的签名密钥,而根证书密钥安全起见由他人代管。

GOGOGO!

1. 初始化 step-ca

step-ca 提供了很多种安装方式,裸机,docker,k8s等等。由于计划部署 step-ca 的机器上并没有集群环境,裸机又不方便 remake,通过 docker 镜像安装便成为了最佳选择。

https://hub.docker.com/r/smallstep/step-ca

docker pull smallstep/step-ca
docker run -it --rm -v step:/home/step smallstep/step-ca step ca init --remote-management

上面的命令会拉取 step-ca 的镜像,使用step ca init --remote-management替换原有的启动命令启动容器同时创建一个名为 step 的卷挂载到 /home/step,还使用了-it参数进入交互式。

✔ What would you like to name your new PKI? (e.g. Smallstep): DN11
✔ What DNS names or IP addresses would you like to add to your new CA? (e.g. ca.smallstep.com[,1.1.1.1,etc.]): acme.dn11
✔ What address will your new CA listen at? (e.g. :443): :443
✔ What would you like to name the first provisioner for your new CA? (e.g. you@smallstep.com): <你的账户名>
✔ What do you want your password to be? [leave empty and we'll generate one]:

在交互式终端中,我们根据他的指引完成配置,其中:

  • PKI name 无所谓。
  • DNS names 填写我们预先解析过来的域名,后续将使用这个域名访问 ACME 服务
  • 端口无所谓,后续使用 docker 映射到外部
  • first provisioner name 的邮箱可以不存在,但是邮箱域必须在中间证书签发范围内,在本实验中可以使用abc@acme.dn11,下面以此为例。
  • 密码留空让他自己生成
✔ Admin provisioner: abc@acme.dn11 (JWK)
✔ Super admin subject: step

完成上面的初始化后,终端会告诉你 Admin provisioner 的名称和超级管理的名称,后续我们将使用这两项和上面的 password 来管理 step-ca,务必牢记。

此外我们还需要手动把密码写入到容器里

挂载 step 卷并打开容器 shell docker run -it --rm -v step:/home/step smallstep/step-ca sh

将上面生成的密码写入到 secrets/password

2. 启动 step ca 并配置

可以初次启动step ca了,下面配置一下 admin 账户和证书。

docker run -d -p 172.16.255.2:443:443 -v step:/home/step smallstep/step-ca

启动容器,映射容器内的 443 端口到外部 172.16.255.2:443

启动后使用 docker exec -it <容器ID> /bin/bash 进入容器环境。

切换 admin 账户到 DN11 域

由于我们手上的根证书只能签发给 dn11 域名,所以需要先把 super admin 的账户名改到 dn11 域,不然后续无法管理只能 remake

step ca admin add abc@acme.dn11 abc@acme.dn11 --super

依次输入 step 和你的密码添加一个超级用户

step ca admin remove step

依次输入你的 abc@acme.dn11 和你的密码来删除 step 账户

step ca admin list

你可以用这个命令检查 admin 的删改是否正确

替换证书

可以使用 vi 把原有的 certs/intermediate_ca.crt certs/root_ca.crt certs/root_ca.crt secrets/intermediate_ca_key 替换为你的中间证书,根证书,中间证书签名秘钥

注意格式,全部都是 pem 纯文本格式,如果你的格式不对请使用 openssl 转换

secrets/root_ca_key已经没有用了,删除即可。

替换完证书后输入 exit 退出 shell。

docker stop <容器ID>
docker start <容器ID>

重启容器

3. step-ca 远程管理

我们现在的 step-ca 他位于 docker 内,那我们其实不好每次都 docker exec 进去管理,所以最好能在其他地方管理,至少是宿主机吧。

其实 step-ca 提供了这样的接口而且我们一开始部署的时候就打开了远程管理。按照 step-ca 的原版教程,我们可以使用step ca bootstrap命令创建远程配置文件,但是我并没有创建成功,提示根证书下载失败,这里提供一个手动的安装方法。

mkdir -p .step/certs
mkdir -p .step/config
docker cp <容器ID>:/home/step/config/defaults.json .step/config/defaults.json
docker cp <容器ID>:/home/step/certs/root_ca.crt .step/certs/root_ca.crt

先把配置从 docker 里拷贝出来,然后再修改一下defaults.json文件。ca-config字段可以删除了,root 字段的内容改为刚刚拷贝出来的root_ca.crt的绝对路径。

可以通过列出 provisioner 的方式step ca provisioner list检查一下配置文件,列 provisioner 无需鉴权。

4. ACME 服务配置

下面在 step-ca 上配置 ACME 服务

step ca provisioner add acme --type ACME
step ca provisioner update acme \
   --x509-min-dur=20m \
   --x509-max-dur=8760h \
   --x509-default-dur=2160h

上面的两个命令首先添加了一个名为 acme 类型为 ACME 的 provisioner,然后修改了证书的默认有效期最长有效期和最短有效期

step-ca 默认的默认有效期为一天,如果正式使用 step-ca 签发的证书那最好换一个比较长的时间。

上面的命令默认签发为30天,最长签发为365天,不要签发超过一年的证书,APPLE 公司在新版本的系统中拒绝了签发有效期超过一年的证书,这可能会导致你的证书在 APPLE 的设备上无法使用。

5. 安装根证书

在这个实验里,根证书可以通过https://acme.dn11/roots.pem下载,只要临时允许一下不安全的证书就可以了。

访问任何一个使用了该根证书签发的 SSL 证书的网站前都需要安装根证书,这当然也包括你的服务器,因为 acme.sh 需要这个证书来和 ACME 服务器交互。

Linux

curl -k https://acme.dn11/roots.pem -O roots.pem
chmod 644 roots.pem
sudo mv roots.pem /usr/local/share/ca-certificates/DN11_CA.crt
sudo chown root /usr/local/share/ca-certificates/DN11_CA.crt
sudo update-ca-certificates

看到控制台输出 1 added 就说明证书被添加到系统了。

Windows

DN11-CA.crt 双击安装,没有的可以用 openssl 把从https://acme.dn11/roots.pem下载到的证书转为x.509格式再安装

windowsinstallroot

安装的时候不要让 windows 自动选择证书存储位置,这可能会出错,请手动选择受信任的根证书颁发机构

IOS

使用 Safari 访问 https://acme.dn11/roots.pem 下载证书,出现证书错误的提示时点击显示详细信息并坚持访问,Safari会提示安装描述文件,点击允许。

打开设置会在最上面出现"已下载描述文件",点击并安装 DN11 Root Authority CA。最后在 设置-关于本机-证书信任设置 启用对 DN11 Root Authority CA 的完全信任。

关于老版本 IOS,android,MacOS 自寻出路。

6. 签发证书

首先需要安装 acme.sh

curl https://get.acme.sh | sh

拉取 acme.sh 安装脚本并执行,如果你的服务器到海外的线路不是很通,也可以换个地方下载安装脚本后 scp 到服务器执行

acme.sh 会被安装到 ~/.acme.sh/ 目录下

建议切换到 root 安装,他可能需要修改 nginx 配置文件,这样会少一点权限问题。

如果你使用 nginx 作为反向代理,我们有两种方式可以签发证书,一种是使用 http-01 一种是 dns-01

http-01

cd .acme.sh
./acme.sh --issue -d <你的域名> --server https://acme.dn11/acme/acme/directory --nginx

http-01 通过向域名指向的服务器发起一个 HTTP 请求来验证你对这个服务器的所有权。在这个过程中 acme.sh 会修改你的 nginx 配置文件, 最终会恢复现场。

dns-01

acme.sh 不支持指定 DNS 服务器,只支持在少数几个 DNS 服务器中进行选择,这会导致检查 TXT 解析是否生效这一步卡住。幸运的是他有超时控制,只会卡5分钟,如果要改变这个行为只能魔改acme.sh了,暂时还没下手。

当然等五分钟也是没有问题的,下面以 PowerDNS-Admin 为例

export PDNS_Url="<PowerDNS-Admin地址>"
export PDNS_ServerId="localhost"
export PDNS_Token="<你的token>"
export PDNS_Ttl=60
./acme.sh --issue --dns dns_pdns -d <你的域名> --server https://acme.dn11/acme/acme/directory
  • PDNS_ServerId 默认为 localhost,如果有修改也要跟着修改
  • PDNS_Token 可以在管理面板的 API Keys 里申请,申请时 Role 选择 User,Domain Access Control 选择对于的域

等待五六分钟即可,所有的环境变量都会被 acme.sh 保存为配置文件,下次无需重新写环境变量

7. 安装证书

下面以nginx为例

./acme.sh --install-cert -d example.dn11 \
--key-file       /etc/nginx/ssl/example.dn11.pem  \
--fullchain-file /etc/nginx/ssl/example.dn11.crt \
--reloadcmd     "service nginx force-reload"

使用 acme.sh 复制证书和秘钥到nginx目录下,acme.sh 会记住证书安装的位置,每次刷新证书都会重新复制一份证书覆盖到上面指定的路径。

server {
    listen       80;
    listen       443 ssl;
    server_name  example.dn11;

    access_log  /var/log/nginx/example.dn11.access.log  main;

    ssl_certificate /etc/nginx/ssl/example.dn11.crt;
    ssl_certificate_key /etc/nginx/ssl/example.dn11.pem;

    location ~ {
        proxy_pass   http://127.0.0.1:8080;
    }
}

nginx 配置文件样例,上面配置了一个到127.0.0.1:8080的反向代理,并指定了证书的位置,在443端口上开起了 https 监听。

上面并没有配置 http 到 https 的跳转更没有配置 hsts。这是为了留一条后路,可能并不是所有人都愿意安装自签的证书的。

show

效果拔群

参考资料