1. 程式人生 > 其它 >Nginx 與 X-Forwarded-For

Nginx 與 X-Forwarded-For


HTTP擴充套件頭部 X-Forwarded-For,以及在nginx中使用http_x_forwarded_for變數來完成一些"特殊"功能,例如網站後臺面向內部工作人員,希望只允許辦公室網路IP訪問。

X-Forwarded-For,它用來記錄代理伺服器的地址,每經過一個代理該欄位會追加上一個記錄。例如:6.6.6.6, 8.8.8.8。


拿出生產環境的一個例子,客戶端瀏覽網站發出一個請求,請求先經過阿里雲SLB負載均衡器,然後進入Rancher內部的LB負載均衡器,經過兩次負載均衡器轉發後請求到達nginx伺服器。


X-Forwarded-For HTTP擴充套件頭部

日誌中的記錄表示 client: 101.251.xxx.192 、proxy1: 100.97.xxx.187,不是說 X-Forwarded-For用來記錄代理伺服器的地址,每經過一個代理該欄位會追加上一個記錄,為什麼client IP 會出現在這個欄位中呢?

帶著疑惑這裡有必要專門講一講 X-Forwarded-For HTTP頭部。X-Forwarded-For 是一個 HTTP擴充套件頭部,HTTP/1.1(RFC 2616)協議並沒有對它的定義,它最開始是由 Squid快取代理軟體引入,用來表示 HTTP請求端真實IP。最終成為事實上的標準被寫入 RFC 7239(Forwarded HTTP Extension)標準之中。

X-Forwarded-For 標準格式

X-Forwarded-For: client, proxy1, proxy2

從標準格式可以看出,X-Forwarded-For頭部資訊可以有多個,中間使用逗號分隔,第一項為真實的客戶端IP剩下的就是經過的代理或負載均衡的IP地址,經過幾個就會出現幾個。

回到上面的示例,HTTP請求到達nginx伺服器之前,經過了兩個代理Proxy1、Proxy2,IP 分別為IP1、IP2,使用者真實IP為 IP0,那麼按照 XFF標準格式,nginx伺服器最終的XFF變數如下:

X-Forwarded-For: IP0, IP1

Proxy2是直連伺服器的,它會給 XFF追加IP1

,表示它是在幫 Proxy1轉發請求,IP2是在服務端通過 Remote Address 獲得。Remote Address 也無法偽造,因為建立TCP連線需要三次握手,如果偽造了源IP,無法建立TCP連線,更不會有後面的 HTTP請求。


nginx 中的 http_x_forwarded_for 變數用來表示 X-Forwarded-For ,下面用一個例子說明 nginx 如何使用 http_x_forwarded_for,例如借用這個變數限制網站後臺訪問。

1. 環境

browser -> haproxy -> nginx

目標判斷 haproxy負載均衡傳遞的 http_x_forwarded_for變數,確定是否為辦公室IP?是否允許訪問網站後臺?

2. 方法

a. 修改 nginx 虛擬主機配置檔案,新增以下語句。

cat default.conf

server  
{    
  #... 其它配置項省略

    location ^~ /admin/ {

      if ($http_x_forwarded_for !~ 'your_office_ip') {
         return 403;
      }
      
      #... 其它配置項省略    
    }

}

b. 重新載入

nginx -t && nginx -s reload

c. 偽造XFF

需要特別說明的是XFF是可以偽造的,例如使用curl 傳送一個帶有"X-Forwarded-For:8.8.8.8"的頭部資訊。

curl -IL -H "X-Forwarded-For:8.8.8.8" https://www.test.com/static/09.png

假設你採用XFF對比IP方式來限制網站後臺訪問,如果對方知道你的網站在用這個策略限制後臺訪問,並且通過一些方法知道了你辦公室的IP地址,那麼這個策略也就失效了。如果你的網站"前後臺"可以分離,那麼可以為分離後的後臺伺服器新增防火牆規則,通過網路層限制來源IP地址達到同樣目的。