Как я могу перенаправить порты на сервере, на котором работает 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