水一水,好快乐
Introduction
社团的 ssl 证书要过期了,但是自动更新证书的任务一直失败,感觉很奇怪。
我以为是一个小问题,重新配置一下就行了,但是我错了。
letsencrypt 的认证方式有多种,最好用的莫过于 dns 认证,只需要配置一下 dns 解析就可以申请,哪怕没有服务器也可以。
但是社团的情况有点特殊,没有 dns 管理权限,没有 80 端口。也因此,我对于之前如何申请的证书感到好奇。
原来是 letsencryt 还支持另外一种叫做 tls-alpn-01 的认证方式。
优点
- 不需要 80 端口
- 在 ssl 层面执行
其实之前还有过一个 TLS-SNI-01 认证方式, 不过因为有缺陷被禁用了。
缺点
- It’s not supported by Apache, Nginx, or Certbot, and probably won’t be soon.
- Like HTTP-01, if you have multiple servers they need to all answer with the same content.
- This method cannot be used to validate wildcard domains.
看到这里,我心理都凉了,居然不支持 nginx?
我更加好奇了,于是询问了一下学长。
学长告诉我不要修改 socket 配置的相关内容。
啊这!
原来都是我的锅呀 ,难怪我感觉 nginx 的配置好生奇怪。
那就进入今天的正题
nginx tls-alpn-01(https)
我带着问题查了一下,好家伙,第一个就是学长的博客(膜拜一波大佬)
原理
Nginx 不仅是 HTTP/HTTPS 服务器,跟提供了全面的 TLS、UDP 甚至是邮件协议支持。
Nginx 的 ngx_stream_ssl_preread_module 模块提供了 ClientHello 访问。通过$ssl_preread_alpn_protocols 变量,即可实现不同协议的分流。
nginx 有一个模块可以根据协议进行分流,于是我们根据这一点来实现 letsencrypt 认证时候的流量转发,进而实现不停服务情况下进行 ssl 证书 renew。
nginx 之 map 作用
学习一下 map 指令
map 指令是由 ngx_http_map_module
模块提供的,默认情况下安装 nginx 都会安装该模块。
map 的主要作用是创建自定义变量,通过使用 nginx 的内置变量,去匹配某些特定规则,如果匹配成功则设置某个值给自定义变量。 而这个自定义变量又可以作于他用。
map 指令的三个参数
- default : 指定源变量匹配不到任何表达式时将使用的默认值。当没有设置 default,将会用一个空的字符串作为默认的结果。
- hostnames : 允许用前缀或者后缀掩码指定域名作为源变量值。这个参数必须写在值映射列表的最前面。
- include : 包含一个或多个含有映射值的文件。
map $var1 $var2 {
match1 value1;
default default-value;
...
}
在 Nginx 配置文件中的作用段: http{}
注意 map 不能写在 server{} 否则会报错
map 的 $var1 为源变量,通常可以是 nginx 的内置变量,$var2 是自定义变量。 $var2 的值取决于 $var1 在对应表达式的匹配情况。 如果一个都匹配不到则 $var2 就是 default 对应的值。
配置
- nginx 配置
stream {
tcp_nodelay on;
map $ssl_preread_alpn_protocols $tls_addr {
~\bacme-tls/1\b 127.0.0.1:10443; # TLS-ALPN-01验证服务的地址
default 127.0.0.1:8443; # HTTPS服务地址,此处以本机8443为例
}
server {
listen 443;
listen [::]:443;
proxy_pass $tls_addr; # 使用对应变量进行访问
proxy_protocol on; # 开启PROXY protocol,见后文
ssl_preread on;
}
}
这里就把 ssl 的流量分成了两个一个是localhost:8443
的提供 web 服务器的 ssl 流量,另一个就是letsencrypt
tls-alpn-01 的认证流量,这个流量走localhost:10443
一切变得简单起来了,对于 web 服务,将端口修改成 8443 即可,对于认证 ssl 服务,监听10443
端口即可。
注意,由于经过这个操作后,从 8443 端口来的流量就是代理的协议了,需要使用代理协议,即添加
proxy_protocol
同时需要通过proxy_protocol_addr
来获取真实的 IP 地址。
acme.sh 配置
接下来就是配置 acme.sh 了,只需要修改 tls-apln 的监听端口即可。
示例
acme.sh --issue --domain your-domain.example --alpn --tlsport 10443
如果一切正常,通过上面的命令就可以完成 ssl 证书的申请了。
小插曲
在我完成配置修改的时候,直接使用nginx -s reload
进行配置的更新
但是并没有卵用,这个更新无法涉及 socket 修改的变得
也因此,我一直卡在最后一步无法解决
就当我要放弃的时候突入来了一句systemctl restart nginx
然后,就申请成功了。 (我太菜了)
最后
其实我很早就像写这篇了,但是因为拖延症患者,导致现在才有机会写(还是占用上课时间写的)
好了,水了一篇博文好开心。
延伸链接