可信代理

当 OxPHP 运行在反向代理(Kubernetes Ingress、Cloudflare、AWS ALB、nginx)之后时,每个请求都来自代理的 IP 地址。如果不配置可信代理,限流、访问日志和 $_SERVER['REMOTE_ADDR'] 看到的都会是代理 IP,而不是真实的客户端 IP。

配置

bash
# 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"
Note

未设置时,OxPHP 会忽略所有转发请求头。这是安全的默认行为。

工作原理

当请求来自一个可信 IP 时,OxPHP 会按优先级顺序检查转发请求头:

  1. ForwardedRFC 7239)—— 标准化的请求头
  2. 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 使用的方法相同:

text
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 的 httphttps 来自转发的协议
$_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_PORT0,除非有一个 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 的请求,其转发请求头会被完全忽略

另请参阅

  • 限流 —— 按 IP 限流使用解析出的客户端 IP
  • 访问日志 —— remote_ip 字段显示解析出的客户端 IP
  • 配置参考 —— 所有环境变量