2계층 서버의 두 번째 계층인 Nginx에서 사용자 IP를 얻는 방법
1. 이전에 nginx 서버를 구성할 때 서버에서 클라이언트의 최대 동시 연결을 제한하는 기능을 사용했는데, 이 기능의 구현은 서버에서
$remote-addr
$proxy_add_x_forwarded_for
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; } }
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; } }
[lugt@localhostnginx]$ ./sbin/nginx –t
서버 시작
[lugt@localhostnginx]$ ./sbin/ nginx
4. 효과를 보려면 ab 도구를 사용하십시오.
[lugt@localhost nginx]$ ab –c 10 –n 100 –v 4 http://127.0.0.1/ | grep HTTP/1.1
이 줄의 의미: Pass AB test Tool 접근 주소, 동시 연결 수는 30, 총 테스트 횟수는 300, HTTP return 헤더 정보가 표시됩니다
ab 도구를 통해 얼마나 많은 연결이 전송되는지 측정할 수 있습니다. 동시에 결국 200을 성공적으로 반환하는 것은 nginx의 최대 동시성 제한이므로 IP 제한 기능을 사용할 수 있음을 증명할 수 있습니다. 참고자료는 FAQ2를 참고하세요
FAQ 1 버전 문제
현재 사용 중인 Nginx 버전이 1.7.1 버전이 되지 않았다면 nginx가 아직 이 기능을 지원하지 않을 가능성이 높습니다.
이때, Limit_conn_handler 함수에 삽입된 코드를 통해 요청에서 x_forwarded_for 값을 얻어야 합니다.
버전 1.6.1을 예로 들면 다음과 같이 코드가 추가됩니다. src/http/modules/ngx_http_limit_conn.c 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>} }
HTTP /1.1503 서비스를 일시적으로 사용할 수 없음
HTTP/1.1503 서비스를 일시적으로 사용할 수 없음
HTTP/1.1503 서비스 TEMAVAILBLBALBALE T>
HTTP/1.1503 서비스 일시적으로 대학 서비스를 일시적으로 제공할 수 없습니다
HTTP/1.1503 서비스를 일시적으로 제공할 수 없습니다
HTTP/1.1503 서비스를 일시적으로 제공할 수 없습니다
HTTP/1.1503 서비스를 일시적으로 제공합니다 사용할 수 없음
HTTP/1.1503 서비스를 일시적으로 사용할 수 없음
HTTP/1.1503 서비스를 사용할 수 없음
HTTP/1.1 200 OK
HTTP/1.1503 서비스를 일시적으로 사용할 수 없음
HTTP/1.1503 서비스를 일시적으로 사용할 수 없습니다
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_for
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 서비스를 일시적으로 사용할 수 없습니다
HTTP/1.1503 서비스를 일시적으로 사용할 수 없습니다
HTTP/1.1503 서비스를 일시적으로 사용할 수 없습니다
HTTP/1.1503 서비스를 일시적으로 사용할 수 없습니다
HTTP/1.1503 서비스를 일시적으로 사용할 수 없습니다
HTTP/1.1503 서비스를 일시적으로 사용할 수 없습니다
HTTP/1.1503 서비스를 일시적으로 사용할 수 없습니다
HTTP/1.1503 서비스를 일시적으로 사용할 수 없습니다
HTTP /1.1503 서비스를 일시적으로 사용할 수 없음
HTTP/1.1 200 OK
<… HTTP/503 8회, HTTP/200 1회 등 반복>
위 내용은 관련 내용을 포함하여 2계층 서버의 2계층 Nginx에서 사용자 IP를 얻는 방법을 소개하고 있으니 PHP 튜토리얼에 관심이 있는 친구들에게 도움이 되었으면 좋겠습니다.