NGINX Plus

지리적 위치에 따른 액세스 제한

NGINX Plus 는 GeoIP2 동적 모듈을 사용하여 클라이언트의 지리적 위치에 따라 액세스를 제어하거나 다른 Upstream 서버로 트래픽을 전달할 수 있습니다.

목차

1. 소개
2. 전제 조건
3. 데이터베이스 가져오기
4. 데이터베이스 구조 이해하기
5. NGINX Plus에서 GeoIP2 구성하기

6. 시나리오: 최적의 서버 선택하기
6-1. 예제

1. 소개

NGINX Plus는 지리적 위치에 따라 사용자를 세분화할 수 있습니다. 예를 들어 국가 별 웹사이트 콘텐츠를 다르게 설정하거나 특정 Country 또는 City에만 콘텐츠를 배포하도록 설정할 수 있습니다.

NGINX Plus는 타사 MaxMind 데이터베이스를 사용하여 사용자의 IP 주소와 위치를 일치시킵니다. 지리적 위치가 파악되면 map 또는 split_clients 모듈에서 geoip 기반 변수를 사용할 수 있습니다.

Note: MaxMind GeoLite Legacy 데이터베이스는 현재 단종되었으며, 대신 MaxMind GeoIP2 또는 GeoLite2 데이터베이스와 NGINX Plus GeoIP2 모듈을 사용해야 합니다.

지리적 위치에 따른 제한은 HTTP와 TCP/UDP 프로토콜 모두에서 작동합니다.

2. 전제 조건

3. 데이터베이스 가져오기

GeoIP2 또는 GeoLite2 데이터베이스는 MaxMind 다운로드 페이지에서 얻을 수 있습니다. 이 예제에서는 무료로 다운로드할 수 있는 GeoLite2 데이터베이스를 사용했습니다.

GeoLite2 Country 데이터베이스를 가져오고 압축을 풉니다.

$ wget http://geolite.maxmind.com/download/geoip/database/GeoLite2-Country.mmdb.gz
$ gunzip GeoLite2-Country.mmdb.gz

GeoLite2 City 데이터베이스를 가져오고 압축을 풉니다.

$ wget http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.mmdb.gz
$ gunzip GeoLite2-City.mmdb.gz

4. 데이터베이스 구조 이해하기

사용 가능한 지리 데이터를 확인하려면 mmdblookup 유틸리티를 사용하여 GeoLite2-Country 및 GeoLite2-City 데이터베이스를 Query할 수 있습니다. 지리 데이터는 JSON 트리로 표시됩니다.

libmaxminddb 데이터베이스 유틸리티를 설치합니다.

Amazon Linux, CentOS, Oracle Linux 및 RHEL의 경우:

$ yum install libmaxminddb-devel

Debian 및 Ubuntu의 경우:

$ apt-get install libmaxminddb-dev

SLES의 경우:

$ zypper install libmaxminddb-devel

데이터베이스에 대한 Query는 다음 형식으로 보낼 수 있습니다.

mmdblookup –file [FILE PATH] –ip [IP ADDRESS] [DATA PATH]

예를 들어 8.8.8.8 IP 주소에 대해 사용 가능한 모든 지리 데이터를 가져오려면 다음 명령을 전송합니다.

$ mmdblookup --file /usr/local/etc/geoip2/GeoLite2-Country.mmdb --ip 8.8.8.8

출력은 다음과 같습니다.

{
    "continent":
      {
        "code":
          "NA" <utf8_string>
        "geoname_id":
          6255149 <uint32>
        "names":
          {
            "de":
              "Nordamerika" <utf8_string>
            "en":
              "North America" <utf8_string>
            "es":
              "Norteamérica" <utf8_string>
            "fr":
              "Amérique du Nord" <utf8_string>
            "ja":
              "北アメリカ" <utf8_string>
            "pt-BR":
              "América do Norte" <utf8_string>
            "ru":
              "Северная Америка" <utf8_string>
            "zh-CN":
              "北美洲" <utf8_string>
          }
      }
    "country":
      {
        "geoname_id":
          6252001 <uint32>
        "iso_code":
          "US" <utf8_string>
        "names":
          {
            "de":
              "USA" <utf8_string>
            "en":
              "United States" <utf8_string>
            "es":
              "Estados Unidos" <utf8_string>
            "fr":
              "États-Unis" <utf8_string>
            "ja":
              "アメリカ合衆国" <utf8_string>
            "pt-BR":
              "Estados Unidos" <utf8_string>
            "ru":
              "США" <utf8_string>
            "zh-CN":
              "美国" <utf8_string>
          }
      }
    "registered_country":
      {
        "geoname_id":
          6252001 <uint32>
        "iso_code":
          "US" <utf8_string>
        "names":
          {
            "de":
              "USA" <utf8_string>
            "en":
              "United States" <utf8_string>
            "es":
              "Estados Unidos" <utf8_string>
            "fr":
              "États-Unis" <utf8_string>
            "ja":
              "アメリカ合衆国" <utf8_string>
            "pt-BR":
              "Estados Unidos" <utf8_string>
            "ru":
              "США" <utf8_string>
            "zh-CN":
              "美国" <utf8_string>
          }
      }
  }

예를 들어 특정 Country의 ISO 코드만 가져오려면 명령 끝에 country iso_code 매개변수를 추가합니다.

$ mmdblookup --file /usr/local/etc/geoip2/GeoLite2-Country.mmdb --ip 8.8.8.8 country iso_code

이러한 매개변수는 NGINX용 GeoIP2 모듈에서 변수를 생성할 때도 사용됩니다.

5. NGINX Plus에서 GeoIP2 구성하기

1. NGINX Plus용 GeoIP2 동적 모듈을 설치합니다.

Amazon Linux, CentOS, Oracle Linux 및 RHEL의 경우:

