2013/10/14

Raspberry PIでWoLリピータ的な物を作った

RPiに埃が被り始め,ちょうどWi-Fiのドングルも余ってたので,WoL (Wake on LAN) リピータ的な物を作った.

使ったもの

  • Raspberry Pi, Model B, revision 2
  • Raspbian wheezy, 2013-09-25
  • PLANEX GW-USValue-EZ
  • PC (Windows 7)

作るもの

(Internet)---(Modem)---(Wi-Fi Router)
                              z  192.168.111.1
                       wlan0  z  192.168.111.8
                            (RPi) ←これ
                        eth0  |  192.168.0.1
                              |  192.168.0.2
                            (PC)
【凡例】
 - : ケーブル
 | : これもケーブル
 z : 電波

RPiはインターネットからwlan0経由で流れてきたWoLのUDPパケットを,eth0にforwardする.RPiさえ常時電源ONにしておけば,PCの電源がOFFでも,インターネットからやってきたWoLパケットマジックパケットがRPi経由でPCまで届く.モデムとかごちゃごちゃしてる部屋の一角から,そこから少し離れたPCまでケーブルをのばさなくて良いのがポイント.

準備 : OSを入れる

ここからRaspbianのイメージを取ってきて,Win32DiskImagerでSDカードに焼いた.

準備 : SSHでRPiに接続する (no display)

手元にHDMIケーブルがなかったので,RPiにディスプレイは繋がず,PCからSSHで接続することにした.
Raspbianは最初からDHCPを使うように設定されているようなので,DHCPサーバーさえあれば楽ちんである.しかし,有線ルーターを持っていないので,仕方なくPCとRPiを直接イーサネットケーブルで繋ぎ,PCにOpen DHCP Serverを入れて対処することにした.
まず,Open DHCP Serverをインストールする.インストール先のディレクトリを開き,OpenDHCPServer.iniを開き編集する.
108行目くらいに[RANGE_SET]という部分があるので,その下にあるDHCPRangeを次のように変更して保存する.
DHCPRange=192.168.0.1-192.168.0.1

次にPCのローカルエリア接続のIPアドレスを192.168.0.2,サブネットマスクを255.255.255.0に設定した.そして,コマンドプロンプトからOpen DHCP Serverのバイナリがあるディレクトリに移動してRunStandAlone.batを起動すると,リアルタイムにログが流れる (実行する前にOpen DHCP Serverのサービス停止しないとだめかも).この状態でRPiとPCをイーサネットケーブルで繋ぎ,RPiの電源を入れる.しばらくすると,コマンドプロンプトにDHCPDISCOVERなどと表示され,ホストraspberrypiに192.168.0.1を割り振ったというメッセージが表示される (下図).
ファイアウォールへは例外を登録しないとDHCPDISCOVERを検知できないかも (ファイアウォールを一時的にOFFにするのもあり).
これで,RPiにIPアドレスが割り当てられたので,Tera TermなどからSSHで接続できる.
SSHで接続し,次回以降DHCPサーバーが不要となるよう
/etc/network/interfaces
を開いて,
iface eth0 inet dhcp
を#でコメントアウトし,代わりに
auto eth0
iface eth0 inet static
    address 192.168.0.1
    netmask 255.255.255.0
と書いて保存しておく.この時点で,PCで起動しておいたOpen DHCP Serverは終了してよい (PCのIPアドレスを192.168.0.2に固定した設定はそのまま残しておく).

この後の作業でRPiをインターネットからアクセス可能にするので,鍵認証の設定をしたほうがいい (説明はここには書かない).

準備 : Wi-Fi APに接続

まず,RPiにWi-Fiのドングルを挿す.すると何故か勝手に再起動されてしまうので,再びRaspbianが起動するのを1分程度待つ.起動したっぽかったら,PCからイーサネット経由でRPiにSSHで接続する.
lsusbをすると,GW-USValue-EZは自動的に認識されていることがわかる.
$ lsusb
Bus 001 Device 002: ID 0424:9512 Standard Microsystems Corp.
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp.
Bus 001 Device 004: ID 2019:ed17 PLANEX GW-USValue-EZ 802.11n Wireless Adapter [Realtek RTL8188CUS]

なので,/etc/wpa_supplicant/wpa_supplicant.confをいじるだけで良かった気がする (記憶が曖昧).
また,特に他の設定をしなくても,次回起動時に勝手に接続してくれた気がする (しかし,このままだとPCとイーサネットケーブルでつないだまま(再)起動すると,起動後にwlan0が落ちるはず(ドングルのLEDランプが消えてしまう).ケーブルを挿さず,ドングルだけ挿せばwlan0が生きるはず.).

