>  기사  >  백엔드 개발  >  2계층 서버의 두 번째 계층인 Nginx에서 사용자 IP를 얻는 방법

2계층 서버의 두 번째 계층인 Nginx에서 사용자 IP를 얻는 방법

WBOY
WBOY원래의
2016-08-08 09:31:041385검색

2계층 서버의 두 번째 계층인 Nginx에서 사용자 IP를 얻는 방법

1. 이전에 nginx 서버를 구성할 때 서버에서 클라이언트의 최대 동시 연결을 제한하는 기능을 사용했는데, 이 기능의 구현은 서버에서

$remote-addr

이런 구성으로 가능합니다. 하지만 프런트엔드 레이어(로드, CDN, 방화벽, 보안 서비스) 서버를 추가한 후에는 획득한 클라이언트 IP가 실제 사용자 IP 주소가 아닌 프런트엔드 서버의 IP가 됩니다.

2. 이런 문제로 nginx 공식 홈페이지 소개를 여러번 다시 읽어보니 특히 중요한 또 다른 변수

$proxy_add_x_forwarded_for

이 변수는 클라이언트 액세스 값이라는 것을 알게 되었습니다. 요청에 있는 X-forwarded-for 필드의 요청에 이 필드가 포함되어 있지 않으면 이 변수는 자동으로 remote-addr 변수와 동일합니다. 이를 통해 일반적으로 HTTP 요청에서 프런트 엔드 서버에 의해 저장되는 클라이언트의 실제 IP 주소 필드(일반적으로 X_FORWARDED_FOR 필드라고 함)를 얻을 수 있으며, 이 방법을 통해 다양한 기능을 구현할 수 있습니다.

3. 아래에서 간단한 데모를 보여드리겠습니다. 부족한 부분이 많은데 정정 부탁드립니다.

먼저 Nginx 환경을 설정합니다. 여기서는 1.7 시리즈의 최신 버전 1.7.9를 예로 사용합니다. (버전에 대한 질문은 FAQ 1을 참조하세요.)

다운로드 및 WGET 필수 주소 http://nginx.org/download/nginx-1.7.9.tar.gz

1. Nginx 다운로드

[lugt@localhostmysql]$ wget http://nginx .org/ download/nginx-1.7.9.tar.gz

2. 압축 해제

[lugt@localhostmysql]$ tar zxvf nginx-1.7.9.tar.gz

3 .        직접 컴파일(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. 그런 다음 nginx.conf 구성 파일을 수정합니다

[lugt@localhost nginx-1.7.9]$ su

[lugt @localhost nginx-1.7.9]$cd /usr/local/nginx

[lugt@localhostnginx]$ vi conf/nginx.conf

그런 다음 nginx.conf에서 이것을 찾아 추가하세요. 로드 밸런싱을 설정하려면 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;
}
}

을 모방하고 포트 8080,

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>}                                                                                                                                                 }          
                                                                            >
[lugt@localhost~]$ ab -c 10 -n 100 -v 4 http://127.0. 0.1/ | grep HTTP/1.1

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 

 variable with the  
$proxy_add_x_forwarded_for
  variable. 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 서비스를 일시적으로 사용할 수 없습니다

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 튜토리얼에 관심이 있는 친구들에게 도움이 되었으면 좋겠습니다.

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
이전 기사:PHP DOM 구문 분석다음 기사:PHP DOM 구문 분석