|||||||||||||||||||||

なんぶ電子

- 更新: 

Win11世代の Wake On Lan

WOL設定

久しぶりにWake On Lan が必要になって設定をしようと思ったら、近年のネットワークやWindows環境では以前と違ってうまくいかなかったので、ここにメモを残しておきます。

Wake On Lanの設定

WOLを有効にするには該当のPCで次の点を設定・確認する必要があります。

  1. BIOS(UEFI)でWOLを有効化

    コンシューマー向けのPCではWOLはデフォルトでOFFになっている事が多いと思います。WOLを設定すると電源OFFの状態でもネットワークインタフェースには給電し続ける必要があるので、省電力化の観点からの措置でしょう。

    OFFになっている場合は、設定をONにする必要があります。

    マザーボード毎にBIOS(UEFI)の仕様が違いますが、一般的には、PC起動時に、F12やDELでBIOS(UEFI)を立ち上げで、電源関連のオプション値から設定します。不明な場合は各ベンダーのページを参照してください。

  2. WindowsのネットワークアダプタでWOLを有効化

    ネットワークインタフェースのWOLオプションで、WOLを許可する必要があります。項目名等はベンダーにも依存すると思います。

    筆者の環境では、Microsoftが提供している汎用ドライバ―には該当の項目がありませんでした。そのためベンダー提供のドライバ―に差し替えています。

    電源の管理のタブで、「電力の節約のために……」の項目にチェックを入れている場合は、その下の「スタンバイ状態を解除できるようにする」にチェックを入れておきます。

    「電力の節約のために……」のチェックをOFFにしている場合はそのままでも問題ありません。

    WOL設定
  3. 高速スタートアップの無効化

    筆者の環境では高速スタートアップを有効にしているとWOLは機能しませんでした。ネットワークインターフェースやWindowsのバージョンによっても違うかもしれませんが、WOLが機能しない際はこちらも確認してみるといいと思います。

  4. 対象となるPCのMACアドレスの取得

    WOL送信時はIPアドレスではなくMACアドレスで指定します。電源がONの状態ならIPアドレスからMACアドレスを取得できますが、電源が切れた状態で操作したいのがWOLですので事前に控えておきます。

    WindowsでMACアドレス(物理アドレス)を表示させるには、PowerShellなどのプロンプトから ipconfig /all を実行します。

    ネットワークインターフェースがすべて表示されますので、多くの場合は「イーサネット アダプター」になると思いますが、目的のインターフェースがどれかを見極める必要があります。

    PowerShell

    ipconfig /all
    ...
    イーサネット アダプター イーサネット:...
    説明. : Intel(R) Ethernet Connection (7) I219-V
    物理アドレス: XX-XX-XX-XX-XX-XX
    DHCP 有効: いいえ
    ...
    
  5. アプリケーションのインストール

    これはWOLを送信する側のPCに設定する必要があります(受信側は不要です)。

    VPNでリモートでマジックパケットを送信するならVPNを利用するPC、常時稼働しているサーバー等があるならそれに配置します。

WOLアプリ

WOLは電源ONのために特殊なパケット(マジックパケット)を送信します。そのパケットを送信するWindows用のツールのひとつに、筆者がよく利用させていただいてるWake on LAN for Windows があります。

これをインストールしたPCを目的のPCがあるネットワーク内に接続したのちに実行します。

MACアドレスがよくわからない時は、対象のPCが電源が入っている状態で立ち上げればアプリケーションから確認、保存することもできます。

Linuxサーバーでは文字通り「wakeonlan」というアプリがあり、Debianではレポジトリからインストール可能です。使い方も簡単で、wakeonlan [:区切りのMACアドレス] という形式になっています。

他にはYamahaのルーターの一部の製品には、WOLパケットを送信するコマンドが用意されていて、次のようにすることでWOLのパケットを送信できます。

Yamahaルーターコマンド

wol send [ lan1 等のネットワークインターフェース名 ] [ 対象のMACアドレス ]

ここまでの設定がすべて正常にできれば、同一ネットワークに存在する電源OFFの状態のPCの電源を入れられると思います。

もし異なるネットワークからパケットを送りたい場合は、VPNを使うか後述するような特殊な設定が必要になります。

マジックパケットの中身

WOLの利用に関してはここまでの話で終了なのですが、これ以降はもう少し踏み込んだ仕組みの話をしていきます。

まず、そもそもマジックパケットは何だろうという話ですが、これは専用のデータが書き込まれたUDPパケットです。

データの中身は、先頭6バイトにFF(FFが6個)、あとは対象ハードウェアのMACアドレスが16回繰り返されるもの(6バイト×16)となっています。

