- Вопрос или проблема
- Ответ или решение
- Решение проблемы с неправильной работой firewall-cmd для перенаправления портов в KVM сервере
- Контекст проблемы
- Понимание внутренней работы firewalld и libvirt
- Шаги для решения проблемы
- 1. Настройка сетевой конфигурации libvirt
- 2. Настройка зон в firewalld
- 3. Создание NAT и проброса портов
- Заключение
- Резюме
Вопрос или проблема
У меня есть KVM сервер (хост) с несколькими виртуальными машинами (гостями).
Моя цель – перенаправить порт 222 хоста на порт 22 гостя, на котором работает сервис ssh.
Это работает…
iptables -I OUTPUT -d 0.0.0.0/0 -j ACCEPT
iptables -I FORWARD -d 0.0.0.0/0 -j ACCEPT
iptables -I INPUT -d 0.0.0.0/0 -j ACCEPT
iptables -t nat -I PREROUTING -d 0.0.0.0/0 -p tcp --dport 222 -j DNAT --to-destination 10.1.0.9:22
Это не работает…
firewall-cmd --permanent --zone=public --direct --add-rule ipv4 filter OUTPUT 0 -d 0.0.0.0/0 -j ACCEPT
firewall-cmd --permanent --zone=public --direct --add-rule ipv4 filter FORWARD 0 -d 0.0.0.0/0 -j ACCEPT
firewall-cmd --permanent --zone=public --direct --add-rule ipv4 filter INPUT 0 -d 0.0.0.0/0 -j ACCEPT
firewall-cmd --permanent --zone=public --direct --add-rule ipv4 nat PREROUTING 0 -d 0.0.0.0/0 -p tcp --dport 222 -j DNAT --to-destination 10.1.0.9:22
firewall-cmd --reload
Это тоже не работает…
firewall-cmd --permanent --zone=public --add-forward-port=port=222:proto=tcp:toport=22:toaddr=10.1.0.9
firewall-cmd --reload
ВОПРОС: Почему правила, установленные с помощью firewall-cmd
, не работают?
ПРИМЕЧАНИЕ I: firewall-cmd
– это служба брандмауэра по умолчанию для CentOS 7. Мне кажется, это проблема без решения! Я искал на множестве форумов, и ничего не работает! Я начинаю думать, что это ограничение или ошибка в firewall-cmd
…
ПРИМЕЧАНИЕ II: Я знаю, что ssh
сам по себе предоставляет средства для того, чтобы это было возможно, но я действительно хочу, чтобы этот процесс был “прозрачным” для пользователя, чтобы он мог получать доступ к гостю напрямую.
[Ссылки: https://serverfault.com/q/915257/276753 ,
https://serverfault.com/q/980223/276753 ,
https://sebastianblade.com/how-to-modify-ssh-port-in-centos7/ ,
https://www.rootusers.com/how-to-use-firewalld-rich-rules-and-zones-for-filtering-and-nat/ ,
https://www.centos.org/forums/viewtopic.php?f=50&t=71454 ]
СИМПТОМ:
Команда…
ssh root@[HOST_IP] -p 222
… возвращает мне следующую ошибку…
ssh: connect to host 172.16.13.8 port 222: Connection refused
ОБНОВЛЕНИЕ I:
@mwfearnley вывод iptables-save…
iptables-save – РАБОТАЕТ…
[root@localhost ~]# iptables-save
# Generated by iptables-save v1.4.21 on Thu Aug 22 11:59:17 2019
*nat
:PREROUTING ACCEPT [1:70]
:INPUT ACCEPT [1:70]
:OUTPUT ACCEPT [2:146]
:POSTROUTING ACCEPT [3:206]
:OUTPUT_direct - [0:0]
:POSTROUTING_ZONES - [0:0]
:POSTROUTING_ZONES_SOURCE - [0:0]
:POSTROUTING_direct - [0:0]
:POST_public - [0:0]
:POST_public_allow - [0:0]
:POST_public_deny - [0:0]
:POST_public_log - [0:0]
:PREROUTING_ZONES - [0:0]
:PREROUTING_ZONES_SOURCE - [0:0]
:PREROUTING_direct - [0:0]
:PRE_public - [0:0]
:PRE_public_allow - [0:0]
:PRE_public_deny - [0:0]
:PRE_public_log - [0:0]
-A PREROUTING -p tcp -m tcp --dport 222 -j DNAT --to-destination 10.1.0.9:22
-A PREROUTING -j PREROUTING_direct
-A PREROUTING -j PREROUTING_ZONES_SOURCE
-A PREROUTING -j PREROUTING_ZONES
-A OUTPUT -j OUTPUT_direct
-A POSTROUTING -s 10.1.0.0/24 -d 224.0.0.0/24 -j RETURN
-A POSTROUTING -s 10.1.0.0/24 -d 255.255.255.255/32 -j RETURN
-A POSTROUTING -s 10.1.0.0/24 ! -d 10.1.0.0/24 -p tcp -j MASQUERADE --to-ports 1024-65535
-A POSTROUTING -s 10.1.0.0/24 ! -d 10.1.0.0/24 -p udp -j MASQUERADE --to-ports 1024-65535
-A POSTROUTING -s 10.1.0.0/24 ! -d 10.1.0.0/24 -j MASQUERADE
-A POSTROUTING -j POSTROUTING_direct
-A POSTROUTING -j POSTROUTING_ZONES_SOURCE
-A POSTROUTING -j POSTROUTING_ZONES
-A POSTROUTING_ZONES -o ens33 -g POST_public
-A POSTROUTING_ZONES -o br0 -g POST_public
-A POSTROUTING_ZONES -g POST_public
-A POST_public -j POST_public_log
-A POST_public -j POST_public_deny
-A POST_public -j POST_public_allow
-A PREROUTING_ZONES -i ens33 -g PRE_public
-A PREROUTING_ZONES -i br0 -g PRE_public
-A PREROUTING_ZONES -g PRE_public
-A PRE_public -j PRE_public_log
-A PRE_public -j PRE_public_deny
-A PRE_public -j PRE_public_allow
COMMIT
# Completed on Thu Aug 22 11:59:17 2019
# Generated by iptables-save v1.4.21 on Thu Aug 22 11:59:17 2019
*mangle
:PREROUTING ACCEPT [672:77587]
:INPUT ACCEPT [610:68993]
:FORWARD ACCEPT [58:7886]
:OUTPUT ACCEPT [655:151604]
:POSTROUTING ACCEPT [713:159490]
:FORWARD_direct - [0:0]
:INPUT_direct - [0:0]
:OUTPUT_direct - [0:0]
:POSTROUTING_direct - [0:0]
:PREROUTING_ZONES - [0:0]
:PREROUTING_ZONES_SOURCE - [0:0]
:PREROUTING_direct - [0:0]
:PRE_public - [0:0]
:PRE_public_allow - [0:0]
:PRE_public_deny - [0:0]
:PRE_public_log - [0:0]
-A PREROUTING -j PREROUTING_direct
-A PREROUTING -j PREROUTING_ZONES_SOURCE
-A PREROUTING -j PREROUTING_ZONES
-A INPUT -j INPUT_direct
-A FORWARD -j FORWARD_direct
-A OUTPUT -j OUTPUT_direct
-A POSTROUTING -j POSTROUTING_direct
-A PREROUTING_ZONES -i ens33 -g PRE_public
-A PREROUTING_ZONES -i br0 -g PRE_public
-A PREROUTING_ZONES -g PRE_public
-A PRE_public -j PRE_public_log
-A PRE_public -j PRE_public_deny
-A PRE_public -j PRE_public_allow
COMMIT
# Completed on Thu Aug 22 11:59:17 2019
# Generated by iptables-save v1.4.21 on Thu Aug 22 11:59:17 2019
*security
:INPUT ACCEPT [609:68793]
:FORWARD ACCEPT [58:7886]
:OUTPUT ACCEPT [660:152010]
:FORWARD_direct - [0:0]
:INPUT_direct - [0:0]
:OUTPUT_direct - [0:0]
-A INPUT -j INPUT_direct
-A FORWARD -j FORWARD_direct
-A OUTPUT -j OUTPUT_direct
COMMIT
# Completed on Thu Aug 22 11:59:17 2019
# Generated by iptables-save v1.4.21 on Thu Aug 22 11:59:17 2019
*raw
:PREROUTING ACCEPT [672:77587]
:OUTPUT ACCEPT [655:151604]
:OUTPUT_direct - [0:0]
:PREROUTING_ZONES - [0:0]
:PREROUTING_ZONES_SOURCE - [0:0]
:PREROUTING_direct - [0:0]
:PRE_public - [0:0]
:PRE_public_allow - [0:0]
:PRE_public_deny - [0:0]
:PRE_public_log - [0:0]
-A PREROUTING -j PREROUTING_direct
-A PREROUTING -j PREROUTING_ZONES_SOURCE
-A PREROUTING -j PREROUTING_ZONES
-A OUTPUT -j OUTPUT_direct
-A PREROUTING_ZONES -i ens33 -g PRE_public
-A PREROUTING_ZONES -i br0 -g PRE_public
-A PREROUTING_ZONES -g PRE_public
-A PRE_public -j PRE_public_log
-A PRE_public -j PRE_public_deny
-A PRE_public -j PRE_public_allow
COMMIT
# Completed on Thu Aug 22 11:59:17 2019
# Generated by iptables-save v1.4.21 on Thu Aug 22 11:59:17 2019
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:FORWARD_IN_ZONES - [0:0]
:FORWARD_IN_ZONES_SOURCE - [0:0]
:FORWARD_OUT_ZONES - [0:0]
:FORWARD_OUT_ZONES_SOURCE - [0:0]
:FORWARD_direct - [0:0]
:FWDI_public - [0:0]
:FWDI_public_allow - [0:0]
:FWDI_public_deny - [0:0]
:FWDI_public_log - [0:0]
:FWDO_public - [0:0]
:FWDO_public_allow - [0:0]
:FWDO_public_deny - [0:0]
:FWDO_public_log - [0:0]
:INPUT_ZONES - [0:0]
:INPUT_ZONES_SOURCE - [0:0]
:INPUT_direct - [0:0]
:IN_public - [0:0]
:IN_public_allow - [0:0]
:IN_public_deny - [0:0]
:IN_public_log - [0:0]
:OUTPUT_direct - [0:0]
-A INPUT -j ACCEPT
-A INPUT -i virbr0 -p udp -m udp --dport 53 -j ACCEPT
-A INPUT -i virbr0 -p tcp -m tcp --dport 53 -j ACCEPT
-A INPUT -i virbr0 -p udp -m udp --dport 67 -j ACCEPT
-A INPUT -i virbr0 -p tcp -m tcp --dport 67 -j ACCEPT
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -j INPUT_direct
-A INPUT -j INPUT_ZONES_SOURCE
-A INPUT -j INPUT_ZONES
-A INPUT -m conntrack --ctstate INVALID -j DROP
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -j ACCEPT
-A FORWARD -d 10.1.0.0/24 -o virbr0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -s 10.1.0.0/24 -i virbr0 -j ACCEPT
-A FORWARD -i virbr0 -o virbr0 -j ACCEPT
-A FORWARD -o virbr0 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -i virbr0 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i lo -j ACCEPT
-A FORWARD -j FORWARD_direct
-A FORWARD -j FORWARD_IN_ZONES_SOURCE
-A FORWARD -j FORWARD_IN_ZONES
-A FORWARD -j FORWARD_OUT_ZONES_SOURCE
-A FORWARD -j FORWARD_OUT_ZONES
-A FORWARD -m conntrack --ctstate INVALID -j DROP
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
-A OUTPUT -j ACCEPT
-A OUTPUT -o virbr0 -p udp -m udp --dport 68 -j ACCEPT
-A OUTPUT -j OUTPUT_direct
-A FORWARD_IN_ZONES -i ens33 -g FWDI_public
-A FORWARD_IN_ZONES -i br0 -g FWDI_public
-A FORWARD_IN_ZONES -g FWDI_public
-A FORWARD_OUT_ZONES -o ens33 -g FWDO_public
-A FORWARD_OUT_ZONES -o br0 -g FWDO_public
-A FORWARD_OUT_ZONES -g FWDO_public
-A FWDI_public -j FWDI_public_log
-A FWDI_public -j FWDI_public_deny
-A FWDI_public -j FWDI_public_allow
-A FWDI_public -p icmp -j ACCEPT
-A FWDO_public -j FWDO_public_log
-A FWDO_public -j FWDO_public_deny
-A FWDO_public -j FWDO_public_allow
-A INPUT_ZONES -i ens33 -g IN_public
-A INPUT_ZONES -i br0 -g IN_public
-A INPUT_ZONES -g IN_public
-A IN_public -j IN_public_log
-A IN_public -j IN_public_deny
-A IN_public -j IN_public_allow
-A IN_public -p icmp -j ACCEPT
-A IN_public_allow -p tcp -m tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT
COMMIT
# Completed on Thu Aug 22 11:59:17 2019
iptables-save – НЕ РАБОТАЕТ…
[root@localhost ~]# iptables-save
# Generated by iptables-save v1.4.21 on Thu Aug 22 11:59:16 2019
*nat
:PREROUTING ACCEPT [1:72]
:INPUT ACCEPT [1:72]
:OUTPUT ACCEPT [5:371]
:POSTROUTING ACCEPT [5:371]
:OUTPUT_direct - [0:0]
:POSTROUTING_ZONES - [0:0]
:POSTROUTING_ZONES_SOURCE - [0:0]
:POSTROUTING_direct - [0:0]
:POST_public - [0:0]
:POST_public_allow - [0:0]
:POST_public_deny - [0:0]
:POST_public_log - [0:0]
:PREROUTING_ZONES - [0:0]
:PREROUTING_ZONES_SOURCE - [0:0]
:PREROUTING_direct - [0:0]
:PRE_public - [0:0]
:PRE_public_allow - [0:0]
:PRE_public_deny - [0:0]
:PRE_public_log - [0:0]
-A PREROUTING -j PREROUTING_direct
-A PREROUTING -j PREROUTING_ZONES_SOURCE
-A PREROUTING -j PREROUTING_ZONES
-A OUTPUT -j OUTPUT_direct
-A POSTROUTING -s 10.1.0.0/24 -d 224.0.0.0/24 -j RETURN
-A POSTROUTING -s 10.1.0.0/24 -d 255.255.255.255/32 -j RETURN
-A POSTROUTING -s 10.1.0.0/24 ! -d 10.1.0.0/24 -p tcp -j MASQUERADE --to-ports 1024-65535
-A POSTROUTING -s 10.1.0.0/24 ! -d 10.1.0.0/24 -p udp -j MASQUERADE --to-ports 1024-65535
-A POSTROUTING -s 10.1.0.0/24 ! -d 10.1.0.0/24 -j MASQUERADE
-A POSTROUTING -j POSTROUTING_direct
-A POSTROUTING -j POSTROUTING_ZONES_SOURCE
-A POSTROUTING -j POSTROUTING_ZONES
-A POSTROUTING_ZONES -o ens33 -g POST_public
-A POSTROUTING_ZONES -o br0 -g POST_public
-A POSTROUTING_ZONES -g POST_public
-A POST_public -j POST_public_log
-A POST_public -j POST_public_deny
-A POST_public -j POST_public_allow
-A PREROUTING_ZONES -i ens33 -g PRE_public
-A PREROUTING_ZONES -i br0 -g PRE_public
-A PREROUTING_ZONES -g PRE_public
-A PRE_public -j PRE_public_log
-A PRE_public -j PRE_public_deny
-A PRE_public -j PRE_public_allow
-A PREROUTING -p tcp -m tcp --dport 222 -j DNAT --to-destination 10.1.0.9:22
-A PRE_public -j PRE_public_log
-A PRE_public -j PRE_public_deny
-A PRE_public -j PRE_public_allow
COMMIT
# Completed on Thu Aug 22 11:59:16 2019
# Generated by iptables-save v1.4.21 on Thu Aug 22 11:59:16 2019
*mangle
:PREROUTING ACCEPT [12:1319]
:INPUT ACCEPT [11:1259]
:FORWARD ACCEPT [1:60]
:OUTPUT ACCEPT [12:1070]
:POSTROUTING ACCEPT [12:1070]
:FORWARD_direct - [0:0]
:INPUT_direct - [0:0]
:OUTPUT_direct - [0:0]
:POSTROUTING_direct - [0:0]
:PREROUTING_ZONES - [0:0]
:PREROUTING_ZONES_SOURCE - [0:0]
:PREROUTING_direct - [0:0]
:PRE_public - [0:0]
:PRE_public_allow - [0:0]
:PRE_public_deny - [0:0]
:PRE_public_log - [0:0]
-A PREROUTING -j PREROUTING_direct
-A PREROUTING -j PREROUTING_ZONES_SOURCE
-A PREROUTING -j PREROUTING_ZONES
-A INPUT -j INPUT_direct
-A FORWARD -j FORWARD_direct
-A OUTPUT -j OUTPUT_direct
-A POSTROUTING -j POSTROUTING_direct
-A PREROUTING_ZONES -i ens33 -g PRE_public
-A PREROUTING_ZONES -i br0 -g PRE_public
-A PREROUTING_ZONES -g PRE_public
-A PRE_public -j PRE_public_log
-A PRE_public -j PRE_public_deny
-A PRE_public -j PRE_public_allow
COMMIT
# Completed on Thu Aug 22 11:59:16 2019
# Generated by iptables-save v1.4.21 on Thu Aug 22 11:59:16 2019
*security
:INPUT ACCEPT [11:1259]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [12:1070]
:FORWARD_direct - [0:0]
:INPUT_direct - [0:0]
:OUTPUT_direct - [0:0]
-A INPUT -j INPUT_direct
-A FORWARD -j FORWARD_direct
-A OUTPUT -j OUTPUT_direct
COMMIT
# Completed on Thu Aug 22 11:59:16 2019
# Generated by iptables-save v1.4.21 on Thu Aug 22 11:59:16 2019
*raw
:PREROUTING ACCEPT [12:1319]
:OUTPUT ACCEPT [12:1070]
:OUTPUT_direct - [0:0]
:PREROUTING_ZONES - [0:0]
:PREROUTING_ZONES_SOURCE - [0:0]
:PREROUTING_direct - [0:0]
:PRE_public - [0:0]
:PRE_public_allow - [0:0]
:PRE_public_deny - [0:0]
:PRE_public_log - [0:0]
-A PREROUTING -j PREROUTING_direct
-A PREROUTING -j PREROUTING_ZONES_SOURCE
-A PREROUTING -j PREROUTING_ZONES
-A OUTPUT -j OUTPUT_direct
-A PREROUTING_ZONES -i ens33 -g PRE_public
-A PREROUTING_ZONES -i br0 -g PRE_public
-A PREROUTING_ZONES -g PRE_public
-A PRE_public -j PRE_public_log
-A PRE_public -j PRE_public_deny
-A PRE_public -j PRE_public_allow
COMMIT
# Completed on Thu Aug 22 11:59:16 2019
# Generated by iptables-save v1.4.21 on Thu Aug 22 11:59:16 2019
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:FORWARD_IN_ZONES - [0:0]
:FORWARD_IN_ZONES_SOURCE - [0:0]
:FORWARD_OUT_ZONES - [0:0]
:FORWARD_OUT_ZONES_SOURCE - [0:0]
:FORWARD_direct - [0:0]
:FWDI_public - [0:0]
:FWDI_public_allow - [0:0]
:FWDI_public_deny - [0:0]
:FWDI_public_log - [0:0]
:FWDO_public - [0:0]
:FWDO_public_allow - [0:0]
:FWDO_public_deny - [0:0]
:FWDO_public_log - [0:0]
:INPUT_ZONES - [0:0]
:INPUT_ZONES_SOURCE - [0:0]
:INPUT_direct - [0:0]
:IN_public - [0:0]
:IN_public_allow - [0:0]
:IN_public_deny - [0:0]
:IN_public_log - [0:0]
:OUTPUT_direct - [0:0]
-A INPUT -i virbr0 -p udp -m udp --dport 53 -j ACCEPT
-A INPUT -i virbr0 -p tcp -m tcp --dport 53 -j ACCEPT
-A INPUT -i virbr0 -p udp -m udp --dport 67 -j ACCEPT
-A INPUT -i virbr0 -p tcp -m tcp --dport 67 -j ACCEPT
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -j INPUT_direct
-A INPUT -j INPUT_ZONES_SOURCE
-A INPUT -j INPUT_ZONES
-A INPUT -m conntrack --ctstate INVALID -j DROP
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -d 10.1.0.0/24 -o virbr0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -s 10.1.0.0/24 -i virbr0 -j ACCEPT
-A FORWARD -i virbr0 -o virbr0 -j ACCEPT
-A FORWARD -o virbr0 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -i virbr0 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i lo -j ACCEPT
-A FORWARD -j FORWARD_direct
-A FORWARD -j FORWARD_IN_ZONES_SOURCE
-A FORWARD -j FORWARD_IN_ZONES
-A FORWARD -j FORWARD_OUT_ZONES_SOURCE
-A FORWARD -j FORWARD_OUT_ZONES
-A FORWARD -m conntrack --ctstate INVALID -j DROP
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
-A OUTPUT -o virbr0 -p udp -m udp --dport 68 -j ACCEPT
-A OUTPUT -j OUTPUT_direct
-A FORWARD_IN_ZONES -i ens33 -g FWDI_public
-A FORWARD_IN_ZONES -i br0 -g FWDI_public
-A FORWARD_IN_ZONES -g FWDI_public
-A FORWARD_OUT_ZONES -o ens33 -g FWDO_public
-A FORWARD_OUT_ZONES -o br0 -g FWDO_public
-A FORWARD_OUT_ZONES -g FWDO_public
-A FWDI_public -j FWDI_public_log
-A FWDI_public -j FWDI_public_deny
-A FWDI_public -j FWDI_public_allow
-A FWDI_public -p icmp -j ACCEPT
-A FWDO_public -j FWDO_public_log
-A FWDO_public -j FWDO_public_deny
-A FWDO_public -j FWDO_public_allow
-A INPUT_ZONES -i ens33 -g IN_public
-A INPUT_ZONES -i br0 -g IN_public
-A INPUT_ZONES -g IN_public
-A IN_public -j IN_public_log
-A IN_public -j IN_public_deny
-A IN_public -j IN_public_allow
-A IN_public -p icmp -j ACCEPT
-A IN_public_allow -p tcp -m tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT
COMMIT
# Completed on Thu Aug 22 11:59:17 2019
iptables-save – НЕ РАБОТАЕТ ТАКЖЕ…
[root@localhost ~]# iptables-save
# Generated by iptables-save v1.4.21 on Thu Aug 22 11:59:36 2019
*nat
:PREROUTING ACCEPT [5:371]
:INPUT ACCEPT [1:67]
:OUTPUT ACCEPT [2:134]
:POSTROUTING ACCEPT [2:134]
:OUTPUT_direct - [0:0]
:POSTROUTING_ZONES - [0:0]
:POSTROUTING_ZONES_SOURCE - [0:0]
:POSTROUTING_direct - [0:0]
:POST_public - [0:0]
:POST_public_allow - [0:0]
:POST_public_deny - [0:0]
:POST_public_log - [0:0]
:PREROUTING_ZONES - [0:0]
:PREROUTING_ZONES_SOURCE - [0:0]
:PREROUTING_direct - [0:0]
:PRE_public - [0:0]
:PRE_public_allow - [0:0]
:PRE_public_deny - [0:0]
:PRE_public_log - [0:0]
-A PREROUTING -j PREROUTING_direct
-A PREROUTING -j PREROUTING_ZONES_SOURCE
-A PREROUTING -j PREROUTING_ZONES
-A OUTPUT -j OUTPUT_direct
-A POSTROUTING -s 10.1.0.0/24 -d 224.0.0.0/24 -j RETURN
-A POSTROUTING -s 10.1.0.0/24 -d 255.255.255.255/32 -j RETURN
-A POSTROUTING -s 10.1.0.0/24 ! -d 10.1.0.0/24 -p tcp -j MASQUERADE --to-ports 1024-65535
-A POSTROUTING -s 10.1.0.0/24 ! -d 10.1.0.0/24 -p udp -j MASQUERADE --to-ports 1024-65535
-A POSTROUTING -s 10.1.0.0/24 ! -d 10.1.0.0/24 -j MASQUERADE
-A POSTROUTING -j POSTROUTING_direct
-A POSTROUTING -j POSTROUTING_ZONES_SOURCE
-A POSTROUTING -j POSTROUTING_ZONES
-A POSTROUTING_ZONES -o ens33 -g POST_public
-A POSTROUTING_ZONES -o br0 -g POST_public
-A POSTROUTING_ZONES -g POST_public
-A POST_public -j POST_public_log
-A POST_public -j POST_public_deny
-A POST_public -j POST_public_allow
-A PREROUTING_ZONES -i ens33 -g PRE_public
-A PREROUTING_ZONES -i br0 -g PRE_public
-A PREROUTING_ZONES -g PRE_public
-A PRE_public -j PRE_public_log
-A PRE_public -j PRE_public_deny
-A PRE_public -j PRE_public_allow
-A PREROUTING -p tcp -m mark --mark 0x64 -j DNAT --to-destination 10.1.0.9:22
COMMIT
# Completed on Thu Aug 22 11:59:36 2019
# Generated by iptables-save v1.4.21 on Thu Aug 22 11:59:36 2019
*mangle
:PREROUTING ACCEPT [17:1649]
:INPUT ACCEPT [12:1285]
:FORWARD ACCEPT [5:364]
:OUTPUT ACCEPT [10:3037]
:POSTROUTING ACCEPT [14:3341]
:FORWARD_direct - [0:0]
:INPUT_direct - [0:0]
:OUTPUT_direct - [0:0]
:POSTROUTING_direct - [0:0]
:PREROUTING_ZONES - [0:0]
:PREROUTING_ZONES_SOURCE - [0:0]
:PREROUTING_direct - [0:0]
:PRE_public - [0:0]
:PRE_public_allow - [0:0]
:PRE_public_deny - [0:0]
:PRE_public_log - [0:0]
-A PREROUTING -j PREROUTING_direct
-A PREROUTING -j PREROUTING_ZONES_SOURCE
-A PREROUTING -j PREROUTING_ZONES
-A INPUT -j INPUT_direct
-A FORWARD -j FORWARD_direct
-A OUTPUT -j OUTPUT_direct
-A POSTROUTING -j POSTROUTING_direct
-A PREROUTING_ZONES -i ens33 -g PRE_public
-A PREROUTING_ZONES -i br0 -g PRE_public
-A PREROUTING_ZONES -g PRE_public
-A PRE_public -j PRE_public_log
-A PRE_public -j PRE_public_deny
-A PRE_public -j PRE_public_allow
-A PRE_public_allow -p tcp -m tcp --dport 222 -j MARK --set-xmark 0x64/0xffffffff
COMMIT
# Completed on Thu Aug 22 11:59:36 2019
# Generated by iptables-save v1.4.21 on Thu Aug 22 11:59:36 2019
*security
:INPUT ACCEPT [12:1285]
:FORWARD ACCEPT [4:304]
:OUTPUT ACCEPT [10:3037]
:FORWARD_direct - [0:0]
:INPUT_direct - [0:0]
:OUTPUT_direct - [0:0]
-A INPUT -j INPUT_direct
-A FORWARD -j FORWARD_direct
-A OUTPUT -j OUTPUT_direct
COMMIT
# Completed on Thu Aug 22 11:59:36 2019
# Generated by iptables-save v1.4.21 on Thu Aug 22 11:59:36 2019
*raw
:PREROUTING ACCEPT [17:1649]
:OUTPUT ACCEPT [10:3037]
:OUTPUT_direct - [0:0]
:PREROUTING_ZONES - [0:0]
:PREROUTING_ZONES_SOURCE - [0:0]
:PREROUTING_direct - [0:0]
:PRE_public - [0:0]
:PRE_public_allow - [0:0]
:PRE_public_deny - [0:0]
:PRE_public_log - [0:0]
-A PREROUTING -j PREROUTING_direct
-A PREROUTING -j PREROUTING_ZONES_SOURCE
-A PREROUTING -j PREROUTING_ZONES
-A OUTPUT -j OUTPUT_direct
-A PREROUTING_ZONES -i ens33 -g PRE_public
-A PREROUTING_ZONES -i br0 -g PRE_public
-A PREROUTING_ZONES -g PRE_public
-A PRE_public -j PRE_public_log
-A PRE_public -j PRE_public_deny
-A PRE_public -j PRE_public_allow
COMMIT
# Completed on Thu Aug 22 11:59:36 2019
# Generated by iptables-save v1.4.21 on Thu Aug 22 11:59:36 2019
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [8:2813]
:FORWARD_IN_ZONES - [0:0]
:FORWARD_IN_ZONES_SOURCE - [0:0]
:FORWARD_OUT_ZONES - [0:0]
:FORWARD_OUT_ZONES_SOURCE - [0:0]
:FORWARD_direct - [0:0]
:FWDI_public - [0:0]
:FWDI_public_allow - [0:0]
:FWDI_public_deny - [0:0]
:FWDI_public_log - [0:0]
:FWDO_public - [0:0]
:FWDO_public_allow - [0:0]
:FWDO_public_deny - [0:0]
:FWDO_public_log - [0:0]
:INPUT_ZONES - [0:0]
:INPUT_ZONES_SOURCE - [0:0]
:INPUT_direct - [0:0]
:IN_public - [0:0]
:IN_public_allow - [0:0]
:IN_public_deny - [0:0]
:IN_public_log - [0:0]
:OUTPUT_direct - [0:0]
-A INPUT -i virbr0 -p udp -m udp --dport 53 -j ACCEPT
-A INPUT -i virbr0 -p tcp -m tcp --dport 53 -j ACCEPT
-A INPUT -i virbr0 -p udp -m udp --dport 67 -j ACCEPT
-A INPUT -i virbr0 -p tcp -m tcp --dport 67 -j ACCEPT
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -j INPUT_direct
-A INPUT -j INPUT_ZONES_SOURCE
-A INPUT -j INPUT_ZONES
-A INPUT -m conntrack --ctstate INVALID -j DROP
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -d 10.1.0.0/24 -o virbr0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -s 10.1.0.0/24 -i virbr0 -j ACCEPT
-A FORWARD -i virbr0 -o virbr0 -j ACCEPT
-A FORWARD -o virbr0 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -i virbr0 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i lo -j ACCEPT
-A FORWARD -j FORWARD_direct
-A FORWARD -j FORWARD_IN_ZONES_SOURCE
-A FORWARD -j FORWARD_IN_ZONES
-A FORWARD -j FORWARD_OUT_ZONES_SOURCE
-A FORWARD -j FORWARD_OUT_ZONES
-A FORWARD -m conntrack --ctstate INVALID -j DROP
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
-A OUTPUT -o virbr0 -p udp -m udp --dport 68 -j ACCEPT
-A OUTPUT -j OUTPUT_direct
-A FORWARD_IN_ZONES -i ens33 -g FWDI_public
-A FORWARD_IN_ZONES -i br0 -g FWDI_public
-A FORWARD_IN_ZONES -g FWDI_public
-A FORWARD_OUT_ZONES -o ens33 -g FWDO_public
-A FORWARD_OUT_ZONES -o br0 -g FWDO_public
-A FORWARD_OUT_ZONES -g FWDO_public
-A FWDI_public -j FWDI_public_log
-A FWDI_public -j FWDI_public_deny
-A FWDI_public -j FWDI_public_allow
-A FWDI_public -p icmp -j ACCEPT
-A FWDO_public -j FWDO_public_log
-A FWDO_public -j FWDO_public_deny
-A FWDO_public -j FWDO_public_allow
-A INPUT_ZONES -i ens33 -g IN_public
-A INPUT_ZONES -i br0 -g IN_public
-A INPUT_ZONES -g IN_public
-A IN_public -j IN_public_log
-A IN_public -j IN_public_deny
-A IN_public -j IN_public_allow
-A IN_public -p icmp -j ACCEPT
-A IN_public_allow -p tcp -m tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT
COMMIT
# Completed on Thu Aug 22 11:59:16 2019
ОБНОВЛЕНИЕ II:
Первое правило в FORWARD из “работает” – это ACCEPT. Это позволяет пересылать все пакеты. Другие правила принимают DNAT-пакеты, но позже в цепочке. Итак… Мы можем попытаться решить проблему, если выясним, почему это работает…
iptables -I FORWARD -d 0.0.0.0/0 -j ACCEPT
firewall-cmd --permanent --zone=public --add-forward-port=port=222:proto=tcp:toport=22:toaddr=10.1.0.9
firewall-cmd --reload
… и почему это нет…
firewall-cmd --permanent --zone=public --direct --add-rule ipv4 filter FORWARD 0 -d 0.0.0.0/0 -j ACCEPT
firewall-cmd --permanent --zone=public --add-forward-port=port=222:proto=tcp:toport=22:toaddr=10.1.0.9
firewall-cmd --reload
НАСТОЯЩАЯ ПРОБЛЕМА:
Команда…
firewall-cmd --permanent --zone=public --direct --add-rule ipv4 filter FORWARD 0 -d 0.0.0.0/0 -j ACCEPT
firewall-cmd --permanent --zone=public --add-forward-port=port=222:proto=tcp:toport=22:toaddr=10.1.0.9
firewall-cmd --reload
… описанная в “ОБНОВЛЕНИИ II”, работает так же, как и firewalld (используемый в CentOS 7).
Проблема заключается в KVM (libvirt), который при запуске сети “virbr0” вводит правила (вероятно, через firewalld), которые предотвращают (принцип первого совпадения) любые попытки перенаправления портов стандартными способами с использованием firewall-cmd
. Введенные KVM (libvirt) правила находятся в верхней части FORWARD и POSTROUTING, перед обычным набором правил firewalld. Поскольку netfilter работает по принципу первого совпадения, эти правила.
РЕШЕНИЕ:
Из-за проблем, вызванных правилами, вводимыми KVM (libvirt) в брандмауэр, решение заключается в использовании хаков/обходных путей, называемых libvirt-hook-qemu, как мы объяснили ниже…
Скачайте и установите libvirt-hook-qemu…
yum -y install git-core
cd /usr/local/src
git clone https://github.com/saschpe/libvirt-hook-qemu.git
cd libvirt-hook-qemu
make install
cd ..
rm -rf libvirt-hook-qemu
Список ваших виртуальных машин (гостей)…
virsh list --all
… и скопируйте имя целевой виртуальной машины.
Выключите виртуальную машину…
virsh shutdown "<VM_NAME>" --mode acpi
Откройте файл “hooks.json”, удалите его содержимое…
vi /etc/libvirt/hooks/hooks.json
… и введите ваши правила по шаблону ниже (возможны и другие способы настройки)…
{
"<VM_NAME>": {
"interface": "virbr0",
"private_ip": "<VM_IP>",
"port_map": {
"tcp": [[<PORT_ON_HOST>, <PORT_ON_GUEST>]]
}
}
}
Перезапустите libvirtd…
systemctl restart libvirtd.service
… и запустите виртуальную машину…
virsh start "<VM_NAME>"
Готово! =D
ДАЛЕЕ:
Такое поведение KVM (libvirt) – внедрение правил, которые предотвращают любые попытки перенаправления портов – является ПОЖИРАТЕЛЬНЫМ, ВТОРЖЕНИЕМ И НЕОБХОДИМЫМ… Во-первых, потому что, поскольку нет перенаправления портов на хосте, никакая виртуальная машина не будет доступна в стандартной сети (virbr0), и во-вторых, потому что это заставляет нас использовать хак/обходной путь (или “gato” https://superuser.com/”gambiarra”, как мы это называем в Бразилии =D).
На наш взгляд, нет смысла навязывать пользователю, как он должен строить свою инфраструктуру… Это не имеет смысла! Если говорить прямо, мы думаем, что было бы лучше, если бы эти настройки были опциональными (внедрение правил…) так, как это делают другие ведущие гипервизоры. И мы еще дальше… Если KVM (libvirt) контролирует такого рода вещи, то он также должен предлагать способы сопоставления портов с виртуальными машинами.
KVM (libvirt) является ВЕЛИКОЛЕПНЫМ инструментом, но не все пользователи готовы – по различным причинам – размещать свои машины непосредственно в сети хостовой машины, как и не все пользователи готовы отказаться от всей гибкости/доступности, которую предлагает стандартная сеть (virbr0).
Спасибо!
[Ссылки.: https://bugzilla.redhat.com/show_bug.cgi?id=846810 ,
https://libvirt.org/firewall.html ,
https://libvirt.org/formatnetwork.html#examplesRoute,
https://saschpe.wordpress.com/2014/03/06/dynamic-iptables-port-forwarding-for-nat-ed-libvirt-networks/ ,
https://serverfault.com/q/170079/276753 ,
https://serverfault.com/q/915257/276753 ,
https://wiki.libvirt.org/page/VirtualNetworking#Routed_mode ,
https://www.centos.org/forums/viewtopic.php?f=50&t=71454&sid=7f5190a29eebbf755235ec3dc404a47f ,
https://www.cyberciti.biz/faq/kvm-forward-ports-to-guests-vm-with-ufw-on-linux/ ]
ОБНОВЛЕНИЕ:
внедряет правила, которые предотвращают любые попытки перенаправления портов
-> Текущий upstream KVM (libvirt) решил проблему!
Смотрите это: …текущий upstream KVM (libvirt) решил проблему…
Я нашел еще одно решение, которое не требует никакого дополнительного кода. Это было протестировано на Fedora 41; я не уверен насчет CentOS 7, который на данный момент довольно старый.
Все команды из этих инструкций должны выполняться от имени root.
Отредактируйте сеть libvirt (virsh net-edit default
обычно), найдите , измените на . Затем либо просто перезагрузите ваш хост, либо перезапустите сеть, обычно так:
virsh net-destroy default
virsh net-start default
На этом этапе ваши гости потеряли связь с “внешним миром”, потому что вы отключили NAT libvirt, но теперь вы добавляете свой собственный NAT.
Во-первых, взгляните на ваши зоны с firewall-cmd --get-active-zones
. Вот что я получил:
# firewall-cmd --get-active-zones
FedoraServer (default)
interfaces: ens18
libvirt
interfaces: virbr0
Ваша публичная зона может иметь другое имя, соответственно измените остальные команды (я думаю, что обычно это “public” в RHEL и производных). Если вы не видите virbr0 в зоне libvirt, добавьте его: firewall-cmd --zone libvirt --add-interface virbr0
. Если virbr0 находится в какой-то другой зоне, используйте это имя зоны вместо этого. Но не должно быть в вашей публичной зоне.
Теперь создадим новый NAT:
firewall-cmd --permanent --new-policy libvirt-nat
firewall-cmd --permanent --policy libvirt-nat --set-target ACCEPT
firewall-cmd --permanent --policy libvirt-nat --add-ingress-zone libvirt
firewall-cmd --permanent --policy libvirt-nat --add-egress-zone FedoraServer
firewall-cmd --permanent --policy libvirt-nat --add-masquerade
firewall-cmd --reload
Ваши гости должны восстановить свою подключаемость, и с этим NAT ваше перенаправление портов будет довольно простым, например:
firewall-cmd --permanent --zone FedoraServer --add-forward-port=port=8080:proto=tcp:toport=8080:toaddr=192.168.122.117
firewall-cmd --reload
Замените номер порта и внутренний адрес по мере необходимости.
Есть особый случай: когда ваши гости имеют реальные IPv6 адреса и вы уже настроили маршрутизацию этих адресов через ваш хост. В этом случае вы можете захотеть разрешить внешнему миру подключаться к вашим гостям. Если – а это если – вы хотите это сделать, добавьте еще одну политику:
firewall-cmd --permanent --new-policy libvirt-inbound
firewall-cmd --permanent --policy libvirt-inbound --set-target ACCEPT
firewall-cmd --permanent --policy libvirt-inbound --add-egress-zone libvirt
firewall-cmd --permanent --policy libvirt-inbound --add-ingress-zone FedoraServer
firewall-cmd --reload
Иногда облачный провайдер дает вам IPv6 адреса, но не маршрутизирует их. Все еще есть способ использовать их таким образом, это называется “проксирование NDP”, но это выходит за рамки этого ответа.
Ответ или решение
Решение проблемы с неправильной работой firewall-cmd
для перенаправления портов в KVM сервере
Если вы столкнулись с проблемой, когда команда firewall-cmd --add-forward-port
не работает на хост-системе KVM с виртуальными машинами (гостями), это может быть связано с особенностями взаимодействия между firewalld
и правилами, автоматически генерируемыми libvirt.
Контекст проблемы
Согласно вашему описанию, вы пытаетесь перенаправить порт 222 на порт 22 у виртуальной машины с работающим SSH-сервисом. При этом команды iptables
работают корректно, в то время как firewall-cmd
нет. Это может вызывать недоумение, так как обе утилиты, по сути, управляют одними и теми же правилами Netfilter.
Понимание внутренней работы firewalld и libvirt
-
Структура взаимодействия:
firewalld
управляет правилами через зоны и политики. Однако libvirt, создавая сеть по умолчанию (virbr0), добавляет свои правила в цепочки, которые могут блокировать попытки перенаправления портов, осуществляемыеfirewall-cmd
. -
Принцип "первого совпадения": Netfilter обрабатывает пакеты по порядку правил (первое совпадение выигрывает). Если вы добавляете правила через
firewall-cmd
, но overshadowed by libvirt’s rules above it in the chain, они могут никогда не срабатывать.
Шаги для решения проблемы
1. Настройка сетевой конфигурации libvirt
Для того чтобы избавиться от конфигураций, мешающих использованию firewall-cmd
, вы можете изменить настройки сети libvirt. Например, отключить NAT и использовать собственное перенаправление портов.
virsh net-edit default
Измените тип сети с NAT на Routed или BAG. Затем перезапустите сеть:
virsh net-destroy default
virsh net-start default
2. Настройка зон в firewalld
Убедитесь, что интерфейс virbr0
добавлен в зональный контекст, не мешающий вашим основным настройкам. Можно добавить его в зону libvirt
:
firewall-cmd --zone=libvirt --add-interface=virbr0
3. Создание NAT и проброса портов
После изменения конфигурации сети libvirt, создайте новую политику NAT, которая будет работать независимо от libvirt.
firewall-cmd --permanent --new-policy libvirt-nat
firewall-cmd --permanent --policy libvirt-nat --set-target ACCEPT
firewall-cmd --permanent --policy libvirt-nat --add-ingress-zone libvirt
firewall-cmd --permanent --policy libvirt-nat --add-egress-zone public
firewall-cmd --permanent --policy libvirt-nat --add-masquerade
firewall-cmd --reload
После этого выполните команду проброса порта:
firewall-cmd --permanent --zone=public --add-forward-port=port=222:proto=tcp:toport=22:toaddr=10.1.0.9
firewall-cmd --reload
Заключение
Если вы следовали приведённым шагам, но проблема не исчезла, возможно, стихийные конфликты с другими правилами. Рекомендуется проверять результат команд iptables-save
и firewall-cmd --list-all
, чтобы убедиться, что ваши правила корректно работают.
Кроме того, вы также можете рассмотреть возможность использования libvirt-hook-qemu
для динамического управления правилами IP в зависимости от состояния виртуальных машин. Это может добавить дальнейшую гибкость и решение текущих трудностей.
Резюме
VIRTUEL (виртуальные машины), как и их конфигурация сетевого взаимодействия, требуют внимательного отношения к правилам безопасности, особенно когда дело касается NAT и портов. Понимание структуры и логики управления сетевыми правилами в KVM-среде может существенно упростить их администрирование и устранить множество проблем.