Wake on LAN してみる Part 4 (SOCKS5 を越えて)
『Wake on LAN をしてみる Part 2』 で Wake on LAN を JavaFX で実装する方法について書いた。
未だ完成には いたらないのものの、とりあえず、居間にいながらにして
別の部屋にある Linux サーバの電源の ON/OFF を行えるぐらいにはなった。
とりあえず、当初の目的は十分達成できたので 後は適当に画面を作れば 何となくアプリケーションは完成するはずだったのだが...
人間の欲望というのは恐ろしいもので、これだけ便利だと 居間からだけではなく、
会社からも ON/OFF できるようにしたくなる。
ネットワークにつながっていれば どこからでも一緒でしょ!! なんて言う甘い考えで試してみることに...
会社のデスクから 自宅の PC を起動するためには 会社の PC から自宅のプライベートネットワークに
マジックパケットをブロードキャストしなくてはならない。
しかも
- 自宅のルータ
- 会社のプロキシ
こんな感じで...
会社PC ----> [会社のプロキシ] ---- インターネット ----> [自宅のルータ] ----> 自宅PC巷で ルータ越え とか プロキシ越え とか言われているやつ。
前者は利用しているルータにもよるが、大抵の場合 ルータの設定を変更するだけでなんとかなるはず...
もし、不幸にも なんともならなかったら、そんな ルータ は買い替えてしまえばよい。
で、実際何を設定すれば良いかと言うと
任意のポートに送信されてきた UDP のパケットを プライベートネットワークのブロードキャストアドレス宛に転送するように設定するだけで良い。
例えば、
5555 -- 転送 --> 192.168.0.255:5555のように設定すると...
ルータの 5555 ポート (5555 でなくてもよい) 宛に マジックパケットを送信するだけで ルータが勝手にプライベートネットワークに ブロードキャストしてくれる。
早速、自宅のルータでも設定してみたのだが、なんと!!
『IP アドレス は 255 より小さな値でなければなりません。』とか言われて 255 への転送を許可してくれない。
確かに、下手に ブロードキャストアドレスに転送できてしまったら Smurf 攻撃の踏み台にされかねないので、しかたがないのだが...
とは言え、簡単にはあきらめられないので、試しに サブネットマスクを 255.255.255.128 に変更してみた。
これは、単にブロードキャストアドレスの4バイト目を 255 以外にしてみれば 良いんじゃない という安易な考えだったのだが...
なんと!!
5555 -- 転送 --> 192.168.0.127:5555という感じで ブロードキャストアドレス 192.168.0.127 に転送するように設定できた。
家庭用ルータなんてこんなもんなんだね。^^;)
と言うことで...
早速 Linux サーバが起動されるかテストしてみたが、
もちろん問題なく起動してくれた。
ちなみに ルータのグローバルアドレスは 大抵 DHCP で割り当てられているので、
固定のドメイン名でアクセスできるように ダイナミックDNS に登録しておけば完璧だ。
これで 公衆無線LANからなら どこからでも 自宅のサーバを起動することができてとっても便利だ。
これで1つ目の壁は無事乗り越えることができたのだが...
会社から 自宅の Linux サーバを立ち上げるには まだもう一つ超えなくてはならない 『プロキシ』 という壁がある。
通常、JavaFX は Java Web Start や Applet として起動するため アプリケーション側で プロキシ のことを気にする必要はない。
Java Preferences でプロキシの設定ができるからである。ちなみに 通常は システムの設定がそのまま利用される。
しかし、これは HTTP 等の TCP に限った話だ。
TCP については J2SE 5.0 で プロキシをサポートするようになったのだが、UDP については Java 6 でもサポートされていない。(詳細は こちら)
プロキシには HTTP や SOCKS など いくつかの種類があるが UDP で利用できるプロキシは SOCKS5 以外にない。
SOCKS5 は rfc1928 でちゃんとスペックが決まっているので、自前で実装することもできるのだが...
google で検索したら jsocks という Java のライブラリが見つかったので それを使うことにした。
JSch もそうだが 既存の Java のライブラリがそのまま利用できるのは JavaFX のメリットの一つでもある。
このライブラリには SOCKS5 のプロキシ経由で UDP パケットを送信するための Socks5DatagramSocket というクラスが用意されている。
使い方は いたって簡単だ。以下のように 通常の DatagramSocket の代わりに使うだけ...
import java.lang.Integer.parseInt; import java.net.DatagramSocket; import socks.Socks5DatagramSocket; import socks.Socks5Proxy; // 起動する PC の NIC の MAC アドレス public var macAddress = "aa:bb:cc:dd:ee:ff" // マジックパケットの送信先ホスト名 (ルータのダイナミックDNSのドメイン名) public var host = "host.to.wake.on.lan"; // マジックパケットの送信先ポート (ルータのポート) public var port = 5555; // SOCKS5 プロキシサーバのホスト名 又は IPアドレス def proxyHost = "socks5.proxy"; // SOCKS5 プロキシサーバのポート番号 def proxyPort = 1080; // マジックパケット def magicPacket = [ for (i in [1..6]) { 0xff } for (i in [1..16], b in macAddress.split("-|:")) { parseInt(b, 16) } ]; // プロキシサーバ def proxy = new Socks5Proxy(proxyHost, proxyPort); proxy.resolveAddrLocally(false); // マジックパケットを任意のポートにブロードキャストするための UDPデータグラムパケット // ここでは送信先のホスト名は指定してはいけない。 // プロキシの内側のネットワークでは外部のネットワークの名前解決ができない場合があるため... def packet = new DatagramPacket(magicPacket, sizeof magicPacket, null, port); // プロキシサーバ経由で マジックパケット 送信 def socket = new Socks5DatagramSocket(proxy, 0, null); socket.send(packet, host); // ここでホスト名を指定する。
『Wake on LAN をしてみる Part 2』 のサンプルコードと見比べても そんなに違いはない。
たったこれだけのコードでプロキシを越えられるなんて少し拍子抜けしてしまったが...
これで いざというときに 会社から自宅の PC を起動することができてしまう。
なんて幸せなんだろう...
プロキシを越えられる WOL のアプリケーションは見たことがないので これはなかなかおもしろいかもしれない。
今回は起動だけしか試せなかったが 同様にサーバを停止することだってできるはずである。
これについては またの機会ということで...