また送信先はブロードキャストアドレスとなっています。というのも、該当のPCが電源がOFFの状態だとARPに反応しないため、通常のARP変換(IPアドレスからMACアドレスへの変換)が行われないため目的のハードウェアにパケット(フレーム)を送信することができません。

送信ポートは、一般的にUDPの9番を使います。まれにUDPの7番を使うこともあるようです。UDPの9番はDiscard(破棄)、7番はEcho(そのまま返す)となっており、誤って送信されても問題が起きることが少なくなるように設計されているそうです。

これらを実装すればいいので、わりと簡単にコードを書くことができます。たとえば socket拡張があるPHPでは次のようにすることでマジックパケットの送信ができます。

magick.php

// マジックパケットを送信
// PHP Socket拡張が必要です

function sendMagickPacket($strTargetAddress,$strMacAddress,$intPort=9) {
  // MACアドレス中の:や-を除去
  $strSanitizeMac = str_replace([':','-'],'',$strMacAddress);
  
  // 16進数マックアドレスをバイナリに変換
  // Hは16進数からの変換、12は先頭12字の意味
  $binMac = pack('H12',$strSanitizeMac);
  
  // 送信データを生成
  $binSendData = str_repeat(chr(0xFF),6).str_repeat($binMac,16);
  
  // ソケットを生成
  // AF_INET で IPv4 
  // SOCK_DGRAM で UDP用にソケットタイプをデータグラムに指定
  // SOL_UDP で プロトコルをUDPに
  $sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
  
  if ($sock===false) {
    // エラー
    echo socket_strerror(socket_last_error());
    return false;
  }
  
  // ブロードキャスト用のオプションを指定※
  // SOL_SOCKETでオプションをソケットレベルに指定
  // SO_BROADCAST に 1をセット
  if (socket_set_option($sock, SOL_SOCKET,SO_BROADCAST,1)===false) {
    // エラー
    echo socket_strerror(socket_last_error());
    socket_close($sock);
    return false;
  }
  
  // socket_sendto:接続の有無にかかわらずソケットメッセージを送信
  $ret = socket_sendto($sock, $binSendData, strlen($binSendData), 0, $strTargetAddress, $intPort);
  
  if ($ret===false) {
    // エラー
    echo socket_strerror(socket_last_error());
    socket_close($sock);
    return false;
  }
  
  // ソケットを閉じる
  socket_close($sock);
  
  return true;
}

// 通常は同一ネットワーク内からブロードキャストアドレス宛に送信する
sendMagickPacket("172.16.1.255","00D861AF3846",9);

ルーター越え

前述の通り、マジックパケットはブロードキャストで送信されます。

たとえば192.168.200.0/24ネットワークなら、192.168.200.255がブロードキャストアドレスとして設定されていますので、それを前述のPHPコードでは指定します。

この時ルーター内側のネットワークにブロードキャストを送信しようとするPCが所属している場合は問題ないのですが、そうでない場合はルーターはブロードキャストパケット無視されるのが一般的です(外側からのブロードキャスト宛のパケットは無視されます)。

異なるネットワークではWOLが使えない理由はここにあります。

これを回避する方法は、いくつか考えられます。ポートフォワードの宛先にブロードキャストが使えるルーターなら、ルーター宛のUDP9番を内側のブロードキャストに変換するようにします。

VPNやSSHで同一ネットワークのシェルからマジックパケットを送信するという方法も考えられます。

ここで試してみたいのは、単一アドレス宛のマジックパケットを受信しようとする試みです。

ブロードキャストであることはWOLの条件ではないので、先の通りの内容のUDPパケットを起動したいPC受信できればWOLは稼働します。

ARPの仕組みを知っていると理屈が分かりやすいのですが、対象のPCの電源が切れていると、IPアドレスからMACアドレスへの変換ができない為に単一アドレス宛てのマジックパケットが届かないので、常時稼働の別のPCから本来のPCに代わってARP応答をします。

そのロジックを次のようなPythonスクリプトで実現できます。

IPアドレスを指定することでルータを越えることができ、ARP解決を別のPCから維持することでマジックパケットが目的のPCへ届くようになります。VPNやSSHのようにネットワーク内に穴を開けるわけではないので、若干セキュリティ強度が高いと思われます。

次のコードの実行には、scapy ライブラリのインストールが必要です。Debianでは python3-scapyとしてAPTレポジトリで配布されています。

wakeon.py

from scapy.all import *
import time

