Closed10

WSL上で動くnpm run devサーバにローカルネットワーク上からアクセスしたい

MaretolMaretol

やりたいこと

  • Next.jsでのWebページの開発
  • スマホ・タブレットからのチェックを行いたい
  • 開発環境はWSL2上のUbuntuでnpm run devしている
  • これを同一ネットワーク上の各種端末からアクセスしたい
MaretolMaretol

ここでは取り扱わないもの

Next.jsの開発

普通に npm run devhttp://localhost:3000 が立ち上がるものとする

ブラウザ間の仕様の差

一応手元だとiPadのSafariで変になってるなーとかはわかってる

デベロッパーツールとかもみたいが一旦ここでは扱わない

MaretolMaretol

現状の資料

https://qiita.com/smallriv/items/698fb1373887aa1f7784

とりあえずこれをやれば動くだろうというのはわかっている(まだ試していない

ただリンク先の記事はIPアドレス等を確認して毎回打ち込む必要がありそうなので、wslconfigとかで固定できないかなと考えてる

ゴール地点としてはそこ(設定ファイルを記述して各種設定をこなしたら再起動等をしても特に問題なく接続できる状態

MaretolMaretol

諸々の管理が楽になるので一旦Hyper-Vを有効化する

Win+Rでファイル名を指定して実行を開き、optionalfeatures を入力。Hyper-Vを有効化して再起動

MaretolMaretol

WSLのドキュメントを読んでいたら見つけた

https://learn.microsoft.com/ja-jp/windows/wsl/networking#mirrored-mode-networking

ネットワークモードを 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と同様

https://learn.microsoft.com/ja-jp/windows/wsl/wsl-config#experimental-settings

ただこのポート設定だが、WSL設定にはignoredPorts設定(日本語項目名:無視されたポート)がある。これにポート番号を指定するとWindows側でポートを使用している場合でもWSL上でポートが使用できる。これを指定するとWSL内で完結したポートとして扱われる(と思う。ドキュメントを読んでもよくわからん)。おそらくDockerとかはこれを指定しないと動かないっぽい?(ドキュメントの例に書かれていた

MaretolMaretol

あと書き忘れてたけど localhost でつながる機能も別途設定が必要になる

通常の(NATモードの)ときはデフォルトで localhost:port を指定するとWindows側からWSL側につなぐことができたが、mirroredモードではそれはできない

できないが、ホストアドレスのループバック設定をオンにするとできるようになる。これはWindows→WSLのみならず逆方向のWSL→Windowsもできる様になってるのでそこは注意

MaretolMaretol

というわけでFirewallに穴を開ける

https://learn.microsoft.com/ja-jp/windows/security/operating-system-security/network-security/windows-firewall/hyper-v-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 に外からアクセスしてほしいのでポートとプロトコルを指定したうえで通したい

https://learn.microsoft.com/ja-jp/windows/wsl/networking#mirrored-mode-networking

というわけでこれに注釈で載っているコマンドを下に以下のようにしてみる

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には穴を開けられた はず

MaretolMaretol

最後にWindows本体のFirewallにも許可設定を追加する

設定アプリからプライバシーとセキュリティのタブを選択、Windowsセキュリティのページへ移動しそこから「Windowsセキュリティを開く」でセキュリティアプリが開く

さらにそこから「ファイアウォールとネットワーク保護」のタブを押し、移動したページの「詳細設定」で「セキュリティが強化されたWindows Defender ファイアウォール」のアプリケーションが開く

開いた直後は上の画像のような感じのはず(ここまでが遠い

あとはサイドバーの「受信の規則」を開き、右のサイドバーの「新しい規則…」を押すと「新規の受信の規則ウィザード」のウィンドウが開く

あとはここでポート3000の通信を許可してあげればいい。TCPとUDPはそれぞれ設定する必要があるので1つずつ作成する。設定する必要があるのはプロトコルとポートだけで、ほかはデフォルトでよい

一応この時点でアクセスできるようになるが、ポートの制限のみでIPアドレスの制限がかかっていないので作成後に規則をダブルクリックまたは右クリックでプロパティを開き、スコープのタブからIPアドレスを設定し、内部のネットワークのアクセスのみを通過するようにできる

これで完了する はず

MaretolMaretol

というわけで開発マシンのIPアドレスを把握したうえで

$ npm run dev

localhostで動いていることをまず確認

続いて開発マシンに自身のIPアドレスを打ってアクセス

最後に同一のアドレスをスマートフォンなりタブレットなり同ネットワーク上の端末からアクセスしてみる

すべて確認して完了。少なくとも私の手元ではできた。のでクローズ

もしかしたらちゃんとした記事にまとめるかも

このスクラップは2025/01/11にクローズされました