目标
- 在非443端口开启HTTPS
- 使用正规机构签发的证书
- 到期自动续签
当前条件
- 有公网IP,但是不固定
- 有域名
- 一台linux服务器
方案
目前常见的服务器开启 HTTPS 并自动续期的方案有两种: Caddy 和 Nginx + Certbot 。 后者配置的复杂程度很高,就算利用 docker 也不能避免冗长的配置编写过程,而 Caddy 内置了 HTTPS 以及自动续期的支持,配置也相对简洁,因此下面介绍使用 Caddy 部署 HTTPS 的方法。
配置步骤
域名配置
- 申请域名
- 将域名与公网IP做绑定
- 如果公网IP不固定,需要做动态域名绑定(ddns)
软件下载
Caddy 默认使用 HTTP-01 验证方式,要通过 DNS-01 验证需要对应的插件支持,通过软件源安装的 Caddy 没有这些插件,需要在下载页下载或是通过 xcaddy 从源码构建。
下载页 caddy-dns 开头的几个插件就是 DNS-01 验证的插件,插件与 DNS 提供商有关,因此有好几个,本文使用阿里云 DNS ,因此选中了 caddy-dns/lego-deprecated 插件(这个插件最近在用 go 重写,新版功能还不全,因此先用着旧版)。 Linux amd64 + lego 插件的二进制包[下载地址]。(https://caddyserver.com/api/download?os=linux&arch=amd64&p=github.com%2Fcaddy-dns%2Flego-deprecated&idempotency=80128464204175)
caddy配置
下载之后执行 chmod +x caddy && mv caddy /usr/bin
赋予执行权限并移到 bin 目录
下面编写 caddy 的配置文件 Caddyfile :
{
http_port 1999
https_port 2000
}
A.yourdomain.com {
#反向代理http网站
reverse_proxy localhost:2001
tls {
dns lego_deprecated alidns
}
}
B.yourdomain.com {
#反向代理https网站,该https网站已有自签证书
reverse_proxy https://192.168.0.3:8888 {
transport http {
#关闭tls校验,慎用
tls_insecure_skip_verify
}
}
}
这里第一个大括号内是全局配置,声明了 caddy 要在哪个端口监听外部的 HTTP / HTTPS 请求,这个端口也是做 DDNS 的路由器需要转发到外部的端口。 后面 A.yourdomain.com 需要替换成个人的域名,大括号内是这个域名的配置: 反向代理本地 2001 端口的 Web 服务,且 tls 证书申请通过 dns 方式进行,使用的插件为 lego_deprecated , alidns 为插件的参数。
根据 lego 的文档 ,我们需要把阿里云的 Access key ID 与 Access Key secret 设置为环境变量,这两个值可以在阿里云的控制台获取。 鼠标悬停在右上角头像上,弹出的名片里有一项 Access Key 管理,进入之后点击创建 Access Key 就可以得到一组 Access key ID 与 Access Key secret ,将这两个值保存在一个环境变量文件 alidns.env
里:
ALICLOUD_ACCESS_KEY=id
ALICLOUD_SECRET_KEY=secret
作为测试,可以先起一个 python 简易服务器:
python3 -m http.server 2001
之后运行 caddy 服务:
caddy run --config Caddyfile --envfile alidns.env
如果一切正常,应该可以在终端日志看到 caddy 通过 dns challenge 申请到证书的过程,之后就可以通过域名 + 非 443 端口通过 HTTPS 访问本地的 Web 服务了。
注意
- 建议只代理http协议的网址,将https证书的管理工作都交给caddy,即A.yourdomain.com的方式。
- B.yourdomain.com的配置仅供参考,仅在后端web服务器的https无法替换为caddy提供的方式时使用,tls_insecure_skip_verify配置项后期可能会被移除。
合规性提醒
目前对于个人用户能否搭建服务器貌似没有明确的规定(无论是否为80/443端口),此前也有非标准端口搭建 Web 服务导致宽带被封的案例,因此建议不要把此方案应用于对流量与稳定性有较高需求的场景。