Nginx CloudFlare 客戶端真實IP


問題再現

由於 tomcat 被 Nginx 反向代理, 因此request.getRemoteAddr()只能獲取到本地回環地址,
Nginx 提供了變量 $remote_addr, 可用於使用 proxy_set_header 設置頭信息, 實現向上游的 tomcat 服務器提供遠端客戶端IP地址

proxy_set_header X-Real-IP $remote_addr;

但是, 一旦使用了 CDN 的話, 這個地址就變成了 CDN 節點的地址, 並且同一個用戶不同時間發出的IP都不一樣.
CDN 通常會在 Header 中提供客戶端真實IP, 如 CloudFlare 在 x-forwarded-for, cf-connecting-ip 中設置了此數據.

Nginx 提供了變量 $http_x_forwarded_for 用於獲取 x-forwarded-for 的值, 因此可以在 Nginx 配置文件中為 X-Real-IP 設置以下兩個值:

remote_addr
http_x_forwarded_for

它們分別代表了未使用 CDN 和使用了 CDN 的客戶端真實IP.



# Nginx 配置實現
                #CloudFlare
                set $CDN "CloudFlare";
                #set $CDN "NO"; # 如果未使用 CloudFlare, 則取消該行代碼的注釋

                set $Real_IP $remote_addr;
                if ($CDN = "CloudFlare") {
                        set $Real_IP $http_x_forwarded_for;
                }

                #設置代理 Header
                proxy_set_header Host $host;
                proxy_set_header X-Real-IP $Real_IP;
                ......


# 民間傳說, 一個電信反代的 CF IP

104.25.183.205

這個IP的電信延遲非常低, 而且速度非常不錯, 你懂的!

當自選該IP后, x-real-ip 也就是 x-forwarded-for 變成了 59.174.137.107,140.206.61.106
cf-connecting-ip 更是變成了被反代的 140.206.61.106

這種特殊情況應當被考慮.

所以我寫了一個 static 方法, 用來從 HttpServlet 中獲取 Real-IP:

package common;

import javax.servlet.http.HttpServletRequest;

/**
 * 系統工具 & 配置
 */

public class Sys {
	private static final CDN cdn;

	private enum CDN {
		Nginx, CloudFlare,

	}

	static {
		cdn = CDN.Nginx;
	}

	public static String getRemoteIP(HttpServletRequest thiz) {
		switch (cdn) {
		case Nginx:
			return thiz.getHeader("X-Real-IP");
		case CloudFlare:
			return thiz.getHeader("CF-Connecting-IP");
		default:
			return thiz.getRemoteAddr();
		}
	}
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM