Encaminhando portas para convidados em libvirt / KVM

33

Como posso encaminhar portas em um servidor executando libvirt / KVM para portas especificadas em VMs, ao usar NAT?

Por exemplo, o host tem um IP público de 1.2.3.4. Desejo encaminhar a porta 80 para 10.0.0.1 e a porta 22 para 10.0.0.2.

Suponho que preciso adicionar regras do iptables, mas não sei onde é apropriado e o que exatamente deve ser especificado.

Saída de iptables -L

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     udp  --  anywhere             anywhere            udp dpt:domain 
ACCEPT     tcp  --  anywhere             anywhere            tcp dpt:domain 
ACCEPT     udp  --  anywhere             anywhere            udp dpt:bootps 
ACCEPT     tcp  --  anywhere             anywhere            tcp dpt:bootps 

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             10.0.0.0/24         state RELATED,ESTABLISHED 
ACCEPT     all  --  10.0.0.0/24          anywhere            
ACCEPT     all  --  anywhere             anywhere            
REJECT     all  --  anywhere             anywhere            reject-with icmp-port-unreachable 
REJECT     all  --  anywhere             anywhere            reject-with icmp-port-unreachable 

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         

Saída de ifconfig

eth0      Link encap:Ethernet  HWaddr 00:1b:fc:46:73:b9  
          inet addr:192.168.1.14  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: fe80::21b:fcff:fe46:73b9/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:201 errors:0 dropped:0 overruns:0 frame:0
          TX packets:85 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:31161 (31.1 KB)  TX bytes:12090 (12.0 KB)
          Interrupt:17 

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

virbr1    Link encap:Ethernet  HWaddr ca:70:d1:77:b2:48  
          inet addr:10.0.0.1  Bcast:10.0.0.255  Mask:255.255.255.0
          inet6 addr: fe80::c870:d1ff:fe77:b248/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:6 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:0 (0.0 B)  TX bytes:468 (468.0 B)

Estou usando o Ubuntu 10.04.

steveh7
fonte
1
por que usar ifconfig? ip é o sucessor do ifconfig. ;)
Manuel Faux
5
A pergunta 233760 aborda isso em versões nunca do libvirt. serverfault.com/questions/233760
akaihola 28/10

Respostas:

37

A versão estável mais recente do libvirt para Ubuntu é a versão 0.7.5, que não possui alguns recursos mais recentes (como ganchos de script e filtros de rede) que facilitam a configuração automática da rede. Dito isto, veja como habilitar o encaminhamento de porta para libvirt 0.7.5 no Ubuntu 10.04 Lucid Lynx.

Essas regras do iptables devem fazer o truque:

iptables -t nat -I PREROUTING -p tcp -d 1.2.3.4 --dport 80 -j DNAT --to-destination 10.0.0.1:80
iptables -t nat -I PREROUTING -p tcp -d 1.2.3.4 --dport 22 -j DNAT --to-destination 10.0.0.2:22
iptables -I FORWARD -m state -d 10.0.0.0/24 --state NEW,RELATED,ESTABLISHED -j ACCEPT

A configuração NAT do KVM padrão fornece uma regra semelhante à terceira que forneci acima, mas omite o estado NEW, essencial para aceitar conexões de entrada.

Se você escrever um script de inicialização para adicionar essas regras e não for cuidadoso, a libvirt 0.7.5 as substituirá inserindo suas próprias. Portanto, para garantir que essas regras sejam aplicadas corretamente na inicialização, você deve garantir que a libvirt tenha sido inicializada antes de inserir suas regras.

Adicione as seguintes linhas ao /etc/rc.local, antes da linha exit 0:

(
# Make sure the libvirt has started and has initialized its network.
while [ `ps -e | grep -c libvirtd` -lt 1 ]; do
        sleep 1
done
sleep 10
# Set up custom iptables rules.
iptables -t nat -I PREROUTING -p tcp -d 1.2.3.4 --dport 80 -j DNAT --to-destination 10.0.0.1:80
iptables -t nat -I PREROUTING -p tcp -d 1.2.3.4 --dport 22 -j DNAT --to-destination 10.0.0.2:22
iptables -I FORWARD -m state -d 10.0.0.0/24 --state NEW,RELATED,ESTABLISHED -j ACCEPT
) &

