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
$아이피알
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
virsh 없이 NAT가 작동할 수 있나요?
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-Network_bridge다른 네트워크 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 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
호스트$ 핑 10.0.2.2
(just hangs)
오류에 더 취약할 수 있는 많은 스크립트에 비해 프로세스/시스템 기본의 복원력을 테스트하려면 명령줄을 선호합니다. - 명령줄 작동 여부 및 오류를 더 쉽게 추적하고 격리하고 재현할 수 있습니다. Linux 특성에 따라 특정 스크립트/스크립트의 일부(제공되는 XML 대체 솔루션에 통합된 것과 같은)가 작동할 수도 있고 작동하지 않을 수도 있습니다. 위의 명령을 수행하여 모든 Linux 버전에서 kvm 브리징을 재현할 수 있다면 cli 명령을 사용하여 kvm NAT를 달성할 수도 있을 것 같습니다. 이 게시물의 요점을 명확히 하기 위해 NAT kvm에 대한 cli 단계는 다음과 같습니다. 더 표준화되어 있으므로 바람직합니다.
일반적으로 @NikitaKipriyanov 답변은 올바른 도로였습니다. 이것이 답변이었지만 명령을 조정하려면 조정이 필요했습니다.
$ sudo kvm -m 3G -hdb /dev/sde -net nic -net 사용자,hostfwd=tcp::1810-:22
Tweak vm 명령을 사용하면 기본처럼 인터넷과 통신할 수 있고 SSH를 통해 호스트와도 통신할 수 있습니다. 조정을 위해 @NikitaKipriyanov 및 @cnst에게 감사드립니다.https://stackoverflow.com/a/54120040
사용자는 localhost 주소를 사용하여 포트 1810을 사용하여 SSH를 실행해야 합니다.
$ ssh p@localhost -p 1810
답변1
NAT의 일반적인 아이디어는보지 못하다번역된 주소. 그들에게 가는 경로가 없습니다. 그것들은 당신을 위해 존재하지 않습니다. 번역된 주소만 볼 수 있습니다.
QEMU 사례도 다르지 않습니다. 이 경우 호스트는 "외부"이고 VM은 "내부"이므로 할당된 주소로는 VM에 액세스할 수 없습니다. VM의 주소는 10.0.2.2/24이지만 인터넷에 도달하면 해당 패킷이 192.168.1.172로 변환됩니다.QEMU 프로세스를 통해, 따라서 호스트는 해당 패킷을 QEMU 프로세스에 의해 생성된 것으로 간주하고 로컬에서 실행되는 웹 브라우저 또는 이와 유사한 다른 패킷처럼 처리합니다.
호스트에서 VM에 액세스하는 방법은 무엇입니까? NAT가 있을 때 뒤에 숨겨진 호스트에 도달하기 위해 NAT를 설치합니다.DNAT규칙. 그리고 QEMU의 경우도 마찬가지입니다. 몇 가지 규칙을 설정해야 하며, 그런 다음 호스트에서(원하는 경우 다른 호스트에서도) VM의 선택된 포트로 패킷을 보내 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
그런 다음 예를 들어 -nic bridge,br=natbr0
또는 를 사용하여 qemu를 시작하면 VM이 동적 방식으로 브리지에 연결 -netdev bridge,br=natbr0,id=nb0 -device virtio-net,netdev=nb0
됩니다 (즉 , VM이 종료되면 인터페이스가 제거됩니다).tap
tap
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 서버를 구성하는 것을 잊지 마세요.
동일한 브리지를 사용하는 VM은 특정 수단(예: ebtables)으로 이러한 통신을 차단하지 않는 한 서로 통신할 수 있습니다.
경로 default
(및 사용할 DNS 서버)는 VM이 "외부"에 도달할 수 있도록 하려는 경우에만 필요합니다. VM 호스트와 통신하기 위해서만 필요한 경우 두 번째 명령을 건너뛰고 읽기를 중지할 수 있습니다. (글쎄요, 읽어보세요 P.S.
)
VM에서 특정 "공용" DNS 서버를 사용하지 않으려면 호스트의 dnsmasq를 DNS 전달자로 구성하는 것이 가장 좋을 것입니다. 단, DNAT를 사용하여 DNS 요청을 전달하는 것이 192.168.1.1
기본 요청에는 작동해야 합니다. .
그런 다음 IP 전달을 활성화해야 합니다.
# sysctl -w net.ipv4.ip_forward=1
net.ipv4.ip_forward = 1
특정 네트워크 인터페이스(예를 들어 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
)은 일시적입니다. 즉, 재부팅하면 해당 조작은 사라집니다(배포판이 어리석은 짓을 하지 않는 한). 다양한 방법/접근 방식이 있고 배포판별로 다를 수 있으므로 이를 지속성으로 만드는 방법에 대해서는 자세히 다루지 않겠습니다.