反向代理與Real-IP和X-Forwarded-For(轉)

如下圖所示,客戶端通過Nginx Proxy1 和 Nginx Proxy2 兩層反向代理才訪問到具體服務Nginx Backend(或如Tomcat服務)。那Nginx Backend如何才能拿到真實客戶端IP呢?

接下來我們來看看如何才能獲取到客戶端真實IP。


場景1
  場景1是很簡單的場景,Nginx Proxy直接把請求往后轉發,沒有做任何處理。
  Nginx Proxy
  192.168.107.107 nginx.conf
  location /test {
  proxy_pass http://192.168.107.112:8080;
  }
  192.168.107.112 nginx.conf
  location /test {
  proxy_pass http://192.168.107.114:8080;
  }
  Nginx Proxy就是簡單的把請求往后轉發。
  Nginx Backend
  192.168.107.114 nginx.conf
  location /test {
  default_type text/html;
  charset gbk;
  echo "$remote_addr || $http_x_forwarded_for";
  }
  Nginx Backend輸出客戶端IP($remote_addr)和X-Forwarded-For請求頭($http_x_forwarded_for),當訪問服務時輸出結果如下所示:
  192.168.107.112 ||
  分析
$remote_addr代表客戶端IP,當前配置的輸出結果為最后一個代理服務器的IP,并不是真實客戶端IP;
在沒有特殊配置情況下,X-Forwarded-For請求頭不會自動添加到請求頭中,即Nginx Backend的$http_x_forwarded_for輸出為空。


場景2
  場景2通過添加X-Real-IP和X-Forwarded-For捕獲客戶端真實IP。
  Nginx Proxy
  192.168.107.107 nginx.conf
  location /test {
  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_pass http://192.168.107.112:8080;
  }
  192.168.107.112 nginx.conf
  location /test {
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_pass http://192.168.107.114:8080;
  }
  Nginx Backend
  192.168.107.114 nginx.conf
  location /test {
  default_type text/html;
  charset gbk;
  echo "$remote_addr ||$http_x_real_ip ||$http_x_forwarded_for";
  }
  當訪問服務時,輸出結果為:
  192.168.107.112 || 192.168.162.16 || 192.168.162.16, 192.168.107.107
  分析

  1. 在離用戶最近的反向代理NginxProxy 1,通過“proxy_set_header X-Real-IP $remote_addr”把真實客戶端IP寫入到請求頭X-Real-IP,在NginxBackend輸出$http_x_real_ip獲取到了真實客戶端IP;而Nginx Backend的“$remote_addr”輸出為最后一個反向代理的IP;
  2. “proxy_set_headerX-Forwarded-For $proxy_add_x_forwarded_for”的是把請求頭中的X-Forwarded-For與$remote_addr用逗號合起來,如果請求頭中沒有X-Forwarded-For則$proxy_add_x_forwarded_for為$remote_addr。

  X-Forwarded-For代表了客戶端IP,反向代理如Nginx通過$proxy_add_x_forwarded_for添加此項,X-Forwarded-For的格式為X-Forwarded-For:real client ip, proxy ip 1, proxy ip N,每經過一個反向代理就在請求頭X-Forwarded-For后追加反向代理IP。
  到此我們可以使用請求頭X-Real-IP和X-Forwarded-For來獲取客戶端IP及客戶端到服務端經過的反向代理IP了。這種方式還是很麻煩,$remote_addr并不是真實客戶端IP。


