发布版说明
- 已对真实域名、公网 IP、具体云厂商指代做脱敏处理。
- 原始学习笔记未改动,这一版用于公开发布。
专题:HTTPS 与 Let’s Encrypt
这篇专门把前面你已经真实遇到过的 HTTPS 问题讲透。
不是教你背一条 Certbot 命令,而是要真正搞明白:
- HTTPS 到底解决什么问题
- Let’s Encrypt 到底在验证什么
- 为什么明明本机正常,证书还是签不下来
- 为什么明明证书已经在机器上了,公网访问还是超时
一、先把 HTTPS 这件事讲人话
用户访问:
http://status.example.com
和访问:
https://status.example.com
区别不是“多了个 s”这么简单。
本质区别有两件事:
1.1 数据被加密了
HTTP 明文传输,链路中间如果有人抓包,理论上能看到内容。
HTTPS 会先建立 TLS 加密通道,再传 HTTP 数据。
所以浏览器、服务器之间传的内容,不再是裸奔。
1.2 浏览器能确认“你连的真是这个域名”
这就涉及证书。
浏览器不是无条件相信服务器的,它需要看:
- 这个证书是不是可信 CA 签发的
- 证书里的域名是不是当前访问的域名
- 证书有没有过期
如果都对,浏览器才会给你安全锁。
二、证书不是“给服务器签”的,是“给域名签”的
这个点特别重要。
比如你申请的是:
status.example.com
那证明的是:
你对这个域名具备控制权
不是证明:
- 你拥有这台服务器
- 你会配 Nginx
- 你的应用没问题
所以证书签发这件事,本质上是:
CA 要确认你真能控制这个域名的访问路径。
三、Let’s Encrypt 的 HTTP-01 挑战到底在干什么
前面你申请证书时,最典型的报错是:
- CA 去访问
http://status.example.com/.well-known/acme-challenge/... - 拿到的不是挑战文件
- 而是你站点自己的 HTML
这背后其实是 Let’s Encrypt 在做这件事:
3.1 它先给你一个随机 challenge 文件
Certbot 会在你指定的 webroot 里写一个临时文件。
路径通常长这样:
/.well-known/acme-challenge/<token>
3.2 Let’s Encrypt 从公网访问这个 URL
它会主动访问:
http://你的域名/.well-known/acme-challenge/<token>
注意这里是:
HTTP 80 端口
不是先验证 443。
这点很多人一开始容易搞反。
3.3 如果它能拿到正确内容,就认为你控制了这个域名
因为只有真正控制这个域名解析和站点响应的人,才能让这个 URL 返回正确的 challenge 内容。
所以:
HTTP-01 挑战是在验证“域名控制权”,不是在验证 HTTPS 自己是否已经可用。
四、为什么证书签发依赖 80,而不是先依赖 443
这是很多新手最容易绕进去的地方。
直觉上会觉得:
我要申请 HTTPS 证书,那不是应该先验证 443 吗?
其实不是。
原因很简单:
- 你现在还没有可被浏览器信任的证书
- 443 这一层还没法先建立可信 HTTPS
- 所以 CA 必须用一个更基础的方法验证你控制了域名
这个更基础的方法,就是:
先走 HTTP 80 的 challenge。
所以如果 80 不通、或者 challenge 路径被吞了,证书就签不下来。
五、你前面遇到的证书失败,到底失败在哪
当时报错核心是:
Invalid response from http://status.example.com/.well-known/acme-challenge/...
并且返回的是一段 HTML 页面。
这说明不是 DNS 没解析,也不是 Certbot 没写文件,而是:
5.1 CA 已经成功访问到了你的服务器
这点非常关键。
如果它完全访问不到,报错就更偏向:
- 超时
- 连接失败
- 找不到主机
而你这里拿到的是“错误内容”。
说明请求到服务器了,只是被错误处理了。
5.2 挑战路径没有被正确映射到 webroot
最常见原因是:
location / {
proxy_pass http://127.0.0.1:3001;
}
这种通配规则把 challenge 请求也一起转发走了。
或者你本来做的是静态站点,结果 challenge 请求被默认首页接住了。
于是:
- Certbot 认为 challenge 文件应该从某个目录直接读出来
- 但 Nginx 没按这个逻辑处理
- CA 最终拿到的就不是 token 文件,而是别的页面
这就是你当时失败的根因。
六、正确理解 Nginx 里 challenge 路径的优先级
申请证书时,Nginx 最少要保证一件事:
/.well-known/acme-challenge/这条路径能返回 challenge 文件本身
最典型的思路是给它单独留一个 location:
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
或者你用 webroot 模式时,让它明确指向 Certbot 写文件的目录。
重点不是非得背这个写法,而是理解:
- challenge 路径必须有独立处理逻辑
- 不能被笼统的
location /规则吞掉
这就是证书申请时最容易踩的 Nginx 坑。
七、证书签下来了,为什么公网 HTTPS 还是超时
你前面又碰到了第二个非常典型的坑:
- 本机
curl --resolve ... 443:127.0.0.1能通 - 证书也已经在机器上了
nginx也监听了443- 但公网访问
https://status.example.com还是超时
最后发现不是 Nginx 本身,而是:
云厂商安全组没放行 443
这件事非常值钱,因为它直接把“本机配置”和“公网链路”分开了。
八、你那次问题,按层拆开到底是什么样
那次其实可以拆成 4 层:
8.1 域名层
dig +short "status.example.com" 能返回:
203.0.113.10
说明域名已经指向服务器。
8.2 应用/Nginx 本机层
你测过:
curl -vkI --resolve "status.example.com:443:127.0.0.1" "https://status.example.com"
它能正常建立 TLS,并返回 302 /dashboard。
这说明:
- Nginx 的 443 站点存在
- 证书加载成功
- 本机 HTTPS 链路没问题
8.3 Linux 防火墙层
你当时 ufw status 已经显示:
80已放行443已放行
说明 Ubuntu 本机防火墙并没有拦住它。
8.4 云安全组层
外网还是超时,最后问题落在云厂商安全组。
这一步一旦没放行,外面的流量根本到不了你这台机器。
所以才会出现这种看起来很拧巴的现象:
- 本机一切正常
- 公网就是不通
不是系统玄学,就是外层网络策略拦住了。
九、所以 HTTPS 问题以后该怎么排
以后你碰到 HTTPS 不通,不要一上来就反复删证书重签,先按层查。
第 1 步:查域名解析
dig +short "status.example.com"
先确认域名确实指向你的服务器公网 IP。
第 2 步:查 80 端口的 HTTP 站点是否可达
curl -I "http://status.example.com"
如果连 HTTP 都完全不通,先别谈证书。
因为 HTTP-01 挑战本来就依赖 80。
第 3 步:查 challenge 路径是否真的能拿到文件
证书申请时最重要的是这一层。
如果 challenge 请求拿到的是:
- 默认页
- 应用首页
- 302 跳转
- 404
那都说明 challenge 路径没被正确接住。
第 4 步:查 Nginx 配置语法和监听
sudo nginx -t
sudo ss -lntp | grep -E ':80|:443'
看:
- 配置有没有语法错误
80/443有没有真的被 Nginx 监听
第 5 步:查本机 HTTPS 是否正常
curl -vkI --resolve "status.example.com:443:127.0.0.1" "https://status.example.com"
这个命令非常硬核,价值很高。
它验证的是:
- 域名证书是否装进了 Nginx
- 本机 443 站点本身是否可用
如果这一步通,说明 Nginx 和证书八成没问题。
第 6 步:查防火墙和云安全组
如果本机 443 正常,但公网访问超时,就去查:
ufw- 云厂商安全组
这一步你已经亲手踩过一次了,以后就不会忘。
十、证书文件装上去以后,Nginx 在干什么
HTTPS 站点大概会变成这样:
server {
listen 443 ssl http2;
server_name status.example.com;
ssl_certificate /etc/letsencrypt/live/status.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/status.example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:3001;
}
}
这几行的意思其实很朴素:
listen 443 ssl:这个站点走 HTTPSssl_certificate:浏览器握手时发给对方的证书链ssl_certificate_key:和证书配套的私钥proxy_pass:TLS 解开以后,再把 HTTP 请求转给后端应用
所以 HTTPS 往往是:
浏览器
-> HTTPS 到 Nginx
-> Nginx 解密
-> HTTP 到本机后端
很多应用本身并不需要自己处理证书,这正是反代架构的好处。
十一、你现在应该彻底建立的几个判断
11.1 证书申请阶段,重点是 80 和 challenge 路径
不是先盯着 443。
11.2 本机证书正常,不代表公网一定通
因为公网还受:
- 本机防火墙
- 云安全组
影响。
11.3 challenge 失败,不一定是 Certbot 命令错了
很多时候是:
- Nginx 路由规则不对
- challenge 文件目录不对
- 80 端口没通
11.4 浏览器报 HTTPS 问题,不一定是应用有问题
先分清:
- 是证书签发失败
- 还是证书装载失败
- 还是 443 外网不通
- 还是应用反代后端挂了
这四个不是一回事。
十二、把你这几次实战串成一句完整的话
现在你前面做过的那几次部署,已经能用一句非常完整的话描述:
先让域名解析到服务器,再让 Nginx 在 80 口正确接住域名请求,给 challenge 路径留出能被 CA 访问到的静态文件入口,签发 Let’s Encrypt 证书后,再在 443 口加载证书并把 HTTPS 请求反代到本机后端应用;如果本机正常但公网超时,还要继续检查 Linux 防火墙和云安全组。
你能说出这句话,说明 HTTPS 这套逻辑已经不是“会用命令”,而是真懂了。
十三、下一步最适合继续学什么
下一课建议接:
06-专题:云服务器网络分层排障
或者更直接一点叫:
07-专题:云厂商安全组、UFW、端口监听与公网访问
因为你现在最值钱的经验,已经不只是“应用怎么部署”,而是开始真正进入:
- 请求到底卡在哪一层
- 为什么本机通但公网不通
- 怎么快速定位是 DNS、Nginx、应用、Linux 防火墙,还是云安全组
这块一旦吃透,以后排障效率会直接翻倍。

















暂无评论内容