程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> 如何取得nginx做反向代理時的真實IP?

如何取得nginx做反向代理時的真實IP?

編輯:JAVA綜合教程

如何取得nginx做反向代理時的真實IP?


nginx做反向代理時的真實IP.pdf

1.編譯

對於client->nginxreverseproxy->apache,

要想在程序中取得真實的IP,在執行nginx的configure時,必須指定參數“--with-http_realip_module”,示例:

./configure--prefix=/data/nginx--with-http_realip_module--with-stream--with-pcre=/tmp/X/pcre-8.32--with-openssl=/tmp/X/openssl-1.0.2a

參數說明:

--prefix=指定安裝目錄,也就是makeinstall後程序文件等的存放目錄

--with-http_realip_module使得程序可以通過環境變量HTTP_X_REAL_IP取得真實的客戶端IP地址

--with-stream表示啟用TCP代理

--with-pcre=指定依賴的pcre,注意為pcre源代碼解壓後的目錄路徑,而不是安裝路徑

--with-openssl=指定依賴的openssl,注意為openssl源代碼解壓後的目錄路徑,而不是安裝路徑

另外,最簡單的確認方法是使用nm命令查看nginx程序文件,看看是否有包含real相關的符號,對於版本nginx-1.9.4,可以發現存在“0809c54btngx_http_realip”。

2.程序代碼

測試程序代碼(後續測試基於它):

//g++-g-ohello.cgihello.cpp

#include<stdio.h>

#include<stdlib.h>

intmain()

{

printf("Content-Type:text/html;charset=utf-8\r\n\r\n");

printf("<p>HTTP_X_FORWARDED_FOR:%s\n",getenv("HTTP_X_FORWARDED_FOR"));

printf("<p>HTTP_X_REAL_IP:%s\n",getenv("HTTP_X_REAL_IP"));

printf("<p>REMOTE_ADDR:%s\n",getenv("REMOTE_ADDR"));

printf("<p>");

return0;

}

測試是在nginx自帶配置文件nginx.conf上進行的修改:

proxy_set_header可以添加在nginx.conf的http段,也可以是server段,還可以是location段,一級一級間是繼承和覆蓋關系。

3.相關配置

示例:

location/{

#roothtml;

#indexindex.htmlindex.htm;

proxy_passhttp://20.61.28.11:80;

proxy_redirectoff;

proxy_set_headerHost$host;

proxy_set_headerX-Real-IP$remote_addr;#這個是必須的

proxy_set_headerX-Forwarded-For$proxy_add_x_forwarded_for;

}

X-Forwarded-For和X-Real-IP的區別是,如果請求時已帶了X-Forwarded-For,則nginx追加方式,這樣可以通過它顯示轉發的軌跡。

當然請求時完全可以構造假的X-Forwarded-For,在配置文件打開了X-Real-IP及編譯指定了--with-http_realip_module時,環境變量HTTP_X_REAL_IP總是為真實的客戶端IP。

如果是:

client->nginxreverseproxy(A)->nginxreverseproxy(B)->apache

HTTP_X_REAL_IP又會是什麼了?

4.測試1

假設如下部署:

client(10.6.81.39)->nginx(10.6.223.44:8080)->nginx(10.6.208.101:8080)->apache(10.6.208.101:80)

?A

假設nginx(10.6.223.44:8080)的配置均為(在nginx默認配置上的修改部分):

server{

listen8080;

server_name10.6.223.44;

location/{

#roothtml;

#indexindex.htmlindex.htm;

proxy_passhttp://10.6.208.101:8080;

proxy_redirectoff;

proxy_set_headerHost$host;

proxy_set_headerX-Real-IP$remote_addr;

proxy_set_headerX-Forwarded-For$proxy_add_x_forwarded_for;

}

假設nginx(10.6.208.101:8080)的配置均為(在nginx默認配置上的修改部分):

server{

listen8080;

server_name10.6.208.101;

location/{

#roothtml;

#indexindex.htmlindex.htm;

proxy_passhttp://10.6.208.101:80;

proxy_redirectoff;

proxy_set_headerHost$host;

proxy_set_headerX-Real-IP$remote_addr;

proxy_set_headerX-Forwarded-For$proxy_add_x_forwarded_for;

}

上述測試程序輸出的結果為:

<p>HTTP_X_FORWARDED_FOR:10.6.81.39,10.6.223.44

<p>HTTP_X_REAL_IP:10.6.223.44

<p>REMOTE_ADDR:10.6.81.39

?B

但如果client在HTTP請求頭中加入:

X-FORWARDED-FOR:8.8.8.7

CLIENT-IP:8.8.8.8

X-REAL-IP:8.8.8.10

後輸出結果變成:

<p>HTTP_X_FORWARDED_FOR:8.8.8.7,10.6.81.39,10.6.223.44

<p>HTTP_X_REAL_IP:10.6.223.44

<p>REMOTE_ADDR:8.8.8.7

?C

基於A,如果只nginx(10.6.223.44:8080)配置注釋掉“X-Forwarded-For”,輸出結果變成:

<p>HTTP_X_FORWARDED_FOR:10.6.223.44

<p>HTTP_X_REAL_IP:10.6.223.44

<p>REMOTE_ADDR:10.6.223.44

?D

基於A,如果只nginx(10.6.208.101:8080)配置注釋掉“X-Forwarded-For”,輸出結果變成:

<p>HTTP_X_FORWARDED_FOR:10.6.81.39

<p>HTTP_X_REAL_IP:10.6.223.44

<p>REMOTE_ADDR:10.6.81.39

5.測試2

基於測試1的配置,

當訪問路徑變成:client(10.6.81.39)->nginx(10.6.208.101:8080)->apache(10.6.208.101:80)時,程序輸出結果為:

<p>HTTP_X_FORWARDED_FOR:10.6.81.39

<p>HTTP_X_REAL_IP:10.6.81.39

<p>REMOTE_ADDR:10.6.81.39

但如果client在HTTP請求頭中加入:

X-FORWARDED-FOR:8.8.8.7

CLIENT-IP:8.8.8.8

X-REAL-IP:8.8.8.10

後輸出結果變成:

<p>HTTP_X_FORWARDED_FOR:8.8.8.7,10.6.81.39

<p>HTTP_X_REAL_IP:10.6.81.39

<p>REMOTE_ADDR:8.8.8.7

從上可以看出,只配置正確使用了real-ip功能,除HTTP_X_REAL_IP外,其它內容可以被干擾,client可以篡改它們。

6.結論

如果正確編譯和配置了nginx反向代理,當只有一層nginx反向代理時,可以通過“HTTP_X_REAL_IP”取得client的真實IP。

如果有二層nginx反向代理,則client的真實IP被包含在“HTTP_X_FORWARDED_FOR”中。

最不可信的是“REMOTE_ADDR”,它的內容完全可以被client指定!總之只要編譯和配置正確,“HTTP_X_FORWARDED_FOR”總是包含了client的真實IP。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved