Reverse proxy with Real-IP and X-Forwarded-For

 

Opening remarks: Since the publication of Kaitao's new work "Core Technology of Website Architecture with Billion-Level Traffic", the blog post has been attacked by waves of DDos from readers asking for the time of publication. In the face of the enthusiasm of billions of traffic, we are also very grateful - the quality of this work is indeed excellent, it will not live up to the high expectations of fans, and Kaitao's highly responsible and considerate blessings make her absolutely superior. Value, long-lasting fragrance. Below, see a pre-sales support from this technical warm man. 
——Book planning editor Xia Shao

  The author of this article is Zhang Kaitao. In order to ensure the continuity of the content of the book "Core Technology of Website Architecture with Billion-Level Traffic", some content that readers need to understand, or the supplementary and extended content of the book, will guide readers to read and learn through QR code embedding. You can follow the author's official account "Kaitao's Blog", and check related content from the menu bar "My New Book".

  This article is what you need to know in the "Configuration Example of Limiting the Number of Concurrent Connections by IP" in the "4.4 Access Layer Current Limiting" section. 
  When we access services on the Internet, most of the time, the client does not directly access the server, but the client first requests the reverse proxy, and the reverse proxy forwards it to the server to achieve service access. Through the reverse proxy Implement strategies such as routing/load balancing. In this way, the client IP obtained on the server side will be the reverse proxy IP, not the real client IP, so a method is needed to obtain the real client IP. 
  As shown in the figure below, the client can only access the specific service Nginx Backend (or Tomcat service) through the two-layer reverse proxy of Nginx Proxy1 and Nginx Proxy2. How can Nginx Backend get the real client IP? 
image description

  Next, let's take a look at how to get the real IP of the client.

scene 1

  Scenario 1 is a very simple scenario. Nginx Proxy directly forwards the request to the back without any processing.

Nginx Proxy 192.168.107.107 nginx.conf
location /test {
    proxy_pass http://192.168.107.112:8080;
} 192.168.107.112 nginx.conf
location /test {
    proxy_pass http://192.168.107.114:8080;
}
Nginx Proxy就是简单的把请求往后转发。
Nginx Backend 192.168.107.114 nginx.conf
location /test {
    default_type text/html;
    charset gbk; echo "$remote_addr || $http_x_forwarded_for";
}

  Nginx Backend outputs the client IP ($remote_addr) and the X-Forwarded-For request header ($http_x_forwarded_for). When accessing the service, the output is as follows:

192.168.107.112 ||

analyze

1.$remote_addr代表客户端IP,当前配置的输出结果为最后一个代理服务器的IP,并不是真实客户端IP; 
2.在没有特殊配置情况下,X-Forwarded-For请求头不会自动添加到请求头中,即Nginx Backend的$http_x_forwarded_for输出为空。

场景2

  场景2通过添加X-Real-IP和X-Forwarded-For捕获客户端真实IP。

Nginx Proxy 192.168.107.107 nginx.conf
location /test {
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass http://192.168.107.112:8080;
} 192.168.107.112 nginx.conf
location /test {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass http://192.168.107.114:8080;
}
Nginx Backend 192.168.107.114 nginx.conf
location /test {
    default_type text/html;
    charset gbk; echo "$remote_addr ||$http_x_real_ip ||$http_x_forwarded_for";
}

  当访问服务时,输出结果为:

192.168.107.112 || 192.168.162.16 || 192.168.162.16, 192.168.107.107

分析

1.在离用户最近的反向代理NginxProxy 1,通过“proxy_set_header X-Real-IP $remote_addr”把真实客户端IP写入到请求头X-Real-IP,在NginxBackend输出$http_x_real_ip获取到了真实客户端IP;而Nginx Backend的“$remote_addr”输出为最后一个反向代理的IP; 
2.“proxy_set_headerX-Forwarded-For $proxy_add_x_forwarded_for”的是把请求头中的X-Forwarded-For与$remote_addr用逗号合起来,如果请求头中没有X-Forwarded-For则$proxy_add_x_forwarded_for为$remote_addr。 
  X-Forwarded-For代表了客户端IP,反向代理如Nginx通过$proxy_add_x_forwarded_for添加此项,X-Forwarded-For的格式为X-Forwarded-For:real client ip, proxy ip 1, proxy ip N,每经过一个反向代理就在请求头X-Forwarded-For后追加反向代理IP。 
  到此我们可以使用请求头X-Real-IP和X-Forwarded-For来获取客户端IP及客户端到服务端经过的反向代理IP了。这种方式还是很麻烦,$remote_addr并不是真实客户端IP。

场景3

  为了更方便的获取真实客户端IP,可以使用nginx http_realip_module模块解决,在安装nginx时通过–with-http_realip_module安装该模块。NginxProxy配置和场景2一样。

Nginx Backend 192.168.107.114 nginx.conf
real_ip_header X-Forwarded-For; set_real_ip_from 192.168.0.0/16; 
real_ip_recursive on; 

location /test {
    default_type text/html;
    charset gbk; echo "$remote_addr || $http_x_real_ip ||$http_x_forwarded_for";
}

  当访问服务时,输出结果为:

192.168.162.16 || 192.168.162.16 || 192.168.162.16, 192.168.107.107

分析

1.X-Real-IP和X-Forwarded-For和场景2一样; 
2.使用realip模块后,$remote_addr输出结果为真实客户端IP,可以使用$realip_remote_addr获取最后一个反向代理的IP; 
3.real_ip_headerX-Forwarded-For:告知Nginx真实客户端IP从哪个请求头获取,如X-Forwarded-For; 
4.set_real_ip_from192.168.0.0/16:告知Nginx哪些是反向代理IP,即排除后剩下的就是真实客户端IP,支持配置具体IP地址、CIDR地址; 
5.real_ip_recursive on:是否递归解析,当real_ip_recursive配置为off时,Nginx会把real_ip_header指定的请求头中的最后一个IP作为真实客户端IP;当real_ip_recursive配置为on时,Nginx会递归解析real_ip_header指定的请求头,最后一个不匹配set_real_ip_from的IP作为真实客户端IP。 
  如果配置“real_ip_recursive off; ”,则输出结果为:

192.168.107.107 || 192.168.162.16 ||192.168.162.16, 192.168.107.107

总结

1. Through "proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for", separate the real client IP and reverse proxy IP by commas and add them to the request header; 
2. You can configure "proxy_set_header X- Real-IP $remote_addr” to get the real client IP; 
3. The real client IP can also be obtained from X-Forwarded-For with the realip module. 
  The first reverse proxy in the entire reverse proxy chain can not configure "proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for", otherwise the client can forge X-Forwarded-For to forge the client's real IP, if the server uses X- Forwarded-For the first IP as the real client IP, then there is a problem. This problem will not occur if you configure the X-Real-IP request header or cooperate with the realip module. If you parse X-Forwarded-For yourself, remember to use the realip algorithm to parse it instead of taking the first one. 
When we limit the flow, we must pay attention to the real client IP, not the reverse proxy IP. I have encountered many colleagues who have problems in this area.

 


If you want to get more exciting articles in time, you can search for " Blog Viewpoint " in WeChat or scan the QR code below and follow.
image description

Guess you like

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