Windows内のネットワークを整理：②WSL2編

前回の記事はこちら

https://qiita.com/taclose/items/ca51db8ca5190fc5deaf

今回は引き続き、WSL2のネットワークの世界を紹介しようと思います!!今回のアジェンダは以下です。

- WSL2は仮想マシンのNetwork設定のやり方
- WSL2は仮想マシン全てに同じIPを割り当てているが、こう回避しているのだ

この2点をお話しようと思います。


# WSL2の仮想マシンのNetwork設定のやり方

何から話しますかね。まずはWSL2で名前解決出来なくてそもそも通信できない話をよく聞くので、そのトラブルシューティングをしながら話を進めましょう。

## 名前解決ができない！

```bash
$ curl -I google.com
curl: (6) Couldn't resolve host 'google.com'
```

このエラーメッセージ見たら、確認すべきは`/etc/resolv.conf`です。
**そんな事知ってるんですけど？** って方もいるでしょうが落ち着いてください。

WSL2で気を付けなくてはいけないのは、**`/etc/resolv.conf`が毎回生成されてしまう**という事です。

### 解決方法

#### /etc/resolv.confを編集する

標準的には以下を定義すれば問題ありません。

```config:/etc/resolv.conf
nameserver 8.8.8.8
nameserver 8.8.4.4
```
ただ、社内でDNSサーバ持ってる場合とかはWindows側のDNS設定を確認して、同じIPにしちゃってくださいね！
次に、この設定が消されないように設定する方法です。

#### /etc/resolv.confを再生成しなくする

まずは、WSLの設定を変更するために以下を記述します。

```config:/etc/wsl.conf
[network]
generateResolvConf = false # /etc/resolv.confを再生成しなくする
```

と、ここまではよく説明見かけるのですが、更に**以下もやっておかないとなぜか消されます**...

```bash
$ chattr +i /etc/resolv.conf
```

一応上記はファイルシステム(ext2とか3のあれ）に対して変更禁止を促す命令になります。つまり、

私：wsl.confに書いたけど、再生成しないでね！
WSL：わかった！再生成はしないね！（**変更しちゃうけどな！**）

って事でしょうか？そんなバカな...

ともあれ、これで名前解決の問題解決ですね！

ではWSL2を2台用意して、更に通信がどうなっているのか調べてみましょう！
ここでは、UbuntuとCentOS7を用意して確認を進めました。

## WSL2は仮想マシン全てに同じIPを割り当てている！通信はどう流れるのか

いや、「同じIPが同じ仮想Switch上で振られているとか動くわけないじゃないですか」と思うなかれ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9872/64465042-2e5f-29c7-14b9-e19d15a4effb.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9872/96238d55-35ce-4fe9-911b-053552cd5107.png)

**oh..ほんまに同じIP振られとる...** じゃこれどう通信が振り分けられてるのでしょうか？

:::note warn
※画像ではIPアドレスが`172.18.100.50`となってますが、後続の説明は前回の記事と同じIP想定で資料作ってます。
:::

### 試しにUbuntu側でWebServerを立ててみよう！

まずServerを立てる前にPowerShellで以下のコマンドを実行して、80ポート使われてないかを確認。

```powershell:PowerShell
> netstat -ano | findstr :80
# 何も出ない
```

次にUbuntu側でWebServer立てるわけですが、今回はSimpleにPythonで以下のように起動させました。

```bash:Ubuntu
$ sudo python3 -m http.server 80 
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
```

じゃもう一度PowerShellでPort80を使ってる人いないかを確認してみましょう！

```powershell:PowerShell
> netstat -ano | findstr :80
  TCP         127.0.0.1:80           0.0.0.0:0              LISTENING       19024
  TCP         172.19.17.152:42892    163.139.173.139:80     ESTABLISHED     22936
> tasklist /FI "PID eq 19024"
イメージ名                     PID セッション名     セッション# メモリ使用量
========================= ======== ================ =========== ============
wslhost.exe                  19024 Console                    3      4,740 K
```

でました！**wslhost.exe** このプロセスが80番ポートで受け付けてますね！
という事は、Windowsにきた通信はwslhost.exeがキャッチしてUbuntuに渡してくれるのか？
試してみましょう！

### Windowsでlocalhsotに通信してみる

ブラウザで`localhost`を開いてみましょう。すると`Ubuntu`側のコンソールはこうなるはず。
※PowerShellからやるなら`curl -I localhost`とかが手軽です。通信経路は同じ。

```bash:Ubuntu
$ sudo python3 -m http.server 80 # さっき立てたWebServerです。
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
127.0.0.1 - - [12/Dec/2023 20:30:04] "GET / HTTP/1.1" 200 -
```
`127.0.0.1`から通信がきてますね！
図であらわすと以下

![wsl-WSL内部NW（host-_wsl）.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9872/26856e7a-e5c8-eda8-6687-2125cb4d912d.png)

点線はホストOSを外部に公開している通信も含めた時の話で、
実際の所は赤い実線がlocalhostに向けた内部通信になります。

### WindowsでWSL2のIPにアクセスしてみる

では、`172.18.110.165`にアクセスするとどうなるのか？

```bash:Ubuntu
127.0.0.1 - - [12/Dec/2023 20:30:04] "GET / HTTP/1.1" 200 -   # localhost
172.18.96.1 - - [12/Dec/2023 20:41:20] "GET / HTTP/1.1" 200 - # WSL2のIP指定
```

アクセス元のIPが代わりましたね！ご存知の通り、仮想スイッチ経由になりました。
図であらわすとこうですね！

![wsl-WSL内部NW（host-_wsl）２.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9872/901c2baf-7887-3e34-74fd-043d7808f8d9.png)

ちなみにWSL2では同時に同じポートでのLISTENは受け付けてくれないので、衝突は発生せず先勝ちとなるようでした。通信経路が見えると色々わかってきますね！

# 最後に

はい、内部の通信について理解が深まったでしょうか？
おそらく次の疑問としては、WSL2を外部からアクセス可能にするためにはどうしたらいいのだろうか？とか思う人もいるんじゃないでしょうか。私はその必要に迫られた事はないので試してませんが、おそらくの答えとしては、仮想スイッチ[WSL]を外部ネットワークに変更し、物理NIC[WiFi]に繋げる事で外部からのアクセスもできると予想されます。
あとは、Hyper-Vが通信受けられるようにWindowsのファイアウォールとかの調整も必要かもしれませんね。

**仕組みを理解出来ていれば、このように外部通信からの応用やエラーの原因究明もスムーズに行う事ができます。**

みなさんも、これまで理解せず使っていた機能とかがどうなっているのか調べてみてはいかがでしょうか！

気が向いたら第３回としてDockerも含めた内部Network整理しようと思います！

お疲れ様です！