CentOS 6.6 - mod_geoipでWebサーバに対するアクセスを国別で制限してみた。

例えば、VPSなどでWebサイトを運営していて海外からのアクセスが鬱陶しい場合はありませんか??

Webサイトが国内向けで、広告収入など気にしない場合に海外からのアクセスはサーバのリソースを無駄に消費するだけだと思います。

 

アクセスは国内からだけ!中国とロシアからだけはアクセスさせたくない!などの要望を簡単に叶えてくれるのが mod_geoipです。(apache、nginxどちらでも使えます)

 

本投稿では、mod_geoipのインストール方法とApacheの設定方法を紹介します。

 

はじめに

作業環境

- カゴヤ・クラウド/VPS type A

- CentOS 6.6

- Apache 2.2.15

 

Yumリポジトリを追加

Yumのリポジトリ「EPEL」を追加します。

# yum install epel-release

 

Webサーバを構築

Apacheをインストール

Apacheをインストールします。

# yum install httpd

 

VirtualHostの追加

Webサーバには、IPアドレスでアクセスできるようVirtualHostの設定を追加します。

# vim /etc/httpd/conf.d/virtualhost.conf
NameVirtualHost *:80
<virtualhost *:80>
    DocumentRoot /var/www/html
    ServerName <WebサーバのIPアドレス>
    ErrorLog logs/<WebサーバのIPアドレス>-error_log
    CustomLog logs/<WebサーバのIPアドレス>-access_log common
</virtualhost>

 

テストページを作成

テストページは、先ほどVirtualHostで指定したドキュメントルートに「index.html」を作成します。

# echo "mod_geoip testpage" > /var/www/html/index.html

 

Webサーバの起動と自動起動設定に追加

Webサーバを起動します。

# service httpd start

サーバ起動にWebサーバも起動するよう自動起動設定に追加します。

# chkconfig httpd on

 

 

テストページを確認

WebサーバのIPアドレスにアクセスし、テストページが表示されるか確認します。

ブラウザでのアクセスが面倒なので、コマンドで確認します。

# curl -s http://<サーバIPアドレス>/
mod_geoip testpage

 

テストページが表示されていることを確認できました。

 

mod_geoipをインストールする

mod_geoipをインストール

Yumリポジトリの「EPEL」指定して、mod_geoipをインストールします。

# yum install mod_geoip

 

mod_geoipの初期設定

mod_geoipをインストールすると、「/etc/httpd/conf.d/geoip.conf」が自動生成されるので設定を追加します。

# vim /etc/httpd/conf.d/geoip.conf
LoadModule geoip_module modules/mod_geoip.so

<IfModule mod_geoip.c>
  GeoIPEnable On
  GeoIPDBFile /usr/share/GeoIP/GeoIP.dat Standard
</IfModule>

##日本からのアクセスを拒否する
<DirectoryMatch />
SetEnvIf GEOIP_COUNTRY_CODE JP BlockCountry
Order allow,deny
Allow from all
Deny from env=BlockCountry
</DirectoryMatch>

動作テストで分かりやすいように日本からアクセスを拒否するよう設定します。

 

Apacheを再起動

Apacheを再起動すれば、mod_geoipがモジュールとして読み込まれます。

# service httpd restart

無事、再起動が終われば、mod_geoipの準備完了です。

 

動作確認

「geoip.conf」に日本からのアクセスのみ、拒否するよう設定したので正しく動作しているか確認します。

テストページにアクセス

WebサーバのIPアドレスにアクセスして、テストページが表示されるか確認します。

# curl -s http://<サーバIPアドレス>/
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>403 Forbidden</title>
</head><body>
<h1>Forbidden</h1>
<p>You don't have permission to access /
on this server.</p>
<p>Additionally, a 403 Forbidden
error was encountered while trying to use an ErrorDocument to handle the request.</p>
<hr>
<address>Apache/2.2.15 (CentOS) Server at <WebサーバIPアドレス>/ Port 80</address>
</body></html>

403エラーが表示されているので、設定通りに動作していることがわかります。

 

GeoIPとGeoLiteのデータベースを更新

mod_geoipが参照しているデータベースは、月に1回(たしか2日)更新されます。

データベースの定期更新は必須です。もし、更新を忘れると意図しないアクセスを拒否や許可する可能性があります。

 

データベースを更新

基本的なデータベースは、「geoipupdate」コマンドで更新できます。

※geoipupdateコマンドでは、「GeoLiteCountry.dat」「GeoLiteCity.dat」「GeoLiteASNum.dat」が更新できます。

# geoipupdate

 

その他データベースを追加

「geoiplookup」コマンドを更に便利にするのデータベースを追加します。

※「-f」オプションは、エラーを無視することができます。

