NAT越しのWake On Lan

長らく実家にて運用しているVPNクライアントルーターについて、一部改善した。

Linux の NAT 環境では、デフォルト設定のままではマジックパケットなどの ブロードキャストパケットが転送されない。
そのため、VPN+NAT を介した Wake on LAN(WoL)は通常そのままでは利用できない。

これは iptables の NAT 機能そのものというより、Linux の IPv4 スタックがブロードキャストパケットのフォワーディングを抑制している仕様によるものだ。

●bc_forwarding によるブロードキャスト転送の有効化

Linux では /proc/sys/net/ipv4/conf/ 配下に、ネットワークデバイスごとの IPv4 動作を制御するパラメータが用意されている。
この中にある bc_forwarding を 1 に設定することで、ブロードキャストパケットの転送を許可できる。

これを利用して、NAT 越しの WoL を可能にする。

マジックパケット(ブロードキャスト)の転送を有効化
sysctl -w net.ipv4.conf.all.bc_forwarding=1
sysctl -w net.ipv4.conf.wlan0.bc_forwarding=1
sysctl -w net.ipv4.conf.vpn_vpn.bc_forwarding=1

all
→ 今後生成されるインタフェースに対してもデフォルト値として適用

wlan0
→ 無線 LAN 側

vpn_vpn
→ VPN トンネルインタフェース

関連するすべてのインタフェースについて bc_forwarding=1 を設定する必要がある。

●VPN デバイスは動的生成される点に注意

注意すべき点として、vpn_vpn デバイスは VPN クライアント起動時に動的に生成される。
そのため、起動直後に sysctl を実行すると、デバイスが存在せず設定に失敗する。

この問題を回避するため、起動プロセスの最終段階(default.target 到達後)で設定を行う仕組みを用意した。

●起動完了後に実行する systemd サービス

サービスファイル
/lib/systemd/system/rc-latest.service

[Unit]
After=default.target

[Install]
WantedBy=default.target

[Service]
Type=oneshot
ExecStart=/etc/rc.latest
RemainAfterExit=yes

※ 単発で実行するだけなので、Type=oneshot が適切。

●自動起動を有効化
systemctl --system enable rc-latest

●実行スクリプトの作成

/etc/rc.latest を作成し、実行権限を付与する。

chmod +x /etc/rc.latest

/etc/rc.latest
#!/bin/sh

ブロードキャスト(マジックパケット)転送を有効化

sysctl -w net.ipv4.conf.all.bc_forwarding=1
sysctl -w net.ipv4.conf.wlan0.bc_forwarding=1
sysctl -w net.ipv4.conf.vpn_vpn.bc_forwarding=1

●効果と注意点

この設定により、ルーターへ SSH ログインして手動でコマンドを実行しなくても、Wolwin などの Windows アプリケーションから VPN 経由でリモート PC を起動できるようになった。

なお、bc_forwarding を有効にすると、VPN を越えてブロードキャストパケットが流れるようになるため、

・信頼できる VPN 環境内でのみ使用すること
・不要なインタフェースでは有効化しないこと

といった点には注意が必要である。

●まとめ

・NAT 越し WoL が動かない原因は Linux のブロードキャスト抑制仕様
・bc_forwarding を有効化することで解決可能
・VPN デバイスの動的生成に注意し、起動完了後に設定するのがポイント

「実用的だが情報が少ない」領域なので、同じところでハマる人の助けになれば幸いです。