HTTP協議頭中X-Forwarded-For是能做什么?

X-Forwarded-For和相關幾個頭部的理解

  • $remote_addr

    是nginx與客戶端進行TCP連接過程中,獲得的客戶端真實地址. Remote Address 無法偽造,因為建立 TCP 連接需要三次握手,如果偽造了源 IP,無法建立 TCP 連接,更不會有后面的 HTTP 請求

  • X-Real-IP

    是一個自定義頭。X-Real-Ip 通常被 HTTP 代理用來表示與它產生 TCP 連接的設備 IP,這個設備可能是其他代理,也可能是真正的請求端。需要注意的是,X-Real-Ip 目前并不屬于任何標準,代理和 Web 應用之間可以約定用任何自定義頭來傳遞這個信息

  • X-Forwarded-For

    X-Forwarded-For 是一個擴展頭。HTTP/1.1(RFC 2616)協議并沒有對它的定義,它最開始是由 Squid 這個緩存代理軟件引入,用來表示 HTTP 請求端真實 IP,現在已經成為事實上的標準,被各大 HTTP 代理、負載均衡等轉發服務廣泛使用,并被寫入 RFC 7239(Forwarded HTTP Extension)標準之中.

X-Forwarded-For請求頭格式非常簡單,就這樣:

X-Forwarded-For:client, proxy1, proxy2

可以看到,XFF 的內容由「英文逗號 + 空格」隔開的多個部分組成,最開始的是離服務端最遠的設備 IP,然后是每一級代理設備的 IP。

如果一個 HTTP 請求到達服務器之前,經過了三個代理 Proxy1、Proxy2、Proxy3,IP 分別為 IP1、IP2、IP3,用戶真實 IP 為 IP0,那么按照 XFF 標準,服務端最終會收到以下信息:

X-Forwarded-For: IP0, IP1, IP2

Proxy3 直連服務器,它會給 XFF 追加 IP2,表示它是在幫 Proxy2 轉發請求。列表中并沒有 IP3,IP3 可以在服務端通過 remote_address 來自 TCP 連接,表示與服務端建立 TCP 連接的設備 IP,在這個例子里就是 IP3。

詳細分析一下,這樣的結果是經過這樣的流程而形成的:

  1. 用戶IP0—> 代理Proxy1(IP1),Proxy1記錄用戶IP0,并將請求轉發個Proxy2時,帶上一個Http Header X-Forwarded-For: IP0

  2. Proxy2收到請求后讀取到請求有 X-Forwarded-For: IP0,然后proxy2 繼續把鏈接上來的proxy1 ip追加到 X-Forwarded-For 上面,構造出X-Forwarded-For: IP0, IP1,繼續轉發請求給Proxy 3

  3. 同理,Proxy3 按照第二部構造出 X-Forwarded-For: IP0, IP1, IP2,轉發給真正的服務器,比如NGINX,nginx收到了http請求,里面就是 X-Forwarded-For: IP0, IP1, IP2 這樣的結果。所以Proxy 3 的IP3,不會出現在這里。

  4. nginx 獲取proxy3的IP 能通過remote_address就是真正建立TCP鏈接的IP,這個不能偽造,是直接產生鏈接的IP。$remote_address 無法偽造,因為建立 TCP 連接需要三次握手,如果偽造了源 IP,無法建立 TCP 連接,更不會有后面的 HTTP 請求。

