JAVA obtains real IP address: Is the IP address you obtained real?

You must be familiar with this code:

public String getIpAddr(HttpServletRequest request) {
	String ip = request.getHeader("x-forwarded-for");
	if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
		ip = request.getHeader("Proxy-Client-IP");
	}
	if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
		ip = request.getHeader("WL-Proxy-Client-IP");
	}
	if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
		ip = request.getRemoteAddr();
	}
	return ip;
}


Yes, most of the "java gets real IP address" you searched for. However, is the above code really correct?
So let's look at the specific code. As above, the priority of judging the ip address is "x-forwarded-for">"Proxy-Client-IP">"WL-Proxy-Client-IP">request.getRemoteAddr(), where the quotation marks are from the header obtained.
etc! We all know that the value in the header can be changed.
for example:
$.ajax({
	type : "GET",
	headers : {"X-Forwarded-For":randomIp,"WL-Proxy-Client-IP":randomIp},
	contentType : 'application/x-www-form-urlencoded;charset=utf-8',
	url : url,
	data:params,
	dataType : "text",
	success : function(data) {
		count++;
		console.log("Time: ["+new Date()+"] Successful execution: ["+count+"] times: "+data);
	if(max>0){
		setTimeout(function wait(){
			console.log("等待"+(timeWait)+"ms ...");
			vote(max,getRandomNum(maxWait,minWait));
		}, timeWait);
	}
	}
});

Code from: https://github.com/caiyongji/vote-2.0/blob/master/Vote-2.0.js

The headers attributes X-Forwarded-For, WL-Proxy-Client-IP are not changed?
So, why is there this version of the "java get real IP address" method? And most of the results that search engines can retrieve are this one?
For example, if the solution is a cheat book, then all we find is the "java gets the real IP address" scrap .
And the rest is here:
#nginx settings
location  ~  ^/static {
proxy_pass  ....;
proxy_set_header X-Forward-For $remote_addr ;
}

This configuration is on the front-end Nginx reverse proxy (please search for other reverse proxies by yourself). What this configuration does is to replace X-Forward-For with remote_addr, and then replace X-Forward-For on the internal network. Secure transmission between servers.
Here I will explain some more about TCP/IP. It is well known that TCP/IP requires three-way handshake when establishing a connection, and only if the IP address requested by the client is known, the data from the server can be returned to the client, so the client wants to get the The data must provide the real IP (except for DDOS attacks), and request.getRemoteAddr() obtains the most real IP of the user.
So why not use the request.getRemoteAddr() method directly?
Of course it works without a reverse proxy. But for security reasons, most of the services now use proxy servers (such as Nginx, the proxy server can be understood as an intermediary between the user and the server, both parties can be trusted.), and the HTTP request initiated by the user to the proxy server, the proxy server The server makes a "secondary request" to the corresponding service actually deployed in the service cluster, so the final IP obtained is the IP address of the proxy server in the intranet, such as 192.168.xx.xx/10.xx.xx.xx, etc. .

Therefore, when a reverse proxy is used, request.getRemoteAddr() obtains the ip address of the response proxy in the intranet. So in the reverse proxy replace X-Forward-For with remote_addr, ie, the real IP address. After that, the x-forwarded-for obtained in the intranet is the real ip address.


Finally, a complete solution is given (Nginx as an example):
  • JAVA part (from foreign friend Bashan):
public class IpUtils {
	public static final String _255 = "(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)";
	public static final Pattern pattern = Pattern.compile("^(?:" + _255 + "\\.){3}" + _255 + "$");

	public static String longToIpV4(long longIp) {
		int octet3 = (int) ((longIp >> 24) % 256);
		int octet2 = (int) ((longIp >> 16) % 256);
		int octet1 = (int) ((longIp >> 8) % 256);
		int octet0 = (int) ((longIp) % 256);
		return octet3 + "." + octet2 + "." + octet1 + "." + octet0;
	}

	public static long ipV4ToLong(String ip) {
		String[] octets = ip.split("\\.");
		return (Long.parseLong(octets[0]) << 24) + (Integer.parseInt(octets[1]) << 16)
				+ (Integer.parseInt(octets[2]) << 8) + Integer.parseInt(octets[3]);
	}

	public static boolean isIPv4Private(String ip) {
		long longIp = ipV4ToLong(ip);
		return (longIp >= ipV4ToLong("10.0.0.0") && longIp <= ipV4ToLong("10.255.255.255"))
				|| (longIp >= ipV4ToLong("172.16.0.0") && longIp <= ipV4ToLong("172.31.255.255"))
				|| longIp >= ipV4ToLong("192.168.0.0") && longIp <= ipV4ToLong("192.168.255.255");
	}

	public static boolean isIPv4Valid(String ip) {
		return pattern.matcher(ip).matches();
	}

	public static String getIpFromRequest(HttpServletRequest request) {
		String ip;
		boolean found = false;
		if ((ip = request.getHeader("x-forwarded-for")) != null) {
			StrTokenizer tokenizer = new StrTokenizer(ip, ",");
			while (tokenizer.hasNext()) {
				ip = tokenizer.nextToken().trim();
				if (isIPv4Valid(ip) && !isIPv4Private(ip)) {
					found = true;
					break;
				}
			}
		}
		if (!found) {
			ip = request.getRemoteAddr();
		}
		return ip;
	}
}


  • Nginx part (from Moon Shadow Wuhen):
location  ~  ^/static {
proxy_pass  ....;
proxy_set_header X-Forward-For $remote_addr ;
}


Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325443365&siteId=291194637
Recommended