Назад | Перейти на главную страницу

Перенаправление портов гостям в libvirt / KVM

Как я могу перенаправить порты на сервере, на котором работает libvirt / KVM, на указанные порты на виртуальных машинах при использовании NAT?

Например, хост имеет общедоступный IP-адрес 1.2.3.4. Я хочу перенаправить порт 80 на 10.0.0.1 и порт 22 на 10.0.0.2.

Я предполагаю, что мне нужно добавить правила iptables, но я не уверен, где это уместно и что именно следует указать.

Вывод 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         

Вывод 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)

Я использую Ubuntu 10.04.

Последним стабильным выпуском libvirt для Ubuntu является версия 0.7.5, в которой нет некоторых новых функций (например, обработчиков сценариев и сетевых фильтров), упрощающих автоматическую настройку сети. Тем не менее, вот как включить переадресацию портов для libvirt 0.7.5 в Ubuntu 10.04 Lucid Lynx.

Эти правила iptables должны помочь:

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

Конфигурация KVM NAT по умолчанию предоставляет правило, подобное третьему, которое я дал выше, но в нем отсутствует состояние NEW, которое необходимо для приема входящих подключений.

Если вы напишете сценарий запуска для добавления этих правил и не будете осторожны, libvirt 0.7.5 переопределит их, вставив свои собственные. Итак, чтобы убедиться, что эти правила применяются правильно при запуске, вам необходимо убедиться, что libvirt инициализирован. перед вы вставляете свои правила.

Добавьте следующие строки в /etc/rc.local перед строкой 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 10 выше - это хитрость, позволяющая убедиться, что у демона libvirt была возможность инициализировать свои правила iptables, прежде чем мы добавим свои собственные. Не могу дождаться, пока они выпустят libvirt версии 0.8.3 для Ubuntu.

Есть способ настроить перенаправление портов на лету когда гость использует сеть в пользовательском режиме, Я писал об этом здесь:

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

Вы можете увидеть подробности там, но для удобства вот решение, которое я придумал:

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

Этот однострочный ответ намного проще, чем другие ответы, но работает только в некоторых сценариях (сетевой стек пользовательского режима).

Более "официальный" [1] способ сделать это - создать сценарий перехвата, как описано на веб-сайте libvirt:

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

... в основном этот сценарий будет вызываться при загрузке гостевой системы KVM. Сам скрипт добавит соответствующие правила iptable (аналогично ответу Исаака Сазерленда выше) с правильно добавленным состоянием подключения «NEW». Обратите внимание, что вы должны изменить сценарий, указав правильные значения для ваших хостов и портов.

[1] хотя в самой документации libvirt говорится, что это своего рода взлом, поймите

«Единственный» способ сделать переадресацию порта с помощью KVM (libvirt) с «сетью по умолчанию» (virbr0) - это использовать хак / обходной путь, проинформированный @Antony Nguyen. Или, проще говоря, вы можете использовать libvirt-крючок-qemu.

В этом потоке есть полное объяснение того, как решить эту проблему для CentOS 7 (и, конечно, для других дистрибутивов) с помощью libvirt-hook-qemu: https://superuser.com/a/1475915/195840 .

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