GoogleAppEngineでアクセス元のIPアドレスによって処理を分けたい場合があります。(主にガラケー対応)
その場合IPアドレスを表現するオブジェクトを使いたいところですが、その用途にあったPythonモジュールなかなか見つかりません。
そこで今回は
- IP Address をオブジェクトとして扱う
- IP Address をCIDR表記で範囲として扱う
という2点をPythonでクリアするための方法を紹介します。
IPy モジュールを使う
Freeで公開されているIPyというモジュールを使います。
IPy - A python Module for handling IP-Addresses and Networks http://c0re.23.nu/c0de/IPy/
こちらで紹介されているモジュールはPerlのNet::IPに似たモジュールで、IPv6にも対応しています。
最新版をダウンロードしましょう
IPy-0.42.tar.gz
まずはPythonインタプリタで動作確認
解凍すると IPy-0.42/build/lib/IPy.py が得られるので lib ディレクトリの階層でPythonインタプリタを起動します。
$ tar xzvf IPy-0.42.tar.gz $ IPy-0.42/build/lib $ python
IPy.pyはそのままではunicode errorが起こるので、762, 763の特殊文字を消します。
(コピーライトの文字が入っていました。)
では試しにOverviewにあるようにIPyを使ってみましょう。
>>> import IPy >>> ip = IPy.IP('120.3.4.5/1') Traceback (most recent call last): File "<stdin>", line 1, in <module> File "IPy.py", line 294, in __init__ raise ValueError, "%s goes not well with prefixlen %d" % (hex(self.ip), self._prefixlen) ValueError: 0x78030405L goes not well with prefixlen 1
するとこのようにエラーが起こってしまいます。
すこしソースコードを編集してみましょう。1220行目をコメントアウトし、1221行目のようにします。
1218 def _checkNetaddrWorksWithPrefixlen(net, prefixlen, version): 1219 """Check if a base addess of e network is compatible with a prefixlen""" 1220 #if net & _prefixlenToNetmask(prefixlen, version) == net: 1221 if net: 1222 return 1 1223 else: 1224 return 0 1225
GoogleAppEngine での利用
IPy モジュールを GoogleAppEngine で使うためにソースファイルのIPy.py をGoogleAppEngieのルートディレクトリに配置します。
(GoogleAppEngineLaunchdr の Path に表示されているところにコピーします。)
$ mv IPy.py /path/to/gae/root
では、SDK Console の Interactive Console で動作確認をしよう。
Textareaに
import IPy ip = IPy.IP('192.168.1.100')
と打って [Run Program] ボタンを押し、右側にエラーが表示されなければ成功。
この状態になれば、下層の*.pyでもimportすることができます。
では実際のコードで使ってみましょう。
サンプルとして、携帯キャリアのIP帯域からのアクセスかを判定するメソッドを作ります。
import IPy from google.appengine.ext import webapp class Main(webapp.RequestHandler): ''' 中略 ''' def include(self): # 簡素化するためにRequestParameterでキャリアとIPが送られてくる前提です^_^; carrier = self.request.get('carrier') remote_ip = IPy.IP(self.request.get('ip')) elif carrier == 'softbank': soft_ip = [ IPy.IP('123.108.237.0/27'), IPy.IP('202.253.96.224/27'), IPy.IP('210.146.7.192/26'), IPy.IP('123.108.237.224/27'), IPy.IP('202.253.96.0/27')] # CIDRで範囲指定されたIP群の中に含まれているかを判断します for ip in soft_ip: if remote_ip in ip: return True return false else: return False
こんな感じでIPyを使う事でIPアドレスにより制御をGoogleAppEngineで実現できます。