安全矩阵

 找回密码
 立即注册
搜索
查看: 2049|回复: 0

关于X-Forwarded-For被伪造情况下获取真实ip的处理

[复制链接]

180

主题

231

帖子

1180

积分

金牌会员

Rank: 6Rank: 6

积分
1180
发表于 2022-1-7 00:50:14 | 显示全部楼层 |阅读模式
原文链接:关于X-Forwarded-For被伪造情况下获取真实ip的处理


背景
在风控场景下,有很多基于客户端ip的风控规则。通常通过http协议头中的X-Forwarded-For来获取ip,但该字段很容易被伪造,这种情况下该如何处理?

概念
X-Forwarded-For X-Forwarded-For 是一个扩展头。HTTP/1.1(RFC 2616)协议并没有对它的定义,它最开始是由 Squid 这个缓存代理软件引入,用来表示 HTTP 请求端真实 IP,现在已经成为事实上的标准,被各大 HTTP 代理、负载均衡等转发服务广泛使用,并被写入 RFC 7239(Forwarded HTTP Extension)标准之中.

$remote_addr
是nginx与客户端进行TCP连接过程中,获得的客户端真实地址. Remote Address 无法伪造,因为建立 TCP 连接需要三次握手,如果伪造了源 IP,无法建立 TCP 连接,更不会有后面的 HTTP 请求

$X-Real-IP
是一个自定义头。X-Real-Ip 通常被 HTTP 代理用来表示与它产生 TCP 连接的设备 IP,这个设备可能是其他代理,也可能是真正的请求端。需要注意的是,X-Real-Ip 目前并不属于任何标准,代理和 Web 应用之间可以约定用任何自定义头来传递这个信息

分析
网络请求通常是浏览器(或其他客户端)发出请求,通过层层网络设备的转发,最终到达服务端。那么每一个环节收到请求中的remote_addr必定是上游环节的真实IP,这个无法伪造。那从全链路来看,如果需要最终请求的来源,则通过X-Forwarded-For来进行追踪,每一环节的ip(remote_addr)都添加到X-Forwarded-For字段之后,这样X-Forwarded-For就能串联全链路了。
  1. X-Forwarded-For: client_ip, proxy1_ip, proxy2_ip
复制代码
以Nginx为例,添加X-Forwarded-For的配置方式为:
  1. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
复制代码
如果用户在请求时候伪造的话,那么会出现上面案例的client1前面,出现伪造的ip:
  1. X-Forwarded-For: 伪造ip1, 伪造ip2, client_ip, proxy1_ip, proxy2_ip
复制代码
这样的话,需要取真实的client_ip,则需要取proxy1_ip前一个ip值;
如果想要过滤掉或覆盖伪造的ip的话,则需要第一层代理(proxy1)用remote_addr来覆盖X-Forwarded-For:
  1. proxy_set_header X-Forwarded-For $remote_addr;
复制代码
验证
准备Mock服务
  1. from flask import Flask
  2. from flask import request

  3. app = Flask(__name__)

  4. @app.route('/HelloWorld')
  5. def hello_world():
  6.     print request.headers
  7.     return "Hello World!"

  8. if __name__ == "__main__":
  9.     app.run
复制代码
准备Nginx代理
  1. #user  nobody;
  2. worker_processes  1;

  3. events {
  4.     worker_connections  1024;
  5. }


  6. http {
  7.     include       mime.types;
  8.     default_type  application/octet-stream;

  9.     log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
  10.                       '$status $body_bytes_sent "$http_referer" '
  11.                       '"$http_user_agent" "$http_x_forwarded_for"';

  12.     access_log  logs/access.log  main;

  13.     sendfile        on;
  14.     #tcp_nopush     on;

  15.     #keepalive_timeout  0;
  16.     keepalive_timeout  65;

  17.     #gzip  on;

  18.     proxy_set_header Host $host;
  19.     proxy_set_header Cookie $http_cookie;
  20.     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

  21.     server {
  22.         listen       80;
  23.         server_name  localhost;

  24.         #charset koi8-r;

  25.         #access_log  logs/host.access.log  main;

  26.         location / {
  27.             root   html;
  28.             index  index.html index.htm;
  29.             proxy_pass http://localhost:5000/;
  30.         }

  31.         #error_page  404              /404.html;

  32.         # redirect server error pages to the static page /50x.html
  33.         #
  34.         error_page   500 502 503 504  /50x.html;
  35.         location = /50x.html {
  36.             root   html;
  37.         }
  38.     }
复制代码
PostMan伪造x-forwarded-for发起请求


Nginx打印日志,可以看到前面打印的是$remote_addr真实IP,后面打印的是X-Forwarded-For伪造IP




Mock服务日志,可以看到真实地址已经被Nginx拼到X-Forwarded-For后面了



回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2025-5-16 19:19 , Processed in 0.012244 second(s), 18 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表