WSL上で動くnpm run devサーバにローカルネットワーク上からアクセスしたい
やりたいこと
- Next.jsでのWebページの開発
- スマホ・タブレットからのチェックを行いたい
- 開発環境はWSL2上のUbuntuでnpm run devしている
- これを同一ネットワーク上の各種端末からアクセスしたい
ここでは取り扱わないもの
Next.jsの開発
普通に npm run dev
で http://localhost:3000 が立ち上がるものとする
ブラウザ間の仕様の差
一応手元だとiPadのSafariで変になってるなーとかはわかってる
デベロッパーツールとかもみたいが一旦ここでは扱わない
現状の資料
とりあえずこれをやれば動くだろうというのはわかっている(まだ試していない
ただリンク先の記事はIPアドレス等を確認して毎回打ち込む必要がありそうなので、wslconfigとかで固定できないかなと考えてる
ゴール地点としてはそこ(設定ファイルを記述して各種設定をこなしたら再起動等をしても特に問題なく接続できる状態
諸々の管理が楽になるので一旦Hyper-Vを有効化する
Win+Rでファイル名を指定して実行を開き、optionalfeatures
を入力。Hyper-Vを有効化して再起動
これいらなかったな
WSLのドキュメントを読んでいたら見つけた
ネットワークモードを mirrored にするとIPアドレスとかそういうの気にしなくていいっぽい
ちょうどWSL設定とかいうアプリが最近(半年ぐらい前?)Windows11には追加されている。このアプリのネットワークのタブを見るとここにあるネットワークモードの設定があり、ご丁寧にプルダウンで選択できるようになっている
デフォルトは NAT だが、これを Mirrored に変更する
試しに起動したWSLで $ ip addr
コマンドを叩くとWindows側と同じIPアドレスになっていることがわかる
しかしこれだけでは外からアクセスはできない。Firewallの設定があるからだ(なので続く
ちょっとだけまとめる
WSLのネットワークモードはデフォルトではNAT
これは LAN → 親Windows → WSL で接続する際に、親Windowsの特定のポートの通信をWSL側に転送しているということ(NATの詳細は省く。こんなふうに特定のポートをネットワーク下の特定のIPに飛ばすのをNATという
今回、当初はこのNATの設定とFirewallの設定をいじることで WSL 上で動くNode.jsのサーバにLANからアクセスできないかと考えていた
で、今回見つけたこの Mirrored ネットワークでは LAN → 親Windows / WSL という感じで同一の通信が届く形になる。たとえばWindowsが8080ポートを利用、WSLが8081ポートを利用しているときに、外からのアクセスで8080を指定したリクエストが届けばWindows側に、8081を指定したリクエストが届けばWSL側に転送してくれる
ただもちろん上記の通り、この構造だとポート番号が同じアプリケーションを動かすことはできない。これは通常のOSと同様
ただこのポート設定だが、WSL設定にはignoredPorts設定(日本語項目名:無視されたポート)がある。これにポート番号を指定するとWindows側でポートを使用している場合でもWSL上でポートが使用できる。これを指定するとWSL内で完結したポートとして扱われる(と思う。ドキュメントを読んでもよくわからん)。おそらくDockerとかはこれを指定しないと動かないっぽい?(ドキュメントの例に書かれていた
あと書き忘れてたけど localhost でつながる機能も別途設定が必要になる
通常の(NATモードの)ときはデフォルトで localhost:port を指定するとWindows側からWSL側につなぐことができたが、mirroredモードではそれはできない
できないが、ホストアドレスのループバック設定をオンにするとできるようになる。これはWindows→WSLのみならず逆方向のWSL→Windowsもできる様になってるのでそこは注意
というわけでFirewallに穴を開ける
このページを参考にしつつ、まず管理者権限でPowerShellを起動させる
で、VMCreatorIdを取得する
PS C:\Users\maretol> Get-NetFirewallHyperVVMCreator
VMCreatorId : {40E0AC32-46A5-438A-A0B2-2B479E8F2E90}
FriendlyName : WSL
ちなみにWSLのVMCreatorIdは常にこの値らしい。つまるところ上記のコマンドは不要っぽいが、一応確認で叩いたほうがいい気はする
続いて現状のデフォルト設定を確認する
PS C:\Users\maretol> Get-NetFirewallHyperVVMSetting -PolicyStore ActiveStore -Name '{40E0AC32-46A5-438A-A0B2-2B479E8F2E90}'
Name : {40E0AC32-46A5-438A-A0B2-2B479E8F2E90}
Enabled : True
DefaultInboundAction : Block
DefaultOutboundAction : Allow
LoopbackEnabled : True
AllowHostPolicyMerge : True
書いているとおりだが、Inboundはすべてブロックされている
上に貼ったリンクではInboundのデフォルトをAllowにして全部通過させようとしているが、まあぶっちゃけFirewallとしては基本的に全部ブロックしていてもらいたいので(一応理解したうえで言っているが、このFirewall設定はWindows自体のFirewallの設定ではないので全部Allowにしても大丈夫といえば大丈夫なはずだが、それはさておき)localhost:3000 に外からアクセスしてほしいのでポートとプロトコルを指定したうえで通したい
というわけでこれに注釈で載っているコマンドを下に以下のようにしてみる
PS C:\Users\maretol> New-NetFirewallHyperVRule -Name "NextDevServer" -DisplayName "Next.js dev server" -Direction Inbound -VMCreatorId '{40E0AC32-46A5-438A-A0B2-2B479E8F2E90}' -Protocol any -LocalPorts 3000
Name : NextDevServer
DisplayName : Next.js dev server
Direction : Inbound
VMCreatorId : {40E0AC32-46A5-438A-A0B2-2B479E8F2E90}
Protocol : Any
LocalAddresses : Any
LocalPorts : 3000
RemoteAddresses : Any
RemotePorts : 3000
Action : Allow
Enabled : True
EnforcementStatus : OK
PolicyStoreSourceType : Local
Profiles : Any
PortStatuses : {
SwitchName: 30BE601B-A2AB-4EDC-9AD5-9D2600CF7CF0
PortName: DA2FDCB8-493A-45A5-A884-9BD0B80DCC6B
Profile: Public
NetworkType: FSE
InterfaceGuid: {7CBD9F53-4593-4865-AEED-0ECFB4135EB3}
PartitionGuid: {75D3A8AD-3ED5-41BF-9EC6-1788394712FD}
VMCreatorId: {40E0AC32-46A5-438A-A0B2-2B479E8F2E90}
EnforcementStatus: OK
}
{
SwitchName: 30BE601B-A2AB-4EDC-9AD5-9D2600CF7CF0
PortName: D11CD891-3B31-4058-88C0-5135D10D05B2
Profile: Public
NetworkType: FSE
InterfaceGuid: {B124778B-4F2F-11EC-AFF8-806E6F6E6963}
PartitionGuid: {75D3A8AD-3ED5-41BF-9EC6-1788394712FD}
VMCreatorId: {40E0AC32-46A5-438A-A0B2-2B479E8F2E90}
EnforcementStatus: OK
}
{
SwitchName: 30BE601B-A2AB-4EDC-9AD5-9D2600CF7CF0
PortName: C54243C2-FE87-4615-89B7-EEB852084428
Profile: Public
NetworkType: FSE
InterfaceGuid: {3DA627A7-986D-4836-AB7F-2B3677172DF4}
PartitionGuid: {75D3A8AD-3ED5-41BF-9EC6-1788394712FD}
VMCreatorId: {40E0AC32-46A5-438A-A0B2-2B479E8F2E90}
EnforcementStatus: OK
}
これでアドレス問わずポート3000のプロトコルをすべて許容する形になった
……ここまでやるのだったらLocalAddressesとRemoteAddressesあたりも指定したほうが良かった気がする。まあとりあえずこれでHyper-VのFirewallには穴を開けられた はず
最後にWindows本体のFirewallにも許可設定を追加する
設定アプリからプライバシーとセキュリティのタブを選択、Windowsセキュリティのページへ移動しそこから「Windowsセキュリティを開く」でセキュリティアプリが開く
さらにそこから「ファイアウォールとネットワーク保護」のタブを押し、移動したページの「詳細設定」で「セキュリティが強化されたWindows Defender ファイアウォール」のアプリケーションが開く
開いた直後は上の画像のような感じのはず(ここまでが遠い
あとはサイドバーの「受信の規則」を開き、右のサイドバーの「新しい規則…」を押すと「新規の受信の規則ウィザード」のウィンドウが開く
あとはここでポート3000の通信を許可してあげればいい。TCPとUDPはそれぞれ設定する必要があるので1つずつ作成する。設定する必要があるのはプロトコルとポートだけで、ほかはデフォルトでよい
一応この時点でアクセスできるようになるが、ポートの制限のみでIPアドレスの制限がかかっていないので作成後に規則をダブルクリックまたは右クリックでプロパティを開き、スコープのタブからIPアドレスを設定し、内部のネットワークのアクセスのみを通過するようにできる
これで完了する はず
というわけで開発マシンのIPアドレスを把握したうえで
$ npm run dev
localhostで動いていることをまず確認
続いて開発マシンに自身のIPアドレスを打ってアクセス
最後に同一のアドレスをスマートフォンなりタブレットなり同ネットワーク上の端末からアクセスしてみる
すべて確認して完了。少なくとも私の手元ではできた。のでクローズ
もしかしたらちゃんとした記事にまとめるかも