Get User Real Ip

Get User Real Ip In Docker Nginx
On this page

It’s a pretty simple question, but in the process of information dissemination, some mistakes happen.

For example, some people will say, just configure X-Real-Ip, and that’s it.

Or some people will ask, what is the difference between X-Real-Ip and X-Forward-For, and what is the principle?

Obviously, they misunderstood X-Real-Ip.

This article will show you what X-Real-Ip is.

Quick Answer

X-Real-Ip is nothing. You can use My-Real-Ip, His-Real-Ip, whatever.

1server {
2        ...
3        location / {
4                ...
5                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
6                $proxy_add_x_forwarded_for; proxy_set_header Host $host; proxy_set_header
7                proxy_set_header His-Real-Ip2 $remote_addr; }
8        }
9}

The above configuration sets three request headers, X-Forwarded-For, Host, and His-Real-Ip2, and the backend java server can get the real IP based on His-Real-Ip2.

It sounds hurtful, but X-Real-Ip really just seems to be an official, hidden field of some sort, which it really isn’t.

Stop asking questions like What is the principle of X-Real-Ip? or special request header X-Real-Ip, what really matters is the built-in variable $remote_addr.

nginx in Docker

The $remote_addr could be 172.*.0.1 in docker nginx, which is the address of the docker bridge interface ip addr.

So how do you get the user’s real ip?

Your nginx container must use the host network.

Here is a docker compose example:

 1services:
 2  my-nginx:
 3      restart: always
 4      container_name: my-nginx
 5      image: nginx:latest
 6      network_mode: host # note this mode is host
 7  my-server:
 8    restart: always
 9    container_name: my-server
10    network_mode: host
11      - spring_cloud_default
12networks:
13    spring_cloud_default:
14    driver: bridge

In your back-end server code, you should write something like (using java as an example, assuming we are using His-Real-Ip2):

 1RequestAttributes ra = RequestContextHolder.getRequestAttributes();
 2ServletRequestAttributes sra = (ServletRequestAttributes) ra;
 3if (null != sra) {
 4	HttpServletRequest request = sra.getRequest();
 5	realIp = request.getHeader("His-Real-Ip"); // Let's say you have two nginx, a forward to b, b forward to server. the first nginx set His-Real-Ip
 6	if (notValidIp(realIp)) { // notValidIp can be implemented on your own, e.g. not starting with 172, or 192.168, etc.
 7		realIp = request.getHeader("His-Real-Ip2"); // The second nginx set His-Real-Ip2. By doing so, it is possible to distinguish which traffic is coming in via the gateway and which is coming in directly. It's not useful, just as an illustration
 8		if (notValidIp(realIp)) {
 9			realIp = request.getRemoteAddr();
10		}
11	}
12}

Conclusion

Well, let’s not make a falsehood out of a falsehood, although it’s a simple question, it’s not simple to realize it.