WR8500Nのネットワーク機能をコマンドラインから切断、接続する。
自宅で使ってる無線LANルータはWR-8500N というNECの製品です。
いくつもある製品からこれを選んだ決め手は以下の点でした。
- 11n, 11g, 11bを同時に使える。
- 1000BASE-Tの有線LAN4ポート搭載
- WPAとWEPを使い分けられるマルチSSID機能
- ネットでの評判がそれなりに良い
が!
そもそもパケットフィルタの設定がすごくやりずらい
という2点が致命的で、私にとっては割と残念な製品でした。
これならバッファロ~あたりを選んでいた方がよっぽど幸せになれたかもしれない。
まあ、安い買い物でもないし、当面は使い続けますけどね。
さて、この製品も他の製品同様、ISPとの回線接続、回線切断等の操作はWebブラウザからやるわけですが、いちいちWebからやらずとも、Rubyでできないかというのが今日の課題。
上の写真で赤枠で囲まれている「切断」ボタンを押すと回線が切断され「接続」と表示が変わります。
そしてさらに「接続」ボタンを押すと、回線が接続され、表示が「切断」に変わります。
最初は、Web画面の自動操作をスクリプトから行う機能を持つ、Ruby::Mechanize のサンプルとしてブログネタにするつもりだったのですが、htmlソースを見て断念。
ボタン押せば、単にform.submit()するだけだと思っていたら、なんかJAVA Scriptでごちゃごちゃとコーディングされてました。
ソース読むのもめんどくさかったので、ボタンを押した時のパケットをキャプチャーして、その内容を http.post/getでそのまま送り込む方針に転換しました。
Webブラウザでルータの設定画面を表示させ、後はボタンを押すだけの状態にします。
その後、rootになって以下のコマンドを打ち込む。
# tcpdump -A host 192.168.0.1 and port 80 -A はパケット内容をASCII表示するためのオプションです。 リクエストの文字データをそのまま見たいだけなので16進数表示とかは不要なのです。 さらにいえば、ip部分の表示も不要なのですが、そういったことをしてくれるオプションは見つからなかった。
tcpdumpがパケットキャプチャーを開始したら、Webブラウザの切断ボタン、接続ボタンを押します。
これでパケットのログが取れているはずなので、tcpdumpの実行をCTRL+Cで停止させます。
そしてキャプチャー結果から、HTTPリクエスト部分を抜き出します。
切断時のリクエストがこれ。
POST /index.cgi/index_contents_set HTTP/1.1 Host: 192.168.0.1 Authorization: Basic xxxxxxxxxxxxxxxxxxxx= (一部略) CONNECT=0&BUTTON_STATUS=%C0%DA%C3%C7&DISABLED_CHECKBOX=
接続時のリクエストがこれ
POST /index.cgi/index_contents_set HTTP/1.1 Host: 192.168.0.1 Authorization: Basic xxxxxxxxxxxxxxxxxxxx= (一部略) CONNECT=0&BUTTON_STATUS=%C0%DC%C2%B3&DISABLED_CHECKBOX=
もしかして、接続なのか、切断なのかは、ボタン文字列で判定してますか?*2
かなりダサダサな実装な気が致しますが、それを元に作ったスクリプトがこれ。
require 'net/http' Net::HTTP.version_1_2 req = Net::HTTP::Post.new( '/index.cgi/index_contents_set' ) req.basic_auth 'admin', '.....' # basic 認証の username / passwordを入れる req.body=("CONNECT=0&BUTTON_STATUS=%C0%DA%C3%C7&DISABLED_CHECKBOX=") Net::HTTP.start( '192.168.0.1' ) { |http| response = http.request(req) } sleep 3 req.body=("CONNECT=1&BUTTON_STATUS=%C0%DC%C2%B3&DISABLED_CHECKBOX=") Net::HTTP.start( '192.168.0.1' ) { |http| response = http.request(req) }
やってることは
HTTP::Postオブジェクト作成
切断リクエストをpost
3秒まつ
接続リクエストをpost
これだけです。