Generally, applications use Nginx as a reverse proxy, and Nginx may be multi-tiered. If you want to get the original client IP address in the internal service. You need to do some configuration.
Outermost Nginx
To prevent forgery of the X-Forwarded-For header, the X-Forwarded-For can be set to the real IP$remote_addr in the outermost Nginx. The $remote_addr is the client IP (similar to request.getRemoteAddr() in Java) that is directly connected to TCP, which cannot be forged, even if the client forgery is overwritten, not appended.
upstream innerservice { server 192.168.12.33:9001; server 192.168.12.34:9002; } server { listen 9000; server_name 192.168.12.22; root /usr/share/nginx/html; include /etc/nginx/default.d/*.conf; location / { proxy_pass http://innerservice; proxy_set_header Host $host:$server_port; proxy_set_header X-Real-PORT $remote_port; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $remote_addr; } }
Follow-up Nginx configuration
upstream innerservice { server 192.168.12.33:9001; server 192.168.12.34:9002; } server { listen 9000; // xxx location / { proxy_pass http://innerservice; proxy_set_header Host $host:$server_port; proxy_set_header X-Real-PORT $remote_port; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }
Getting Real IP in Java
/** * Description: Client Information Acquisition Filter */ public class ClientContextFilter extends OncePerRequestFilter { /** * Nginx IP Address Header Added by Default */ public static final String HEADER_X_FORWARDED_FOR = "X-Forwarded-For"; /** * Additional IP address headers are invoked between internal microservices */ public static final String HEADER_X_REMOTE_USER_IP = "X-Remote-User-IP"; /** * IP Segmentation symbols of response heads */ private static final String IP_HEADER_DELIMITER = ","; @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { try { String remoteUserIP = loadRemoteUserIP(request); ClientContext context = new ClientContext(); context.setClientIP(request.getRemoteAddr()); context.setRemoteUserIP(remoteUserIP); ClientContextHolder.setContext(context); filterChain.doFilter(request, response); } finally { ClientContextHolder.clearContext(); } } private String loadRemoteUserIP(HttpServletRequest request) { String xForwardedHeader = request.getHeader(HEADER_X_FORWARDED_FOR); // First try to get it from X-Forwarded-For if (xForwardedHeader != null && xForwardedHeader.trim().length() > 0) { String[] ips = xForwardedHeader.split(IP_HEADER_DELIMITER); return ips[0].trim(); } else { // Attempt to retrieve from an internal custom header String internalIPHeader = request.getHeader(HEADER_X_REMOTE_USER_IP); if (null != internalIPHeader && internalIPHeader.trim().length() > 0) { return internalIPHeader.trim(); } else { return null; } } } }
The principle is to define a custom header when the service is passed back, and put the real IP in this header. Background services can take two IP addresses
- request.getRemoteAddr() - Gets the intranet IP address of the caller service
- Load RemoteUserIP - Get the Real Client IP Address at the Source