当用户在浏览器访问站点域名时,底层依次经历 DNS 权威解析、TCP 三次握手、TLS 密钥协商与 HTTP 报文传输四个阶段。其中任一环节配置不当,都会表现为首屏加载缓慢或证书报错。
本文记录域名 DNS 记录配置、dig 解析排查、Linux 内核开启 TCP BBR 拥塞控制,以及使用 acme.sh 申请和自动续期 Let's Encrypt ECC 证书的步骤。
DNS 域名解析:建站常用的 5 类记录
在 Cloudflare、阿里云或 DNSPod 托管域名(例如 example.com)时,建站主要涉及以下 5 种记录类型:
| 记录类型 | 主机记录 (Name) |
记录值 (Value) 示例 |
TTL 建议 | 作用与配置说明 |
|---|---|---|---|---|
A |
@ 或 blog |
203.0.113.10 |
300s ~ 600s |
将主域名(example.com)或子域名指向云服务器的 IPv4 公网地址 |
AAAA |
@ 或 blog |
2001:db8::1 |
300s ~ 600s |
将域名指向云服务器的 IPv6 公网地址;若服务器未配置 IPv6 监听则不要添加,否则双栈客户端会优先尝试 IPv6 导致连接超时 |
CNAME |
www |
example.com. |
600s ~ 3600s |
将别名域名指向另一个域名(或 CDN 提供的加速域名) |
CAA |
@ |
0 issue "letsencrypt.org" |
3600s |
声明仅允许指定 CA 机构(如 Let's Encrypt)为该域名签发证书 |
TXT |
_acme-challenge |
X9kL2mP... |
120s |
用于申请通配符证书(*.example.com)时的 DNS-01 域名所有权校验,或配置邮件 SPF/DKIM |
使用 dig 绕过本地缓存核验 DNS 记录
修改 DNS 记录后,本机 ping 出来的往往还是旧 IP,因为操作系统、路由器和运营商 Local DNS 都会按 TTL(Time To Live)缓存旧记录。
排查 DNS 时,可用 dig 命令直接向公共递归 DNS 或权威名称服务器发起查询:
1 | # Ubuntu / Debian 安装 dnsutils 工具包(提供 dig 与 nslookup) |
TCP 三次握手、端口状态与 BBR 拥塞控制
浏览器拿到服务器 IP(如 203.0.113.10)后,会向服务器的 80(HTTP)或 443(HTTPS)端口发起 TCP 三次握手:
- 客户端 $\rightarrow$ 服务端(
SYN):客户端发送同步序列号包SYN (seq=x),请求建立连接。 - 服务端 $\rightarrow$ 客户端(
SYN + ACK):服务端内核确认端口有进程监听(如 Nginx),回复SYN+ACK (seq=y, ack=x+1)。 - 客户端 $\rightarrow$ 服务端(
ACK):客户端回复确认包ACK (ack=y+1),TCP 连接建立(耗时 1 个往返时延1 RTT)。
1. 区分 Connection timed out 与 Connection refused
部署站点后如果打不开网页,用 curl -v 测试时最常遇到以下两种报错,排查方向不同:
- 现象 A:
Connection timed out(连接超时)- 原因:客户端发出的
SYN包在途中被丢弃(DROP),没有收到回包,直到等待超时。 - 排查位置:检查云厂商控制台的「安全组」或服务器上的
ufw防火墙是否放行了80/443端口,以及服务器公网 IP 是否填写正确。
- 原因:客户端发出的
- 现象 B:
Connection refused(连接被拒绝)- 原因:客户端的
SYN包已经穿过安全组和防火墙到达服务器内核,但内核发现当前没有进程监听443端口,立即返回RST(Reset)包拒绝连接。 - 排查位置:防火墙是通的,问题在于 Nginx 或 Docker 容器未启动,或者容器端口映射写成了
-p 127.0.0.1:443:443(仅监听本机回环而未监听公网网卡)。
- 原因:客户端的
1 | # 在服务器上核查 80 与 443 端口被哪个进程监听、绑定在哪个地址上 |
2. 开启 Linux 内核 TCP BBR 拥塞控制算法
启用 Linux 内核自带的 TCP BBR 拥塞控制算法,可以改善跨运营商或高丢包链路下的吞吐与响应延迟:
1 | # 写入内核参数配置文件(Ubuntu 24.04 内核已内置 tcp_bbr 模块) |
TLS 1.3 加密配置与 ACME 证书自动签发续期
现代浏览器会将未配置 HTTPS 的站点标记为“不安全”,且 HTTP/2 多路复用与 navigator.clipboard(代码块复制)等 Web API 均要求在安全上下文(HTTPS)下运行。
1. 启用 TLS 1.3 的优势
- 握手耗时更短(1-RTT):TLS 1.2 需要 2 次网络往返(2-RTT)完成密钥协商;TLS 1.3 将密钥交换与
ClientHello合并,只需 1-RTT 即可开始传输应用层数据。 - 前向安全性(Forward Secrecy):TLS 1.3 移除了静态 RSA 密钥传输,默认使用临时椭圆曲线迪菲-赫尔曼(
ECDHE)算法。即使日后服务器私钥泄露,也无法解密此前抓包记录的加密流量。
2. 使用 acme.sh 申请并自动续期 Let's Encrypt 证书
相比依赖 Python 环境的 certbot,基于 Shell 的 acme.sh 无额外运行时依赖,支持主流 DNS 服务商 API 自动续期:
1 | # 1. 安装 acme.sh(将邮箱替换为接收证书到期提醒的邮箱) |
注意:不要直接把 Nginx 的
ssl_certificate指向~/.acme.sh/内部目录(其内部结构可能随版本调整)。应使用--install-cert将证书复制到/etc/nginx/ssl/...,acme.sh每 60 天通过crontab自动续期后会覆盖目标文件并执行--reloadcmd重载 Nginx。
使用 curl 与 openssl 诊断各阶段耗时
站点上线后,可以用 curl 的格式化输出测量 DNS 解析、TCP 握手、TLS 握手、首字节响应(TTFB)与总耗时:
1 | # 测量 HTTPS 请求各阶段耗时 |
常见网络与证书故障排查表
| 故障现象 | 诊断命令 | 原因与处理方式 |
|---|---|---|
新配的域名打不开,提示 NXDOMAIN |
dig @8.8.8.8 example.com A |
域名未添加 A 记录,或刚修改 NS 服务器尚未完成同步 |
curl 等待后报错 Connection timed out |
检查云控制台安全组 + sudo ufw status |
云厂商安全组或宿主机防火墙未放行 80/tcp 与 443/tcp |
| 证书续期后浏览器仍显示旧证书 | docker exec blog-nginx nginx -s reload |
磁盘证书文件已更新,但 Nginx Worker 内存仍使用旧证书,需执行 reload |
| 电脑访问正常,部分移动端报证书链不完整 | 检查 ssl_certificate 配置项 |
Nginx 需指向包含中间证书的 fullchain.pem,而非单张域名证书 cert.pem |