x-forwarded-for 實踐研究:

  1. uwsgi_pass的情況下,nginx 沒有設置proxy_pass x-forwarded-for: $proxy_add_x_forwarded_for;

    • 如果請求頭傳了XFF,在flask里面能正常讀取請求頭里面的XFF,就是當是一個普通的頭讀出;如果header不傳這個XFF的話,就讀不到
  2. proxy_pass 情況下

    • 沒有傳 # proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for 的話,跟上面的uwsgi_pass 一樣,都是在沒有設置header XFF情況下,讀不到。

    • 如果傳了 proxy_set_header X-Forwarded-For remote_address),因為這句proxy_set_header 會讓nginx追加一個$remote_address到XFF。

    • header 傳xff的話, 程序里面可以讀到Xff 頭: X-Forwarded-For: 188.103.19.120, 10.0.2.2 (第一個是我自己編的,第二個是proxy_add_x_forwarded_for 這句而追加$remote_addr到XFF。

總結:

  1. 只要nginx前端(例如lvs, varnish)轉發請求給nginx的時候,帶了x-forwarded-for ,那么程序就一定能讀到這個字段,如果nginx還設置了proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for, 那么程序能讀到XFF是:ip0, ip1 (客戶端Ip,lvs或者varnishIP)。 如果nginx沒有設置,那么nginx還是會原樣把http頭傳給程序,也就是說程序也能讀到XFF,而且XFF就是ip0 客戶端IP。

  2. proxy_pass 設置這個頭 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 是站在一個作為代理的角度把。能繼續傳輸多級代理的頭。

  3. nginx的日志格式寫了$http_x_forwared_for 說明前端(lvs)確實傳了這個頭過來。所以是程序是讀取到的

  4. uwsgi_pass 不能設置 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 這個頭,是因為這個頭是對http代理來說,用來傳遞IP的,uwsgi 不可能充當一個代理。

  5. nginx->程序,這里其實有兩個鏈接過程,其他IP與nginx的TCP連接, nginx與程序的TCP連接。所以$remote_addr都是對各自來說的。程序的remote_addr: remote_addr 127.0.0.1 (跟它鏈接的是nginx 內網127.0.0.1)nginx的remote_addr : X-Real-Ip: 10.0.2.2 (跟它鏈接的是我的電腦,IP 10.0.2.2)

  6. 對程序來說,讀取的request.remote_addr 也永遠是直接跟他鏈接的ip, 也就是反向代理nginx

  7. The access_route attribute uses the X-Forwarded-For header, falling back to the REMOTE_ADDRWSGI variable; 也就是說access_route默認讀取XFF頭,如果沒有,降級讀取WSGI的REMOTE_ADDR變量,這個 WSGI的REMOTE_ADDR變量 就是 $remote_addr

  8. request.envron 是WSGI的變量,都是wsgi server轉過來的,普通的頭都是加了HTTP_前綴的 ,包括proxy_set_header Host proxy_add_x_forwarded_for;
    添加的頭都會出現在處理,因為他們就是普通的http頭

  9. LVS->nginx的情況下, 請求的時候主動加XFF,程序讀取的時候沒顯示。因為LVS設置XFF的時候,直接把直連的IP賦值給LVS,忽略掉所有本來有的XFF,要從LVS這里開始。 所以程序讀到的XFF是 :XFF headers 218.107.55.254, 10.120.214.252
    前面的是我的IP, 后面的是LVS的IP

X-Forwarded-For和相關幾個頭部的理解

  • $remote_addr

    是nginx與客戶端進行TCP連接過程中,獲得的客戶端真實地址. Remote Address 無法偽造,因為建立 TCP 連接需要三次握手,如果偽造了源 IP,無法建立 TCP 連接,更不會有后面的 HTTP 請求

  • X-Real-IP

    是一個自定義頭。X-Real-Ip 通常被 HTTP 代理用來表示與它產生 TCP 連接的設備 IP,這個設備可能是其他代理,也可能是真正的請求端。需要注意的是,X-Real-Ip 目前并不屬于任何標準,代理和 Web 應用之間可以約定用任何自定義頭來傳遞這個信息

  • X-Forwarded-For

    X-Forwarded-For 是一個擴展頭。HTTP/1.1(RFC 2616)協議并沒有對它的定義,它最開始是由 Squid 這個緩存代理軟件引入,用來表示 HTTP 請求端真實 IP,現在已經成為事實上的標準,被各大 HTTP 代理、負載均衡等轉發服務廣泛使用,并被寫入 RFC 7239(Forwarded HTTP Extension)標準之中.

X-Forwarded-For請求頭格式非常簡單,就這樣:

X-Forwarded-For:client, proxy1, proxy2

可以看到,XFF 的內容由「英文逗號 + 空格」隔開的多個部分組成,最開始的是離服務端最遠的設備 IP,然后是每一級代理設備的 IP。

如果一個 HTTP 請求到達服務器之前,經過了三個代理 Proxy1、Proxy2、Proxy3,IP 分別為 IP1、IP2、IP3,用戶真實 IP 為 IP0,那么按照 XFF 標準,服務端最終會收到以下信息:

X-Forwarded-For: IP0, IP1, IP2

Proxy3 直連服務器,它會給 XFF 追加 IP2,表示它是在幫 Proxy2 轉發請求。列表中并沒有 IP3,IP3 可以在服務端通過 remote_address 來自 TCP 連接,表示與服務端建立 TCP 連接的設備 IP,在這個例子里就是 IP3。

詳細分析一下,這樣的結果是經過這樣的流程而形成的:

  1. 用戶IP0—> 代理Proxy1(IP1),Proxy1記錄用戶IP0,并將請求轉發個Proxy2時,帶上一個Http Header X-Forwarded-For: IP0

  2. Proxy2收到請求后讀取到請求有 X-Forwarded-For: IP0,然后proxy2 繼續把鏈接上來的proxy1 ip追加到 X-Forwarded-For 上面,構造出X-Forwarded-For: IP0, IP1,繼續轉發請求給Proxy 3

  3. 同理,Proxy3 按照第二部構造出 X-Forwarded-For: IP0, IP1, IP2,轉發給真正的服務器,比如NGINX,nginx收到了http請求,里面就是 X-Forwarded-For: IP0, IP1, IP2 這樣的結果。所以Proxy 3 的IP3,不會出現在這里。

  4. nginx 獲取proxy3的IP 能通過remote_address就是真正建立TCP鏈接的IP,這個不能偽造,是直接產生鏈接的IP。$remote_address 無法偽造,因為建立 TCP 連接需要三次握手,如果偽造了源 IP,無法建立 TCP 連接,更不會有后面的 HTTP 請求。

x-forwarded-for 實踐研究:

  1. uwsgi_pass的情況下,nginx 沒有設置proxy_pass x-forwarded-for: $proxy_add_x_forwarded_for;

    • 如果請求頭傳了XFF,在flask里面能正常讀取請求頭里面的XFF,就是當是一個普通的頭讀出;如果header不傳這個XFF的話,就讀不到
  2. proxy_pass 情況下

    • 沒有傳 # proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for 的話,跟上面的uwsgi_pass 一樣,都是在沒有設置header XFF情況下,讀不到。

    • 如果傳了 proxy_set_header X-Forwarded-For remote_address),因為這句proxy_set_header 會讓nginx追加一個$remote_address到XFF。

    • header 傳xff的話, 程序里面可以讀到Xff 頭: X-Forwarded-For: 188.103.19.120, 10.0.2.2 (第一個是我自己編的,第二個是proxy_add_x_forwarded_for 這句而追加$remote_addr到XFF。

總結:

  1. 只要nginx前端(例如lvs, varnish)轉發請求給nginx的時候,帶了x-forwarded-for ,那么程序就一定能讀到這個字段,如果nginx還設置了proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for, 那么程序能讀到XFF是:ip0, ip1 (客戶端Ip,lvs或者varnishIP)。 如果nginx沒有設置,那么nginx還是會原樣把http頭傳給程序,也就是說程序也能讀到XFF,而且XFF就是ip0 客戶端IP。

  2. proxy_pass 設置這個頭 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 是站在一個作為代理的角度把。能繼續傳輸多級代理的頭。

  3. nginx的日志格式寫了$http_x_forwared_for 說明前端(lvs)確實傳了這個頭過來。所以是程序是讀取到的

  4. uwsgi_pass 不能設置 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 這個頭,是因為這個頭是對http代理來說,用來傳遞IP的,uwsgi 不可能充當一個代理。

  5. nginx->程序,這里其實有兩個鏈接過程,其他IP與nginx的TCP連接, nginx與程序的TCP連接。所以$remote_addr都是對各自來說的。程序的remote_addr: remote_addr 127.0.0.1 (跟它鏈接的是nginx 內網127.0.0.1)nginx的remote_addr : X-Real-Ip: 10.0.2.2 (跟它鏈接的是我的電腦,IP 10.0.2.2)

  6. 對程序來說,讀取的request.remote_addr 也永遠是直接跟他鏈接的ip, 也就是反向代理nginx

  7. The access_route attribute uses the X-Forwarded-For header, falling back to the REMOTE_ADDRWSGI variable; 也就是說access_route默認讀取XFF頭,如果沒有,降級讀取WSGI的REMOTE_ADDR變量,這個 WSGI的REMOTE_ADDR變量 就是 $remote_addr

  8. request.envron 是WSGI的變量,都是wsgi server轉過來的,普通的頭都是加了HTTP_前綴的 ,包括proxy_set_header Host proxy_add_x_forwarded_for;
    添加的頭都會出現在處理,因為他們就是普通的http頭

  9. LVS->nginx的情況下, 請求的時候主動加XFF,程序讀取的時候沒顯示。因為LVS設置XFF的時候,直接把直連的IP賦值給LVS,忽略掉所有本來有的XFF,要從LVS這里開始。 所以程序讀到的XFF是 :XFF headers 218.107.55.254, 10.120.214.252
    前面的是我的IP, 后面的是LVS的IP

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/37794.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/37794.shtml
英文地址,請注明出處:http://en.pswp.cn/web/37794.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

javascript 的 屬性、方法、事件

使用 javascript 設計一個學生類、(屬性:ID、姓名、性別,方法:學習、休息、,事件:上學、放學、上課、下課)學校有定時器每1秒鐘觸發一次時鐘事件,每節課45分鐘,課間15分鐘 var Stud…

13. Lammps入門in文件簡介-1

來源: “碼農不會寫詩”公眾號 鏈接:Lammps入門in文件簡介-1 文章目錄 01 in文件簡介02 in文件命令解析規則 書回正文 Lammps通過一次一行地從輸入腳本(文本文件,通常稱in文件)中讀取命令來執行計算,當輸入…

7-1作業

1.實驗目的:完成字符收發 led.h #ifndef __GPIO_H__ #define __GPIO_H__#include "stm32mp1xx_rcc.h" #include "stm32mp1xx_gpio.h" #include "stm32mp1xx_uart.h"//RCC,GPIO,UART初始化 void init();//字符數據發送 void set_tt…

Web端登錄頁和注冊頁源碼

前言&#xff1a;登錄頁面是前端開發中最常見的頁面&#xff0c;下面是登錄頁面效果圖和源代碼&#xff0c;CV大法直接拿走。 1、登錄頁面 源代碼&#xff1a; <!DOCTYPE html> <html><head><meta charset"utf-8"><title>登錄</ti…

Django 和 Django REST framework 創建對外 API

1. 環境準備 確保你已經安裝了 Python 和 Django。如果尚未安裝 Django REST framework&#xff0c;通過 pip 安裝它&#xff1a; pip install djangorestframework 2. 創建 Django 項目 如果你還沒有 Django 項目&#xff0c;可以通過以下命令創建&#xff1a; django-ad…

每日復盤-20240701

今日關注&#xff1a; 20240701 六日漲幅最大: ------1--------301182--------- 凱旺科技 五日漲幅最大: ------1--------300977--------- 深圳瑞捷 四日漲幅最大: ------1--------300977--------- 深圳瑞捷 三日漲幅最大: ------1--------300461--------- 田中精機 二日漲幅最…

Lua實現鏈表(面向對象應用)

Lua實現面向對象 面向對象核心三要素Lua面向對象大致原理面向對象示例繼承與多態示例 面向對象核心三要素 1.封裝&#xff1a;對一個事物的抽象為一些屬性和行為動作的集合&#xff0c;封裝將屬性和行為動作&#xff08;操作數據的方法&#xff09;綁定在一起&#xff0c;并隱藏…

快錢支付股東全部股權已被質押!

根據近期工商信息&#xff0c;第三方支付機構快錢支付清算信息有限公司&#xff08;簡稱“快錢支付”&#xff09;實際控股方快錢金融服務&#xff08;上海&#xff09;有限公司&#xff08;簡稱“快錢金融”&#xff09;&#xff0c;作為出質股權標的企業&#xff0c;被出質給…

【SGX系列教程】(三)Intel-SGX 官方示例分析(SampleCode)——SampleEnclave

文章目錄 一. 引言二. README2.1 項目目的2.2 構建和執行示例代碼的步驟2.3 配置參數解釋2.4 配置文件分析2.5 啟動令牌初始化 三. 重點代碼分析3.1 App文件夾3.1.1 App/App.cpp3.1.2 App/Edger8rSyntax文件夾3.1.2.1 App/Edger8rSyntax/Arrays.cpp3.1.2.2 App/Edger8rSyntax/F…

一文全概括,建議收藏,那些你不可錯過的IC設計書籍合集(可下載)

集成電路設計工程師的角色不僅是推動技術創新的中堅力量&#xff0c;更是實現產品從概念到現實的關鍵橋梁。隨著對高性能、低功耗芯片的需求不斷增長&#xff0c;IC設計工程師的專業技能和知識深度成為了衡量其職業價值的重要標準。無論是在數字邏輯設計、功能驗證、可測試性設…

JMeter--定時執行的方法

原文網址&#xff1a;JMeter--定時執行的方法_IT利刃出鞘的博客-CSDN博客 簡介 本文介紹JMeter如何使用定時器定時執行測試任務。 Java技術星球&#xff1a;way2j.com 方法 第一步&#xff1a;新建定時器 右鍵測試任務> Add > Timer> Constant Timer 如下圖所示…

qt中數據庫和excel互導數據————附帶詳細步驟和代碼

文章目錄 0 背景1 準備QXlsx環境1.1 cmake安裝使用1.2 qmake使用 2 把excel數據導出到mysql數據庫3 把mysql數據庫的數據寫入到excel4 完整代碼5 項目代碼倉庫 0 背景 因為需要批量導入和導出數據&#xff0c;所以需要用到excel。實現把數據庫的數據導入到excel中&#xff0c;…

圓圈序號1~10復制粘貼直接用

1. 空心圓圈數字序號&#xff1a; ①、②、③、④、⑤、⑥、⑦、⑧、⑨、⑩ 2. 實心圓圈數字序號&#xff1a; ?、?、?、?、?、?、?、?、?、? 3. 空心圓圈中文序號&#xff1a; 一、二、三、四、五、六、七、八、九、十

linux高級編程(線程)(1)

虛擬地址&#xff1a; 線程&#xff1a; 概念&#xff1a;線程是輕量級進程&#xff0c;一般是一個進程中的多個任務。 進程是系統中最小的資源分配單位。&#xff08;競爭計算機資源的最小單位&#xff09;&#xff08;進程能分配硬件資源&#xff0c;線程不行&#x…

解析QAnything啟動命令過程

一.啟動命令過程日志 啟動命令bash ./run.sh -c local -i 0 -b hf -m Qwen-1_8B-Chat -t qwen-7b-chat。輸入日志如下所示&#xff1a; rootMM-202203161213:/mnt/l/20230918_RAG方向/QAnything# bash ./run.sh -c local -i 0 -b hf -m Qwen-1_8B-Chat -t qwen-7b-chat From …

Leetcode Java學習記錄——棧和隊列 IDEA

文章目錄 棧和隊列stack Classqueue InterfaceDeque Interfaceadd 和 push Priority Queue -- Class題目 codestyleIDEA 操作快捷鍵選擇代碼生成類 棧和隊列 stack Class google stack java 8/12 empty() peek() pop() push(E item) search(Object o) 最近相關性會用到棧 …

湘潭大學軟件工程數據庫總結

文章目錄 前言試卷結構給學弟學妹的一些參考自己的一些總結 前言 自己可能很早很早之前就準備復習了&#xff0c;但是感覺還是沒有學到要點&#xff0c;主要還是沒啥緊迫的壓力&#xff0c;我們是三月份開學&#xff0c;那時候實驗室有朋友挺認真開始學習數據庫了&#xff0c;…

理性決策的藝術:從購房到擇偶的數學智慧;37% 規則,做出最佳決策的秘訣;用數學模型解決人生難題

在面對人生重大決策時&#xff0c;如購房或擇偶&#xff0c;我們常常感到迷茫和困惑。然而&#xff0c;如果我們能夠將這些看似復雜的問題簡化為數學模型&#xff0c;我們就能以更加理性和系統的方式做出決策。 37%規則 1950年代&#xff0c;當時幾位數學家開始研究這樣一個問…

值得收藏!盤點那些適合普通人方便又好用的AIGC工具!(下)

【導讀】接上一篇文章&#xff0c;盤點國內外適合普通人能夠輕松上手的AIGC工具&#xff08;上&#xff09;。今天又為大家整理了一些好用又方便的AI設計工具、AI辦公工具、AI編程工具、AI指令工具和AI檢測工具&#xff0c;如果有沒更新到的工具也歡迎大家評論區交流。 一 、A…

Kafka 入門指南

Kafka 入門指南 簡介 Kafka 是一個由 Apache 軟件基金會開發的開源流處理平臺。它最初由 LinkedIn 開發&#xff0c;并在 2011 年作為開源項目發布。Kafka 是一個分布式、可擴展、高吞吐量的消息隊列系統&#xff0c;廣泛應用于實時數據流處理場景。 主要概念 1. 主題 (Top…