共计 1844 个字符,预计需要花费 5 分钟才能阅读完成。
起因是用 $request->ip() 来获取 ip 限流,忽然受到大面积误杀。排查 access.log 日志,简直所有申请的 $remote_addr,都为某几个固定 ip。征询运维后发现是他轻轻给前端加了 cdn。那为何会产生这种问题呢?
remote_addr 和 http_x_forwarded_for
先来理解一下前置常识。
remote_addr 是实在的与 Web 服务建设连贯的 ip。在不通过代理服务器的时候,能获取到用户实在 IP,不可伪造。
但少数申请都通过反向代理、CDN 减速等服务,再达到 Web 服务。这时候与 Web 服务实在建设连贯的就是代理服务器。相应地 remote_addr 的值也变成了代理服务器的 ip。那么通过代理服务器的服务,如何能力获取到用户实在 IP 呢?
X-Forwarded-For 则应运而生。它是一个 HTTP 扩大头部,用来记录一个申请路径服务器的 ip,能够了解为一个 ip 链条。每路径一台代理服务器,它会把访问者的 ip,追加到 X-Forwarded-For 中。
但 X-Forwarded-For 是 能够伪造 的,客户端可能从最后收回的申请中 X-Forwarded-For 就携带者几个 ip。
格局如下:
X-Forwarded-For:client_ip, proxy1_ip, proxy2_ip
Laravel 获取 ip
Symfony 的 Request 类中这样实现 getClientIps()
public function getClientIps()
{$ip = $this->server->get('REMOTE_ADDR');
if (!$this->isFromTrustedProxy()) {return [$ip];
}
return $this->getTrustedValues(self::HEADER_X_FORWARDED_FOR, $ip) ?: [$ip];
}
首先,从 REMOTE_ADDR 中获取了与 Web 服务建设实在连贯的客户端 ip。而后,判断此 ip 是否是受信赖的代理,如果不是则间接返回此 ip。最初,调用 getTrustedValues() 来获取和解决 X-Forwarded-For。
(因为 Laravel 默认是受信赖代理是空,所以导致了开篇提到的问题,如何设置信赖代理见下文)
getTrustedValues() 次要有两个引入瞩目的操作:
- 如果 X-Forwarded-For 的 ip 链条中,也存在受信赖的代理 ip,会被过滤。
- 将过滤后的 ip 链条 反转 返回;如果过滤后的 ip 链条 为空,则返回受信赖的代理 ip。
getClientIps() 返回 ip 链接条,与 X-Forwarded-For 程序相同,这时常会让开发者踩坑。那为什么会这么设计呢?
Symfony 开发者在正文中是这么解释的:
返回的数组中,最受信赖的 ip 排在第一位,最不受信赖的 ip 排在最初一位。“实在”的客户端 ip 排在最初一位,但它也是最不受信赖的。受信赖的代理 ip 已被从中移除。
看完你会豁然开朗。
如何食用
如果,一个申请如下:
client->proxy1->proxy2->proxy3->web service
proxy1-3 是咱们的代理服务器
那么,它的 X-Forwarded-For:client_ip, p1_ip, p2_ip
因为,proxy1-3 是咱们的代理服务器是可信的。
咱们将 p1_ip, p2_ip, p3_ip 退出受信赖代理。
namespace App\Http\Middleware;
……
class TrustProxies extends Middleware
{
protected $proxies = [p1_ip, p2_ip, p3_ip];
……
那么,getClientIps() 会返回
[client_ip]
因为,client_ip 是由 proxy1 代理服务器追加到 X-Forwarded-For,所以是可信的,可作为用户的实在 IP。
如果,客户端申请前 X-Forwarded-For 就已有一个 ip(client0_ip)
getClientIps() 会返回
// 信任度从高到底
[
client_ip,
client0_ip
]
client0 有可能是用户实在的 ip,也有可能是本人伪造的 X-Forwarded-For,并不能信赖它。
参考文章
https://www.cnblogs.com/lcawe…
https://learnku.com/articles/…
PS: 写完后,发现一篇写的很棒的文章 https://segmentfault.com/a/11…