# curl -f http://geolite.maxmind.com/download/geoip/database/GeoIPv6.dat.gz | zcat > /usr/share/GeoIP/GeoIPv6.dat
# curl -f http://geolite.maxmind.com/download/geoip/database/GeoLiteCityv6-beta/GeoLiteCityv6.dat.gz | zcat > /usr/share/GeoIP/GeoIPCityv6.dat
# curl -f http://download.maxmind.com/download/geoip/database/asnum/GeoIPASNum.dat.gz | zcat > /usr/share/GeoIP/GeoIPASNum.dat

加えて、シンボリックリンクを作成を行います。 1度行えば、それ以降は必要ありません。

# cd /usr/share/GeoIP/
# ln -s GeoLiteCity.dat GeoIPCity.dat
# ln -s GeoLiteCountry.dat GeoIPCountry.dat

 

データベース更新自動化スクリプト

データベースの定期更新が面倒な方は、シェルスクリプトをCRONで実行することをお勧めします。

CRONの準備

カゴヤ・クラウド/VPSでは、crontabがインストールされていません。そのため、crontabをインストールします。

# yum install -y crontabs

 

サーバ起動時にCRONが自動起動するよう設定します。

# service crond start
# chkconfig crond on

 

データベース定期更新シェルスクリプト

こんな感じでいいかな・・・

# vim /etc/cron.weekly/geoip_database_update.sh
#!/bin/sh

GEOIP_URL01="http://geolite.maxmind.com/download/geoip/database/GeoIPv6.dat.gz"
GEOIP_URL02="http://geolite.maxmind.com/download/geoip/database/GeoLiteCityv6-beta/GeoLiteCityv6.dat.gz"

####GeoIPデータベースの場所#######################################
GEOIP_FILE_IPv6="/usr/share/GeoIP/GeoIPv6.dat"
GEOIP_FILE_IPv6_NEW="/usr/share/GeoIP/GeoIPv6.dat.NEW"
GEOIP_FILE_LiteCity_IPv6="/usr/share/GeoIP/GeoIPCityv6.dat"
GEOIP_FILE_LiteCity_IPv6_NEW="/usr/share/GeoIP/GeoIPCityv6.dat.NEW"
##################################################################

/usr/bin/geoipupdate

curl -f $GEOIP_URL01 | zcat > $GEOIP_FILE_IPv6_NEW 1>/dev/null 2>/dev/null
if [ $  -eq 1 ]; then
        exit 1
fi

curl -f $GEOIP_URL02 | zcat > $GEOIP_FILE_LiteCity_IPv6_NEW 1>/dev/null 2>/dev/null
if [ $  -eq 1 ]; then
        exit 1
fi

##「-s」オプションは、ダウンロードファイルが0KB以上であることを確認している
if [ -s $GEOIP_FILE_IPv6_NEW ]; then
        mv -f $GEOIP_FILE_IPv6_NEW $GEOIP_FILE_IPv6
fi

if [ -s $GEOIP_FILE_LiteCity_IPv6_NEW ]; then
        mv -f $GEOIP_FILE_LiteCity_IPv6_NEW $GEOIP_FILE_LiteCity_IPv6
fi

exit 0

/etc/cron.weekly 直下に設置することで、週1回データベースが更新されます。

また、シェルスクリプトには実行権限を与える必要があります。

# chmod +x /etc/cron.weekly/geoip_database_update.sh

 

アクセス制限のサンプル

mod_geoipで可能なアクセス制限の記述方法を紹介します。

日本からのみ、アクセスを許可する設定
<DirectoryMatch / >
SetEnvIf GEOIP_COUNTRY_CODE JP AllowCountry
Order deny,allow
Deny from all
Allow from env=AllowCountry
</DirectoryMatch>
国と大陸からのアクセスを許可する設定

日本・アメリカ・北アメリカ・南アメリカ・オセアニア・ヨーロッパからアクセスを許可する設定

<DirectoryMatch / >
SetEnvIf GEOIP_COUNTRY_CODE US AllowCountry
SetEnvIf GEOIP_COUNTRY_CODE JP AllowCountry
SetEnvIf GEOIP_CONTINENT_CODE SA AllowContinent
SetEnvIf GEOIP_CONTINENT_CODE EU AllowContinent
SetEnvIf GEOIP_CONTINENT_CODE NA AllowContinent
SetEnvIf GEOIP_CONTINENT_CODE OC AllowContinent
Order deny,allow
Deny from all
Allow from env=AllowCountry
Allow from env=AllowContinent
</DirectoryMatch>

GEOIP_CONTINENT_CODEで選択できる大陸一覧

AF - アフリカ

AS - アジア

EU - ヨーロッパ

NA - 北米

OC - オセアニア

SA - 南アメリカ

 

中国とロシアからのアクセスを拒否する設定
<DirectoryMatch />
SetEnvIf GEOIP_COUNTRY_CODE CN BlockCountry
SetEnvIf GEOIP_COUNTRY_CODE RU BlockCountry
Order allow,deny
Allow from all
Deny from env=BlockCountry
</DirectoryMatch>