Я установил крючок на /etc/libvirt/hooks/qemu
с разрешениями 755, принадлежащими 0: 0, со следующим содержимым:
#!/bin/bash
if [ "${1}" = "virtualmachine" ]; then
GUEST_IP=192.168.122.2
GUEST_PORT=1234
HOST_PORT=1234
if [ "${2}" = "stopped" ] || [ "${2}" = "reconnect" ]; then
/sbin/iptables -D FORWARD -o virbr0 -d $GUEST_IP -j ACCEPT
/sbin/iptables -t nat -D PREROUTING -p tcp --dport $HOST_PORT -j DNAT --to $GUEST_IP:$GUEST_PORT
fi
if [ "${2}" = "start" ] || [ "${2}" = "reconnect" ]; then
/sbin/iptables -I FORWARD -o virbr0 -d $GUEST_IP -j ACCEPT
/sbin/iptables -t nat -I PREROUTING -p tcp --dport $HOST_PORT -j DNAT --to $GUEST_IP:$GUEST_PORT
fi
fi
Однако, когда я запускаю его и пытаюсь подключиться через telnet 192.168.1.1 1234
(Я знаю, что это не "правильно", просто проверяю порт вперед), это не удается. Служба работает, и к ней можно подключиться напрямую через выделенный порт. Однако я не могу сохранить выделенный порт, так как не могу выделить физический порт для каждой виртуальной машины.
Хост работает под управлением сервера Ubuntu 19.04, а гость работает под управлением Debian 10.
# 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:67
Chain FORWARD (policy ACCEPT)
target prot opt source destination
ACCEPT all -- anywhere 192.168.122.2
ACCEPT all -- anywhere 192.168.122.0/24 ctstate RELATED,ESTABLISHED
ACCEPT all -- 192.168.122.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
ACCEPT udp -- anywhere anywhere udp dpt:bootpc
# qemu-system-x86_64 --version
QEMU emulator version 3.1.0 (Debian 1:3.1+dfsg-2ubuntu3.3)
Copyright (c) 2003-2018 Fabrice Bellard and the QEMU Project developers
# libvirtd --version
libvirtd (libvirt) 5.0.0
Как я могу исправить проблемы с переадресацией портов?
Я разобрался в проблеме, оказывается, мне нужно было запустить iptables -t nat -A POSTROUTING -j MASQUERADE
.
Теперь это работает!
Если вы запускаете telnet в хост-системе, вам следует расширить правила. Чтобы перенаправить пакеты, отправленные локально, вы должны добавить правило DNAT в nat/OUTPUT
цепь. В вашем случае вам следует добавить строку при соответствующем условии (запуск или переподключение):
/sbin/iptables -t nat -I OUTPUT -p tcp --dport $HOST_PORT -j DNAT --to $GUEST_IP:$GUEST_PORT
Также добавьте противоположную команду для удаления правила.
/sbin/iptables -t nat -D OUTPUT -p tcp --dport $HOST_PORT -j DNAT --to $GUEST_IP:$GUEST_PORT
Чтобы перечислить полный набор правил со счетчиками, лучше использовать iptables-save -c
команда вместо iptables
, которая по умолчанию показывает только таблицу фильтров.