将 Cloudflare 记录切换为 DNS Only
后,请求会直接到达源站,浏览器也会直接校验源站证书。要在
8443 等非标准端口上提供可信 HTTPS,只需通过 DNS-01 签发
Let’s Encrypt 证书,并由 Nginx 加载。
DNS-01 不依赖 80/443
端口,也不需要临时自签名证书。本文按 签发证书 → 配置 Nginx →
验证源站 → 切换 DNS 的顺序操作。
DNS Only 仅使用 Cloudflare 权威 DNS。源站 IP
将公开,CDN、WAF、Cloudflare Access
等代理能力也会失效。备案和网络接入要求请遵守当地法规及云厂商规则。
一、原理与准备
切换后的链路如下:
1 2
| 用户 → 源站:8443 → Nginx → 本地服务 Let’s Encrypt 证书
|
证书绑定域名而非端口,因此可用于 8443。DNS 只解析
IP,访问时仍需显式指定端口:
1
| https://api1.example.com:8443/
|
本文以腾讯云
Ubuntu/Debian、两个域名和两个本地服务为例。先替换以下变量:
1 2 3 4 5 6 7
| DOMAIN1=api1.example.com DOMAIN2=api2.example.com ORIGIN_IP=203.0.113.10 HTTPS_PORT=8443 NGINX_FILE=/etc/nginx/conf.d/example.conf EMAIL=admin@example.com CF_CREDENTIALS=/root/.secrets/certbot/cloudflare.ini
|
203.0.113.10 是文档示例地址,必须替换为源站公网 IP。
安装依赖:
1 2
| sudo apt update sudo apt install -y nginx certbot python3-certbot-dns-cloudflare
|
在腾讯云安全组中放行源站 TCP 8443;若启用了
UFW,再执行:
最终由浏览器直连,安全组不能只允许 Cloudflare IP。使用公网 IPv6
时,还需同步配置 IPv6 防火墙、Nginx 监听和 AAAA 记录。
二、签发 Let’s Encrypt 证书
1. 配置 Cloudflare API Token
进入 Cloudflare API Tokens → Create Token,使用
Edit zone DNS 模板,并将权限限制为目标 Zone 的
DNS: Edit。不要使用 Global API Key。
创建 Certbot 凭据文件:
1 2 3 4
| sudo install -d -m 700 /root/.secrets/certbot sudo touch "$CF_CREDENTIALS" sudo chmod 600 "$CF_CREDENTIALS" sudoedit "$CF_CREDENTIALS"
|
写入:
1
| dns_cloudflare_api_token = YOUR_CLOUDFLARE_API_TOKEN
|
该文件用于自动续期,不要提交到仓库或在签发后删除。
2. 签发证书
1 2 3 4 5 6 7 8
| for DOMAIN in "$DOMAIN1" "$DOMAIN2"; do sudo certbot certonly \ --dns-cloudflare \ --dns-cloudflare-credentials "$CF_CREDENTIALS" \ --dns-cloudflare-propagation-seconds 60 \ --cert-name "$DOMAIN" -d "$DOMAIN" \ --email "$EMAIL" --agree-tos --non-interactive done
|
每个域名单独签发,便于续期和排错。DNS-01
可在记录仍为橙色云时完成,不会中断现有代理流量。
三、配置 Nginx
编辑配置:
以下示例将两个域名分别转发到本地 11025 和
11026:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| server { listen 8443 ssl; server_name api1.example.com;
ssl_certificate /etc/letsencrypt/live/api1.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/api1.example.com/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3;
client_max_body_size 50M;
location / { proxy_pass http://127.0.0.1:11025; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } }
server { listen 8443 ssl; server_name api2.example.com;
ssl_certificate /etc/letsencrypt/live/api2.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/api2.example.com/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3;
client_max_body_size 50M;
location / { proxy_pass http://127.0.0.1:11026; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } }
|
如无需 WebSocket,可删除 Upgrade 和
Connection 两行。加载配置:
1
| sudo nginx -t && sudo systemctl reload nginx
|
四、验证源站并切换 DNS
切换前使用 --resolve 绕过当前 DNS,直接验证源站、SNI
和证书:
1 2 3 4 5 6 7
| for DOMAIN in "$DOMAIN1" "$DOMAIN2"; do curl --noproxy '*' --connect-timeout 10 \ --resolve "${DOMAIN}:${HTTPS_PORT}:${ORIGIN_IP}" \ -sS -o /dev/null \ -w "domain=${DOMAIN} HTTP=%{http_code} remote=%{remote_ip} TLS=%{ssl_verify_result}\n" \ "https://${DOMAIN}:${HTTPS_PORT}/" done
|
确认 remote 为源站 IP、TLS=0,且 HTTP
状态符合应用预期。不要使用 -k,否则无法验证证书。
若源站只允许 Cloudflare IP,或启用了 Authenticated Origin
Pulls、Cloudflare Access
等边缘鉴权,应先调整限制,否则浏览器无法直连。
验证通过后,在 Cloudflare DNS → Records
中将记录改为灰色云:
| A |
api1 |
源站公网 IPv4 |
DNS only |
| A |
api2 |
源站公网 IPv4 |
DNS only |
没有公网 IPv6 时,应删除对应的 AAAA 记录。等待 DNS
缓存更新后,即可访问:
1 2
| https://api1.example.com:8443/ https://api2.example.com:8443/
|
DNS 无法将 443 自动映射到
8443。如需省略端口,入口服务必须监听 443。
五、自动续期
创建 deploy hook,使 Nginx 在证书续期后自动重载:
1 2 3 4 5 6 7 8 9
| sudo install -d -m 755 /etc/letsencrypt/renewal-hooks/deploy sudo tee /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh >/dev/null <<'EOF'
nginx -t && systemctl reload nginx EOF sudo chmod 755 /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh
sudo systemctl enable --now certbot.timer sudo certbot renew --dry-run --run-deploy-hooks
|
保留 Cloudflare 凭据文件及 Token;修改 Token 后需同步更新文件。
参考资料