可信代理
当 OxPHP 运行在反向代理(Kubernetes Ingress、Cloudflare、AWS ALB、nginx)之后时,每个请求都来自代理的 IP 地址。如果不配置可信代理,限流、访问日志和 $_SERVER['REMOTE_ADDR'] 看到的都会是代理 IP,而不是真实的客户端 IP。
配置
# Comma-separated CIDR list
TRUSTED_PROXIES="10.0.0.0/8,172.16.0.0/12,192.168.0.0/16"
# Shorthand: all RFC-1918 + loopback + link-local (IPv4 and IPv6)
TRUSTED_PROXIES="private"未设置时,OxPHP 会忽略所有转发请求头。这是安全的默认行为。
工作原理
当请求来自一个可信 IP 时,OxPHP 会按优先级顺序检查转发请求头:
Forwarded(RFC 7239)—— 标准化的请求头X-Forwarded-For/X-Forwarded-Proto/X-Forwarded-Host/X-Forwarded-Port—— 事实上的后备方案
如果存在 Forwarded 请求头,则忽略 X-Forwarded-* 请求头。
客户端 IP 提取
OxPHP 采用最右侧非可信算法 —— 与 nginx(real_ip_recursive on)、Caddy、Traefik 和 Apache 使用的方法相同:
X-Forwarded-For: 203.0.113.50, 172.16.1.1, 10.0.0.5
TCP peer: 10.0.0.1 (trusted)
Walk right-to-left:
10.0.0.5 → trusted → skip
172.16.1.1 → trusted → skip
203.0.113.50 → NOT trusted → client IP这能防止通过在前面追加伪造值来进行欺骗。攻击者可以在左侧添加虚假 IP,但最右侧的非可信 IP 是由链路中最后一个可信代理设置的。
有哪些变化
当配置了 TRUSTED_PROXIES 且连接的 IP 是可信的时:
| 组件 | 未配置可信代理 | 配置可信代理后 |
|---|---|---|
$_SERVER['REMOTE_ADDR'] |
代理 IP | 真实客户端 IP |
$_SERVER['REMOTE_PORT'] |
代理源端口 | 来自 Forwarded: for=ip:port 的客户端端口,否则为 0 |
$_SERVER['HTTPS'] |
基于 OxPHP 的 TLS 配置 | 来自 Forwarded: proto= 或 X-Forwarded-Proto |
$_SERVER['REQUEST_SCHEME'] |
来自 TLS 的 http 或 https |
来自转发的协议 |
$_SERVER['SERVER_NAME'] |
来自 Host 请求头 |
来自 Forwarded: host= 或 X-Forwarded-Host |
$_SERVER['SERVER_PORT'] |
来自 Host 请求头 |
来自 X-Forwarded-Port,否则取 X-Forwarded-Host / Forwarded: host= 的端口,否则为 443/80 |
| 限流 | 按代理 IP | 按客户端 IP |
| 访问日志 | 代理 IP | 真实客户端 IP |
代理之后 REMOTE_PORT 为 0,除非有一个 RFC 7239 的 Forwarded: for=ip:port 节点携带了客户端的源端口。X-Forwarded-For 没有端口字段,因此重写后的值无法重建,会被置零而不是猜测。
private 网络
private 简写包括:
| 网络 | 说明 |
|---|---|
10.0.0.0/8 |
A 类私有地址 |
172.16.0.0/12 |
B 类私有地址 |
192.168.0.0/16 |
C 类私有地址 |
127.0.0.0/8 |
回环地址 |
169.254.0.0/16 |
链路本地地址 |
::1/128 |
IPv6 回环地址 |
fc00::/7 |
IPv6 唯一本地地址 |
fe80::/10 |
IPv6 链路本地地址 |
安全性
- 安全的默认行为 —— 未设置
TRUSTED_PROXIES时,不处理任何转发请求头 - CIDR 校验 ——
TRUSTED_PROXIES中的无效值会导致启动错误 - 抗欺骗能力 —— 最右侧非可信算法会忽略攻击者在前面追加的值
- 来自非可信 IP 的请求,其转发请求头会被完全忽略