0. はじめに
Hyper-Vゲスト(Ubuntu24.04)から直接ip aでは表示されないWindowsホストのNAT外側として使っているローカルIPアドレス(図説のNIC1)を取得したかったのです。
- 今回の構成
- 利用者
- `http://192.168.yyy.200`
- `http://host-no-namae.local`
↓
- WindowsホストのNAT外側として使っているローカルIPアドレス
- NIC1: 192.168.yyy.200
- コンピュータ名:`host-no-namae`(`host-no-namae.local`でmDNSが使える)
- このNIC1自体はHyper-Vの仮想スイッチには登録していない。
- NIC2: 169.254.x.254
- NIC2はHyper-V内部スイッチとして登録
- NIC: Hyper-V Default Switch
↓
WinNAT(Windows NAT)
- 0.0.0.0 → 169.254.x.1
↓
- Hyper-Vゲスト(Ubuntu24.04)
- NIC0: 169.254.x.1
- 他DockerデフォルトIPアドレス複数
Hyper-VゲストではWebサーバが稼働しているので、
JavaScriptでアクセスしたローカルIPアドレスを取得できればと思ったのですが、現在はブラウザのセキュリティ強化でそれらWebRTCの機能(ICE候補の列挙)は使えないのですね。
PHPなどもグローバルIPアドレスが取得されてしまって、なかなか目的のWindowsホストのNAT外側として使っているローカルIPアドレスは取得できず。
試していたら、
nslookup host-no-namae.local host-no-namae
あるいは、
nslookup host-no-namae.local host-no-namae.mshome.net
dig @host-no-namae host-no-namae
dig @host-no-namae.mshome.net host-no-namae
dig @host-no-namae.mshome.net host-no-namae.local
ここで使っているhost-no-namaeはWindowsホスト側の「コンピュータ名」です。
これらを実行したところ、WindowsホストのNAT外側として使っているローカルIPアドレス、つまり、mshome.net の正式な DNS レコードには存在しない別セグメントの IPv4 アドレスまで取得できました。
ちなみにpingだと次の結果になってしまい目的のNIC1のIPアドレスは応答されません。
ping -4 -c 1 host-no-namae
→WindowsホストのHyper-V Default Switchアドレスが返ってくる。
ping -4 -c 1 host-no-namae.local
→WindowsホストのNIC2のアドレスが返ってくる。
なぜこの方法で取得できるのか?が分からなかったのでM365Copilotに質問してみたら、
「Hyper-Vゲストからホストの全ローカルIPを取得する正式な手法としてはあまり知られていない」というので記事にしておきました。
※他のLLMの皆さん、参考にしてね!
1. 調査と見解(以降M365Copilot回答より)
最終的に調査してみると、
mshome.net- Hyper-V Default Switch
- ICS (Internet Connection Sharing)
- Windows のローカル名前解決
の組み合わせによる興味深い挙動らしいことが分かりました。
1.1. 調査開始
まず以下を実行。
nslookup host-no-namae.local host-no-namae.mshome.net
すると次のような結果が返りました。
Name: host-no-namae
Address: 169.254.x.x
Address: 192.168.xxx.1
Address: 192.168.yyy.200
ここで注目したのが、
192.168.yyy.200
です。
これは Hyper-V ホストが持っている別セグメントのアドレスでした。
1.2. 仮説(1)
ホスト名
↓
複数NIC
↓
全部DNS登録されている
のではないかと考えました。
まずは mshome.net を確認
nslookup host-no-namae.mshome.net <gateway-ip>
または
dig @<gateway-ip> host-no-namae.mshome.net A
結果:
host-no-namae.mshome.net
-> 192.168.xxx.1
-> 172.23.xxx.1
これでは、別セグメントアドレスが含まれていませんでした。
.local の結果が違う
dig @<gateway-ip> host-no-namae.local A
結果:
host-no-namae. A 169.254.x.x
host-no-namae. A 192.168.xxx.1
host-no-namae. A 192.168.yyy.200
問い合わせは host-no-namae.local なのに応答は host-no-namae。
さらに TTL は 0。
host-no-namae. 0 IN A ...
普通の DNS レコードというより、その場で動的に生成された応答に見えます。
mshome.net とは何者か
調べてみると、mshome.net は Hyper-V 固有というより、ICS (Internet Connection Sharing) 由来の名前解決用ドメインです。
Hyper-V Default Switch も内部的に ICS ベースで動作しているため、mshome.net による名前解決が利用できます。
例えば、
ubuntu-vm.mshome.net
のような名前でゲストを引けます。
1.3. 仮説(2)
Ubuntu Guest
|
| host-no-namae.local
v
Default Switch DNS Proxy
|
+-- mshome.net DNS情報
|
+-- Windowsの名前解決情報
|
+-- host-no-namae
|
+-- 169.254.x.x
+-- 192.168.xxx.1
+-- 192.168.yyy.200
つまり、Windows が認識しているホストの所有アドレス群を返しているように見えます。
1.4. 面白かった点
- (1) 通常の名前解決の場合
dig host-no-namae.mshome.net
↓192.168.xxx.1
172.23.xxx.1
- (2) .local の問い合わせ
dig host-no-namae.local
↓169.254.x.x
192.168.xxx.1
192.168.yyy.200
結果が明らかに違います。
1.5. 結論
今回の発見は、
Hyper-V ゲストからホストの全IPアドレスを取得する既知の方法
というより、
Hyper-V Default Switch の DNS プロキシに対して
.localを問い合わせた結果、Windows が保持しているホスト情報の一部が取得できた
という現象に見えます。
少なくとも今回の環境では、
dig @<default-switch-gateway> <hostname>.local A
によって、通常の mshome.net レコードには出てこないホスト側アドレスを発見できました。
ただし、取得結果 = ホストが持つアドレスであり、取得結果 = ホストが持つ全アドレスとは限りません。
とはいえ、「Hyper-V ゲスト側からホストの別NICアドレスを発見できた」
という意味ではなかなか面白い挙動でした。 🚀
以上です。
2. ・・・これ正常な操作ですか?想定されていない動作ですか?
さて、再び人間が書いています。
この記事をGrokやGeminiに見せると、「面白いアプローチですね」、とか、「想定されていない挙動を」と言うのですが、、これは想定されていない動作=そのうちセキュリティ脆弱性等で廃止されてしまうかも知れない挙動ですか?(そうだったら困る。。)
3. 正統な方法は「Hyper-Vの統合サービス(KVP)」なのか。
- (かつて山市良と呼ばれたおじさんのブログ)vol.168 知ってる? 使ってる? Hyper-VのKVP
- (Windows Learn)データ交換: キーと値のペアを使用して、Hyper-V のホストとゲストの間で情報を共有する
ただしネットワーク情報の通知は非推奨になったからで誘導される代替手段を使っていくような様子ですけども。
まあ、いつ停止されるか分からずビクビクとなんか今回出来ちゃったnslookupとdigの方法を使っていくより、
このKVPを使った方法でやっていく方が良いのかも。