nginx 真實IP Remote-Addr X-Forwarded-For X-Real-IP

工作中做負載均衡的時候回經常用到。在這裏記錄下。

普及下各個機器的名稱

發送請求方的機器 名稱叫客戶端。
請求轉發和反向代理的機器叫負載均衡或者LB
最終邏輯處理的機器叫WEB機器。【碼農寫的邏輯基本上都在WEB機器上】

先說下我們的測試的機器IP分佈。

客戶端IP 100.100.100.1
負載均衡LB 100.100.100.2
web機器 100.100.100.3

remote_addr

客戶端的IP,如果有代理的話表示最後一個代理服務器的IP。Nginx變量。這個變量是建立TCP連接的IP變量。remote_addr所表示的IP是不可更改的。試想下,如果這個變量可隨意更改的話,都無法建立正常的TCP連接。
LB上設置

proxy_set_header   REMOTE-ADDR      100.100.100.100;

WEB機器上打印

ngx.log(ngx.ERR,ngx.req.get_headers()['remote_addr'])
ngx.log(ngx.ERR, ngx.var.remote_addr)

[error] 7566#7566: *5914 [lua] test.lua:
proxy_set_header   REMOTE-ADDR      100.100.100.100
[error] 7566#7566: *5914 [lua] test.lua    100.100.100.2

不管怎麼設置,最終Nginx變量的值都是建立連接的IP。而且需要注意的是header裏面的值和變量裏面的值是不相同的

X-Forwarded-For

Nginx變量,如果每個代理服務器都設置了
proxy_set_header X-Forwarded-For KaTeX parse error: Double subscript at position 12: proxy_add_x_̲forwarded_for 是…remote_addr用逗號合起來,如果請求頭中沒有X-Forwarded-For則KaTeX parse error: Double subscript at position 12: proxy_add_x_̲forwarded_for爲remote。
會記錄請求的路由順序。這個變量只是記錄請求的服務器路由順序。因爲這個變量不管在客戶端還是代理服務商都是可以僞造的。
我們做下測試

ngx.log(ngx.ERR, ngx.var.http_x_forwarded_for)
100.100.100.1 ,100.100.100.2

基本是按照發起方的請求順序記錄的,顯示客戶端IP,然後代理服務器的IP。如果有多層代理的話,就是這樣的

客戶端IP,proxy1,proxy2,proxyN

而且是當前機器追加記錄上一個機器的IP。proxy1追加就客戶端IP,proxy2追加記錄proxy1.
如果請求的時候僞造X-Forwarded-For即加header頭 -H ‘X-Forwarded-For:1.1.1.1,2.2.2.2’。就會是

僞造IP,客戶端IP,proxy1,proxy2,proxyN

所以說取真實IP直接獲取X-Forwarded-For的第一個IP是不合理的。

如果是服務器上,不傳遞X-Forwarded-For,即
proxy_set_header X-Forwarded-For 沒有這個。那下一級的X-Forwarded-For這個變量就是空的。所以X-Forwarded-For 這個值主要是proxy_set_header 傳遞。

X-Real-IP

顧名思義真實IP。這個變量主要是用來記錄真實IP。這個值也主要是以來proxy_set_header傳遞。可以先看下使用

100.100.100.2
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

100.100.100.3
ngx.log(ngx.ERR, ngx.var.http_x_forwarded_for)
ngx.log(ngx.ERR, ngx.var.http_x_real_ip)

100.100.100.1,100.100.100.2
100.100.100.1

可以看到,使用得當,x_real_ip是可以很輕鬆的拿到真實IP。
如果是多級代理的話,一級一級向後傳遞真實IP。

第一級代理寫法
proxy_set_header X-Real-IP $remote_addr;
後面的代理
proxy_set_header X-Real-IP $x_real_ip;

總結

X-Forwarded-For與X-Real-IP 主要依賴proxy_set_header傳遞,所以想傳什麼樣的值就傳什麼樣的值。Remote-Addr建立連接的IP,有的地方也說是上一跳的IP,這個不依賴header頭傳遞,不可更改。
所以用上面的組合,第一層代理獲取到真實IP,remote_addr。使用x_real_ip層層後傳,使用x_real_ip在WEB機器上獲取到真實IP。
真實IP的獲取順序是 先檢查x_real_ip有無值,有就返回。沒有再檢查Remote-Addr有無值,有就返回。X-Forwarded-For主要記錄請求路由順序,可僞造。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章