FieryWing 的技术博客

HTTPS 与证书:浏览器那把小锁背后

2026-05-17

HTTPS 就是在 HTTP 之下加了一层 TLS 加密,目的有三个:内容不被窃听、不被篡改、确认对方就是你要访问的网站。

为什么一定要上 HTTPS

早期的 HTTP 是明文传输的,同一个网络里的人理论上能看到你提交的表单,中间设备甚至能往页面里插内容。HTTPS 解决的就是这件事。现在主流浏览器会把没有 HTTPS 的页面标为“不安全”,很多新的浏览器功能也只在 HTTPS 下可用。对个人博客来说,部署 HTTPS 的成本已经很低,没有理由不做。

TLS 握手的大致过程

  1. 客户端发起连接,告诉服务器自己支持的 TLS 版本和加密套件。
  2. 服务器选定参数,并把自己的证书发给客户端。
  3. 客户端校验证书:是否由受信任的 CA 签发、域名是否匹配、是否在有效期内。
  4. 双方通过密钥交换协商出一把只有彼此知道的会话密钥。
  5. 之后的数据都用这把会话密钥加密传输。

可以这样理解:证书用来证明“你是谁”,密钥交换用来解决“怎么安全地约定密码”,对称加密用来负责“高效地传数据”。三者各司其职。

证书怎么来的

网站向证书颁发机构(CA)申请证书,CA 验证你确实控制这个域名后签发。浏览器内置了受信任的 CA 列表,用它来校验网站出示的证书。

证书里主要包含:域名(现在以 SAN 字段为准)、公钥、有效期、签发者和签名。实际部署中,服务器通常还要提供“中间证书”,组成一条从站点证书到受信任根证书的证书链,缺了中间证书,一些客户端就会报错。

免费且自动:Let's Encrypt

Let's Encrypt 提供免费证书,有效期较短,需要自动续期。Caddy、certbot 等工具可以自动申请和续期。以 Caddy 为例,只要域名已解析到服务器,且 80/443 端口可访问,在配置里写上站点域名就会自动启用 HTTPS。

用 Caddy 的最小配置

在 Debian 或 Ubuntu 上,Caddy 的配置文件通常是 /etc/caddy/Caddyfile。一个托管静态博客的最小例子:

example.com, www.example.com {
    root * /var/www/blog
    file_server
    encode gzip
}

修改后先检查再重载:

sudo caddy validate --config /etc/caddy/Caddyfile
sudo systemctl reload caddy
sudo journalctl -u caddy --no-pager -n 50

最后一条可以查看最近日志,申请证书的成功或失败原因都在这里。更多写法见 Caddy 一文。

用 certbot 的做法

如果你用的是 Nginx,可以用 certbot。在 Debian 或 Ubuntu 上:

sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d example.com -d www.example.com
sudo certbot renew --dry-run

第三条是模拟续期,用来确认自动续期流程没有问题,建议安装后一定执行一次。系统通常会通过定时任务或 systemd 定时器自动执行续期,可以用 systemctl list-timers 查看是否存在 certbot 相关的计时器。

申请证书前的准备清单

常见问题

进一步排查

怀疑证书有问题时,我会先用下面的命令看证书的主题、签发者和有效期:

openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null | openssl x509 -noout -subject -issuer -dates

其中 -servername 很重要,它告诉服务器要访问哪个域名,一台服务器托管多个站点时缺了它会拿到默认证书。也可以用 curl -vI https://example.com 查看握手和响应头。

浏览器里常见的报错也各有含义:证书域名不匹配,说明证书里没有你访问的这个域名;证书已过期,说明续期失败;不受信任的颁发者,可能是缺少中间证书,或使用了自签名证书。自签名证书只适合内部测试,不要用在对外的站点上。

几个容易踩的坑

HSTS 是什么

HSTS 是一个响应头,告诉浏览器在一段时间内只能用 HTTPS 访问本站,防止被降级到 HTTP。启用前要确认 HTTPS 稳定可用,因为一旦设置了较长的有效期,证书出问题时用户将无法通过点击“继续访问”绕过,请谨慎使用较长的时间。

和 SSH 的关系

HTTPS 保护的是访问网站的流量,管理服务器用的 SSH 是另一套加密通道,二者互不替代。服务器的远程登录安全见 SSH 安全加固,机器的基础配置见 VPS 入门。

TLS 版本与加密套件的选择

现代的 TLS 版本有 1.2 和 1.3,更老的 SSL 以及 TLS 1.0、1.1 已被淘汰。Caddy 默认配置已经比较合理,通常不需要改。如果你使用 Nginx,可以参考 Mozilla 提供的 SSL 配置生成器,选择与自己客户端范围匹配的方案,不要凭印象随手拼凑加密套件。除非有明确的兼容性需求,否则不要为了支持极老的设备而降低整体安全水平。

通配符证书与 DNS 验证

普通的 HTTP 验证要求域名解析到服务器并能访问 80 端口。如果你想要一张覆盖 *.example.com 的通配符证书,通常需要使用 DNS 验证:在域名下添加指定的 TXT 记录来证明所有权。这种方式不要求开放 80 端口,也适合内网服务,但需要 DNS 服务商提供 API 或手动添加记录,自动续期时还要配合对应的插件,具体用法请看所用工具的文档,这里不展开。

上线后的检查清单

  1. 用浏览器访问 https 地址,点击小锁确认证书信息与域名一致。
  2. 访问 http 地址,确认会自动跳转到 https。
  3. 打开浏览器开发者工具的控制台,检查是否有混合内容警告。
  4. 确认续期机制存在:Caddy 看日志,certbot 看 systemctl list-timers。
  5. 在日历里记下证书有效期,作为自动续期失效时的最后保险。

总结

HTTPS 通过证书确认身份,通过 TLS 加密传输。免费证书加上自动续期,让个人站点部署它变得很简单。真正容易出问题的地方往往不是加密本身,而是域名解析、端口放行、证书链、续期和混合内容。遇到问题时,沿着“解析是否正确、端口是否能通、日志怎么说、证书长什么样”这条线逐步排查,基本都能找到原因。