1. 背景
    请求 IP 作为用户的身份标识属性之一,是一种非常重要的基础数据。在很多场景下,我们会基于客户端请求 IP 去做网络安全攻击防范或访问风险控制,通常我们可以通过 HTTP 协议 Request Headers 中 X-Forwarded-For 头来获取真实 IP。然而通过 X-Forwarded-For 头获取真实 IP 的方式真的可靠么?,前一段时间,刚好近段有个有关投票的业务,为了业务安全,我们将投票时的ip记录了下来,使用的就是X-Forwarded-For。
  2. 概念
    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
  3. 怎么伪造 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 。
    image.png
  4. 怎么防止 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;


汝何不上九霄
4.6k 声望1.6k 粉丝