早前借助 DNSPod,GitHub Pages 和 Coding Pages,实现了 Jekyll 博客的国内外双线部署。但没有用上 SSL/TLS,浏览器地址栏上缺失的小锁,一直是心中的遗憾。用上 HTTPS 的好处不用多言,谷歌搜索结果优先排列,国内移动上网不会给无耻运营商插入广告。所以,本文将在此前基础上,叙述如何双线启用 HTTPS。
调研双线 SSL 的时候,GitHub Pages 还不允许自定义域名开启 HTTPS,所以本文使用 VPS 反向代理的方式解决此问题。
2018 年 5 月 1 日起,GitHub 官方已经开启自定义域名 HTTPS 支持(见官方公告)。
前提
- 一个域名
- 一台墙外VPS
原理
flowchart LR
subgraph VPS
ssl(Let's Encrypt)
ngx(Nginx)
end
u0([Oversea User]) -- oversea --> dnspod[DNSPod]
u1([Local User]) -. inland .-> dnspod
dnspod -- oversea --> ssl
ngx -- reverse proxy --> gh-pages[GitHub Pages]
ssl o--o ngx
dnspod -. inland ...-> cd-pages["Coding Pages\n(with Certification)"]
在本案例,来访请求由 DNSPod 作动态分析:
- 海外访问请求经过 VPS 上运行的 Nginx 反代至 GitHub Pages,VPS 上须申领一份 Let's Encrypt 的 SSL/TLS 证书。
- 国内的访问则直接连接 Coding Pages,证书由 Coding.net 代由申领,皆为 Let's Encrypt 提供。
笔者拥有的二级域名是 cotes.in
,计划把三级域名 blog.cotes.in
映射至 GitHub Pages 及 Coding Pages 两个站点的博客。接下来,是激动人心的配置过程了。
海外线路
DNSPod配置
GitHub Pages 绑定自定义域名不允许使用 HTTPS, 所以需要添加一个 A 记录指向 VPS 的 IPv4 地址。 进入 DNSPod 控制台,对域名 blog.cotes.in
添加唯一的国外线路记录(此前双线 HTTP 时添加的国外 CNAME 记录删掉):
VPS获取证书
本案例使用 certbot 获取 Let's Encrypt 提供的免费证书,RHEL 7 安装 certbot 具体步骤见安装 certbot,在此不再复述。
申请证书要保证目标服务器的 80 端口可访问,接收 HTTPS 访问需保证 443 端口开放。所以须在 VPS 进站出站规则允许开放 80 及 443 端口。
完成上述准备后,SSH 登录至运行 RHEL 的 VPS,为博客域名 blog.cotes.in
申请证书:
1
$ sudo certbot certonly --standalone -d blog.cotes.in
--standalone
表示 certbot 会自己运行一个 web server 来进行验证,为避免冲突须关闭 Nginx 及 Apache 等服务。
成功的输出信息会包含证书存放目录,若忘记可用命令查看:
1
2
3
4
5
6
7
8
9
10
11
$ sudo certbot certificates
Saving debug log to /var/log/letsencrypt/letsencrypt.log
-------------------------------------------------------------------------------
Found the following certs:
Certificate Name: blog.cotes.in
Domains: blog.cotes.in
Expiry Date: 2018-09-29 07:35:36+00:00 (VALID: 89 days)
Certificate Path: /etc/letsencrypt/live/blog.cotes.in/fullchain.pem
Private Key Path: /etc/letsencrypt/live/blog.cotes.in/privkey.pem
-------------------------------------------------------------------------------
输出信息末端的 Certificate Path
及 Private Key Path
就是证书存放路径。
Nginx SSL反向代理
Nginx 确保开启了 SSL 模块 ngx_http_ssl_module
,在配置文件的 http
模块中添加两个 server:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
server {
listen 443 ssl;
ssl on;
server_name blog.cotes.in;
ssl_certificate /etc/letsencrypt/live/blog.cotes.in/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/blog.cotes.in/privkey.pem;
location / {
proxy_pass https://cotes2020.github.io;
proxy_redirect off;
proxy_set_header Host blog.cotes.in;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
server {
listen 80;
server_name blog.cotes.in;
rewrite ^(.*) https://$server_name$1 permanent;
location / {
proxy_pass https://blog.cotes.in;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
}
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
监听 443 端口的 server 模块里,把 https://blog.cotes.in
跳转至 GitHub Pages 的派发地址:https://cotes2020.github.io
。
监听 80 端口的 server 模块把 HTTP 请求跳转到 HTTPS。
检测配置语法:
1
# nginx -t
重载配置:
1
# nginx -s reload
证书自动更新
见站内 certbot 自动更新描述。
国内线路
由于采用国内外双线部署,DNSPod 需要暂时关闭国外路线:
这样在 Let's Encrypt 检查域名是否可用时,能够正确连接到 CodingPages 的地址。
接着 Coding Pages 项目控制台开启 HTTPS:
成功后 Coding Pages 控制台会出现证书信息:
最后,回到 DNSPod 恢复域名的国外线路记录。
资源格式
采用 HTTPS 的页面,需要将已有的图片、视频资源链接都采用 HTTPS。否则,会导致页面加密失败,变回 HTTP 传输。