← 返回文章列表 专栏:网络与容器架构

更新于

Web 网络与 HTTPS 部署笔记:DNS 解析、TCP BBR 调优与 TLS 1.3 证书自动续期

从浏览器输入域名到建立安全连接,梳理 DNS A/AAAA/CAA 记录配置、Linux 内核 TCP BBR 拥塞控制开启方法,以及 acme.sh 自动签发 ECC 证书。

DNS 权威解析、TCP 三次握手与 BBR 拥塞控制、TLS 1.3 证书自动续期
DNS 权威解析、TCP 三次握手与 BBR 拥塞控制、TLS 1.3 证书自动续期

当用户在浏览器访问站点域名时,底层依次经历 DNS 权威解析、TCP 三次握手、TLS 密钥协商与 HTTP 报文传输四个阶段。其中任一环节配置不当,都会表现为首屏加载缓慢或证书报错。

本文记录域名 DNS 记录配置、dig 解析排查、Linux 内核开启 TCP BBR 拥塞控制,以及使用 acme.sh 申请和自动续期 Let's Encrypt ECC 证书的步骤。

DNS 域名解析:建站常用的 5 类记录

在 Cloudflare、阿里云或 DNSPod 托管域名(例如 example.com)时,建站主要涉及以下 5 种记录类型:

DNS 权威解析、TCP BBR 三次握手与 TLS 1.3 1-RTT 加密传输全链路时序图
HTTPS 请求全链路时序:从 DNS 权威记录解析、TCP 三次握手(启用 BBR 拥塞控制)到 TLS 1.3 1-RTT 密钥协商与证书自动续期。
记录类型 主机记录 (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
2
3
4
5
6
7
8
9
10
11
# Ubuntu / Debian 安装 dnsutils 工具包(提供 dig 与 nslookup)
sudo apt-get update && sudo apt-get install -y dnsutils

# 1. 查询当前系统默认 DNS 返回的结果
dig +short example.com A

# 2. 绕过本机缓存,指定向 Cloudflare (1.1.1.1) 或阿里 (223.5.5.5) 查询
dig @223.5.5.5 example.com A +noall +answer

# 3. 追踪从根域名服务器 (.) -> 顶级域 (.com) -> 权威 DNS 的解析链条
dig +trace example.com A

TCP 三次握手、端口状态与 BBR 拥塞控制

浏览器拿到服务器 IP(如 203.0.113.10)后,会向服务器的 80(HTTP)或 443(HTTPS)端口发起 TCP 三次握手:

  1. 客户端 $\rightarrow$ 服务端(SYN):客户端发送同步序列号包 SYN (seq=x),请求建立连接。
  2. 服务端 $\rightarrow$ 客户端(SYN + ACK):服务端内核确认端口有进程监听(如 Nginx),回复 SYN+ACK (seq=y, ack=x+1)。
  3. 客户端 $\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
2
3
4
5
# 在服务器上核查 80 与 443 端口被哪个进程监听、绑定在哪个地址上
sudo ss -lntp | grep -E ':(80|443)\b'

# 正常输出示例(0.0.0.0:443 代表所有 IPv4 网卡均可访问):
# LISTEN 0 511 0.0.0.0:443 0.0.0.0:* users:(("nginx",pid=1204,fd=6))

2. 开启 Linux 内核 TCP BBR 拥塞控制算法

启用 Linux 内核自带的 TCP BBR 拥塞控制算法,可以改善跨运营商或高丢包链路下的吞吐与响应延迟:

1
2
3
4
5
6
7
8
9
10
11
# 写入内核参数配置文件(Ubuntu 24.04 内核已内置 tcp_bbr 模块)
sudo tee /etc/sysctl.d/99-blog-network.conf >/dev/null <<'EOF'
net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr
net.ipv4.tcp_fastopen = 3
EOF

# 加载生效并核验当前拥塞控制算法
sudo sysctl --system
sysctl net.ipv4.tcp_congestion_control
# 输出:net.ipv4.tcp_congestion_control = 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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 1. 安装 acme.sh(将邮箱替换为接收证书到期提醒的邮箱)
curl https://get.acme.sh | sh -s email=ops@example.com
source ~/.bashrc

# 2. 切换默认 CA 为 Let's Encrypt
~/.acme.sh/acme.sh --set-default-ca --server letsencrypt

# 3. 通过 DNS API 验证并签发主域名 + 泛域名 ECC 证书(以 Cloudflare 为例)
export CF_Token="你的_Cloudflare_DNS_Edit_API_Token"
export CF_Account_ID="你的_Cloudflare_Account_ID"
~/.acme.sh/acme.sh --issue --dns dns_cf -d example.com -d "*.example.com" --keylength ec-256

# 4. 将签发好的证书安装到持久化目录,并配置续期后自动通知 Nginx 重载
sudo mkdir -p /etc/nginx/ssl/example.com
~/.acme.sh/acme.sh --install-cert -d example.com --ecc \
--key-file /etc/nginx/ssl/example.com/privkey.pem \
--fullchain-file /etc/nginx/ssl/example.com/fullchain.pem \
--reloadcmd "docker exec blog-nginx nginx -s reload"

注意:不要直接把 Nginx 的 ssl_certificate 指向 ~/.acme.sh/ 内部目录(其内部结构可能随版本调整)。应使用 --install-cert 将证书复制到 /etc/nginx/ssl/...,acme.sh 每 60 天通过 crontab 自动续期后会覆盖目标文件并执行 --reloadcmd 重载 Nginx。


使用 curl 与 openssl 诊断各阶段耗时

站点上线后,可以用 curl 的格式化输出测量 DNS 解析、TCP 握手、TLS 握手、首字节响应(TTFB)与总耗时:

1
2
3
4
5
6
7
# 测量 HTTPS 请求各阶段耗时
curl -o /dev/null -s -w \
"DNS解析: %{time_namelookup}s\nTCP握手: %{time_connect}s\nTLS握手: %{time_appconnect}s\n首字节(TTFB): %{time_starttransfer}s\n总耗时: %{time_total}s\nHTTP状态码: %{http_code}\n" \
https://example.com/

# 检查线上证书有效期、签发机构与协议版本
echo | openssl s_client -servername example.com -connect example.com:443 2>/dev/null | openssl x509 -noout -dates -issuer -subject

常见网络与证书故障排查表

故障现象 诊断命令 原因与处理方式
新配的域名打不开,提示 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