🍑あわもり教室🫧 クラウドの「手前」を、ちゃんとやる。 はじめる
SET 0345分

仮想マシンの通信を内側から確かめる

手元のPCと仮想マシンのIP設定を比べ、待ち受け、経路、アドレス変換、通信許可を実際の出力から区別します。

このレッスンのメニュー

手元のブラウザから仮想マシンのWebサーバーへ接続するには、ゲストOSの設定、仮想化環境の転送、通信を許可する規則、外部へ公開する設定が必要です。

このページを終えると、次の四つを実際の出力から確認できます。

  • 仮想NICに付いたIPアドレス
  • 別のネットワークへ渡すデフォルトゲートウェイ
  • プロセスが待ち受けるIPアドレスとポート
  • 仮想マシン内では接続できるのに、外部からは接続できない理由
仮想マシン内の仮想NICから仮想スイッチ、仮想ルーター、物理NIC、外部ネットワークへ進む通信経路
ゲストOSが見られるのは仮想NICまでです。その先は仮想化環境とネットワーク側の設定が通信を運びます。

ゲストOSから見える範囲

仮想NICは、仮想マシンへ取り付ける仮想的なネットワークインターフェースです。 ゲストOSは仮想NICを通常のNICとして認識し、MACアドレスとIPアドレスを使って通信します。

Linuxの経路表には、「このネットワークは仮想NICへ直接送る」「それ以外はデフォルトゲートウェイへ渡す」という規則が入ります。 ゲストOSはその先にある物理NICやクラウドのルーターを直接操作しません。 まず仮想NICからパケットを出し、仮想化環境へ渡します。

仮想マシンの外側で転送される

仮想NICから出た通信は、仮想スイッチやブリッジを通ります。 別のネットワークへ進む場合はルーターが次の転送先を決めます。

仮想マシンへプライベートIPアドレスを付ける構成では、外へ出るときにNATやNAPTで送信元を置き換えることがあります。 この変換により、仮想マシンから始めた通信の応答を元の仮想マシンへ戻せます。 外部から新しい接続を始める場合は、公開用のIPアドレスやポート転送、経路、ACLなどを別に設定します。

待ち受けと外部公開は別の状態

Webサーバーが 0.0.0.0:8000 で待ち受けると、ゲストOS内のすべてのIPv4インターフェースで接続を受ける状態になります。 インターネットからの接続には、ゲストOSまでパケットを運ぶ経路と許可設定も必要です。

手元のPCから仮想マシン内のWebサーバーまでについて、IPアドレス、デフォルトゲートウェイ、待ち受けポート、NAT、外部公開設定を別々に確認する図
一つのコマンドですべてを確認せず、仮想マシンの内側から外側へ事実を積み上げます。

手元のPCの経路を確認する

最初に、普段使っているPCにもIPアドレスとデフォルトゲートウェイがあることを確認します。 利用しているOSの欄だけを実行してください。

macOS

ifconfig | grep 'inet '
route -n get default
scutil --dns | grep 'nameserver\[[0-9]*\]'

Linux

ip -brief address
ip route
cat /etc/resolv.conf

Windows PowerShell

Get-NetIPConfiguration
Get-NetRoute -DestinationPrefix "0.0.0.0/0"
Resolve-DnsName github.com

出力から、利用中のインターフェース、LAN側のIPv4アドレス、デフォルトゲートウェイ、DNSの問い合わせ先を一つずつ探します。 ループバックアドレスの 127.0.0.1 は自分自身を表すため、LANへ接続するインターフェースのIPアドレスとは区別します。

手元のPCとLabの仮想マシンを比べる

60分 Linux Labを開き、次を実行します。

ip -brief address
ip route
ip route get 1.1.1.1
getent ahostsv4 github.com | head

紙やメモへ、次の表に沿って値を記録します。

確かめる項目手元のPCLabの仮想マシン
利用中のインターフェース名
付いているIPv4アドレス(ループバック以外)
デフォルトゲートウェイ
github.com の名前解決結果

PCと仮想マシンで値は異なりますが、どちらにも「インターフェースへIPアドレスを付け、別のネットワークはゲートウェイへ渡す」という共通点があります。

次に仮想マシン内でWebサーバーを起動します。

mkdir -p ~/vm-network-lab
printf 'hello from the virtual machine\n' > ~/vm-network-lab/index.html
python3 -m http.server 8000 --bind 0.0.0.0 --directory ~/vm-network-lab >/tmp/vm-network-http.log 2>&1 &
server_pid=$!
ss -lntp | grep ':8000'
curl http://127.0.0.1:8000/

ss0.0.0.0:8000が表示され、curlhello from the virtual machineが返れば、Webサーバーは仮想マシン内で待ち受けています。

手元のブラウザへhttp://仮想マシンのIPアドレス:8000/を入力しても、このLabでは開けません。 仮想マシンのIPアドレスは手元のLANから直接たどれず、8000番ポートを外部へ転送する設定もなく、外部からの接続も許可していないためです。

確認後にWebサーバーを止めます。

kill "$server_pid"

接続できない場所を切り分ける

確認コマンドや設定ここでわかること
プロセスsystemctlpsWebサーバーが動いているか
待ち受けss -lntpどのIPアドレスとポートで受けるか
仮想マシン内の接続curl 127.0.0.1:8000アプリまでTCP接続できるか
IPと経路ip addressip route仮想NICとゲートウェイの設定
仮想マシンの外側NAT、ポート転送、ルート外部と仮想マシンの間をどう運ぶか
通信許可ACL、ファイアウォールその向きとポートを通すか
名前解決getent hostsnslookup名前が期待するIPアドレスになるか

仮想マシン内のcurlが成功して外部から失敗するなら、Webサーバーより外側を調べます。 仮想マシン内のcurlも失敗するなら、まずプロセスと待ち受けを調べます。

確認した結果から範囲を絞る

ssと仮想マシン内のcurlが成功した事実から、Webサーバーは仮想マシン内で利用できると判断できます。 手元のブラウザから接続できない場合は、仮想マシンのIPアドレスへ至る経路、NATやポート転送、ACLを次に確認します。

このレッスンは完了

このページで扱った流れを確認したら、次の内容へ進みます。