In the development work, we often need to obtain the client's IP. The general method to obtain the IP address of the client is: Request.getremoteaddr (), but the real IP address of the client cannot be obtained by the reverse proxy software such as Apache,squid.
Cause: Because the intermediary agent is added between the client and the service, the server cannot get the client's IP directly, and the server-side application cannot return to the client directly by forwarding the requested address.
Now the diagram of proxy Internet and IP relationship:
First case: Do not go online through the proxy, the server to get the real IP
The second situation: through Proxy server such as: Nginx,squid, such as a layer of proxy or multi-layer proxy network, such as:
Note that x-forwarded-for and X-REAL-IP are not the official HTTP protocol header , but squid and other reverse proxy software was first introduced, the reason resin can get, This is because Nginx usually configures the forwarded HTTP request in the default way:
Location/ { proxy_pass http://yourdomain.com; proxy_set_header Host $host; Proxy_set_header X-real-IP $remote _addr; Proxy_set_header X-forwarded-for $proxy _add_x_forwarded_ for;}
After the multi-tier agent, we will find that x-forwarded-for is an overlay process, the latter agent will be the IP of the former agent to join X-forwarded-for, similar to the role of Python list append.
That's it
X-forwarded-for:192.168. 1.2 192.168. 1.3 192.168. 1. n
From the definition of x-forwarded-for, Ips[0] is the original client IP, if this is not, then take the second is more unreliable, we usually test the time, may be directly in the network hanging agent to visit, and outside the network path visited by internet users, The following is not always added is through each layer of proxy IP only, below an example;
request.getremoteaddr () 192.168 . 239.196 request.getheader ( " X-forwarded-for ") 58.63 . 227.162 , 192.168 . 237.178 , 192.168 . 238.218 request.getheader ( " X-real-ip ") 192.168 . 238.218
So the process of access should be this way, the client 58.63.227.162 the request, after 192.168.237.178, 192.168.238.218 Two-tier forwarding, To the 192.168.239.196 this nginx, Nginx put X-REAL-IP head set as oneself see REMOTE_ADDR, That is, sent directly to his 192.168.238.218, this time resin received this package, for resin directly to his remote_addr is Nginx IP, That is 192.168.239.196, then the request.getremoteaddr inside resin () is 192.168.239.196, then Taking the most primitive IP logic in resin (that is, taking the outermost IP you can know) should look like this :
- If Xff is not empty, take Xff's left first
- If Xff is empty, take XRI
- If the xri is empty, can only take request.getremoteaddr (), that is, only to get the most direct to his machine IP
It can also be found that if there is only one layer of proxy, the values of the two headers of x-forwarded-for and X-real-ip are the same.
None of the other is elegant, refer to Java code as follows:
The first type of code:
/** * Obtains the client IP from the request object, handles the HTTP proxy server and the Nginx reverse proxy intercepts the IP * @param request * @return IP */Public static string Getlocalip (HttpServletRequest request) { String remoteaddr = request.getremoteaddr (); String forwarded = Request.getheader ("x-forwarded-for"); String Realip = Request.getheader ("X-real-ip"); String IP = null; if (Realip = = null) { if (forwarded = = null) { IP = remoteaddr; } else { IP = remoteaddr + "/" + Forwa Rded.split (",") [0]; } } else { if (realip.equals (forwarded)) { IP = realip; } else { if (forwarded! = NULL) { forwarded = Forwarded.split (",") [0]; } IP = realip + "/" + forwarded; } } return IP; }
The second type of code:
1 public static string GetIP (HttpServletRequest request) {2 String remoteaddr = Request.getremoteaddr (); 3 String forwarded = Request.getheader ("X-forwarded-for"); 4 String realip = Request.getheader ("X-real-ip"), 5 6 string IP = null, 7 if (Realip = = null) {8 if ( forwarded = = null) {9 IP = remoteaddr;10 } else {one IP = remoteaddr + "/" + forwarded;12 }13 } el SE { realip.equals (forwarded)) { IP = realip;16 } else { + IP = realip + "/" + Forwarded.repla Ceall ("," + Realip, ""); }19 }20 return ip;21 }
The third type of code:
1 public static string getIp2 (HttpServletRequest request) {2 String IP = request.getheader ("X-forwarded-for"); 3 if (Stringutils.isnotempty (IP) &&! " UnKnown ". Equalsignorecase (IP)) {4 ///Multiple reverse proxies will have more than one IP value, the first IP is the real IP 5 int index = Ip.indexof (", "); 6 if (index ! =-1) {7 return ip.substring (0,index); 8 }else{9 return ip;10 }11 }12 IP = Request.getheader ("X-real-ip"); if (Stringutils.isnotempty (IP) &&!) UnKnown ". Equalsignorecase (IP)) { ip;15 }16 return request.getremoteaddr ();
The third is the most suitable, the clearest understanding.
Finally, it is recommended to use x-forwarded-for instead of x-real-ip, although sometimes their values are the same
Getting a real IP is common x-forwarded-for:
1. He is in the forward (such as squid) reverse (such as nginx) agent is the standard usage, and the forward agent is no X-REAL-IP related standards, that is, if the user access to your Nginx reverse proxy, but also through a layer of forward proxy, Even if you configure the X-real-ip in Nginx, it is only the IP of the forward proxy and not the real IP of the client.
2. Most nginx reverse proxy configuration articles are not recommended plus x-real-ip, and only x-forwarded-for, so the more common practice is to take x-forwarded-for
3. Multi-level agent is seldom seen, only the first level of the agent in the case of the two are equivalent
4. If there is a multi-level agent, the x-forwarded-for effect is greater than X-REAL-IP, you can record the complete proxy link
How to differentiate X-forwarded-for and X-REAL-IP in HTTP request headers after Nginx proxy, and Java sample