gmailでグローバルIPアドレス更新を通知
自分のグローバルIPが更新されたとき、gmailに新しいIPアドレスを自動送信するスクリプトを書いてみた。
以前は、DDNSサービスを使いつつ、DiCE for LinuxでIPアドレスの更新をしていたのですが、契約プロバイダ*1がDDNSのIPアドレス更新手順を変更したせいでDiCEが使えなくなってしまいました*2
最近になって、サーバを再公開する目的はできたのですが、DDNSを再契約するのも勿体ないので、簡易的なIPアドレス通知スクリプトを自作することにしました。
このエントリーで紹介するRubyScriptを一定時間おきに起動するようcronに登録しておけば、前回の起動時からGlobalIPアドレスに変更があった場合に gmailで新しいIPAddressを指定したアドレス宛に送信することができます。
なお、スクリプトから参照している『tlsmail』、『hpricot』の2つのライブラリは標準添付されていないため、事前インストールが必要です。
コンソールから以下のコマンドでインストールすることが出来ます。
# gem install tlsmail
# gem install hpricot
ちなみに、tlsmailはRuby標準添付のsmtpライブラリをtls認証に対応させるためのライブラリ、hpricot は、HTMLドキュメントのタグ解析ライブラリとなっています。
スクリプト本体
Fedora系の場合 /etc/cron.hourly/update_global_ip.rb 等として保存すること。
また、当然実行権限をつけておきます。
なお、
$password['gmail_address'] = "...."
$password['gmail_password'] = "...."
の部分は、各人のアカウント情報を適切に設定してください*3。
#!/usr/bin/ruby require 'net/smtp' require 'rubygems' require 'tlsmail' require 'hpricot' require 'open-uri' $password = Hash.new $password['gmail_address'] = "...." $password['gmail_password'] = "...." reIP = Regexp.new( "([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})" ) tmpFile = '/tmp/global_ip.tmp' doc = Hpricot( open("http://www.axisnetworks.biz/tools/gip/").read ) s = "" (doc/:p).each do |e| buf = e.inner_text if ( e['name'] == 'ip' ) && ( e['class'] == 'style4' ) s += reIP.match( buf ).to_a[0] if buf != nil s = "[" + s + "]" if buf != nil end MESSAGE = <<EndOfMail From: Your Name <#{$password["gmail_address"]}> To: Dest Address <#{$password["gmail_address"]}> Subject: [GLOBAL IP NOTIFICATION] Date: #{Time.now} #{s} EndOfMail old = open( tmpFile ).read if File.exist?(tmpFile) open( tmpFile, "w" ).write( s ) if old != s smtpserver = Net::SMTP.new('smtp.gmail.com', 587) smtpserver.enable_tls(OpenSSL::SSL::VERIFY_NONE) smtpserver.start('gmail.com', $password["gmail_address"], $password["gmail_password"], :login) do |smtp| smtp.send_message(MESSAGE, $password["gmail_address"], $password["gmail_address"]) end end
スクリプトの解説
まず、以下の行で『IP君(http://www.axisnetworks.biz/tools/gip/ )』に接続し、自分のグローバルIPアドレスが含まれるhtmlページを取得する。
doc = Hpricot( open("http://www.axisnetworks.biz/tools/gip/").read )
次に、取得したWebページからIPアドレスが表示されている部分を抜き出す。
s = "" (doc/:p).each do |e| buf = e.inner_text if ( e['name'] == 'ip' ) && ( e['class'] == 'style4' ) s += reIP.match( buf ).to_a[0] if buf != nil s = "[" + s + "]" if buf != nil end
最初に取得したWebサイトのURLを通常のブラウザで表示させると、テーブルの上から4行目に自分のグローバルIPアドレスが表示されている。
また、htmlソースを表示させると、IPアドレスの部分は
<p name="ip" class="style4"></p>
でくくられた中にいることがわかる。
なので、スクリプトでは、ページ内の全 pタグを検索し、attributeが name='ip' class='style4' であった場合タグ内のテキストを取り出し、取り出したテキストを正規表現にかけ、自分のグローバルIPアドレス(と思われるもの)を取得している。
ページのレイアウトが変わったときなどはこの部分を書き換えれば対応できるはず。
あとは、メール文面を生成し、前回取得したIPアドレスとと今回取得したIPアドレスが異なっていればgmailのsmtpサーバを使用して自分宛に送信するだけ。
メール送信前に、以下の2行でtls認証の設定を行っている。
smtpserver = Net::SMTP.new('smtp.gmail.com', 587) smtpserver.enable_tls(OpenSSL::SSL::VERIFY_NONE)
なお、hpricot、tlsmail については以下のサイト様を参考にさせていただきました。感謝です。
http://route477.net/d/?date=20070205
http://d.hatena.ne.jp/unageanu/20090429/1241001029
余談ですが、mechanize というライブラリもありまして、こちらを使うとWebフォームへの入力、入力内容の送信といったことも自動化できます。
掲示板の荒らし等、良からぬことを考えないのであれば非常に有用なライブラリだと思います。
上のサイトで紹介されていますので、興味がある方はあわせて参考にしてください。
昔ネトゲ(ff11)をやっていた頃のことですが、これらのライブラリを使って、スクリプトからhttp://www.ffxiah.com にアクセスし、競売の在庫が出たら携帯にメールとかやってたことがあります。
タイムラグが大きく、あまりやくには立ちませんでしたが・・・