今回の接続先はWPA2だったので,/etc/wpa_supplicant/wpa_supplicant.confを以下のようにしたところ,接続できた.

ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1

network={
    ssid="ssid"
    psk="passphrase"
    scan_ssid=1
    proto=RSN
    key_mgmt=WPA-PSK
    pairwise=CCMP TKIP
    group=CCMP TKIP
}

準備 : ifplugdの設定を編集

eth0とwlan0の2つのNICを同時に使おうとすると,ifplugdのせいで,wlan0が使えなくなってしまう (Wi-FiドングルのLEDランプが消える).なので,以下のように設定を変更する.

初期状態だと/etc/default/ifplugdは以下のようになっていたはず (もしかしたら少し違うかも).
INTERFACES="all"
HOTPLUG_INTERFACES="all"
ARGS="-q -f -u0 -d10 -w -I"
SUSPEND_ACTION="stop"

このうち,INTERFACESとHOTPLUG_INTERFACESを以下のように変更する.こうすることで,eth0がifplugdの管理下から外れる (のだと思われる).
INTERFACES=""
HOTPLUG_INTERFACES="wlan0"

これで,次回のRPi起動時は,eth0もwlan0も生きるようになった.

本題 : WoLのパケットをフォワーディングする設定

今回は,iptablesコマンドおよびarpコマンドを使う.
まず,以下のコマンドで,wlan0のUDPのポート9(WoLでよく使われるポート番号である) に来たパケットをPC側に転送するように設定する.
# iptables -t nat -A PREROUTING -d 192.168.111.8 -p udp --dport 9 -j DNAT --to-destination 192.168.0.2

なお,追加したテーブルは以下のように確認できる.
# iptables -t nat -nL

また,誤って登録した場合など,追加した項目を削除したい場合は
# iptables -t nat -D PREROUTING 1
を実行する.最後の1はエントリの番号である.

上記コマンドで登録したルールは,再起動すると消えてしまう.
なので,起動時に自動でルールをロードしてくれる,iptables-persistentをインストールする.
# apt-get install iptables-persistent
インストールの途中で,現在登録されているIPv4のiptablesのルールを保存し,次回以降自動的に読み込むかどうかを問われる.なので,はい(Yes)を選んでおく.IPv6についても同様に聞かれるが,今回は使わなかったので,いいえ(No)を選んだ.
これで,再起動しても上記のiptablesが保持されるようになる.

次に,設定したフォワーディングが動作するよう,ifup時に,/proc/sys/net/ipv4/ip_forwardに1を書き込む様に設定する.以下のスクリプトを/etc/network/if-up.d内に作成する.ここではenable-ipv4-forwardという名前とした.
#!/bin/sh
echo 1 > /proc/sys/net/ipv4/ip_forward

次に,「PCが起動していない時にRPiを再起動した」というシチュエーションを考える.このときarpテーブルを確認すると(arpコマンド),PCのIPアドレスである192.168.0.2に対するMACアドレスが判明していないことが分かる.今回はeth0のネットワークにブロードキャストせず,192.168.0.2だけにパケットを送ろうとしているので,たぶんarpエントリが必要なのだと思う (予想).

そのため,こちらもifup時にstaticなarpエントリを追加するように設定する.以下のスクリプトを/etc/network/if-up.d内に作成する.このサイトを参考に,ここでは,add-my-arp-entryというスクリプトを作成した.
#!/bin/sh
arp -i eth0 -s 192.168.0.2 PCのMACアドレス

その後,これらのスクリプトが実行できるようにパーミッションを忘れずに変更しておく.
# chmod +x /etc/network/if-up.d/enable-ipv4-forward
# chmod +x /etc/network/if-up.d/add-my-arp-entry

これで,起動時にIPv4のフォワーディングが有効となり,arpエントリも追加される.

以上で,インターネットからRPi宛に飛ばしたWoLパケットマジックパケットはPC側に転送されるようになった.

完成!(写真じゃ伝わらないけど)

注意

この記事は作業しながら書いたのではなく,完成後に書いたものなので,手順が抜けていたりするかもしれないです.

感想

久しぶりにブログを書いたら疲れた.
それと文章がレポートみたいになった.語尾の「である」とか
まあいいや

0 件のコメント:

コメントを投稿