지리적 위치에 따른 액세스 제한
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. 전제 조건
- NGINX Plus GeoIP2 동적 모듈
- MaxMind의 GeoIP2 또는 GeoLite2 데이터베이스
- (선택 사항) MaxMind 데이터베이스 파일에서 IP 주소를 조회하는 mmdblookup 유틸리티
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. 예제
이 예제는 http 및 stream 컨텍스트 모두에 적용할 수 있습니다.
# 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 서버를 선택합니다.