負載均衡後獲取客戶端真實ip
String ip3=request.getRemoteAddr(); 如果沒有配負載均衡,則request.getRemoteAddr() 獲取的就是真實客戶端IP,如果配了nginx負載均衡,則request.getRemoteAddr() 獲取的是負載均衡nginx伺服器的ip,而不是真實客戶端IP。
那麼問題來了,經過nginx負載均衡後,如何獲取客戶端真實ip?
location / {
root html;
index index.html index.htm;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://192.168.81.188:8080;
}
程式碼中,Header中使用“X-Forwarded-For”欄位或“X-Real-IP”欄位獲取Client真實 IP。
以一個servlet為例:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub //response.getWriter().append("Served at: ").append(request.getContextPath()); PrintWriter writer = response.getWriter(); //也可以使用小寫的欄位 String ip=request.getHeader("x-forwarded-for"); String ip=request.getHeader("X-Forwarded-For"); writer.println("x-forwarded-for_ip: "+ip); //也可以使用小寫的欄位 String ip2=request.getHeader("x-real-ip"); String ip2=request.getHeader("X-Real-IP"); writer.println("x-real-ip: "+ip2); String ip3=request.getRemoteAddr(); writer.println("RemoteAddr: "+ip3); }
注意:從Header中獲取欄位的時候,是不區分大小寫的。所以 request.getHeader("x-forwarded-for")和request.getHeader("X-Forwarded-For")以及request.getHeader("x-FORWARded-for")效果是一樣的。
如果通過了多級反向代理的話,X-Forwarded-For的值不止一個,而是一串IP值,此時取第一個IP地址就可以了,第一個IP代表客戶端真實IP,比如:
分析:
從CSN開始,每經過一個代理做一次轉發,x_forwarded_for就會在後面追加一個代理IP。請求到達nginx時,x_forwarded_for已經變成一個以逗號分隔的ip串,並且以轉發順序排序。
nginx的內建變數remote_addr(
舉例:如圖,我經過兩層代理,最終到達後端真實業務伺服器:
瀏覽器訪問結果: