文档目录
代理服务器配置

简介

本文件面向在反向代理、负载均衡与多节点部署环境下运行 DouPHP 的运维与开发人员,说明如何正确配置可信代理(trusted_proxies)、实现安全可靠的真实客户端 IP 获取、会话保持与 SSL 终止,并给出 Nginx/Apache 的反向代理最佳实践、代理链信任边界定义以及监控与性能优化建议。DouPHP 通过配置与中间件在 HTTP 边界统一处理代理信任、Host 白名单与安全响应头,确保在复杂网络拓扑下仍具备一致的安全与可观测性。

项目结构

与代理相关的关键位置:

  • 安全配置入口:config/security.php
  • 请求对象与代理信任逻辑:core/web/Http/Request.php
  • 安全响应头中间件基类与各端薄壳:core/foundation/middleware/AbstractSecurityHeadersMiddleware.php 及 front/admin/api 下的 SecurityHeadersMiddleware
  • 中间件注册与装配:core/foundation/middleware/MiddlewareRegistry.php
  • 应用常量与开关:config/config.php(如 DOU_DEBUG)
graph TB
A["Nginx/负载均衡"] --> B["Apache/Nginx(反代)"]
B --> C["DouPHP 应用"]
C --> D["Request::ip()/isSecure()"]
C --> E["SecurityHeadersMiddleware"]
C --> F["中间件注册表"]
C --> G["config/security.php"]

核心组件

  • 可信代理与 Host 白名单:由 config/security.php 的 security.trusted_proxies 与 security.trusted_hosts 控制。默认不信任任何代理,避免 X-Forwarded-* 被恶意伪造。
  • 请求对象 Request:提供 ip()、isSecure()、host()、url() 等接口,严格基于 REMOTE_ADDR 是否命中 trusted_proxies 来决定是否采信转发头。
  • 安全响应头中间件:三端薄壳继承基类,按 security.headers 下发基线安全头;HSTS 仅在 HTTPS 且开启时下发。
  • 中间件注册表:负责将各端默认中间件栈与路由级细化组合为最终执行链。

架构总览

下图展示从反向代理到应用层的请求路径,以及代理信任判定与安全头的下发点。

sequenceDiagram
participant U as "用户浏览器"
participant P as "反向代理/负载均衡"
participant A as "DouPHP 应用"
participant R as "Request"
participant M as "安全响应头中间件"
U->>P : "HTTPS 请求"
P->>A : "转发请求(设置X-Forwarded-*)", "透传Host"
A->>R : "读取REMOTE_ADDR / X-Forwarded-*"
R-->>A : "返回真实IP/协议/主机名"
A->>M : "进入中间件管道"
M-->>A : "下发安全响应头(HSTS/Referrer-Policy等)"
A-->>U : "业务响应"

详细组件分析

可信代理(trusted_proxies)配置与行为

  • 配置位置:config/security.php 的 security.trusted_proxies。支持精确 IP 与 CIDR 范围。
  • 生效时机:由初始化阶段加载安全配置后调用 Request::setTrustedProxies(),确保后续任何 ip() 调用均受信任列表约束。
  • 行为规则:
    • 未配置或为空:仅使用 REMOTE_ADDR,忽略所有 X-Forwarded-*,防止客户端伪造。
    • 已配置:当 REMOTE_ADDR 命中可信代理列表时,才会展开 X-Forwarded-For、HTTP_CLIENT_IP,并按“最靠近客户端”的顺序取第一个有效地址作为客户端 IP。
    • isSecure() 同理:仅在来自可信代理时,才采信 X-Forwarded-Proto 中的原始协议。
flowchart TD
S["开始(ip/isSecure)"] --> T{"REMOTE_ADDR 命中<br/>trusted_proxies?"}
T -- "否" --> O["仅使用REMOTE_ADDR<br/>忽略X-Forwarded-*"]
T -- "是" --> E["展开X-Forwarded-For/HTTP_CLIENT_IP<br/>取最左有效IP"]
E --> I["返回规范化后的客户端IP"]
O --> I
I --> End["结束"]

反向代理安全配置(Nginx/Apache)

  • 必须透传的关键头:
    • Host:确保 host() 能正确解析域名,配合 trusted_hosts 防御 Host 注入。
    • X-Forwarded-For:由代理追加客户端真实 IP 链,应用层仅在 trusted_proxies 匹配时才采信。
    • X-Forwarded-Proto:用于 isSecure() 判断原始协议(http/https)。
    • Authorization:若使用 Bearer Token,需确保代理透传 Authorization 头。
  • 禁止客户端直接访问后端:
    • 仅允许代理出口 IP 访问后端服务端口。
    • 在 WAF/防火墙层面限制源地址。
  • 常见注意事项:
    • 多级代理场景:X-Forwarded-For 会累积多个 IP,应用层按“最靠近客户端”顺序取第一个有效地址。
    • 不要在前端或网关随意改写/删除 X-Forwarded-*,以免破坏信任链。

负载均衡环境下的会话保持与 SSL 终止

  • 会话保持:
    • 若使用本地文件 Session,请确保同一客户端的请求落到同一节点(粘性会话/会话亲和),或使用共享存储(Redis/数据库)。
    • 若使用外部缓存/Session 存储,注意跨节点一致性。
  • SSL 终止:
    • 建议在边缘(Nginx/负载均衡)终止 TLS,并将 X-Forwarded-Proto=https 传给后端。
    • 应用层 isSecure() 会在可信代理条件下采信该头,从而生成正确的 https URL。
    • HSTS:可通过 security.headers.hsts 启用,仅 HTTPS 且 enabled 时下发 Strict-Transport-Security。

代理环境下的真实 IP 获取与客户端地址识别

  • 客户端 IP:
    • 优先从 X-Forwarded-For 最左侧有效 IPv4 或 IPv6 中选取;若无可信代理则回退到 REMOTE_ADDR。
    • 支持 IPv4-mapped IPv6 归一化,保证比较一致性。
  • 主机名与 URL:
    • host() 会结合 trusted_hosts 白名单校验,未命中时回落到白名单首项,避免对外链接被污染。
    • url()/fullUrl() 基于 scheme()+host()+path() 构造,scheme 由 isSecure() 决定。
classDiagram
class Request {
+ip() string
+isSecure() bool
+host() string
+url() string
+fullUrl() string
+bearerToken() string
+csrfToken() string
-collectClientIpCandidates() array
-isFromTrustedProxy() bool
-ipMatches(ip, rule) bool
-normalizeIpv4(ip) string
}

代理链的安全配置与信任边界

  • 信任边界定义:
    • 唯一可信入口为“我方控制的代理/负载均衡”,其出口 IP 必须加入 trusted_proxies。
    • 任何非受信来源不得直接访问后端,否则无法信任 X-Forwarded-*。
  • 代理链要求:
    • 每跳代理应只追加自身上游 IP,不应覆盖已有 X-Forwarded-For。
    • 严禁在不可信环节修改或插入 X-Forwarded-*。
  • 配套措施:
    • 使用 trusted_hosts 限定合法域名,防止 Host 头注入。
    • 在 WAF/防火墙对后端端口进行源地址白名单限制。

安全响应头与中间件管道

  • 基线安全头:
    • X-Frame-Options、X-Content-Type-Options、Referrer-Policy、Permissions-Policy 由 security.headers 控制。
    • HSTS 仅在 HTTPS 且 enabled 时下发。
  • 中间件管道:
    • 三端(前台/后台/API)均继承 AbstractSecurityHeadersMiddleware,行为一致。
    • 中间件注册表负责组装默认栈与路由级细化,缺类时跳过,不影响整体可用性。
sequenceDiagram
participant MW as "中间件注册表"
participant SH as "SecurityHeadersMiddleware"
participant APP as "业务控制器"
MW->>SH : "进入安全头中间件"
SH->>SH : "读取security.headers"
SH-->>APP : "下发安全响应头并继续处理"
APP-->>SH : "返回响应"
SH-->>MW : "完成"

依赖关系分析

  • 配置依赖:
    • config/security.php 提供 trusted_proxies、trusted_hosts、headers、session 等关键安全参数。
    • config/config.php 提供应用级常量(如 DOU_DEBUG),便于调试与日志级别控制。
  • 运行时依赖:
    • Request 在启动早期即根据安全配置设置可信代理与 Host 白名单,确保后续所有 IP/协议/主机名判定一致。
    • 中间件在路由命中后才执行,因此 404 等非命中路由不受安全头中间件影响。
graph LR
CFG["config/security.php"] --> REQ["Request"]
CFG --> MID["SecurityHeadersMiddleware"]
REG["MiddlewareRegistry"] --> MID
CFG2["config/config.php"] --> APP["应用运行期"]
REQ --> APP
MID --> APP

性能考虑

  • 代理层:
    • 启用连接复用与 HTTP/2,减少握手开销。
    • 合理设置超时与缓冲,避免长连接占用资源。
    • 在边缘做静态资源缓存与压缩,降低后端压力。
  • 应用层:
    • 关闭不必要的调试开关(如 DOU_DEBUG)以提升性能。
    • 使用外部缓存/Session 存储提升横向扩展能力。
    • 合理配置 PHP-FPM/进程池与 OPcache。
  • 监控:
    • 记录代理与应用层的关键指标:QPS、延迟、错误率、SSL 握手失败、X-Forwarded-* 异常等。
    • 对 IP 获取链路进行采样与告警,发现异常伪造或丢失。

故障排查指南

  • 症状:客户端 IP 始终显示为代理 IP
    • 检查 trusted_proxies 是否包含代理出口 IP。
    • 确认代理是否正确追加 X-Forwarded-For。
    • 查看 Request::ip() 的候选收集逻辑是否命中可信代理分支。
  • 症状:页面跳转或邮件链接出现 http
    • 检查 isSecure() 是否在可信代理条件下采信 X-Forwarded-Proto=https。
    • 确认代理透传了正确的协议头。
  • 症状:HSTS 未生效
    • 确认 security.headers.hsts.enabled 为 true,且当前请求为 HTTPS。
  • 症状:Host 头注入导致外链异常
    • 配置 trusted_hosts 白名单,使 host() 在未命中时回落到规范域名。

结论

DouPHP 通过集中式安全配置与严格的代理信任机制,在反向代理与负载均衡环境中提供了可靠的安全与可观测性。正确配置 trusted_proxies 与 trusted_hosts,并在代理层透传必要头部,即可实现真实的客户端 IP 获取、安全的协议判定与一致的 URL 生成。结合合理的会话保持、SSL 终止策略与中间件安全头下发,可在生产环境获得高可用与高安全的运行体验。

附录

  • 快速核对清单
    • 已在 config/security.php 中配置 trusted_proxies(精确 IP/CIDR)。
    • 已在代理层透传 Host、X-Forwarded-For、X-Forwarded-Proto、Authorization。
    • 已启用 trusted_hosts 白名单,防止 Host 头注入。
    • 已在边缘终止 TLS,并确保 isSecure() 能正确识别 HTTPS。
    • 已配置安全响应头(HSTS、Referrer-Policy、Permissions-Policy 等)。
    • 已规划会话存储与负载均衡亲和策略。
    • 已建立监控与告警,覆盖代理与应用层关键指标。
添加日期:2026-10-05