Qual é a maneira correta de configurar a rede NAT entre KVM vm e host?
KVM vm:
Nenhum firewall instalado
$ 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
Hospedar:
:~$ 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......
O host não consegue executar ping em 10.0.2.2
Nenhum firewall ativado
Testado
$ 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
O NAT pode funcionar sem virsh?
O NAT pode ser corrigido apenas na linha de comando?
Atualizar:
$ 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
que funciona para conectar o escravo eth0 ao kvm - o vm pode executar ping em outros computadores na rede. mas não a resposta do anfitrião @Tom Yan combinada comarchlinux-Network_bridgecriados acima comandos que podem executar ping em outros IPs da rede
Então tentei alterar a conexão da ponte de trabalho para permitir que o host e o kvm conversassem.
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
$ping 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
mas kvm$ping 10.0.2.1
Destination Host Unreachable
host $ ping 10.0.2.2
(just hangs)
Prefira a linha de comando para testar a resiliência do esqueleto do processo/sistema em comparação com muitos scripts que podem representar mais vulnerabilidade a falhas. - a linha de comando funciona ou não e os erros são mais facilmente rastreados, isolados e reproduzíveis. Dependendo do tipo de Linux, certos scripts/partes de scripts (como aqueles incorporados nas soluções alternativas xml oferecidas) podem funcionar ou não. Se a ponte com o kvm puder ser reproduzida em qualquer versão do Linux seguindo os comandos acima... então parece possível que o kvm NAT também possa ser alcançado usando comandos cli - apenas para esclarecer o ponto desta postagem, as etapas do cli para NAT kvm serão mais padronizado, então preferível.
geralmente a resposta de @NikitaKipriyanov era o caminho correto, esta era a resposta, mas exigia um ajuste no comando
$ sudo kvm -m 3G -hdb /dev/sde -net nic -net user,hostfwd=tcp::1810-:22
usando o comando tweak vm pode se comunicar com a internet como padrão e também se comunicar com o host via ssh. crédito a @NikitaKipriyanov e @cnst pelo ajustehttps://stackoverflow.com/a/54120040
O usuário precisará fazer ssh usando a porta 1810 usando o endereço localhost
$ ssh p@localhost -p 1810
Responder1
A ideia comum do NAT é que vocênão vemosendereços traduzidos. Você não tem rotas para eles. Eles não existem para você. Você vê apenas os endereços para os quais eles estão traduzidos.
O caso do QEMU não é nada diferente. Neste caso, seu host está "fora", sua VM está "dentro", então a VM nunca poderá ser acessada pelo endereço ao qual está atribuída. Você tem o endereço 10.0.2.2/24 da VM, mas quando chega à Internet, seus pacotes são traduzidos para 192.168.1.172pelo processo QEMU, então o host considera esses pacotes como criados pelo processo QEMU e os trata como quaisquer outros pacotes, digamos, de um navegador da Web executado localmente ou algo parecido.
Como acessar uma VM do host? Quando temos NAT, para alcançar hosts ocultos atrás dele, instalamosDNATregras. E novamente, o caso do QEMU não é diferente, você deve configurar algumas regras nele, e então você pode se comunicar com a VM a partir do host (ou de outros hosts, se desejar) enviando pacotes para portas selecionadas dohospedarendereço.
De acordo comDocumentação do QEMU, para configurar regras de DNAT em seu NAT de modo de usuário, você usa a hostfwd
cláusula. Vamos introduzir o seguinte em sua linha de comando:
-netdev user,id=usernet0,hostfwd=tcp::11111-:22 \
-device virtio-net-pci,netdev=usernet0,mac=08:00:27:92:B0:51
Então, a porta tcp 11111 será ocupada pelo qemu-system-x86_64
processo na minha máquina, e se você conectar aohost localporta 11111, a conexão será feita na porta 22 da VM.
A forma geral é hostfwd=hostip:hostport-guestip:guestport
, mas se você omitir hostip
, será localhost e, se omitir guestip
, será o primeiro endereço "não gateway" dentro da rede convidada.
Notei que você foi mencionado virsh
. Estás a correr libvirt
? Então a pergunta é duplicada; Ver comentários.
Responder2
Você pode usar uma ponte sem escravizar nenhuma de suas interfaces Ethernet físicas no host da VM.
Digamos que optemos pela escolha da sub-rede 10.0.2.0/24
(o que NÃO é necessário):
# ip l add natbr0 type bridge
# ip a add 10.0.2.1/24 dev natbr0
Em seguida, crie o seguinte arquivo:
$ echo 'allow natbr0' | sudo tee /etc/qemu/bridge.conf
allow natbr0
Em seguida, inicie o qemu com, por exemplo, -nic bridge,br=natbr0
ou -netdev bridge,br=natbr0,id=nb0 -device virtio-net,netdev=nb0
, que conectará tap
sua VM à ponte de maneira dinâmica (ou seja, a tap
interface será removida assim que a VM for desligada).
Você também precisará configurar o IP estático na VM:
# ip a add 10.0.2.2/24 dev ens3
# ip r add default via 10.0.2.1
A menos que você também configure um servidor DHCP (por exemplo, dnsmasq) no host. Não se esqueça de configurar o servidor DNS para usar também dentro da VM.
Observe que as VMs que fazem uso da mesma ponte podem se comunicar entre si, a menos que você bloqueie tal comunicação por algum meio (por exemplo, ebtables).
A default
rota (e o servidor DNS a utilizar) só são necessários se quiser que a VM consiga chegar ao "exterior". Se você só precisa dele para se comunicar com o host da VM, você deve pular o segundo comando e parar de ler. (Bem, leia o P.S.
)
Provavelmente seria melhor configurar, por exemplo, dnsmasq no host para ser um encaminhador de DNS se você não quiser usar um servidor DNS "público" específico na VM, embora usar DNAT para encaminhar solicitações de DNS, por exemplo, 192.168.1.1
deva funcionar para os básicos .
Então você precisará ativar o encaminhamento de IP:
# sysctl -w net.ipv4.ip_forward=1
net.ipv4.ip_forward = 1
Se você quiser evitar o encaminhamento de IP de/para determinada interface de rede (por exemplo tun0
) por motivos de segurança, você precisará configurar um firewall.Por exemplo:
# iptables -A FORWARD -i tun0 -j DROP
# iptables -A FORWARD -o tun0 -j DROP
Como você possui rotas de túnel (VPN) que praticamente substituem a default
rota, o tráfego da VM para a Internet também irá para o túnel (a menos que você tenha adicionado as regras de exemplo acima). Se você quiser que o tráfego passe, por exemplo, pelo seu roteador, você precisará de roteamento de política. Por exemplo:
# 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
Você também pode impedir que suas VMs alcancem seus hosts LAN:
# iptables -A FORWARD -i natbr0 -d 192.168.1.0/24 -j DROP
Faça exceções (observe o -I
) se for redirecionar solicitações de DNS para o seu roteador:
# 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
Por fim, configure o iptables para executar SNAT dinamicamente (conforme a interface de saída) para sua sub-rede VM:
# iptables -t nat -A POSTROUTING -s 10.0.2.0/24 -j MASQUERADE
Observe que isso NÃO se destina e não impedirá exatamente que certos tráfegos "externos" (seus hosts físicos da LAN ou a Internet; o host da VM não conta) possam alcançar suas VMs. Apenas interrompe a comunicação como efeito colateral quando o endereço de origem dos tráfegos de resposta das VMs é alterado antes de serem encaminhados. Para um isolamento adequado, você precisará de regras apropriadas (adicionais) na FORWARD
cadeia. Considere ter uma configuração "com estado" se você precisar.
Além disso, você pode redirecionar solicitações de DNS para o host das VMs para o seu roteador:
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
O que mais ou menos permitirá que você use 10.0.2.1
como servidor DNS na VM.
PS Todas as manipulações acima (exceto a criação de /write to /etc/qemu/bridge.conf
) são voláteis, ou seja, elas desaparecerão assim que você reiniciar (a menos que sua distro faça algo bobo). Não vou me aprofundar em como você pode torná-los persistentes, já que existem diferentes formas/abordagens e isso pode ser específico da distribuição.