1

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:

  1. 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
  1. 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

  1. Install libvirt-hook-qemu
git clone https://github.com/saschpe/libvirt-hook-qemu.git
make install
  1. 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]
        }
    }
}
  1. Enable and start firewalld-reload-hook.service
systemctl enable firewalld-reload-hook.service
systemctl start firewalld-reload-hook.service
  1. 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

nforced
  • 111
  • 2

0 Answers0