It's been well know that firewalld will flush Libvirt rules upon reload and thus making port forwarding to VMs broken until you restart libvirtd. Here is what I did:
- Create
/etc/systemd/system/firewalld-reload-hook.service
[Unit]
Description=firewalld reload hook - run a hook script on firewalld reload
Wants=dbus-broker.service
After=dbus-broker.service
[Service]
Type=simple
ExecStart=/bin/bash -c '/bin/busctl monitor --system --json=short --match "interface=org.fedoraproject.FirewallD1,member=Reloaded" | while read -r line ; do [ -x /sbin/firewalld-reload-hook ] && /sbin/firewalld-reload-hook ; done'
[Install]
WantedBy=multi-user.target
- Create
/sbin/firewalld-reload-hook
#!/bin/bash
# Invoked by /etc/systemd/system/firewalld-reload-hook.service
set -e
logger "$BASH_SOURCE: Firewalld reload hook triggered."
/usr/bin/systemctl restart libvirtd
logger "$BASH_SOURCE: Libvirt restarted."
exit 0
and make it executable chmod +x /sbin/firewalld-reload-hook
- Install
libvirt-hook-qemu
git clone https://github.com/saschpe/libvirt-hook-qemu.git
make install
- Edit
/etc/libvirt/hooks/hooks.json
to match your needs. This just an example
{
"www": {
"private_ip": "192.168.122.100",
"port_map": {
"tcp": [80, 443]
}
},
"mail": {
"private_ip": "192.168.122.101",
"port_map": {
"tcp": [25, 465]
}
}
}
- Enable and start
firewalld-reload-hook.service
systemctl enable firewalld-reload-hook.service
systemctl start firewalld-reload-hook.service
firewall-cmd --reload
At this point systemctl restart libvirtd
and firewall-cmd --reload
produce the same results and survive reboots (tested on Debian bullseye with nftables and libvirt 7.0/NAT network)
So, is this the best way of doing it?
Refer
libvirt-hook-qemu, firewalld-reload-hook.service, firewalld.dbus