$ yum install nginx-plus-module-geoip2

Debian 및 Ubuntu의 경우:

$ apt-get install nginx-plus-module-geoip2

SLES의 경우:

$ zypper install nginx-plus-module-geoip2

2. main 구성 Level에 지정된 load_module 지시문을 사용하여 NGINX Plus 구성 파일에서 GeoIP2 동적 모듈을 사용하도록 설정합니다.

load_module modules/ngx_http_geoip2_module.so;
load_module modules/ngx_stream_geoip2_module.so;

http {
    # ...
}

3. http { }, stream { } 또는 둘 다에 대한 geoip2 { } 블록을 사용하여 Country 및 City 데이터베이스의 경로를 NGINX 구성에 추가합니다.

http {
    #...
    geoip2 GeoIP2/GeoLite2-Country.mmdb {
        #...
    }

    geoip2 GeoIP2/GeoLite2-City.mmdb {
        #...
    }
}

stream {
    #...
    geoip2 GeoIP2/GeoLite2-Country.mmdb {
        #...
    }

    geoip2 GeoIP2/GeoLite2-City.mmdb {
        #...
    }
}

4. GeoIP 데이터베이스 구조를 기반으로 GeoIP2 데이터베이스의 데이터를 보관할 사용자 정의 변수를 만든 다음 나중에 데이터를 map 또는 split_clients 지시문에 전달합니다(http { }stream { } 컨텍스트 모두에서 적용 가능합니다).

geoip2 GeoIP2/GeoLite2-City.mmdb {
    $geoip2_data_city_name   city names en;
    $geoip2_data_postal_code postal code;
    $geoip2_data_latitude    location latitude;
    $geoip2_data_longitude   location longitude;
    $geoip2_data_state_name  subdivisions 0 names en;
    $geoip2_data_state_code  subdivisions 0 iso_code;
}

geoip2 GeoIP2/GeoLite2-Country.mmdb {
    $geoip2_data_continent_code   continent code;
    $geoip2_data_country_iso_code country iso_code;
}

#...

6. 시나리오: 최적의 서버 선택하기

생성된 변수의 지리적 위치 데이터를 사용하여 클라이언트 연결을 가장 가까운 서버로 리다이렉션하여 네트워크 지연 시간을 줄이고 연결 속도를 개선할 수 있습니다.

이는 변수에 GeoIP2 데이터베이스의 Continent 코드를 사용하고 Continent 위치를 기준으로 가장 가까운 서버가 값이 되는 또 다른 변수를 생성하는 map 모듈을 사용하여 달성할 수 있습니다. 이 값을 기반으로 NGINX는 해당 Upstream 서버 그룹에 요청을 전달합니다.

1. all IP 주소가 GeoIP 데이터베이스와 일치하지 않는 경우를 대비하여 각 Continent 별 서버 또는 Upstream 서버 그룹을 구성했는지 확인합니다(예: 유럽의 경우 eu, 북미의 경우 na).

upstream all {
    server all1.example.com:12345;
    server all2.example.com:12345;
}

upstream eu {
    server eu1.example.com:12345;
    server eu2.example.com:12345;
}

upstream na {
    server na1.example.com:12345;
    server na2.example.com:12345;
}

2. GeoIP2 데이터베이스의 대륙 코드를 가져오는 임의의 이름(예: $geoip2_data_continent_code)의 변수와 함께 geoip2 { } 블록을 추가합니다.

geoip2 GeoIP2/GeoLite2-Country.mmdb {
    $geoip2_data_continent_code continent code;
}

#...

3. $nearest_server 변수를 생성할 map 블록을 생성합니다.

#...
map $geoip2_data_continent_code $nearest_server {
    default all;
    EU      eu;
    NA      na;
    AS      as;
    AF      af;
}
#...

4. $nearest_server 변수에 전달된 값에 따라 Upstream 서버 그룹 중 하나에 요청을 전달할 server { } 블록을 생성합니다.

server {
    listen 12346;
    proxy_pass http://$nearest_server;
}

Continent이 유럽인 경우 $nearest_server의 값은 eu가 되고 연결은 proxy_pass 지시문을 통해 eu Upstream으로 전달됩니다.

#...
server {
    listen 12346;
    proxy_pass http://$nearest_server;
}

upstream all {
    server all1.example.com:12345;
    server all2.example.com:12345;

upstream eu {
    server eu1.example.com:12345;
    server eu2.example.com:12345;
}
upstream na {
    server na1.example.com:12345;
    server na2.example.com:12345;
}
#...

6-1. 예제

이 예제는 httpstream 컨텍스트 모두에 적용할 수 있습니다.

# can be either "http {}" or "stream {}"
#...
geoip2 GeoIP2/GeoLite2-Country.mmdb {
    $geoip2_data_continent_code continent code;
}

map $geoip2_data_continent_code $nearest_server {
    default all;
    EU      eu;
    NA      na;
    AS      as;
    AF      af;
}

server {
    listen 12346;
    proxy_pass http://$nearest_server;
    }

upstream all {
    server all1.example.com:12345;
    server all2.example.com:12345;
}

upstream eu {
    server eu1.example.com:12345;
    server eu2.example.com:12345;
}

upstream na {
    server na1.example.com:12345;
    server na2.example.com:12345;
}

이 예제에서는 GeoLite2-Country.mmdb 데이터베이스에서 IP 주소를 확인하며, 그 결과는 $geoip2_data_continent_code 변수에 기록됩니다. NGINX Plus는 변수 값을 map 지시문의 값과 비교하여 일치시키고 그 결과를 사용자 지정 변수(예: $nearest_server)에 기록합니다. $nearest_server의 값에 따라 proxy_pass 지시문은 해당 Upstream 서버를 선택합니다.