47 votes

Transfert de ports vers des invités dans libvirt / KVM

Comment puis-je rediriger les ports sur un serveur exécutant libvirt/KVM vers des ports spécifiés sur des machines virtuelles, lors de l'utilisation du NAT?

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

Je suppose que je dois ajouter des règles iptables, mais je ne suis pas sûr de l'endroit approprié ni de ce qui doit être spécifié exactement.

Sortie de iptables -L

Chaîne INPUT (politique 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 

Chaîne FORWARD (politique 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 

Chaîne OUTPUT (politique ACCEPT)
target     prot opt source               destination         

Sortie de ifconfig

eth0      Link encap:Ethernet  HWaddr 00:1b:fc:46:73:b9  
          inet adr:192.168.1.14  Bcast:192.168.1.255  Masque:255.255.255.0
          adr inet6: 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 longueur file TX:1000 
          RX octets:31161 (31.1 Ko)  TX octets:12090 (12.0 Ko)
          Interruption:17 

lo        Link encap:Boucle locale  
          adr inet:127.0.0.1  Masque:255.0.0.0
          adr inet6: ::1/128 Scope:Hôte
          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 longueur file TX:0 
          RX octets:0 (0.0 octets)  TX octets:0 (0.0 octets)

virbr1    Link encap:Ethernet  HWaddr ca:70:d1:77:b2:48  
          inet adr:10.0.0.1  Bcast:10.0.0.255  Masque:255.255.255.0
          adr inet6: 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 longueur file TX:0 
          RX octets:0 (0.0 octets)  TX octets:468 (468.0 octets)

J'utilise Ubuntu 10.04.

48voto

Ben Noland Points 10060

La dernière version stable de libvirt pour Ubuntu est la version 0.7.5, qui ne dispose pas de certaines fonctionnalités plus récentes (comme les crochets de script et les filtres réseau) qui facilitent la configuration automatique du réseau. Cela dit, voici comment activer le renvoi de ports 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 NAT KVM par défaut fournit une règle similaire à la 3ème que j'ai donnée ci-dessus, mais elle omet l'état NEW, 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. Ainsi, pour garantir que ces règles sont appliquées correctement au démarrage, vous devez vous assurer que libvirt s'est initialisé avant d'insérer vos règles.

Ajoutez les lignes suivantes à /etc/rc.local, avant la ligne exit 0 :

(
# Assurez-vous que libvirt a démarré et a initialisé son réseau.
while [ `ps -e | grep -c libvirtd` -lt 1 ]; do
        sleep 1
done
sleep 10
# Mettez en place des règles iptables personnalisées.
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 garantir que le démon libvirt a eu l'opportunité d'initialiser ses règles iptables avant que nous ajoutions les nôtres. J'ai hâte qu'ils sortent la version 0.8.3 de libvirt pour Ubuntu.

22voto

Adam Spiers Points 550

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

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

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

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

Cette commande en une ligne est beaucoup plus simple que les autres réponses, mais ne fonctionne que dans certains scénarios (pile réseau en mode utilisateur).

10voto

Antony Nguyen Points 191

Une manière plus "officielle"[1] de faire cela est de créer un script 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é lorsque qu'un invité KVM est démarré. Le script lui-même ajoutera les règles iptables appropriées (similaire à la réponse d'Isaac Sutherland ci-dessus) avec l'état de connexion 'NEW' 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 un peu un bidouillage, allez savoir

3voto

Eduardo Lucio Points 243

La seule façon de faire un transfert de port en utilisant KVM (libvirt) avec le "réseau par défaut" (virbr0) est d'utiliser le hack/contournement informé par @Antony Nguyen. Ou plus simplement, vous pouvez utiliser libvirt-hook-qemu.

Ce fil de discussion contient 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/195840.

0voto

Thomas Points 177

Sur Ubuntu 20.04, j'ai créé le script suivant, qui est enregistré sous /etc/libvirt/hooks/allow-portfw (chmod +x):

#!/bin/bash

CHAIN=LIBVIRT_FWI
IPTCMD="iptables -L $CHAIN -vn"
FILTERCMD="grep -v -e Chain -e pkts -e reject-with -e DNAT"

while $IPTCMD | grep ESTABLISHED | grep -v DNAT >/dev/null
do
    IF=$($IPTCMD | $FILTERCMD | awk '{print $7}' | head -n1)
    NET=$($IPTCMD | $FILTERCMD | awk '{print $9}' | head -n1)
    iptables -D $CHAIN -o $IF -d $NET -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
    iptables -I $CHAIN 1 -o $IF -d $NET -m conntrack --ctstate DNAT,RELATED,ESTABLISHED -j ACCEPT
done

La situation initiale est que nous manquons NOUVEAU entre le drapeau DNAT pour la chaîne FORWARDING, qui est créée automatiquement.

sudo iptables -L LIBVIRT_FWI -vn
Chain LIBVIRT_FWI (1 references)
 pkts bytes target     prot opt in     out     source               destination         
1741K 2661M ACCEPT     all  --  *      virbr0  0.0.0.0/0            192.168.122.0/24     ctstate RELATED,ESTABLISHED
   38  1972 REJECT     all  --  *      virbr0  0.0.0.0/0            0.0.0.0/0            reject-with icmp-port-unreachable

Mon script ajoute le drapeau DNAT à toutes les définitions.

De cette façon, j'ai simplement ajouté la redirection de port dans iptables avec

iptables -A PREROUTING -i mylanIF -p tcp --dport 3389 -j DNAT --to-destination 192.168.122.110:3389

Vous pouvez utiliser les packages iptables-persistent pour sauvegarder cet état (mais bien sûr, vous devez exclure les chaînes libvirt du dump)

Ou utilisez ufw ou tout autre script de pare-feu pour cela.

Mon script est basé sur les résultats de cette adresse https://www.cyberciti.biz/faq/kvm-forward-ports-to-guests-vm-with-ufw-on-linux/

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X