---
背景:为什么公网开放22端口的WordPress是个定时炸弹
很多站长把WordPress直接暴漏在公网:80/443开放、后台路径/wp-admin/谁都看得见。这不是"裸奔"两个字能形容的——是"裸奔且在脸上写着快来打我"。
Cloudflare Tunnel(也叫cloudflared)的核心思路很简单:你的服务器主动连Cloudflare边缘,而不是让外面的流量主动连你。这样 22/3306/wp-admin 这些端口在公网上完全不可见,黑客想打也打不到。
但这个方案配置链条很长,涉及 cloudflared 安装、WordPress IP 检测、Zero Trust Access 策略、SSL 证书、WAF 规则 5 个环节,每个环节都有真实踩坑。我在这篇文章里全部复盘一遍。
---
架构图:Cloudflare Tunnel怎么做零端口暴露
互联网用户 → Cloudflare全球边缘(443端口)→ cloudflared隧道 → 你的VPS(仅本地端口)
关键点:你的 VPS 的 80/443 端口只允许本地的 cloudflared 连接,公网完全无法直接访问你的 WordPress。
---
踩坑一:cloudflared 安装后重启失效
问题现象
按官方文档装了 cloudflared,创建了 tunnel,配好了路由,一切正常。然后 VPS 重启了——systemctl status cloudflared 显示 failed,隧道断了。
排查过程
# 检查服务状态
systemctl status cloudflared
# 查看日志
journalctl -u cloudflared -n 50
日志里经常看到:
error="failed to create quic connection: tls: first flight did not contain a TLS certificate"
根因
cloudflared 默认会自动更新,更新后二进制文件的 hash 变了,但 systemd service 用的还是旧的启动参数,导致 binary 不兼容。
解决方案
固定版本安装(不用最新滚动版):
# 方法1:下载指定版本(推荐 2024年稳定版)
wget https://github.com/cloudflare/cloudflared/releases/download/2024.8.0/cloudflared-linux-amd64
chmod +x cloudflared-linux-amd64
sudo mv cloudflared-linux-amd64 /usr/local/bin/cloudflared
# 方法2:禁用自动更新
# 在 /etc/cloudflared/config.yml 中加:
autoupdate: false
# 方法3:用 docker 运行(重启不丢配置)
docker run -d \
--name cloudflared \
--restart unless-stopped \
-v /etc/cloudflared:/etc/cloudflared \
cloudflare/cloudflared:2024.8.0 \
tunnel run --token ${TUNNEL_TOKEN}
---
踩坑二:WordPress 评论 IP 全部显示为 127.0.0.1
问题现象
评论者的 IP 地址在 WordPress 后台全部显示为 127.0.0.1 或 Cloudflare 边缘节点 IP(如 172.71.134.x),Akismet、Wordfence 的 IP 判断全部失效。
排查过程
登录 WordPress 后台 → 评论列表 → IP 列,全是 127.0.0.1。查看单个评论详情,IP 仍然是 127.0.0.1。
检查 nginx 日志:
tail -f /var/log/nginx/access.log | grep wp-comments-post.php
所有请求的 remote_addr 都是 127.0.0.1(因为请求是 cloudflared 本地转发过来的)。
根因
cloudflared 以**反向代理**身份连接你的 origin(VPS 上的 nginx):它替你服务器连 Cloudflare 边缘,但转发给 nginx 时,remote_addr 自然就是 cloudflared 自己(127.0.0.1)。WordPress 默认读取 REMOTE_ADDR,所以拿到的是本地地址。
解决方案
方法 1:nginx 在 location 里设置 X-Real-IP(推荐)
# /etc/nginx/conf.d/cloudflare-real-ip.conf
# 必须放在 wp-admin 和 wp-login.php 的 location 之前
set_real_ip_from 172.71.128.0/20;
set_real_ip_from 172.70.80.0/20;
set_real_ip_from 172.69.0.0/20;
set_real_ip_from 172.64.0.0/20;
set_real_ip_from 172.68.0.0/20;
set_real_ip_from 172.67.0.0/20;
real_ip_header X-Forwarded-For;
real_ip_header CF-Connecting-IP; # Cloudflare 专用头
real_ip_recursive on;
方法 2:WordPress 强制信任 Cloudflare(在 wp-config.php 顶部加)
// 在 wp-config.php 最顶部加(必须加在最前面)
if (isset($_SERVER['HTTP_CF_CONNECTING_IP'])) {
$_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_CF_CONNECTING_IP'];
}
方法 3:用 Nginx Real IP 模块(生产环境推荐)
nginx 需要编译时带了 with-http_realip_module(大多数发行版默认带):
# 验证模块存在
nginx -V 2>&1 | grep -o http_realip_module
# 然后在 /etc/nginx/sites-available/your-site.conf 的 server 块里加:
real_ip_header CF-Connecting-IP;
set_real_ip_from 0.0.0.0/0; # Cloudflare 所有 IP 都信任
加完之后,WordPress 评论 IP 恢复正常,Akismet 和 Wordfence 的 IP 判断也正常了。
---
踩坑三:SSL 模式不匹配导致 526 错误
问题现象
访问网站时 Cloudflare 报 Error 526: Invalid SSL certificate,网站完全打不开。
排查过程
在 Cloudflare Dashboard → TLS → Overview 里查看 SSL 模式设置:
- **Off**:不加密(不推荐)
- **Flexible**:客户端到 Cloudflare 加密,Cloudflare 到 origin 不加密
- **Full**:加密全程,验证 origin 证书(**最常用**)
- **Full (Strict)**:全程加密 + 验证 Origin 证书是受信任 CA 签发
根因
常见踩坑有两个:
踩坑 A:Origin 用的是自签名证书,但 SSL 模式选了 Full (Strict)
# 很多人为了省事直接用自签名:
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout /etc/ssl/private/nginx-selfsigned.key \
-out /etc/ssl/certs/nginx-selfsigned.crt
然后 Cloudflare SSL 模式选了 Full (Strict) → 526。
踩坑 B:SSL 模式选 Flexible,但 cloudflared tunnel 里配置了 HTTPS 端点
Flexible 模式下 Cloudflare 到 origin 走 HTTP,不是 HTTPS。如果你 nginx 只配了 HTTPS(强制跳转),就会导致重定向循环。
解决方案
方案 A:使用 Cloudflare Origin Certificate(免费且自动续期)
# 在 Cloudflare Dashboard → TLS → Origin Server 点"创建证书"
# 下载 origin certificate(.pem)和 private key(.key)
# 把证书放到 VPS
sudo cp origin.pem /etc/ssl/certs/cloudflare-origin.pem
sudo cp private.key /etc/ssl/private/cloudflare-origin.key
# nginx 配置使用这个证书
ssl_certificate /etc/ssl/certs/cloudflare-origin.pem;
ssl_certificate_key /etc/ssl/private/cloudflare-origin.key;
# Cloudflare SSL 模式设为 Full(不是 Full Strict)
Cloudflare Origin Certificate 由 Cloudflare 自己签发,只在 Cloudflare 边缘节点连接你 origin 时有效,完全免费且自动续期。
方案 B:如果必须用自签名证书
Cloudflare SSL 模式选 Full(不是 Full Strict),然后:
# nginx 配置里加(跳过自签名证书验证,仅适用于 tunnel 场景)
proxy_ssl_verify off; # 如果用 nginx 做反向代理
---
踩坑四:Zero Trust Access 策略覆盖了整个域名
问题现象
设置了 Zero Trust Access 保护 WordPress,结果整个网站所有页面都要登录,任何访客都看到 Cloudflare Access 的登录页。
排查过程
在 Cloudflare Zero Trust → Access → Applications 里查看 Application 配置:
# 错误的配置示例:Policy 覆盖了根路径 /
SessionDuration: 24h
PolicyName: "Block all"
Match: example.com/*
这导致所有路径(静态资源、文章页面)都触发了 Access 验证。
根因
Access 策略默认按域名匹配,如果你创建 Application 时用 example.com/*,**整个域名下所有路径都需要身份验证**,包括图片/CSS/JS 等静态文件,以及已登录用户访问文章页面的正常行为。
解决方案
只保护 wp-admin 和 wp-login.php 这两个入口点:
# 正确的 Access Application 配置
ApplicationName: "WordPress Admin Protection"
SessionDuration: 8h
Policy:
- Name: "WordPress Admin Access"
Include:
- emails: ["your-email@example.com"] # 或用 IdP 集成
Action: "allow"
ForbidOtherIdentityProviders: false
# 在 "Policy" 下方设置 "App domain" 和 "Path"
AppDomain: "example.com"
Path: "/wp-admin/*"
# 再单独创建一个 Application 保护 wp-login.php
AppDomain: "example.com"
Path: "/wp-login.php*"
同时,在 nginx 配置里对这两个路径做特殊处理(仅允许 Cloudflare IP 访问):
location ~ ^/(wp-admin|wp-login\.php) {
# 只允许 Cloudflare IP 访问
allow 172.71.0.0/20;
allow 172.70.0.0/20;
allow 172.69.0.0/20;
allow 172.68.0.0/20;
allow 172.67.0.0/20;
allow 172.64.0.0/20;
deny all;
# 正常代理
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
这样公开文章页面完全不受影响,只有管理员访问 /wp-admin/ 时才需要通过 Cloudflare Access 认证。
---
踩坑五:WAF 规则把 Cloudflare 隧道流量当攻击拦截
问题现象
安装了 ModSecurity + OWASP CRS 后,WordPress 后台完全打不开(504/403 错误),但关掉 WAF 就正常。Cloudflare 的 ModSecurity 日志里大量 Rule 920350(Protocol compliance check)误报。
排查过程
查看 ModSecurity 审计日志:
tail -f /var/log/modsec_audit.log | grep "920350"
发现触发的是这条规则:
[file "/etc/modsecurity.d/owasp-crs/rules/RESPONSE-951-DATA-LEAKAGES.conf"]
[id "951200"] [msg "Cross-site Scripting (XSS) Attack"]
Cloudflare 隧道过来的 HTTP 请求头里包含了一些 WAF 认为可疑的字符(如 URL 里的 Base64 编码参数),被误判为 XSS 攻击。
根因
OWASP CRS 的误报问题在隧道场景下特别明显,因为:
1. Cloudflare 边缘在转发请求时可能会修改/添加一些 header(如 CF-RAY、CF-Cache-Status)
2. 隧道流量的 TLS 握手信息与普通直连流量不同
3. 某些 ModSecurity 规则对 URL 编码字符过于敏感
解决方案
方法 1:在 ModSecurity 配置里白名单 Cloudflare IP(推荐)
# /etc/modsecurity.d/modsecurity.conf 或在 crs-setup.conf 里加
# 白名单 Cloudflare 所有 IP 段(最新 IP 范围见 https://www.cloudflare.com/ips/)
SecRule REMOTE_ADDR "@ipMatch 172.71.0.0/20" \
"id:90001,phase:1,pass,nolog,ctl:ruleRemoveById=920350-921100"
SecRule REMOTE_ADDR "@ipMatch 172.70.0.0/20" \
"id:90002,phase:1,pass,nolog,ctl:ruleRemoveById=920350-921100"
SecRule REMOTE_ADDR "@ipMatch 172.69.0.0/20" \
"id:90003,phase:1,pass,nolog,ctl:ruleRemoveById=920350-921100"
方法 2:降低 Paranoia Level(如果不想逐条白名单)
# 在 /etc/modsecurity.d/crs/crs-setup.conf 里改:
SecAction \
"id:900004,\
phase:1,\
pass,\
t:none,\
setvar:tx.paranoia_level=1"
PL1(低偏执级别)比 PL3 少了很多高误报规则,适合内部服务或 IP 已知的场景。
方法 3:用 Cloudflare 自己的 WAF 替代 ModSecurity(最省事)
Cloudflare 本身就有 WAF 功能(免费版就够用),不需要在 VPS 上再装一层。如果用了 Cloudflare Tunnel,可以把 ModSecurity 完全关掉:
# 关掉 ModSecurity
sudo systemctl stop modsecurity
sudo systemctl disable modsecurity
# 在 Cloudflare Dashboard → Security → WAF → Managed rules
# 开启 "Cloudflare Managed Ruleset"
# 对 WordPress 路径添加自定义规则:
# IF (URI contains "wp-admin") THEN → 启动 "Cloudflare WordPress ruleset"
---
验证方案:配置完成后怎么测试
1. 检查端口是否真的不可达
# 从外部 VPS 测试(用手机热点或其他网络)
nc -zv yourdomain.com 22
nc -zv yourdomain.com 3306
# 应该显示 "Connection refused" 或超时
# 如果显示 "Open",说明端口仍然暴露
2. 测试 WordPress IP 检测是否正常
# 在 WordPress 目录下创建一个测试脚本
cat > /var/www/html/test-ip.php << 'EOF'
3. 验证 Zero Trust Access 策略
# 用隐私模式访问 wp-admin,应该被重定向到 Cloudflare Access 登录页
curl -I https://yourdomain.com/wp-admin/
# 应该看到 302 重定向到 Cloudflare Access 页面
---
相关配置快速命令清单
# 1. 安装 cloudflared
wget https://github.com/cloudflare/cloudflared/releases/download/2024.8.0/cloudflared-linux-amd64
chmod +x cloudflared-linux-amd64 && sudo mv cloudflared-linux-amd64 /usr/local/bin/cloudflared
# 2. 创建 tunnel
cloudflared tunnel create wordpress-tunnel
cloudflared tunnel route dns wordpress-tunnel yourdomain.com
# 3. 配置 nginx real IP(加在 /etc/nginx/conf.d/cloudflare-real-ip.conf)
# 见踩坑二详细配置
# 4. WordPress wp-config.php 顶部加 IP 修复
# 见踩坑二详细代码
# 5. Cloudflare Origin Certificate(免费)
# 在 Cloudflare Dashboard → TLS → Origin Server 创建
# 6. Zero Trust Access 只保护 wp-admin 和 wp-login.php
# 见踩坑四详细配置
---
总结
Cloudflare Tunnel 是 WordPress 零端口暴露的最佳方案,但配置链条长,每个环节都有真实踩坑:
1. cloudflared 自动更新导致重启失效 → 固定版本或用 Docker
2. WordPress IP 判断失效(评论全是127) → nginx real_ip 模块 + wp-config.php 修复
3. SSL 526错误 → 用 Cloudflare Origin Certificate,SSL 模式选 Full
4. Zero Trust Access 覆盖整个域名 → 只保护 wp-admin 和 wp-login.php 两个入口
5. ModSecurity WAF 误拦隧道流量 → 白名单 Cloudflare IP 或直接用 Cloudflare WAF
---
👉 立即参与:https://platform.minimaxi.com/subscribe/token-plan?code=E5yur9NOub&source=link
---
关联阅读:
📌 本文由 AI 辅助生成并经人工审核发布 | TechPassive — AI 驱动的内容测试站点,专注于效率工具与 SaaS 真实评测
🔗 精选推荐工具
使用以下链接支持我们持续产出高质量内容(点击可直接前往购买):