Processing math: 100%

highlight.pack.js

2014年5月3日土曜日

Ubuntu で日本以外からのSSHアクセスを拒否する (GeoIP2 Python API ver.)

前の記事で紹介した方法は手軽なのですが、 実は MaxMind 社の古いAPIを使っているという、ちょっとだけ気になる点が存在します。

そこで、今度は最新のAPIを利用したスクリプトを使用+データーベースの自動更新をやってみたいと思います。

依存ライブラリのインストール

sudo pip install geoip2
で、python スクリプト geoip2 とその依存パッケージをインストールします。

チェック用スクリプトの配置

スクリプトを /opt/geossh/check に配置します。 ファイルの中身は以下のとおりです。

#!/usr/bin/python
import os, sys, traceback
import geoip2.database
ALLOW = 1
DENY = 0
when_error = ALLOW
def rule(code):
if code == "JP": return ALLOW
if code == None: return ALLOW
return DENY
exitcode = when_error
try:
log = os.popen("logger -t geoip/check -p daemon.notice", "w")
logerr = os.popen("logger -t geoip/check -p daemon.err", "w")
sys.stdout = log
sys.stderr = logerr
if len(sys.argv) != 2:
sys.stderr.write("Usage: %s ipaddress\n" % sys.argv0
)
sys.exit(0)
addr = sys.argv1
dirpath = os.path.abspath(__file__)
datafile = os.path.join(os.path.dirname(dirpath), "GeoIP.dat")
r = geoip2.database.Reader(datafile)
if not r:
sys.exit(0)
code = r.country(addr).country.iso_code
exitcode = rule(code)
print("%s %s %s" % (addr, code, exitcode == ALLOW and "allow" or "deny"))
except SystemExit:
pass
except:
traceback.print_exception(sys.exc_type, sys.exc_value, sys.exc_traceback)
sys.exit(exitcode)
view raw check hosted with ❤ by GitHub

配置が終わったら、コマンドで実行権限を付与します。

sudo chmod +x /opt/geossh/check

データベースアップデートスクリプトの配置

データベースをアップデートするスクリプトを /opt/geossh/update に配置します。

#!/usr/bin/python
import os, urllib2, sys
url = "http://geolite.maxmind.com/download/geoip/database/GeoLite2-Country.mmdb.gz"
log = os.popen("logger -t geoip/update -p daemon.notice", "w")
logerr = os.popen("logger -t geoip/update -p daemon.err", "w")
sys.stdout = log
sys.stderr = logerr
datadir = os.path.dirname(os.path.abspath(__file__))
timestamp_file = os.path.join(datadir, "GeoIP.timestamp")
tmpfile = os.path.join(datadir, "GeoIP.tmp")
datfile = os.path.join(datadir, "GeoIP.dat")
try:
timestamp = open(timestamp_file).read()
except IOError:
timestamp = None
headers = {}
if timestamp:
headers"IfModifiedSince"
= timestamp
request = urllib2.Request(url, headers=headers)
try:
conn = urllib2.urlopen(request)
except urllib2.HTTPError, e:
status = getattr(e, "code", None)
if status == 304:
print("Not Modified")
sys.exit(0)
else:
raise
info = conn.info()
timestamp = info.get("Last-Modified", "")
tmp = os.popen("gunzip >%s" % tmpfile, "w")
while True:
buf = conn.read(4096)
if not buf:
break
tmp.write(buf)
tmp.close()
os.rename(tmpfile, datfile)
open(timestamp_file, "w").write(timestamp)
print("Updated to %r" % timestamp)
view raw update hosted with ❤ by GitHub

その後実行権限を、以下のコマンドで与えます。

sudo chmod +x /opt/geossh/update

なお、これらのスクリプトは ts1さん のコードを参考に手直したものです。

データベースのダウンロード

先ほどのスクリプトを利用して、データベースをダウンロードしてきます。

sudo /opt/geossh/update

GeoIP.dat というファイルと、 GeoIP.timestamp というファイルが /opt/geossh 以下に作成されます。

データーベースを定期的にダウンロードするようにする

sudo crontab -e
で、crontab を編集します。以下の内容を追加してください。

59 23 1-8 * 3 /opt/geossh/update
view raw crontab hosted with ❤ by GitHub

これは、月の最初の火曜日にファイルの更新が行われるため、その時に自動でスクリプトを走らせるための設定になります。

/opt/geossh/check の動作確認

前の記事と同じ方法で動作確認を行ってください。

自分が普段使っているクライアントPCののグローバルIPでリターンコードが 1 になることは必ず確認して下さい。

hosts.deny からスクリプトを呼び出す

アクセス制限をかけるために、 /etc/hosts.deny に以下の内容を追加します。

sshd: ALL: aclexec /opt/geossh/check %a

以上で終了です。お疲れ様でした。

0 件のコメント:

コメントを投稿