http://nginx.org/en/docs/http/ngx_http_geoip_module.html
nginxのngx_http_geoip_moduleモジュールを利用して、国を指定してアクセス制御をします。
フィルタリング用のデータは、MaxMindのGeoIPオープンソースデータを利用します。
日本だけにコンテンツを配信したい、もしくは、特定の国からのアクセスを拒否したい、といったときに使えるとおもいます。
環境は、CentOS 6です。
以下、セットアップ方法です。
GeoIPデータベースを準備
GeoIPデータベースと更新コマンドをインストール。
# rpm -ivh http://ftp-srv2.kddilabs.jp/Linux/distributions/fedora/epel/6/x86_64/epel-release-6-8.noarch.rpm # yum install GeoIP geoipupdateGeoIPデータベースファイルが設置されたことを確認。
# stat /usr/share/GeoIP/GeoIP.dat
nginxを準備
nginxをインストール。
# rpm -ivh http://nginx.org/packages/centos/6/noarch/RPMS/nginx-release-centos-6-0.el6.ngx.noarch.rpm # yum install nginx nginx-module-geoip # nginx -v nginx version: nginx/1.10.1nginx設定パラメータにhttp_geoip_moduleが入っているか確認。GeoIPは、動的モジュールとして有効化できるようになっています。
# nginx -V --with-http_geoip_module=dynamicnginx動的モジュールの共有オブジェクトファイルが設置されているか確認。
# ls /etc/nginx/modules/ ngx_http_geoip_module-debug.so ngx_http_geoip_module.so
nginx設定
カントリーコードはこちらのURLを参考にします。
http://dev.maxmind.com/geoip/legacy/codes/iso3166/
load_moduleを追記。modules/ngx_http_geoip_module.soを指定します。
events {} ブロックより上に記述するのがポイントです。
# emacs /etc/nginx/nginx.conf user nginx; worker_processes 1; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; load_module modules/ngx_http_geoip_module.so; events { worker_connections 1024; }
http {} ブロックを編集。
includeより上に記述します。
アメリカ(US)と日本(JP)からのアクセスを拒否する場合。
# emacs /etc/nginx/nginx.conf geoip_country /usr/share/GeoIP/GeoIP.dat; map $geoip_country_code $allowed_country { default yes; US no; JP no; }日本(JP)と韓国(KR)からのアクセスを許可、他の国からのアクセスを拒否する場合。
# emacs /etc/nginx/nginx.conf geoip_country /usr/share/GeoIP/GeoIP.dat; map $geoip_country_code $allowed_country { default no; JP yes; KR yes; }
server {} ブロックを編集。
allowed_countryがnoだったらステータスコード403を返します。
# emacs /etc/nginx/conf.d/default.conf if ($allowed_country = no) { return 403; }
nginx再起動
nginxをリスタート、またはリロード。
# /etc/init.d/nginx restartブラウザなどでアクセスして確認しましょう。思い通りにアクセスコントロールできたでしょうか?
GeoIPデータベースを更新するには?
GeoIPデータベースをアップデートをするには、以下のコマンドを叩きます。定期実行するようにしましょう。
# geoipupdate -v
ELBの場合は?
AWSを使っている場合、ELBを前段に置く場合がほとんどだとおもいます。
ELBからのヘルスチェックでサーバに来るアクセスは、内部IPアドレスのため、国で判別することができません。そのため、VPC内のIPアドレスからアクセスが来た時には、制限をスルーするようにnginxを設定します。
以下の設定では、ELB経由のアクセスから、アクセス元IPアドレスを取得。ELBのヘルスチェックのアクセスを許可、日本からのアクセスを許可、ほかの国は拒否としています。
ついでに、アクセスログにGeo情報を出力するようにしています。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
server { | |
listen 80; | |
server_name localhost; | |
#charset koi8-r; | |
#access_log /var/log/nginx/log/host.access.log main; | |
if ($allowed_country = yes) { | |
set $exclusions 1; | |
} | |
if ($exclusions = "0") { | |
return 403; | |
} | |
location / { | |
root /usr/share/nginx/html; | |
index index.html index.htm; | |
} | |
#error_page 404 /404.html; | |
# redirect server error pages to the static page /50x.html | |
# | |
error_page 500 502 503 504 /50x.html; | |
location = /50x.html { | |
root /usr/share/nginx/html; | |
} | |
# proxy the PHP scripts to Apache listening on 127.0.0.1:80 | |
# | |
#location ~ \.php$ { | |
# proxy_pass http://127.0.0.1; | |
#} | |
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 | |
# | |
#location ~ \.php$ { | |
# root html; | |
# fastcgi_pass 127.0.0.1:9000; | |
# fastcgi_index index.php; | |
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; | |
# include fastcgi_params; | |
#} | |
# deny access to .htaccess files, if Apache's document root | |
# concurs with nginx's one | |
# | |
#location ~ /\.ht { | |
# deny all; | |
#} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
user nginx; | |
worker_processes 1; | |
error_log /var/log/nginx/error.log warn; | |
pid /var/run/nginx.pid; | |
load_module modules/ngx_http_geoip_module.so; | |
events { | |
worker_connections 1024; | |
} | |
http { | |
include /etc/nginx/mime.types; | |
default_type application/octet-stream; | |
log_format main '$remote_addr - $remote_user [$time_local] "$request" ' | |
'$status $body_bytes_sent "$http_referer" ' | |
'"$http_user_agent" "$http_x_forwarded_for"'; | |
geoip_country /usr/share/GeoIP/GeoIP.dat; | |
geoip_city /usr/share/GeoIP/GeoLiteCity.dat; | |
log_format ltsv 'time:$time_iso8601\t' | |
'remote_addr:$remote_addr\t' | |
'request_method:$request_method\t' | |
'request_length:$request_length\t' | |
'request_uri:$request_uri\t' | |
'https:$https\t' | |
'uri:$uri\t' | |
'query_string:$query_string\t' | |
'status:$status\t' | |
'bytes_sent:$bytes_sent\t' | |
'body_bytes_sent:$body_bytes_sent\t' | |
'referer:$http_referer\t' | |
'useragent:$http_user_agent\t' | |
'forwardedfor:$http_x_forwarded_for\t' | |
'request_time:$request_time\t' | |
'upstream_response_time:$upstream_response_time\t' | |
'host:$host\t' | |
'geoip_country_name:$geoip_city_country_name\t' | |
'geoip_country_code3:$geoip_city_country_code3\t' | |
'geoip_city:$geoip_city\t' | |
'geoip_latitude:$geoip_latitude\t' | |
'geoip_longitude:$geoip_longitude'; | |
access_log /var/log/nginx/access.log ltsv; | |
sendfile on; | |
#tcp_nopush on; | |
keepalive_timeout 65; | |
#gzip on; | |
real_ip_header X-Forwarded-For; | |
set_real_ip_from 172.31.0.0/16; | |
map $geoip_country_code $allowed_country { | |
default no; | |
JP yes; | |
} | |
geo $exclusions { | |
default 0; | |
172.31.0.0/16 1; | |
} | |
include /etc/nginx/conf.d/*.conf; | |
} |
Top image from いらすとや