def custom_arp_responder(packet):
  # WOL対象のPCのIPアドレス
  target_ip = "192.168.1.10"
  # WOL対象のPCのMACアドレス
  fake_mac = "aa:bb:cc:dd:ee:ff"

  # ARPリクエストで、かつ対象のIPアドレス宛のものかチェック
  if ARP in packet and packet[ARP].op == 1 and packet[ARP].pdst == target_ip:
    # IPアドレスやNIC変更時に備えてレスポンスを遅延させる
    #(正規のレスポンスがある場合はそちらが優先されるようにします)
    time.sleep(0.6)
    
    # ARP応答パケットを作成
    arp_response = ARP(
      op=2,  # ARP応答はop=2
      psrc=target_ip,  # 応答する側のIPアドレス
      pdst=packet[ARP].psrc,  # 問い合わせてきた側のIPアドレス
      hwsrc=fake_mac,  # 応答する側のMACアドレス
      hwdst=packet[ARP].hwsrc  # 問い合わせてきた側のMACアドレス
    )
    # パケットを送信
    send(arp_response, verbose=False)
    # コンソールにメッセージ表示
    print(f"Sent ARP Response: {target_ip} is at {fake_mac} request from {packet[ARP].psrc}")

# ネットワークインターフェースを指定してパケットスニッフィングを開始
sniff(prn=custom_arp_responder, filter="arp", store=False, iface="eth0")

マジックパケット送信時、先のPHPコードを使う際、単一のIPアドレスを指定する場合は※部分のブロードキャストのオプション設定は不要ですが、設定してあっても稼働しました。

ACPI

WOLはACPIの中で定義されていいます。

ACPI(Advanced Configuration and Power Interface)とは、ハードウェアの電源管理と構成を制御するためのオープンスタンダードです。

オープンスタンダートとは、公開されていて特定の企業に属することのない技術や規格を指します。

ハードウェアがACPIのWOL規格に準拠することで、マジックパケット受信時にマシンの電源がONになります。

オープンスタンダードの例としては、ACPIの他にHTMLやUSBの規格などが上げられます。

S0~S5

WOLの設定をしていてい、ACPIに触れると気になるのがS0~S5といった符号なのではないでしょうか。

これらは電源の状態をさし、それぞれACPIによって次のように定義されています。

  • S0

    S0は「ワーキング」で、ハードウェアが起動し利用可能な状態になっていることを指します。

  • S1

    S1は「スリープ」で、プロセッサは停止しますが、メモリの内容は維持されます(メモリには電源が供給され続けます)。

  • S2

    S1の状態とほぼ一緒ですが、メモリのキャッシュがフラッシュされます。

  • S3

    S3は「サスペンド」で、メモリ以外のほとんどのハードウェアの電源がオフになります。この状態を「スタンバイ」という事もあります。

  • S4

    S4は「ハイバネーション」で、メモリの内容もハードディスクへ保存され、ほぼすべての電源がオフになります。

  • S5

    S5は「ソフトオフ」で、ハードウェアに所属するデバイスへの電源供給がオフになります。

「S4:ハイバネーション」と「S5:ソフトオフ」の違いは、メモリの内容がディスクにある状態からの復旧なのか、いちから起動を行うかの違いだと思います。

一般にWOLはS3かS5の状態から起動させることができます。

BIOSとWindowsでWOLの設定を有効にすると、S5の状態でもネットワークカードへの給電が継続されます。LAN端子のランプが光ったままになることでも確認できます。

実装にもよると思いますがS4の状態ではネットワークカードに給電されない事が多いようで、この状態だとパケットを受信できないのでWOLは機能しません。Windowsの高速スタートアップはS4に近い状態で、カーネルの状態をディスクに保存して、起動時はそれを利用して立ち上げるようです。高速スタートアップが有効な状態でWOLが働かないのもそのような仕組みが一因なのだと思います。


執筆にあたりChatGPTの回答を参考にしています。原則ファクトチェックやコードは稼働チェックを行った上で記載していますが、一部鵜呑みの部分もございます。ご容赦ください。

筆者紹介


自分の写真
がーふぁ、とか、ふぃんてっく、とか世の中すっかりハイテクになってしまいました。プログラムのコーディングに触れることもある筆者ですが、自分の作業は硯と筆で文字をかいているみたいな古臭いものだと思っています。 今やこんな風にブログを書くことすらAIにとって代わられそうなほど技術は進んでいます。 生活やビジネスでPCを活用しようとするとき、そんな第一線の技術と比べてしまうとやる気が失せてしまいがちですが、おいしいお惣菜をネットで注文できる時代でも、手作りの味はすたれていません。 提示されたもの(アプリ)に自分を合わせるのでなく、自分の活動にあったアプリを作る。それがPC活用の基本なんじゃなかと思います。 そんな意見に同調していただける方向けにLinuxのDebianOSをはじめとした基本無料のアプリの使い方を紹介できたらなと考えています。

広告