- 背景
请求 IP 作为用户的身份标识属性之一,是一种非常重要的基础数据。在很多场景下,我们会基于客户端请求 IP 去做网络安全攻击防范或访问风险控制,通常我们可以通过 HTTP 协议 Request Headers 中 X-Forwarded-For 头来获取真实 IP。然而通过 X-Forwarded-For 头获取真实 IP 的方式真的可靠么?,前一段时间,刚好近段有个有关投票的业务,为了业务安全,我们将投票时的ip记录了下来,使用的就是X-Forwarded-For。 概念
X-Forwarded-For 是一个 HTTP 扩展头。HTTP/1.1(RFC 2616)标准中并没有对它的定义,它最开始是由 Squid 这个缓存代理软件引入,用来表示 HTTP 请求端真实 IP,现在已经成为事实上的标准,被各大 HTTP 代理、负载均衡等转发服务广泛使用,并被写入 RFC 7239(Forwarded HTTP Extension)标准之中。网络请求通常是浏览器(或其他客户端)发出请求,通过层层网络设备的转发,最终到达服务端。那么每一个环节收到请求中的 $remote_addr 必定是上游环节的真实 IP,这个无法伪造。那从全链路来看,如果需要最终请求的来源,则通过 X-Forwarded-For 来进行追踪,每一环节的 IP( $remote_addr )都添加到 X-Forwarded-For 字段之后,这样 X-Forwarded-For 就能串联全链路了。即:X-Forwarded-For: client_ip, proxy1_ip, proxy2_ip
- 怎么伪造 X-Forwarded-For
客户端是否能伪造 IP,取决于边缘节点(Edge Node)是如何处理 X-Forwarded-For 字段。客户端直接连接的首个 Proxy 节点都叫做边缘节点(Edge Node),无论是网关、CDN、LB 等,只要这一层是直接接入客户端访问的,那么它就是一个边缘节点。
•不重写 X-Forwarded-For 的边缘节点 边缘节点如果是透传 HTTP 的 X-Forwarded-For 头,那么它就是不安全的,客户端可以在 HTTP 请求中伪造 X-Forwarded-For 值,也就是直接在请求的header里填入X-Forwarded-For的值,就能实现伪造,并且这个值会被向后透传。
因此不重写 X-Forwarded-For 的边缘节点是不安全的边缘节点,用户可以伪造 X-Forwarded-For 。 怎么防止 X-Forwarded-For 被伪造
你可以修改nginx配置重写 X-Forwarded-For server { listen 8085; server_name 127.0.0.1; location /sys { proxy_pass http://127.0.0.1:8085/; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; # 防止X-Forwarded-For头伪造的主要设置在这里 proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } }
如果有多层Nginx代理,内层的Nginx配置:proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。