Let’s Encrypt的证书签发原理实际上和传统的PKI一样,只不过自动化完成了生成CSR和私钥、提交CSR、取回证书的过程。
此外还要验证域名所属,这一部分和传统的签发机构是一样的,不过传统的签发机构还允许我们使用域名whois中填写的邮箱来验证,而Letsencrypt貌似只能通过http challenge的方式来验证。即和验证服务器约定一个uri和随机字符串,验证服务器请求这一uri,如果得到的内容和约定的随机字符串相同,则验证通过。如图所示:
(官网上抄的)
这意味着我们得在每台部署https的前端的负载均衡服务器上都装一个letencrypt工具。有没有什么集中化管理的办法的呢?
实际上,由于challenge的uri的有规律,我们可以将前端服务器收到的这类请求代理到同一台专门用来签发、更新证书的服务器上。如图所示:
- 当在服务器B上发起域名a.example.com新的签发请求后,Let’s Encrypt的签发服务器返回一个challange uri (8303)和response (ed98)。
- 服务器B使用webroot插件将这个uri和response写入本地磁盘上对应的文件。
- Let’s Encrypt的签发服务器为了验证example.com的所属,查询到example.com指向前端服务器A,于是发送一个HTTP请求/.well-known/acme-challenge/8303到服务器A
- 服务器A反代这一请求到服务器B
- B读取刚才第二步时写入到response,返回到A;A返回到Let’s Encrypt的签发服务器
- 验证成功,发证!
然后,我们只要从服务器A上取回存储在B上到证书就可以了。可以在B上做一个RESTful的api。注意要配置allow和deny。
A服务器(前端)的nginx配置如下:
1 2 3 4 5 6 7 8 |
server { # 其他的location # location { ..... } location ~ /.well-known { proxy_pass http://B.example.com:23333; } } |
B服务器的nginx配置如下:
1 2 3 4 5 6 7 8 9 |
server { listen 23333; server_name B.example.com; location ~ /.well-known { root /tmp/letsencrypt; allow IP-OF-A; deny all; } } |
然后在B上运行:
1 |
./letsencrypt-auto --webroot -w /tmp/letsencrypt -d exmaple.com; |