場景3
  為了更方便的獲取真實客戶端IP,可以使用nginx http_realip_module模塊解決,在安裝nginx時通過--with-http_realip_module安裝該模塊。NginxProxy配置和場景2一樣。
  Nginx Backend
  192.168.107.114 nginx.conf
  real_ip_header X-Forwarded-For;
  set_real_ip_from 192.168.0.0/16;
  real_ip_recursive on;
  location /test {
  default_type text/html;
  charset gbk;
  echo "$remote_addr || $http_x_real_ip ||$http_x_forwarded_for";
  }
  當訪問服務時,輸出結果為:
  192.168.162.16 || 192.168.162.16 || 192.168.162.16, 192.168.107.107
  分析

  1. X-Real-IP和X-Forwarded-For和場景2一樣;
  2. 使用realip模塊后,$remote_addr輸出結果為真實客戶端IP,可以使用$realip_remote_addr獲取最后一個反向代理的IP;
  3. real_ip_headerX-Forwarded-For:告知Nginx真實客戶端IP從哪個請求頭獲取,如X-Forwarded-For;
  4. set_real_ip_from192.168.0.0/16:告知Nginx哪些是反向代理IP,即排除后剩下的就是真實客戶端IP,支持配置具體IP地址、CIDR地址;
  5. real_ip_recursive on:是否遞歸解析,當real_ip_recursive配置為off時,Nginx會把real_ip_header指定的請求頭中的最后一個IP作為真實客戶端IP;當real_ip_recursive配置為on時,Nginx會遞歸解析real_ip_header指定的請求頭,最后一個不匹配set_real_ip_from的IP作為真實客戶端IP。

  如果配置“real_ip_recursive off; ”,則輸出結果為:
  192.168.107.107 || 192.168.162.16 ||192.168.162.16, 192.168.107.107


  總結

  1. 通過“proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for” 把從真實客戶端IP和反向代理IP通過逗號分隔,添加到請求頭中;
  2. 可以在第一個反向代理上配置“proxy_set_header X-Real-IP $remote_addr” 獲取真實客戶端IP;
  3. 配合realip模塊從X-Forwarded-For也可以獲取到真實客戶端IP。

  在整個反向代理鏈條的第一個反向代理可以不配置“proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for”,否則客戶端可以偽造X-Forwarded-For從而偽造客戶端真實IP,如果服務端使用X-Forwarded-For第一個IP作為真實客戶端IP,則就出問題了。如果通過配置X-Real-IP請求頭或者配合realip模塊也不會出現該問題。如果自己解析X-Forwarded-For的話,記得使用realip算法解析,而不是取第一個。
  當我們進行限流時一定注意限制的是真實客戶端IP,而不是反向代理IP,我遇到過很多同事在這塊出問題的。

?

轉載于:https://www.cnblogs.com/yunweiqiang/p/8488746.html

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

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

相關文章

Android studio打開之后 cannot load project: java.lang.NUllpointerException

參考來源:http://bbs.csdn.net/topics/391014393 關閉網絡,重新打開Android studio就好了。(但是原因不清楚是為什么?) Internal error. Please report to http://code.google.com/p/android/issuescom.intellij.ide.p…

Val編程-任務編程

不同任務之間可以通過一個標志符來實現互斥事件。 程序代碼&#xff1a; Task2 <span style"font-size:12px;">beginwhile truewait(bTaskFlag)cls()gotoxy(1,1)put("這是Task2")gotoxy(1,2)if bTaskFlagput("BFlag:true ")elseput(&…

【pyqt5學習】——拖拽功能(DragDrop)、剪切板(QApplication.clipboard)

目錄 1、拖拽功能&#xff08;Drag&Drop&#xff09; 2、剪切板&#xff08;QApplication.clipboard&#xff09; 1、拖拽功能&#xff08;Drag&Drop&#xff09; 選擇文本輸入框中的文本&#xff0c;移動到下拉框中自動添加步驟&#xff1a; 1、將文本輸入框設置為可…

oracle12c之 控制pdb中sga 與 pga 內存使用

Memory Management using Resource Manager Oracle數據庫資源管理器(資源管理器)現在可以在多租戶容器數據庫(CDB)中管理可插入數據庫(PDBs)之間的內存使用。這一特性有助于在CDB中維護所有PDBs的性能&#xff0c;確保所有的PDBs都不會占用更多資源&#xff0c;從而導致其他PDB…

[LeetCode] 21. Merge Two Sorted Lists ☆

Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the nodes of the first two lists. 解法&#xff1a; 新建一個鏈表&#xff0c;依次比較兩個鏈表的頭元素&#xff0c;把較小的移到新鏈表中&#xff0c;直到有…

Val編程-特殊函數使用

Waitendmove()和$Waitendmove()使用心得 這是兩個部分&#xff0c;程序運行部分和運動堆棧部分&#xff0c;waitendmove是兩個部分進行交互的一個函數。 一般情況下waitendmove()速度會降到0&#xff0c;相當于blend等于off. 代碼&#xff1a; begincls()userPage()title("…

Redis的五種數據結構

Redis支持持久化只是它的一件武器&#xff0c;它提供了多達5種數據存儲方式&#xff1a; 一 string&#xff08;字符串&#xff09; string是最簡單的類型&#xff0c;你可以理解成與Memcached一模一樣的類型&#xff0c;一個key對應一個value&#xff0c;其上支持的操作與Mem…

【pyqt5學習】——QDateTimeEdit控件學習

目錄 1、同時顯示日期時間QDateTime 2、只顯示日期QDate 3、只顯示時間QTime 4、設置顯示的格式setDisplayFormat 5、 QDateTimeEdit常用信號 6、實例 1、同時顯示日期時間QDateTime # 同時顯示日期時間dateTimeEdit1 QDateTimeEdit()dateTimeEdit2 QDateTimeEdit(QDat…

復選框做成單選效果

