web-dev-qa-db-fra.com

Transfert des ports aux invités dans libvirt / KVM

Comment puis-je transférer des ports sur un serveur exécutant libvirt/KVM vers des ports spécifiés sur des VM, lors de l'utilisation de NAT?

Par exemple, l'hôte a une adresse IP publique de 1.2.3.4. Je veux transférer le port 80 à 10.0.0.1 et le port 22 à 10.0.0.2.

Je suppose que je dois ajouter des règles iptables, mais je ne sais pas où il convient et ce qui doit être spécifié exactement.

Sortie d'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         

Sortie d'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)

J'utilise Ubuntu 10.04.

35
steveh7

La dernière version stable de libvirt pour Ubuntu est la version 0.7.5, qui n'a pas de fonctionnalités plus récentes (c'est-à-dire des crochets de script et des filtres réseau) qui facilitent la configuration automatique du réseau. Cela dit, voici comment activer la redirection de port pour libvirt 0.7.5 sur Ubuntu 10.04 Lucid Lynx.

Ces règles iptables devraient faire l'affaire:

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

La configuration par défaut KVM NAT fournit une règle similaire à la troisième que j'ai donnée ci-dessus, mais elle omet le nouvel état, qui est essentiel pour accepter les connexions entrantes.

Si vous écrivez un script de démarrage pour ajouter ces règles et que vous ne faites pas attention, libvirt 0.7.5 les remplace en insérant les siennes. Donc, pour vous assurer que ces règles sont appliquées correctement au démarrage, vous devez vous assurer que libvirt a initialisé avant vous insérez vos règles.

Ajoutez les lignes suivantes à /etc/rc.local, avant la ligne 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
) &

Le sleep 10 ci-dessus est un hack pour s'assurer que le démon libvirt a eu la chance d'initialiser ses règles iptables avant d'ajouter les nôtres. Je ne peux pas attendre jusqu'à ce qu'ils libèrent la version 0.8.3 de libvirt pour Ubuntu.

38
Isaac Sutherland

Il existe un moyen de configurer la redirection de port à la volée lorsque l'invité utilise un réseau en mode utilisateur , j'ai blogué à ce sujet ici:

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

Vous pouvez voir les détails ici, mais pour plus de commodité, voici la solution que j'ai trouvée:

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

Ce one-liner est beaucoup plus facile que les autres réponses mais ne fonctionne que dans certains scénarios (pile réseau en mode utilisateur).

18
Adam Spiers

Une façon plus "officielle" [1] de le faire est de créer un script de hook comme décrit sur le site Web de libvirt:

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

... en gros, ce script sera invoqué quand un KVM est démarré. Le script lui-même ajoutera les règles iptables appropriées (similaires à la réponse d'Isaac Sutherland ci-dessus) avec la connexion 'NEW' état correctement ajouté. Notez que vous devez modifier le script avec les valeurs correctes pour vos hôtes et ports.

[1] bien que la documentation de libvirt elle-même dise que c'est une sorte de hack, allez comprendre

5
Antony Nguyen

La "seule" façon dont nous pouvons faire un port en avant en utilisant KVM (libvirt) avec le "réseau par défaut" (virbr0) utilise le hack/contournement informé par @Antony Nguyen. Ou plus simplement vous peut utiliser libvirt-hook-qem .

Ce fil a une explication complète de la façon de résoudre ce problème pour CentOS 7 (et certainement pour d'autres distributions) en utilisant libvirt-hook-qemu: https://superuser.com/a/1475915/19584 .

0
Eduardo Lucio