のらぬこの日常を描く

ノージャンルのお役立ち情報やアニメとゲームの話、ソフトウェア開発に関する話などを中心としたブログです。

gmailでグローバルIPアドレス更新を通知

自分のグローバルIPが更新されたとき、gmailに新しいIPアドレスを自動送信するスクリプトを書いてみた。

以前は、DDNSサービスを使いつつ、DiCE for LinuxIPアドレスの更新をしていたのですが、契約プロバイ*1DDNSIPアドレス更新手順を変更したせいで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アドレスが異なっていればgmailsmtpサーバを使用して自分宛に送信するだけ。

メール送信前に、以下の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 にアクセスし、競売の在庫が出たら携帯にメールとかやってたことがあります。

タイムラグが大きく、あまりやくには立ちませんでしたが・・・

*1@nifty

*2Windows版DiCEの方は更新されているようですがLinux版は更新されていないようです

*3:ぼくの場合は、require '~/lib/passdb'等の名前で外部ファイルにまとめて書いてるけど