Przekazywanie portów do gości w libvirt / KVM

33

Jak mogę przekierować porty na serwerze z uruchomionym libvirt / KVM do określonych portów na maszynach wirtualnych, gdy używasz NAT?

Na przykład host ma publiczny adres IP w wersji 1.2.3.4. Chcę przekierować port 80 na 10.0.0.1 i port 22 na 10.0.0.2.

Zakładam, że muszę dodać reguły iptables, ale nie jestem pewien, gdzie jest to właściwe i co dokładnie należy określić.

Wyjście z 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         

Wyjście 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)

Używam Ubuntu 10.04.

steveh7
źródło
1
dlaczego warto korzystać z ifconfig? ip jest następcą ifconfig. ;)
Manuel Faux
5
Pytanie 233760 odnosi się do tej kwestii w nigdy wersjach libvirt. serverfault.com/questions/233760
akaihola

Odpowiedzi:

36

Najnowszą stabilną wersją dla libvirt dla Ubuntu jest wersja 0.7.5, która nie ma niektórych nowszych funkcji (tj. Haków skryptów i filtrów sieciowych), które ułatwiają automatyczną konfigurację sieci. To powiedziawszy, oto jak włączyć przekierowanie portów dla libvirt 0.7.5 na Ubuntu 10.04 Lucid Lynx.

Te reguły iptables powinny załatwić sprawę:

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

Domyślna konfiguracja NAT KVM zapewnia regułę podobną do trzeciej podanej powyżej, ale pomija stan NOWY, który jest niezbędny do przyjmowania połączeń przychodzących.

Jeśli napiszesz skrypt startowy w celu dodania tych reguł i nie będziesz ostrożny, libvirt 0.7.5 zastąpi je, wstawiając własny. Tak więc, aby upewnić się, że reguły te są poprawnie stosowane podczas uruchamiania, musisz się upewnić, że libvirt zainicjował się przed wstawieniem reguł.

Dodaj następujące wiersze do /etc/rc.local, przed wierszem 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
) &

sleep 10Powyżej jest hack, aby upewnić się demon libvirt miał szansę zainicjować jego reguł iptables zanim dodamy nasz własny. Nie mogę się doczekać, aż wydadzą libvirt w wersji 0.8.3 dla Ubuntu.

Isaac Sutherland
źródło
3
Czy możesz wyjaśnić, jak zrobiłbyś to z obecnym libvirt?
Manuel Faux
1
Nie potrzebujesz hakowanych poleceń pętli while i uśpienia, jeśli jeden ze skryptów przechwytujących działa po zainicjowaniu libvirt przez sieć. Nie jestem pewien, czy skrypt / etc / libvirt / hooks / daemon jest uruchamiany przed czy po inicjalizacji sieci, ale jeśli użyjesz / etc / libvirt / hooks / qemu, możesz stworzyć i zniszczyć reguły podczas uruchamiania odpowiednich maszyn wirtualnych i zatrzymać. Nie jestem pewien, jak użyłbyś filtrów sieciowych (jeśli w ogóle), ale niektóre przykłady z libvirt.org/firewall.html pachną, jakby mogły zostać zmodyfikowane w celu zautomatyzowania tworzenia reguł iptables.
Isaac Sutherland,
Świetnie, mogę potwierdzić, że działa, ale nie próbowałem, co się stanie, jeśli zrestartuję serwer ...
Aron Lorincz
18

Istnieje sposób na skonfigurowanie przekierowania portów w locie, gdy gość korzysta z sieci w trybie użytkownika , blogowałem o tym tutaj:

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

Możesz zobaczyć szczegóły, ale dla wygody oto rozwiązanie, które wymyśliłem:

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

Ten jednowierszowy jest o wiele łatwiejszy niż inne odpowiedzi, ale działa tylko w niektórych scenariuszach (stos sieciowy w trybie użytkownika).

Adam Spiers
źródło
3
Twoje rozwiązanie jest dość interesujące - czy możesz podać kilka istotnych szczegółów (lub przynajmniej fragmentów porad) w swojej odpowiedzi, aby nadal były użyteczne, jeśli Twój blog nie działa z powodu konserwacji? :)
voretaq7
Gotowe, pomóż mojej reputacji SF przekroczyć 1 ;-)
Adam Spiers
Takie podejście wymaga użycia sieci w trybie użytkownika, co może nas przynieść pewne nieciekawe ograniczenia. Zobacz: linux-kvm.org/page/Networking#User_Networking . Inne odniesienia: topic.alibabacloud.com/a/… , snippets.webaware.com.au/howto/… ]
Eduardo Lucio
5

Bardziej „oficjalnym” [1] sposobem na to jest utworzenie skryptu przechwytującego, jak opisano na stronie libvirt:

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

... w zasadzie ten skrypt zostanie wywołany podczas uruchamiania gościa KVM. Sam skrypt doda odpowiednie iptable reguły (podobne do powyższej odpowiedzi Isaaca Sutherlanda) z poprawnie dodanym stanem połączenia „NEW”. Pamiętaj, że musisz zmodyfikować skrypt za pomocą poprawnych wartości dla hostów i portów.

[1] chociaż sama dokumentacja libvirt mówi, że jest to rodzaj włamania, idź

Antony Nguyen
źródło
0

„Jedynym” sposobem na przekierowanie portów za pomocą KVM (libvirt) z „domyślną siecią” (virbr0) jest użycie hack / obejścia poinformowanego przez @Antony Nguyen. Lub prościej można użyć libvirt-hook-qemu .

Wątek ten zawiera pełne wyjaśnienie, jak rozwiązać ten problem w CentOS 7 (i na pewno w przypadku innych dystrybucji) za pomocą libvirt-hook-qemu: https://superuser.com/a/1475915/195840 .

Eduardo Lucio
źródło
-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
topdog
źródło
1
Dziękuję za to, ale w przypadku KVM wymagało to również NOWEJ flagi państwowej
steveh7