O exemplo sleep 10acima é um truque para garantir que o daemon libvirt tenha a chance de inicializar suas regras do iptables antes de adicionarmos as nossas. Mal posso esperar até que eles liberem a versão 0.8.3 da libvirt para o Ubuntu.

Isaac Sutherland
fonte
3
Você pode explicar como você faria isso com a libvirt atual?
Manuel Faux
1
Você não precisa dos comandos hacked while loop e sleep se um dos scripts de gancho for executado após a libvirt inicializar sua rede. Não tenho certeza se o script / etc / libvirt / hooks / daemon é executado antes ou após a inicialização da rede, mas se você usar / etc / libvirt / hooks / qemu, poderá criar e destruir as regras quando as máquinas virtuais apropriadas forem iniciadas e Pare. Não tenho certeza de como você usaria filtros de rede (se houver), mas alguns dos exemplos em libvirt.org/firewall.html cheiram como se pudessem ser modificados para automatizar a criação de regras do iptables.
Isaac Sutherland
Ótimo, eu posso confirmar que funciona, no entanto eu não tentei o que acontece se eu reiniciar o servidor ...
Aron Lorincz
18

Existe uma maneira de configurar o redirecionamento de porta em tempo real quando o convidado está usando a rede em modo de usuário . Eu escrevi sobre isso aqui:

http://blog.adamspiers.org/2012/01/23/port-redirection-from-kvm-host-to-guest/

Você pode ver os detalhes lá, mas por conveniência, aqui está a solução que eu descobri:

virsh qemu-monitor-command --hmp sles11 'hostfwd_add ::2222-:22'

Essa linha única é muito mais fácil do que as outras respostas, mas funciona apenas em alguns cenários (pilha de rede no modo de usuário).

Adam Spires
fonte
3
Sua solução é bastante interessante - você pode incluir alguns dos detalhes mais importantes (ou pelo menos os bits de instruções) em sua resposta, para que ainda seja útil se o seu blog estiver em manutenção? :)
voretaq7
Feito, sinta-se livre para ajudar a minha reputação SF ir superior a 1 ;-)
Adam Spires
Essa abordagem requer o uso de uma rede no modo de usuário, o que pode nos trazer algumas limitações desinteressantes. Veja: linux-kvm.org/page/Networking#User_Networking . Outras referências: topic.alibabacloud.com/a/… , snippets.webaware.com.au/howto/… ]
Eduardo Lucio
5

Uma maneira mais "oficial" [1] de fazer isso é criar um script de gancho, conforme descrito no site libvirt:

http://wiki.libvirt.org/page/Networking#Forwarding_Incoming_Connections

... basicamente, esse script será chamado quando um convidado KVM for inicializado. O script em si adicionará as regras iptable apropriadas (semelhante à resposta de Isaac Sutherland acima) com o estado de conexão 'NOVO' adicionado corretamente. Observe que você deve modificar o script com os valores corretos para seus hosts e portas.

[1] embora a própria documentação da libvirt diga que isso é meio que um hack, vai entender

Antony Nguyen
fonte
0

A "única" maneira de encaminhar uma porta usando o KVM (libvirt) com a "rede padrão" (virbr0) é usando o hack / solução alternativa informada por @Antony Nguyen. Ou, mais simplesmente, você pode usar o libvirt-hook-qemu .

Este tópico possui uma explicação completa de como resolver esse problema no CentOS 7 (e certamente em outras distros) usando libvirt-hook-qemu: https://superuser.com/a/1475915/195840 .

Eduardo Lucio
fonte
-1
iptables -t nat -I PREROUTING -d 1.2.3.4 -p tcp --dport 80 -j DNAT --to-destination 10.0.0.1
 iptables -t nat -I PREROUTING -d 1.2.3.4 -p tcp --dport 22 -j DNAT --to-destination 10.0.0.1
melhor cão
fonte
1
Obrigado por esta, mas com KVM especificamente que precisava da NOVO bandeira do estado de bem
steveh7