在 VPS 上搭建 TLS 伪装站点的小记

最近在研究 TLS 协议的 SNI(Server Name Indication)扩展机制时,产生了一个想法:能不能在自己的 VPS 上搭建一个拥有合法 TLS 证书的站点,让外部看起来就是一个普通的个人博客?

经过几天的折腾,我使用 Caddy + Docker 的方案完成了搭建。本文记录完整过程,供有同样需求的朋友参考。

为什么选择 Caddy

传统的方案是用 Nginx + Certbot 手动申请 Let's Encrypt 证书,但 Certbot 需要定期续签,配置也比较繁琐。Caddy 的最大优势是自动 HTTPS——它内置了 ACME 客户端,会在启动时自动向 Let's Encrypt 申请证书,并在证书即将过期时自动续签,完全不需要人工干预。

对比一下两种方案的配置复杂度:

特性 Nginx + Certbot Caddy
自动申请证书 需要手动运行 certbot 内置自动
自动续签 需要配置 cron 内置自动
配置文件 约 30 行 约 5 行
HTTP→HTTPS 跳转 需要手动配置 内置自动

环境准备

我使用的是一台日本 VPS,系统为 Ubuntu 22.04。你需要准备:

  • 一个域名(建议使用子域名,如 blog.example.com
  • 一台有公网 IP 的 VPS
  • 已安装 Docker 和 Docker Compose

DNS 配置

在域名 DNS 管理处添加一条 A 记录,将子域名指向 VPS 的公网 IP。如果你使用 Cloudflare 管理 DNS,请确保代理状态为"仅 DNS"(灰色云朵),否则流量会经过 Cloudflare CDN,Caddy 无法完成 ACME 验证。

Caddy 配置文件

Caddy 的配置文件叫 Caddyfile,语法非常简洁:

blog.example.com {
    tls your-email@example.com
    root * /usr/share/caddy
    file_server
}

只需把域名和邮箱替换成你自己的即可。tls 指令后面的邮箱是 Let's Encrypt 用于账户注册和到期提醒的。

Docker Compose 部署

使用 Docker 部署是最省心的方式,不需要在宿主机上安装 Caddy:

version: '3.8'

services:
  caddy:
    image: caddy:alpine
    container_name: my-site
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - ./site:/usr/share/caddy:ro
      - caddy_data:/data
    restart: unless-stopped

volumes:
  caddy_data:

启动后,Caddy 会自动完成以下操作:

  1. 监听 80 端口,响应 ACME HTTP-01 验证请求
  2. 向 Let's Encrypt 发起证书申请
  3. 获取证书后,自动启用 443 端口的 HTTPS
  4. 配置 HTTP→HTTPS 自动跳转

验证结果

容器启动后,可以通过以下命令查看日志,确认证书是否签发成功:

docker logs my-site 2>&1 | grep certificate

如果看到 certificate obtained successfully 字样,说明一切正常。在浏览器中访问 https://blog.example.com,应该能看到你的站点,并且地址栏显示安全锁标志。

常见问题

证书签发失败

最常见的原因是 80 端口不可达。请检查:

  • VPS 防火墙是否放行了 80 和 443 端口
  • 云服务商安全组是否放行了 80 和 443 端口
  • DNS 是否已正确指向 VPS IP
  • 如果用了 Cloudflare,是否关闭了代理(灰色云朵)

端口被占用

如果 VPS 上已经运行了 Nginx 或 Apache,80/443 端口会被占用。你需要先停止这些服务,或者修改 Caddy 的监听端口(但不建议,因为标准 HTTPS 需要 443)。


整个搭建过程不到 10 分钟,Caddy 的自动 HTTPS 功能确实大大简化了 TLS 站点的部署流程。如果你也有类似需求,强烈推荐试试这个方案。

有任何问题欢迎在评论区讨论,或者发邮件到 linyi@example.com

TLS Caddy VPS