0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

mrubyでWOL

Last updated at Posted at 2020-08-02

FreeBSDでRealtekなethernetインターフェースはWOLに対応しているので、mrubyからたたき起こしてみました。

ターゲットはASRock DeskMini A300で、BIOSの設定はネットで調べてみました。

mrubyはmrbgemsのmruby-socketを入れてビルドしておきます。

s = UDPSocket.new
s.setsockopt(Socket::SOL_SOCKET, Socket::SO_BROADCAST, 1)
mac = "12:34:56:78:9a:bc"
mes = ['FF'].pack('H2') * 6
sp = mac.split(':')
mgc = [sp[0]].pack('H2')
mgc << [sp[1]].pack('H2')
mgc << [sp[2]].pack('H2')
mgc << [sp[3]].pack('H2')
mgc << [sp[4]].pack('H2')
mgc << [sp[5]].pack('H2')
mes << mgc * 16
s.send(mes, 0, '192.168.1.255', 9)

macはターゲットのMACアドレスにします。192.168.1.255は自分のネットワークのブロードキャストアドレスにします。

FreeBSDは12.1でとくに設定は必要なかったです。インターフェースはこんなになってました。

re0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
        options=8209b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM,WOL_MAGC,LINKSTATE>
        ether 12:34:56:78:9a:bc
        inet 192.168.1.2 netmask 0xffffff00 broadcast 192.168.1.255
        media: Ethernet autoselect (1000baseT <full-duplex>)
        status: active
        nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>

tcpdump -e -xX ether broadcastで確認したところ、なぜか

mes << mac.split(':').pack('H2H2H2H2H2H2') * 16

がおかしな動きをしていたのでpackをばらしました。追記:修正済みです

このターゲットは負荷がなければ13Wくらいなのですが、でんこちゃんに怒られるので、未使用時は電源落としています。

昔元祖amd64のHummerなマシンが消費電力が100W以上あってskにパッチを当ててWOLできるようにしてみたことがありました。確かレジスタにフラグを立てるだけだったような記憶があります。

mrubyはFreeBSD/mipsのルーターに入っているのですが、ルーターは3Wくらいなので常時通電しています。

shutdownするときは必ず-pで電源を落とす必要があります。単にHALTしてシングルユーザになるとコントロールできなくなります。FreeBSDやLinuxにはpoweroffというコマンドもあるので、これを使っても良いかもしれません。

WOLのパケットはEtherパケットのヘッダーがブロードキャストアドレス(0xff,0xff,0xff,0xff,0xff,0xff)と自分のMACアドレスでパケットの種別がIP(0x0800)の14バイトになります。その後IPv4パケットが入りIPヘッダーと上のmrubyで作っているデータが入ります。WOL待ちのインターフェースはブロードキャストのEtherパケットを受け取れるようになっていて、その中身が自分宛のWOLパケットのときにパワーオンします。

WOLパケット待ちのreなインターフェースは100BaseTXでLink upした状態になっています。インターフェースがLink Down(LEDが消えてる)してるとWOLはできません。Linkは接続しているスイッチのLEDでも確認できます。

いくら自分しか知らないはずといっても通信がどこかでもれて不正アクセスで起動されると困ります。安全にインターネットから直接パケットを飛ばすことはできないので、VPNを張ってルーターに入ってスクリプトを実行しています。

WOL2.png

追記:FreeBSDには/usr/sbin/wakeというWOLのパケットを送れるコマンドがありました。portsにもいくつかありますが、依存もなくwakeでもよさそうです。とはいえ、ルーターはZRouterでイメージを作っていて、バイナリを追加するのはビルドと焼き直しが必要で、mrubyで処理するのも一つの方法です。

ネットで検索するとncコマンドでWOLのパケットを送信しているページがありますが、LinuxとFreeBSDではncの実装が違うためそのままは使えません。

Windowsのmruby-socket入りのmrubyでも動作しました。

Windows 7以降ではBATファイルでもWOLパケットが送れるようです。

WOLはBIOSで有効にした上で、shutdownする前にインターフェースのWOLをenableしておく必要があります。FreeBSDのreやfxpはデフォルトでWOLがenable(optionのWOL_MAGIC)になっています。

BIOSの設定はWOLとなっている場合もあり、PCI PMEとなってる場合もあり様々です。

PCI 2.1ではWOLはPCIボードとマザーボードをケーブルで接続していましたが、2.2ではPMEとしてPCIバスの中に取り込まれたので、ケーブル接続は必要なくなったようです。

Debianなマシンも起こせました。FreeBSDではデフォルトでWOLが有効なインターフェースが多いですが、Debianでは設定しないと有効にならないようです。

猛牛さんのLGY-PCI-TXDは古いものは蟹さんのRTL8139Cを使っていたようですがハードオフでRTL8139Dな物を110円で購入しDebianなマシンに入れてみたのですがWOLできませんでした。RTL8139DはRTL8139Cと互換がないのかもしれません。

停電があるとWOLできなくなります。機種によってはBIOSに電源復旧後に起動するなどの設定があるので、そうやって立ち上がったものを落とせば大丈夫かもしれません。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?