KVM VM とホスト間の NAT ネットワークを設定する正しい方法は何ですか?
KVM 仮想マシン:
ファイアウォールがインストールされていません
$ sudo arp-scan -r 5 -t 1000 --interface=eth0 --localnet
10.0.2.2 52:55:0a:00:02:02 locally administered
10.0.2.3 52:55:0a:00:02:03 locally administered
$ ip r
default via 10.0.2.2 dev eth0 proto dhcp metric 100
10.0.2.0/24 dev eth0 proto kernel scope link src 10.0.2.15 metric 100
ifconfig
eth0: inet 10.0.2.15 netmask 255.255.255.0 broacast 10.0.2.255
ether 52:54:00:12:34:56
lo: inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1
ホスト:
:~$ ip r
0.0.0.0/1 via 10.211.1.10 dev tun0
default via 192.168.1.1 dev wlan0 proto dhcp metric 600
10.21xxxxxxxx dev tun0 proto kernel scope link src 10.21xxxxx
xxxxxxxxxxxx dev wlan0
128.0.0.0/1 via 10.211.1.10 dev tun0
192.168.1.0/24 dev wlan0 proto kernel scope link src 192.168.1.172 metric 600
192.168.4.0/22 dev eth0 proto kernel scope link src 192.168.4.8 metric 100
:~$ ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.0.2.3 netmask 255.0.0.0 broadcast 10.255.255.255
inet6 fe80::76c8:79b4:88d4:7f5c prefixlen 64 scopeid 0x20<link>
ether ec:8e:b5:71:33:6e txqueuelen 1000 (Ethernet)
RX packets 1700 bytes 194730 (190.1 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 2862 bytes 246108 (240.3 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
device interrupt 16 memory 0xe1000000-e1020000
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 13251 bytes 7933624 (7.5 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 13251 bytes 7933624 (7.5 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
tun0: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST> mtu 1500
inet 10.211.1.69 netmask 255.255.255.255 destination 10.211.1.70
inet6 fe80::a920:941c:ffa8:5579 prefixlen 64 scopeid 0x20<link>
unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 txqueuelen 100 (UNSPEC)
RX packets 4348 bytes 2242726 (2.1 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 3823 bytes 404190 (394.7 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
wlan0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.1.172 netmask 255.255.255.0 broadcast 192.168.1.255
inet6 fe80::651b:5014:7929:9ba3 prefixlen 64 scopeid 0x20<link>
ether d8:55:a3:d5:d1:30 txqueuelen 1000 (Ethernet)
RX packets 114455 bytes 117950099 (112.4 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 67169 bytes 14855011 (14.1 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
~$ sudo arp-scan -r 5 -t 1000 --localnet
just hangs......
ホストは 10.0.2.2 に ping できません
ファイアウォールが有効になっていません
試してみた
$ sudo ip route add default via 10.0.2.0
$ sudo ip route add default via 10.0.2.2
$ sudo ip route add default via 10.0.2.0/24
NAT は virsh なしでも動作しますか?
NAT はコマンド ラインからのみ修正できますか?
アップデート:
$ sudo ip link add natbr0 type bridge
$ sudo ip link set dev natbr0 up
$ sudo ip link set dev eth0 up
$ sudo ip link set dev eth0 master natbr0
eth0スレーブをkvmにブリッジするには機能します - vmはネットワーク上の他のコンピュータにpingを実行できますが、ホストには実行できません@Tom Yanの回答と組み合わせるとarchlinux-ネットワークブリッジ他のネットワークIPにpingできる上記のコマンドを作成しました
そこで、ホストと KVM が通信できるように、動作中のブリッジ接続を変更しようとしました。
Goal: host$ ping kvm
$ sudo ip link add natbr0 type bridge
$ sudo ip link set dev natbr0 up
$ sudo ip a add 10.0.2.1/24 dev natbr0
$ sudo kvm -m 3G -hdb /dev/sde -nic bridge,br=natbr0
kvm$ sudo ip link add natbr0 type bridge
kvm$ sudo ip a add 10.0.2.2
kvm$ sudo ip link set dev natbr0 up
kvm can ping it self
$ 10.0.2.2にpingする
PING 10.0.2.2 (10.0.2.2) 56(84) bytes of data
64 bytes from 10.0.2.2: icmp_seq=1 ttl=64 time=0.027 ms
しかし、kvm$ping 10.0.2.1
Destination Host Unreachable
ホスト$ ping 10.0.2.2
(just hangs)
プロセス/システムの基本的な部分の回復力をテストするには、障害に対してより脆弱になる可能性のある多数のスクリプトよりも、コマンド ラインを優先します。コマンド ラインが機能するかどうかは、エラーの追跡、分離、再現が容易かどうかによって決まります。Linux の種類によっては、特定のスクリプト/スクリプトの一部 (提供されている XML 代替ソリューションに組み込まれているものなど) が機能する場合と機能しない場合があります。上記のコマンドに従って、どの Linux の種類でも kvm によるブリッジを再現できる場合は、cli コマンドを使用して kvm NAT も実現できる可能性があります。この投稿の要点を明確にするために、kvm を NAT する cli 手順はより標準化されるため、こちらの方が望ましいです。
一般的に@NikitaKipriyanovの回答は正しい道でした、これは答えでしたが、コマンドに微調整が必要でした
$ sudo kvm -m 3G -hdb /dev/sde -net nic -net user,hostfwd=tcp::1810-:22
コマンド調整を使用すると、VM はデフォルトのようにインターネットと通信でき、SSH 経由でホストと通信することもできます。調整については @NikitaKipriyanov と @cnst に感謝します。https://stackoverflow.com/a/54120040
ユーザーは、ローカルホストアドレスを使用してポート1810でSSHを実行する必要があります。
$ ssh p@localhost -p 1810
答え1
NATの一般的な考え方は、見えない変換されたアドレス。それらのアドレスへのルートはありません。それらは存在しません。変換されたアドレスのみが表示されます。
QEMU の場合も例外ではありません。この場合、ホストは「外部」、VM は「内部」にあるため、割り当てられたアドレスで VM にアクセスすることはできません。VM のアドレスは 10.0.2.2/24 ですが、インターネットに到達すると、そのパケットは 192.168.1.172 に変換されます。QEMUプロセスによってそのため、ホストはそれらのパケットを QEMU プロセスによって作成されたものと見なし、ローカルで実行されている Web ブラウザーなどからの他のパケットと同様に扱います。
ホストからVMにアクセスするには?NATがある場合、その背後に隠れているホストに到達するには、DNATルール。QEMUの場合も同様で、いくつかのルールを設定する必要があります。その後、ホストから(または必要に応じて他のホストから)VMと通信するには、選択したポートにパケットを送信します。ホスト住所。
によるQEMU ドキュメント、ユーザーモード NAT に DNAT ルールを設定するには、hostfwd
句を使用します。コマンドラインに次のコードを導入してみましょう。
-netdev user,id=usernet0,hostfwd=tcp::11111-:22 \
-device virtio-net-pci,netdev=usernet0,mac=08:00:27:92:B0:51
qemu-system-x86_64
すると、TCPポート11111が私のマシン上のプロセスによって占有され、ローカルホストポート 11111 の場合、VM のポート 22 に接続されます。
一般的な形式は ですhostfwd=hostip:hostport-guestip:guestport
が、 を省略するとhostip
localhost になり、 を省略するとguestip
ゲスト ネットワーク内の最初の「非ゲートウェイ」アドレスになります。
あなたのことが言及されていることに気づきましたvirsh
。 を実行していますかlibvirt
? その場合、質問は重複しています。コメントを参照してください。
答え2
VM ホスト上の物理イーサネット インターフェイスをブリッジに従属させることなく、ブリッジを使用できます。
サブネットの選択に固執するとします10.0.2.0/24
(これは必須ではありません)。
# ip l add natbr0 type bridge
# ip a add 10.0.2.1/24 dev natbr0
次に、次のファイルを作成します。
$ echo 'allow natbr0' | sudo tee /etc/qemu/bridge.conf
allow natbr0
次に、 または を使用して qemu を起動します-nic bridge,br=natbr0
。-netdev bridge,br=natbr0,id=nb0 -device virtio-net,netdev=nb0
これにより、tap
VM が動的にブリッジされます (つまり、tap
VM がシャットダウンされるとインターフェイスが削除されます)。
VM 上で静的 IP も構成する必要があります。
# ip a add 10.0.2.2/24 dev ens3
# ip r add default via 10.0.2.1
ホスト上に DHCP サーバー (dnsmasq など) も設定しない限り、VM 内で使用する DNS サーバーも忘れずに構成してください。
何らかの手段 (ebtables など) で通信をブロックしない限り、同じブリッジを使用する VM は相互に通信できることに注意してください。
ルートdefault
(および使用する DNS サーバー) は、VM が「外部」にアクセスできるようにする場合にのみ必要です。VM ホストと通信できるようにするためだけに必要である場合は、2 番目のコマンドをスキップして、読み進めないでください。(まあ、 を読んでくださいP.S.
)
VM で特定の「パブリック」 DNS サーバーを使用しない場合は、ホスト上の dnsmasq を DNS フォワーダーとして構成するのがおそらく最善ですが、192.168.1.1
基本的な DNS 要求の場合は DNAT を使用して転送することもできます。
次に、IP 転送を有効にする必要があります。
# sysctl -w net.ipv4.ip_forward=1
net.ipv4.ip_forward = 1
特定のネットワークインターフェースからの/へのIP転送を回避したい場合(例えば tun0
) セキュリティ上の理由から、ファイアウォールを設定する必要があります。例えば:
# iptables -A FORWARD -i tun0 -j DROP
# iptables -A FORWARD -o tun0 -j DROP
実質的にルートを上書きする (VPN) トンネル ルートがあるためdefault
、VM からインターネットへのトラフィックもトンネルに入ります (上記の例のルールを追加しない限り)。トラフィックをルーター経由で送信する場合は、ポリシー ルーティングが必要です。例:
# ip ru add iif natbr0 lookup table 123
# ip r add 192.168.1.1 dev wlan0 table 123 # probably optional
# ip r add default via 192.168.1.1 table 123
VM が LAN ホストにアクセスできないようにすることもできます。
# iptables -A FORWARD -i natbr0 -d 192.168.1.0/24 -j DROP
-I
DNS 要求をルーターにリダイレクトする場合は、例外を設けてください ( に注意してください)。
# iptables -I FORWARD -i natbr0 -d 192.168.1.1 -p tcp --dport 53 -j ACCEPT
# iptables -I FORWARD -i natbr0 -d 192.168.1.1 -p udp --dport 53 -j ACCEPT
最後に、VM サブネットに対して SNAT を動的に (送信インターフェイスに従って) 実行するように iptables を構成します。
# iptables -t nat -A POSTROUTING -s 10.0.2.0/24 -j MASQUERADE
これは、「外部」(物理 LAN ホストまたはインターネット。VM ホストはカウントされません) からの特定のトラフィックが VM に到達するのを完全に阻止することを意図したものではなく、阻止することもないことに注意してください。これは、VM からの応答トラフィックの送信元アドレスが転送される前に変更された場合に、副作用として通信が切断されるだけです。適切な分離を行うには、チェーン内に (追加の) 適切なルールが必要になりますFORWARD
。必要な場合は、そこに「ステートフル」なセットアップを検討してください。
さらに、ホストへの DNS 要求を VM からルーターにリダイレクトすることもできます。
iptables -t nat -A PREROUTING -d 10.0.2.1 -p udp --dport 53 -j DNAT --to-destination 192.168.1.1
iptables -t nat -A PREROUTING -d 10.0.2.1 -p tcp --dport 53 -j DNAT --to-destination 192.168.1.1
10.0.2.1
これにより、VM 内の DNS サーバーとして使用できるようになります。
PS 上記のすべての操作 ( の作成 / 書き込みを除く/etc/qemu/bridge.conf
) は揮発性です。つまり、再起動すると消えてしまいます (ディストリビューションが何かおかしなことをしない限り)。さまざまな方法やアプローチがあり、ディストリビューション固有の場合もあるため、これらを永続的にする方法については詳しく説明しません。