Nginx 에서 GeoIP 를 이용해 국가별로 접속 대역폭을 다르게 걸 수 있다. 콘텐츠 CDN 이 없을 때 해외 대역을 쭈꾸미로 만들어서 국내 서비스에 영향을 덜 주는 용도로 많이 쓴다.
두 가지 방법이 있음:
- (A) Maxmind 의 GeoIPCountryWhois.csv 를 쪼개서 geo 모듈에 include
- (B) nginx 의 ngx_http_geoip_module (외부 .dat DB) 사용
(A) 가 의존성 적고 제일 안전. (B) 는 빌드 옵션에 --with-http_geoip_module 이 들어가 있어야 함.
방법 A — CSV → include
CSV 원본 한 줄 예시:
이걸 nginx geo 문법으로 바꿔야 한다:
Yongbok 님이 올려둔 스크립트가 제일 편함:
nginx.conf 의 http 블록에:
가상호스트의 server 블록에 대역폭 분기:
$limit_rate 는 nginx 내장 변수라 값만 넣으면 해당 요청의 limit_rate 로 쓰인다. 따로 limit_rate 디렉티브 안 적어도 됨.
방법 B — geoip_country 모듈
nginx 빌드에 해당 모듈이 들어있어야 한다. Maxmind 의 GeoIP.dat (Country) 또는 GeoIPCity.dat 을 쓴다.
map 쪽이 if 블록보다 설정이 깔끔하고 성능도 낫다. 2014 년 기준이면 거의 모든 nginx 빌드에 map 은 내장.
주의 사항
- nginx 의 if 는 evil 로 알려져 있다. server 레벨에서는 그나마 안전, location 안에서는 가급적 map 을 쓸 것.
- GeoLite DB 는 정기적으로 갱신 필요. 매월 1일쯤 cron 으로 다시 받는 걸 걸어두자.
- CDN / proxy 뒤에 있으면 $remote_addr 가 프록시 IP 라 GeoIP 가 말짱 도루묵. 이 경우 real_ip_header X-Forwarded-For + set_real_ip_from 로 원래 IP 를 먼저 확보한 뒤 GeoIP 가 그 값을 쓰게 해야 한다.
- Maxmind 가 GeoIP2 (MMDB 포맷) 로 가는 중이라, 오래 운영할 프로젝트라면 점차 GeoIP2 계열 모듈 (nginx-mod-http-geoip2) 로 넘어갈 준비 할 것.
원출처: http://www.kutukupret.com/2010/09/16/nginx-limit-website-visitor-bandwidth-by-country/
두 가지 방법이 있음:
- (A) Maxmind 의 GeoIPCountryWhois.csv 를 쪼개서 geo 모듈에 include
- (B) nginx 의 ngx_http_geoip_module (외부 .dat DB) 사용
(A) 가 의존성 적고 제일 안전. (B) 는 빌드 옵션에 --with-http_geoip_module 이 들어가 있어야 함.
방법 A — CSV → include
# wget http://geolite.maxmind.com/download/geoip/database/GeoIPCountryCSV.zip # unzip GeoIPCountryCSV.zip # GeoIPCountryWhois.csv
CSV 원본 한 줄 예시:
"1.11.0.0","1.11.255.255","17498112","17563647","KR","Korea, Republic of"
이걸 nginx geo 문법으로 바꿔야 한다:
1.11.0.0/16 KR;
Yongbok 님이 올려둔 스크립트가 제일 편함:
# wget http://mirror.yongbok.net/ruo91/nginx/script/geo2nginx.pl # chmod +x geo2nginx.pl # ./geo2nginx.pl < GeoIPCountryWhois.csv > /usr/local/nginx/conf/nginxGeo.txt
nginx.conf 의 http 블록에:
geo $country {
default no;
include /usr/local/nginx/conf/nginxGeo.txt;
}
가상호스트의 server 블록에 대역폭 분기:
server {
listen 80;
server_name www.example.com;
if ($country ~ ^(?:US|CA|ES)$) { set $limit_rate 500k; }
if ($country ~ ^(?:RU|CN)$) { set $limit_rate 1k; }
if ($country ~ ^KR$) { set $limit_rate 0; } # 무제한
location /files/ {
root /var/www/files;
}
}
$limit_rate 는 nginx 내장 변수라 값만 넣으면 해당 요청의 limit_rate 로 쓰인다. 따로 limit_rate 디렉티브 안 적어도 됨.
방법 B — geoip_country 모듈
nginx 빌드에 해당 모듈이 들어있어야 한다. Maxmind 의 GeoIP.dat (Country) 또는 GeoIPCity.dat 을 쓴다.
# wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz
# gunzip GeoIP.dat.gz
# mv GeoIP.dat /usr/local/nginx/conf/
# http 블록
geoip_country /usr/local/nginx/conf/GeoIP.dat;
map $geoip_country_code $country_limit_rate {
default 200k;
KR 0;
US 500k;
CA 500k;
RU 1k;
CN 1k;
}
server {
listen 80;
location /files/ {
set $limit_rate $country_limit_rate;
root /var/www/files;
}
}
map 쪽이 if 블록보다 설정이 깔끔하고 성능도 낫다. 2014 년 기준이면 거의 모든 nginx 빌드에 map 은 내장.
주의 사항
- nginx 의 if 는 evil 로 알려져 있다. server 레벨에서는 그나마 안전, location 안에서는 가급적 map 을 쓸 것.
- GeoLite DB 는 정기적으로 갱신 필요. 매월 1일쯤 cron 으로 다시 받는 걸 걸어두자.
# /etc/cron.d/geoip-update 0 3 1 * * root wget -q -O - http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz | gunzip > /usr/local/nginx/conf/GeoIP.dat && /usr/sbin/nginx -s reload
- CDN / proxy 뒤에 있으면 $remote_addr 가 프록시 IP 라 GeoIP 가 말짱 도루묵. 이 경우 real_ip_header X-Forwarded-For + set_real_ip_from 로 원래 IP 를 먼저 확보한 뒤 GeoIP 가 그 값을 쓰게 해야 한다.
- Maxmind 가 GeoIP2 (MMDB 포맷) 로 가는 중이라, 오래 운영할 프로젝트라면 점차 GeoIP2 계열 모듈 (nginx-mod-http-geoip2) 로 넘어갈 준비 할 것.
원출처: http://www.kutukupret.com/2010/09/16/nginx-limit-website-visitor-bandwidth-by-country/