DynDNSのIPを更新するRubyスクリプト
DynDNS使っています
最近のエントリから察せられるように、VineLinuxを入れたPCで自宅サーバを試しています。そして、ダイナミックDNS対策にDynDNSを使っているのですが、IP割り当てが一定時間ごとに変わる一般プロバイダを通していると、定期的にDynDNSへのIPの登録を変更する必要があります。
それを自動で行ってくれるプログラムがいくつか公開されています。
DynDNS Update Clientを作ってみる
ndyndnsはC言語で書かれていて、またソースが公開されているので、ざっくりと中身の流れは分かっていた。それを頭に入れRubyで書いてみることにしました。
処理の流れは、以下の3ステップ。
- 現在のグローバルIPアドレスを取得
- 以前設定したIPアドレスと比較
- 変化があるか?
- なければ終了
- あれば、それを登録して、そのIPアドレスをメモしておく
グローバルIPを取得する
ルータにアクセスしてグローバルIPを取得する、という方法もあったのですが、解析に手間取りそうで却下。
DynDNSがIPを返してくれるページを設置してくれているのでそれを使うことにしました。
また、VALUE-DOMAINも同様なページを設置しています。
Basic認証を行う
Rubyでページを取得するには、"open-uri"という便利なライブラリがあるのですが、Basic認証を超えて取得する方法が分かりにくかったので以下のページを参考に実装しました。
具体的には以下のような内容になります。
require "open-uri" auth = "Basic "+["#{Username}:#{Password}"].pack("m").chomp hashAuth = { "Authorization" => auth, "User-Agent" => "update_dyndns.rb" } open( "http://need-basic.example.com/", hashAuth )
ハマったポイントは以下の2点。
- packした文字列をchompする
- "User-Agent"を設定しておく(DynDNSにつながるのに必要)
update_dyndns.rb
以上の情報をまとめて書いたコードが以下のものです。
使用するには、コードの冒頭に羅列している"DynDNS_"の定数を定義してから実行してみてください。
(これをcronで5分置き程度に実行するように設定すれば完了です。)
#!/usr/bin/ruby DynDNS_Username = "username" DynDNS_Password = "password" DynDNS_Hostname = 'host.dyndns.biz' DynDNS_Wildcard = 'NOCHG' # 'ON', 'NOCHG', 'OFF' DynDNS_MX = 'NOCHG' # 'NOCHG' DynDNS_Backmx = 'NOCHG' # 'YES', 'NO', 'NOCHG' StoredIP_Filename = "/usr/local/bin/StoredIP.txt" #------------------------------------------------------------ # 現在のグローバルIPを取得する. # エラー時には"-1"を返します. #------------------------------------------------------------ def getCurrentIP require "socket" require "open-uri" #urlToGetIP = "http://dyn.value-domain.com/cgi-bin/dyn.fcg?ip" urlToGetIP = "http://checkip.dyndns.com" reIP = /(\d+)\.(\d+)\.(\d+)\.(\d+)/ # IPアドレスの正規表現. begin return open( urlToGetIP ).read.slice( reIP ) rescue return "-1" # error. end end #------------------------------------------------------------ # 前回取得していたIPを取得する. # 取得していなければ "-1" を返します. #------------------------------------------------------------ def getStoredIP begin f_ip = File.open( StoredIP_Filename, "r" ) return f_ip.gets.rstrip # 1行目にIPを記述しています. rescue return "-1" end end #------------------------------------------------------------ # 現在のグローバルIPでアップデートします. # @retval true 成功. #------------------------------------------------------------ def updateDynDNS( ip ) require "open-uri" auth = "Basic " + ["#{DynDNS_Username}:#{DynDNS_Password}"].pack("m").chomp hashAuth = { "Authorization" => auth, "User-Agent" => "update_dyndns.rb" } uriUpdate = "http://members.dyndns.org/nic/update?" + "hostname=#{DynDNS_Hostname}" + "&myip=#{ip}" + "&wildcard=#{DynDNS_Wildcard}" + "&mx=#{DynDNS_MX}" + "&backmx=#{DynDNS_Backmx}" begin print "start update [#{uriUpdate}]\n" open( uriUpdate, hashAuth ) print ".. update success.\n" return true rescue Exception => err print "update error: [#{err}]\n" return false end end #------------------------------------------------------------ # ファイルに格納します. #------------------------------------------------------------ def storeIP( ip ) begin f_ip = File.open( StoredIP_Filename, "w" ) f_ip.puts "#{ip}\n" f_ip.puts Time.now.to_s f_ip.close rescue print "error to store ip\n" end end #------------------------------------------------------------ # 実際の処理. #------------------------------------------------------------ storedIP = getStoredIP() currentIP = getCurrentIP() print "storedIP: [#{storedIP}]\n" print "currentIP: [#{currentIP}]\n" if( storedIP != currentIP ) print "need to update.\n" if updateDynDNS( currentIP ) == true # 成功. storeIP( currentIP ) else # 失敗. print "ERROR: failed to update.\n" end else print "no need to update.\n" end
参考書籍
- 作者: Dave Thomas,Chad Fowler,Andy Hunt,まつもとゆきひろ,田和勝
- 出版社/メーカー: オーム社
- 発売日: 2006/08/26
- メディア: 大型本
- 購入: 7人 クリック: 270回
- この商品を含むブログ (152件) を見る
- 作者: 青木峰郎,後藤裕蔵,高橋征義,まつもとゆきひろ
- 出版社/メーカー: ソフトバンク クリエイティブ
- 発売日: 2007/02/01
- メディア: 単行本
- 購入: 9人 クリック: 182回
- この商品を含むブログ (97件) を見る