是使用$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_ipLaravel获取ipSymfony的Request类实现getClientIps()publicfunctiongetClientIps(){$ip=$this->server->get('REMOTE_ADDR');如果(!$this->isFromTrustedProxy()){返回[$ip];}return$this->getTrustedValues(self::HEADER_X_FORWARDED_FOR,$ip)?:[$ip];}首先从REMOTE_ADDR获取web服务的客户端ip建立真实连接。然后判断这个ip是否是可信代理,如果不是,直接返回这个ip。最后,调用getTrustedValues()获取并处理X-Forwarded-For。(因为Laravel默认可信代理为空,所以导致了开头提到的问题,如何设置可信代理见下文。)getTrustedValues()主要有两个操作值得注意:-Forwarded-For,还有可信的代理ip,会被过滤掉。反转过滤后的ip链并返回;如果过滤后的ip链为空,则返回可信代理ip。getClientIps()返回的是ip链接栏,和X-Forwarded-For顺序相反,经常让开发者踩坑。那么为什么要这样设计呢?Symfony开发者在评论中解释了这一点:在返回的数组中,最受信任的ip排在第一位,最不信任的ip排在最后。“真实”客户端ip排在最后,但也是最不可信的。受信任的代理IP已从中删除。看完你就会恍然大悟。怎么吃如果,一个请求是这样的:client->proxy1->proxy2->proxy3->webserviceproxy1-3那么就是我们的代理服务器,它的X-Forwarded-For:client_ip,p1_ip,p2_ip因为,proxy1-3是我们的代理服务器是可信的。我们将p1_ip、p2_ip、p3_ip添加到受信任的代理中。namespaceApp\Http\Middleware;...classTrustProxiesextendsMiddleware{protected$proxies=[p1_ip,p2_ip,p3_ip];...然后,getClientIps()将返回[client_ip]因为client_ip附加到X-Forwarded-For,因此是可信的,可以作为用户的真实IP。如果X-Forwarded-For在client请求之前已经有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...
