Home >Backend Development >PHP Tutorial >How to get user IP on Nginx, the second layer of two-tier server
How to get user IP on Nginx, the second layer of the two-tier server
1. I encountered a problem when configuring nginx server before. Previously, the server used a function to limit the maximum concurrent connections of the client, and the implementation of this function relied on
$remote-addr
such configuration in the server. achieved. But after adding a front-end layer (load, CDN, firewall, security service) server, the client IP obtained becomes the IP of the front-end server, not the real user IP address.
2. Faced with such a problem, I re-read the introduction of nginx official website several times and found another particularly important variable
$proxy_add_x_forwarded_for
This variable is the value of the X-forwarded-for field in the client access request. If the request does not contain this field, the automatic use of this variable will be equivalent to the remote-addr variable. This allows us to obtain the field of the client's real IP address that is usually saved by the front-end server in the HTTP request, usually what we call the X_FORWARDED_FOR field, and then through this method, we can implement a variety of functions.
Three. Let me give you a simple demonstration below. There are many deficiencies, please correct me.
First we set up the Nginx environment. Here we use the latest version 1.7.9 of the 1.7 series as an example. (For version issues, please see FAQ 1)
Download and WGET required address http://nginx.org/ download/nginx-1.7.9.tar.gz
1. Download Nginx
[lugt@localhostmysql]$ wget http://nginx.org/download/nginx-1.7.9.tar.gz
2. Unzip
[lugt@localhostmysql]$ tar zxvf nginx-1.7.9.tar.gz
3. Compile directly (you need to consider whether you need the support of plug-ins such as openssl)
[lugt@localhost mysql]$cd nginx-1.7. 9
[lugt@localhost nginx-1.7.9]$ ./configure
[lugt@localhost nginx-1.7.9]$ make
[lugt@localhost nginx-1.7.9]$ su
[lugt@ localhostnginx-1.7.9]$ make install
4. Then modify the nginx.conf configuration file
[lugt@localhost nginx-1.7.9]$ su
[lugt@localhost nginx-1.7.9]$cd /usr/local/nginx
[lugt@localhostnginx]$ vi conf/nginx.conf
Then find this in nginx.conf, add it to set up load balancing, imitate CDN
upstream dnsnginx1 { server[*.*.*.*/yourhostname]:8080 weight=10000; #填IP、域名 } server { listen 80; server_name #access_log logs/host.access.log main location /{ proxy_pass http://dnsnginx1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header HTTP_X_FORWARDED_FOR $remote_addr; proxy_redirect default; } }
and set up a virtual server at 8080 Port,
limit_conn_zone $proxy_add_x_forwarded_for zone=addr:10m; # 并发设置 空间10M server { listen 8080; server_name [*.*.*.*/yourhostname]:8080 weight=10000; #填IP、域名 limit_conn addr 1; #限制客户端最大并发连接数为 1 location / { root html; index index.html index.htm; } }
saved. Then test the configuration file syntax
[lugt@localhostnginx]$ ./sbin/nginx –t
Start the server
[lugt@localhostnginx]$ ./sbin/nginx
IV. Use the ab tool to see the effect.
[lugt@localhost nginx]$ ab –c 10 –n 100 –v 4 http://127.0.0.1/ | grep HTTP/1.1
The meaning of this line: access the address through the AB testing tool, the number of concurrent connections is 30, total test 300 times, display HTTP return header information
Using the ab tool, it can be measured that no matter how many connections are sent at the same time, the only one that successfully returns 200 in the end is the maximum number of concurrent connections that previously limited nginx, so it can be proved that the IP restriction function has been Ready to use. For reference data, see FAQ2
FAQ 1 Version issue
If the Nginx version currently in use has not reached version 1.7.1, it is likely that nginx does not support this function.
At this time, you need to use a piece of code to sandwich the limit_conn_handler function. Get the value of x_forwarded_for from request.
Taking version 1.6.1 as an example, the code is added as follows. src/http/modules/ngx_http_limit_conn.c Line 184
hash =ngx_crc32_short(key.data, key.len); If(“” == &ctx->key){ <span style="white-space:pre"> </span>If(NULL!= r->main->headers_in->x_forwarded_for->elts){ key.data= *(char*)r->main->headers_in->x_forwarded_for->elts; key.len = 4; hash =ngx_crc32_short(key.data, key.len); <span style="white-space:pre"> </span>} }
100-v 4 http://127.0.0.1/ | grep HTTP/1.1
HTTP/1.1503 Service Temporarily UnavailableHTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1 503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1 200 OK
HTTP/ 1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1 200 OK
<… repeated 往下均为重复8次HTTP/503 与1次HTTP/200 交替出现>
English Version
How to retrievethe true ip of the client user if there are two layers of servers
Days before, wehave been faced such a difficulty which is we can’t use the variable $remote_addr for gathering the clients’ip address. This problem surfaces when we used a proxy server between the trueserver and client, which is actually a cdn. And that makes our functions oflimiting the maximum connections a client can make to a server at a time. Thissituation can also found if the load balance or any anti-spam service are inuse. So that’s why we can’t use remote_addr variable further.
After I did someresearch on the documentation and the code , I found out that this problem canbe solved by replacing the
$remote_addr
$proxy_add_x_forwarded_forvariable. As this variable allows to retrievethe data from the column X_forwarded_for from the request, we can use thisvariable functioning in many ways.
And now I shall makean easy example to practically use this method.
First of all,build up a Nginx server.
Here, I will usethe 1.7.9 version (latest to the written time) for instance, therefore, thereexist some differences between older versions than 1.7.1 (see FAQ 1)
1. Download A Nginx Copy:
[lugt@localhostmysql]$ wget http://nginx.org/download/nginx-1.7.9.tar.gz
2. Decompress the file
[lugt@localhostmysql]$ tar zxvf nginx-1.7.9.tar.gz
3. Compile The Code
[lugt@localhostmysql]$ cd nginx-1.7.9
[lugt@localhostnginx-1.7.9]$ ./configure
[lugt@localhostnginx-1.7.9]$ make
[lugt@localhostnginx-1.7.9]$ su
[lugt@localhostnginx-1.7.9]$ make install
4. And edit the config file nginx.conf
[lugt@localhost nginx-1.7.9]$ su
[lugt@localhostnginx-1.7.9]$ cd /usr/local/nginx
[lugt@localhostnginx]$ vi conf/nginx.conf
There add suchdirectives to the server1 for emulate for an CDN server
upstream dnsnginx1 { server[*.*.*.*/yourhostname]:8080 weight=1000; #fill in your ip/hostname } server { listen 80; server_name [hostname] #fill your ip/ hostname here #access_log logs/host.access.log main location /{ proxy_pass http://dnsnginx1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header HTTP_X_FORWARDED_FOR $remote_addr; proxy_redirect default; } }
After the end ofone server directive, and in the http directive, add so to function the sever2
limit_conn_zone $proxy_add_x_forwarded_for zone=addr:10m; # sample setting server { listen 8080; server_name [*.*.*.*/hostname]:8080 weight=10000; #fill in ip/hostname here limit_conn addr 1; # Enablethe limitation of connection per ip at a time to 1. location / { root html; index index.html index.htm; } }
And then you cansave , test the config file and run nginx
Test your configfile:
[lugt@localhostnginx]$ ./sbin/nginx –t
Start the nginx server
[lugt@localhostnginx]$ ./sbin/nginx
Now, the serverhas been set and you can run a test at instance.
/* This CommandMeans to run a tool to connect to server as 10conn/once and 10 conns in total*/
[lugt@localhost~]$ ab -c 10 -n 100 -v 4 http://127.0.0.1/ | grep HTTP/1.1
FAQ 1
There is actuallysome little malfunctions when using elder versions than 1.7.1 (Probably the newversion has it for a new feature).So to use this directive in earlier versions,some code need to be added.
As a Example inthe version 1.6.1
In filesrc/http/modules/ngx_http_limit_conn.c Line around 184
hash =ngx_crc32_short(key.data, key.len); If("" == &ctx->key){ If(NULL!= r->main->headers_in->x_forwarded_for->elts){ key.data= *(char*)r->main->headers_in->x_forwarded_for->elts; key.len = 4; hash =ngx_crc32_short(key.data, key.len); }
}<span style="font-family: Arial, Helvetica, sans-serif;"> </span>
FAQ 2 TestingResults
[lugt@localhost~]$ ab -c 10 -n 100 -v 4 http://127.0.0.1/ | grep HTTP/1.1
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1 200 OK
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP /1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1 200 OK
<… repeated as 8times of HTTP/503 and 1 time of HTTP/200 and so on&g t ;
The above introduces how to obtain the user IP on the second layer Nginx of the two-layer server, including the relevant content. I hope it will be helpful to friends who are interested in PHP tutorials.