function zlClick($id){ var eles document.getElementById($id).children; var srcEle event.srcElement; for(var i0;i<eles.length;i){ if(srcEle.checked){ if(eles[i].value!srcEle.value){ eles[i].checkedfalse; } } } } 技術領域可信計算 其他 申請日 200020012…

013. MVC5過濾器

微軟提供了4中過濾器: 1.Action過濾器: 在Action方法執行之前和Action方法執行之后, 會執行此過濾器中的代碼. 比如在執行public ActionResult Index()方法之前或之后; 也可以說是在方法執行前或執行后; 接口: IactionFilter 抽象類名: ActionFilterAttribute 添加一個實現…

Val編程-讀取漢字

Val編程-讀取漢字 Val編程中&#xff0c;對于漢字的讀取不是很友好&#xff0c;利用fileget直接讀取記事本產生的文件字符串會導致亂碼的產生。因為Val只支持使用utf-8進行編碼&#xff0c;因此讀取的文本需要進行utf-8格式轉換。 在GBK中&#xff0c;漢字占兩個字節。并且…

【pyqt5學習】——菜單欄(QMenu())、工具欄QToolBar學習

目錄 1、菜單欄&#xff08;QMenu()&#xff09;——一般在窗口頂部 1&#xff09;創建菜單欄步驟 2&#xff09;信號與方法 3&#xff09;實操 2、工具欄——一般在菜單欄下方 1&#xff09;創建步驟 2&#xff09;方法與信號 信號&#xff1a; 方法&#xff1a; 3&am…

Java核心技術及面試指南 異常部分的面試題歸納以及答案

4.2.4.1 throw和throws有什么差別&#xff1f;異常&#xff08;Exception&#xff09;和錯誤&#xff08;Error&#xff09;有什么差別&#xff1f; throw語句表示拋出異常&#xff0c;由方法體內的語句處理。throws語句用在方法聲明后面&#xff0c;表示如果拋出異常&#xff…

win7win10 配置wlan熱點

win7 & win10 系統自帶wlan功能&#xff0c;配置方法如下&#xff1a; 命令行輸入: 1. netsh wlan set hostednetwork mode allow ssid "Haha" key12345678 2. netsh wlan start hostednetwork netsh wlan show hostednetwork 轉載于:https://www.cnblogs.com/…

java---Socket編程出現的異常種類

.java.net.SocketTimeoutException.這個異常比較常見&#xff0c;socket超時。一般有2個地方會拋出這個&#xff0c;一個是connect的時候&#xff0c;這個超時參數由connect(SocketAddress endpoint,int timeout)中的后者來決定&#xff0c;還有就是setSoTimeout(int timeout)&…

【pyqt5學習】——利用Pyqt5連接打印機(QtPrintSupport、QPrintDialog、QPageSetupDialog)

目錄 1、利用QtPrintSupport直接連接打印機——不常用 1&#xff09;基本知識 2&#xff09;完整代碼案例 3&#xff09;結果 2、 打印對話框QPrintDialog、打印設置對話框QPageSetupDialog 1&#xff09;彈出打印設置對話框 2&#xff09;彈出打印對話框 注&#xff1a…

Val編程-按鍵響應模式

由于Val是通過語句gotoxy函數來進行光標移動的&#xff0c;不支持觸摸屏與鼠標&#xff0c;因此對于其界面編程有很大的局限。 一般有下面幾種模式來進行編程。 1.按鍵響應模式&#xff08;中斷模式&#xff09; 2.輪詢模式 一般推薦使用按鍵響應模式。其原理是對于有按鍵按下…

[Android]SQLite的使用

Android 數據存儲提供了四種存儲方式&#xff1a; Shared Preferences 使用鍵值對&#xff08;Map(key, value)&#xff09;來存儲數據 Internal Storage 內部存儲&#xff0c;存儲在設備內存的 私人數據 External Storage 外部存儲&#xff0c;存儲在外部設備的 公共數據…

第一百四十五節,JavaScript,同步動畫

JavaScript&#xff0c;同步動畫 將上一節的&#xff0c;移動透明動畫&#xff0c;修改成可以支持同步動畫&#xff0c;也就是可以給這個動畫方法多個動畫任務&#xff0c;讓它同時完成 原理&#xff1a; 向方法里添加一個屬性&#xff0c;這個屬性是一個對象&#xff0c;同步動…

Exchange Server 2016管理系列課件39.新建本地移動請求

場景通過新建本地移動請求&#xff0c;可以很方便的將用戶郵箱從一個數據庫遷移到另外一個數據庫。1&#xff09;跨平臺郵件遷移&#xff1b;&#xff08;低exchange遷移到高版本exchange&#xff09;2&#xff09;數據庫平衡與優化&#xff1b;&#xff08;企業當中&#xff0…