關於X-Forwarded-For被偽造情況下獲取真實ip的處理


關於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就能串聯全鏈路了。

X-Forwarded-For: client_ip, proxy1_ip, proxy2_ip

以Nginx為例,添加X-Forwarded-For的配置方式為:

 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

如果用戶在請求時候偽造的話,那么會出現上面案例的client1前面,出現偽造的ip:

X-Forwarded-For: 偽造ip1, 偽造ip2, client_ip, proxy1_ip, proxy2_ip

這樣的話,需要取真實的client_ip,則需要取proxy1_ip前一個ip值;

如果想要過濾掉或覆蓋偽造的ip的話,則需要第一層代理(proxy1)用remote_addr來覆蓋X-Forwarded-For:

proxy_set_header X-Forwarded-For $remote_addr;

驗證

准備Mock服務

from flask import Flask from flask import request app = Flask(__name__) @app.route('/HelloWorld') def hello_world(): print request.headers return "Hello World!" if __name__ == "__main__": app.run

准備Nginx代理

#user nobody; worker_processes 1; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log logs/access.log main; sendfile on; #tcp_nopush on;  #keepalive_timeout 0;  keepalive_timeout 65; #gzip on;  proxy_set_header Host $host; proxy_set_header Cookie $http_cookie; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; server { listen 80; server_name localhost; #charset koi8-r;  #access_log logs/host.access.log main;  location / { root html; index index.html index.htm; proxy_pass http://localhost:5000/; } #error_page 404 /404.html;  # redirect server error pages to the static page /50x.html  #  error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } }

PostMan偽造x-forwarded-for發起請求

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

Mock服務日志,可以看到真實地址已經被Nginx拼到X-Forwarded-For后面了

參考

叉叉哥:利用X-Forwarded-For偽造客戶端IP漏洞成因及防范​zhuanlan.zhihu.com圖標 HTTP 請求頭中的 X-Forwarded-For​www.jianshu.com

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM