POST
WAF 反代架构完整搭建指南
涵盖:雷池 WAF × 宝塔 Nginx × Docker 容器 × WordPress 的完整链路配置
概述
本指南描述的生产环境架构为:
用户 ──HTTPS──→ 雷池 WAF (防火墙/SSL) ──HTTP──→ 宝塔 Nginx (反代) ──HTTP──→ Docker 容器 (应用)
为什么要三层架构?
| 层 | 职责 | 典型工具 |
|---|
| WAF | SSL 证书、Web 防火墙、DDoS 防护 | 雷池 SafeLine |
| 反代 | 站点管理、静态资源、端口转发 | 宝塔 Nginx |
| 容器 | 应用运行环境隔离 | Docker Compose |
WAF 对外暴露 HTTPS,对内用 HTTP 转发给后端。这样证书只需挂在 WAF 一层,后端无需处理 SSL。
一、Docker 安装
1.1 安装 Docker
# Ubuntu / Debian
curl -fsSL https://get.docker.com | bash -s docker
# 验证
docker --version
docker compose version
1.2 Docker Compose 项目结构
以 WordPress 为例:
~/www/yogsothoth.top/
├── docker-compose.yml
├── .env
├── nginx/ # (可选) 如果不走宝塔,用 Nginx 容器
│ └── default.conf
└── wordpress/ # WordPress 数据持久化
└── wp-content/
1.3 docker-compose.yml 示例
version: '3.8'
services:
wordpress:
image: wordpress:6-php8.2-apache
container_name: wp_yogsothoth
restart: always
ports:
- "127.0.0.1:8080:80" # 只监听本地,不暴露公网
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: ${DB_USER}
WORDPRESS_DB_PASSWORD: ${DB_PASSWORD}
WORDPRESS_DB_NAME: ${DB_NAME}
WORDPRESS_CONFIG_EXTRA: |
define('WP_HOME', 'https://yogsothoth.top');
define('WP_SITEURL', 'https://yogsothoth.top');
define('FORCE_SSL_ADMIN', true);
if (strpos(\$_SERVER['HTTP_X_FORWARDED_PROTO'], 'https') !== false) {
\$_SERVER['HTTPS'] = 'on';
}
volumes:
- ./wordpress:/var/www/html
depends_on:
- db
db:
image: mysql:8.0
container_name: wp_db
restart: always
ports:
- "127.0.0.1:3307:3306" # 暴露不同端口避免冲突
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ${DB_NAME}
MYSQL_USER: ${DB_USER}
MYSQL_PASSWORD: ${DB_PASSWORD}
TZ: Asia/Shanghai
command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
volumes:
- db_data:/var/lib/mysql
volumes:
db_data:
1.4 .env 文件
DB_NAME=wordpress
DB_USER=wp_user
DB_PASSWORD=你的密码
MYSQL_ROOT_PASSWORD=你的root密码
⚠️ .env 包含敏感信息,记得 chmod 600 .env
二、WAF(雷池)安装与配置
2.1 安装雷池 WAF
官方文档:https://docs.safeline.cn/
# 一键安装(需要一台独立机器或同一台机器的独立端口)
bash -c "$(curl -fsSLk https://waf.chaitin.com/release/latest/setup.sh)"
安装后雷池会占用以下端口:
| 端口 | 用途 |
|---|
| 9443 | 管理后台(HTTPS) |
| 80 / 443 | WAF 监听入口(用户访问用) |
2.2 在雷池中添加站点
进入雷池管理后台 → 站点管理 → 添加站点:
| 字段 | 填写 |
|---|
| 域名 | yogsothoth.top |
| 上游服务器 | http://127.0.0.1:88(指向宝塔 Nginx 监听端口) |
| SSL 证书 | 上传 yogsothoth.top 的证书 |
| HTTP 自动跳转到 HTTPS | ✅ 开启 |
| 传递 X-Forwarded-Host、X-Forwarded-Proto | ✅ 开启 |
这里的 88 端口指向的是宝塔 Nginx 在该服务器上监听的端口,不是 Docker 容器端口。
三、宝塔 Nginx 配置
3.1 添加站点
在宝塔面板中,正常添加站点 yogsothoth.top。
3.2 关键配置
- SSL → 关闭(SSL 在 WAF 层处理,宝塔这边不配证书)
- 强制 HTTPS → 关闭(同上)
- 反向代理设置 → 填写 Docker 容器地址
3.3 反代配置
在宝塔站点设置 → 反向代理 → 添加:
| 字段 | 填写 |
|---|
| 代理名称 | WordPress |
| 目标 URL | http://127.0.0.1:8080(Docker WordPress 容器的端口) |
| 发送域名 | $http_host |
发送域名 必须设置为 $http_host,否则 WordPress 会收到错误的 Host 头。
3.4 代理透传 X-Forwarded-Proto(可选)
宝塔默认反代会自动传递部分头部,但如果不放心,可以在 配置文件 中添加:
location / {
proxy_pass http://127.0.0.1:8080;
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 X-Forwarded-Host $host;
}
实际上,宝塔的”反向代理”功能会自动加上这些头,一般无需手动编辑。
四、完整端口链路
用户浏览器
│ 访问 https://yogsothoth.top:443
▼
┌─────────────────────────────┐
│ 雷池 WAF (9443 管理后台) │ ← SSL 证书在这里
│ 监听: 80 / 443 │
│ 上游: 127.0.0.1:88 │ ← 转发给宝塔 Nginx
└──────────┬──────────────────┘
│ 协议: HTTP
│ 头部额外: X-Forwarded-Proto: https
▼
┌─────────────────────────────┐
│ 宝塔 Nginx (8888 管理面板) │ ← 无 SSL
│ 监听: 88 (此站点的入口) │
│ 反代: 127.0.0.1:8080 │ ← 转发给 Docker 容器
└──────────┬──────────────────┘
│ 协议: HTTP
▼
┌─────────────────────────────┐
│ Docker WordPress 容器 │
│ 端口: 8080 → 容器内 80 │
│ MySQL 容器: 127.0.0.1:3307 │
└─────────────────────────────┘
端口分配速查表
| 服务 | 监听端口 | 说明 |
|---|
| 雷池 WAF 入口 | 80 / 443 | 公网暴露,用户访问 |
| 雷池管理后台 | 9443 | 仅管理员访问 |
| 宝塔面板 | 8888 | 管理后台 |
| 宝塔 Nginx – 站点入口 | 88 | 仅本地监听,WAF 转发到此处 |
| Docker WordPress | 8080 | 仅本地监听,宝塔反代到此处 |
| Docker MySQL | 3307 | 仅本地监听,仅容器内连接 |
安全原则
- 只有 WAF 的 80/443 暴露在公网
- 宝塔只监听
127.0.0.1:88,不对外
- Docker 容器端口只绑定
127.0.0.1,不对外
- MySQL 绝不暴露公网端口
五、WordPress HTTPS 混合内容修复
5.1 问题现象
开启 HTTPS 后,WordPress 页面样式丢失、JS 不生效。浏览器 Console 报错:
Mixed Content: ... requested an insecure stylesheet 'http://...'
The page at '...' was loaded over HTTPS, but requested an insecure script '...'
5.2 根本原因
WordPress 根据请求的 $_SERVER['HTTPS'] 和 $_SERVER['SERVER_PORT'] 判断:
- 如未检测到 HTTPS → 模板生成的资源 URL 全以
http:// 开头
- 浏览器在 HTTPS 页面下发现
http:// 资源 → 混合内容拦截
WAF 反代模式下,请求到后端时是 HTTP → WordPress 以为没有 HTTPS → 生成 http:// 链接。
5.3 修复方案(二选一)
✅ 方案 A:WAF 传递 X-Forwarded-Proto(推荐)
雷池站点配置中开启 「为上游服务器传递 X-Forwarded-Host、X-Forwarded-Proto」。
然后在 WordPress 的 wp-config.php 中添加。⚠️ 注意放置位置:必须放在 /* That's all, stop editing! Happy publishing. */ 这行注释 之前,否则 WordPress 已加载完毕,不会生效。
// 放在 /* That's all, stop editing! Happy publishing. */ 之前
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) &&
$_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
$_SERVER['HTTPS'] = 'on';
}
strpos 和 === 'https' 两种写法都可以,=== 更严谨一些。
或者直接在 docker-compose.yml 中用环境变量注入(同样会注入到 /* That's all */ 之前的位置):
WORDPRESS_CONFIG_EXTRA: |
define('WP_HOME', 'https://yogsothoth.top');
define('WP_SITEURL', 'https://yogsothoth.top');
define('FORCE_SSL_ADMIN', true);
if (strpos(\$_SERVER['HTTP_X_FORWARDED_PROTO'], 'https') !== false) {
\$_SERVER['HTTPS'] = 'on';
}
本质:告诉 WordPress “你的上游是 HTTPS 的”,它就不会生成 http:// 链接。
✅ 方案 B:数据库直接替换
仅当方案 A 配置后还有残留的硬编码 http:// 链接时使用。
用 Better Search Replace 插件(支持序列化数据安全替换):
插件 → 安装插件 → 搜索 "Better Search Replace" → 安装并启用
工具 → Better Search Replace
搜索: http://yogsothoth.top
替换为: https://yogsothoth.top
勾选所有表 → 运行
或用 WP-CLI:
wp search-replace 'http://yogsothoth.top' 'https://yogsothoth.top' --skip-columns=guid
5.4 不需要的操作
❌ 安装 Really Simple SSL 等 SSL 插件 → 在 WAF 反代模式下无效 ❌ 修改宝塔 Nginx 的 SSL 配置 → SSL 在 WAF 层,宝塔只看 HTTP ❌ 强制 WordPress 后台 HTTPS 检测 → 配置好 X-Forwarded-Proto 后 WordPress 自动识别
六、Docker 部署要点
6.1 WordPress 容器注意事项
- 容器内是 Apache 模式(WordPress 官方镜像基于 Apache),宝塔 Nginx 反代到 Apache,兼容性最好
- WordPress 的 PHP 版本选
php8.2 或更高
- 数据持久化:
./wordpress:/var/www/html
- 启动后首次访问会进安装页面,数据库主机填服务名
db:3306
6.2 MySQL 容器注意事项
- 时区设置:
TZ: Asia/Shanghai
- 字符集:
--character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
- 端口用
3307 避免和宿主机的 MySQL 冲突
- 数据持久化:
db_data 命名卷或绑定挂载
6.3 docker-compose 操作
# 启动
docker compose up -d
# 查看日志
docker compose logs -f
# 重启(重新加载配置,不会重建)
docker compose restart
# 重建(加载新的 env / 镜像)
docker compose up -d --force-recreate
# 停止
docker compose down
6.4 内存限制
services:
wordpress:
deploy:
resources:
limits:
memory: 512M
db:
deploy:
resources:
limits:
memory: 512M
七、排错 checklist
| 症状 | 检查点 |
|---|
| HTTPS 访问不了 | 检查 WAF 80/443 是否正常;服务器安全组是否放行 |
| SSL 证书无效 | 检查 WAF 站点配置中证书是否正确上传 |
| 502 Bad Gateway | 检查 WAF 指向的宝塔端口(88)是否正确;Docker 容器是否运行 |
| Mixed Content 报错 | 检查 WAF 是否开启了 传递 X-Forwarded-Proto |
| WordPress 页面空白 | 检查容器日志 docker compose logs wordpress;检查 wp-config.php 中数据库连接 |
| 数据库连接失败 | 检查 .env 中的密码;检查 MySQL 容器是否健康 docker compose ps |
| 上传文件失败 | 检查 WordPress 目录权限:chown -R 33:33 wordpress/(33 是 www-data UID) |
| 修改 .env 不生效 | 必须 docker compose up -d --force-recreate,restart 不会加载新环境变量 |
八、常见场景速查
场景 1:新站点从零搭建
- 服务器装 Docker + 宝塔
- 创建
~/www/yourdomain/ → 写 docker-compose.yml + .env
docker compose up -d 启动
- 宝塔添加站点、配置反代到 Docker 端口
- 雷池添加站点、绑定域名、上传 SSL 证书
- 访问域名,走完 WordPress 安装向导
场景 2:已有站点切换 HTTPS
- 确保 WAF 已配置 SSL 证书
- 打开 传递 X-Forwarded-Proto
- 修改
wp-config.php 添加 X-Forwarded-Proto 检测
- 清空所有缓存
- 如还有硬编码 http 链接 → Better Search Replace 扫一遍
场景 3:WAF 升级或迁移
- 在旧 WAF 导出站点配置
- 在新 WAF 导入 → 重新上传证书
- 上游服务器地址不变(仍指向宝塔的 88 端口)
- DNS 解析切到新 WAF IP(注意 TTL 提前改短)
- 验证 HTTPS 正常后再把旧 WAF 下线
更新日志
| 日期 | 内容 |
|---|
| 2026-06-22 | 初版:WAF 反代 + WordPress HTTPS 修复 |
| 2026-06-22 | 重写:完整架构,含 Docker 部署、宝塔 Nginx、端口链路、排错表 |
评论(0)
暂无评论