9

Similar to this old request on BugZilla for Fedora 8, I'm hoping something has changed since then or someone knows another way.

I want to manage the iptables rules by hand—the one-size-fits-all automatic rules don't suit me at all. These rules seem to be added and removed when a network is started and destroyed. Is there a way of either preventing these rules being added at all or hooking a script into the network start that restores the default rules afterwards.

For now, I'm using a very crude method with cron, but I hope there is a better way:

  *  *  *  *  * root    iptables-restore < /etc/sysconfig/iptables
3
  • Is KVM using a modular script to start virtual network devices? If so you could manipulate that script (this is how I would do this on XEN).
    – Nils
    Dec 10, 2012 at 14:56
  • I don't think so but tbh I'm not sure how to find out.
    – user83664
    Dec 10, 2012 at 17:38
  • The best place to ask is the libvirt devel list or on their IRC channel (#virt on OFTC)
    – dyasny
    Dec 10, 2012 at 21:52

4 Answers 4

8

Well I've found an answer that suits me: I've gone back to school and learned to do it the old fashioned way. No need to use libvirt's fancy networking functions as I can just:

  • set up my own bridged network(s) (not attached to any physical network port)
  • use a DHCP server on the host and masquerade in iptables
  • edit the libvirt guest config files to use the bridge(s)
  • have complete flexibility in how I want to configure security with iptables
1
  • +1 just use bridged mode, or move on to 802.1Qbg/h
    – dyasny
    Dec 10, 2012 at 21:53
3

It is not possible to modify these rules, since they are not in a configuration file or a script, but in the sourcecode.

But in 2016 the "open"-network "forward mode" was added. When specified for a network, libvirt does not generate any iptables rules for the network. See bug 846810.

So edit your network (virsh net-edit) to <forward mode='open'/>.

open is like route, but there will be no firewall rules added to either enable or prevent any of this traffic. See Network XML format for more details.

2

Per Red Hat Bugzilla:

First, it is already possible to avoid the iptables rules - simply do not request a NAT based virtual network. The 'default' virtual network is intentionally NAT based. You are free to remove this & default one which doesn't provide NAT.

So to avoid the cron job:

virsh net-destroy default
virsh net-undefine default

Of course, as @user83664 wrote, you'll have to use either a bridge or hostonly networks going forward.

2

Use hooks to restore your iptables rules:

# The "hooks/" folder is not created by default by Libvirt
mkdir /etc/libvirt/hooks

# Libvirt supports multiple possible listeners like "daemon", "qemu", etc. 
# We are generating automatically all of these listeners in one go.
for f in daemon qemu lxc libxl network; do

  echo '#!/bin/sh
iptables-restore < /etc/sysconfig/iptables' > "/etc/libvirt/hooks/$f"
  chmod +x "/etc/libvirt/hooks/$f"

done

# Restarting Libvirt to confirm that rules are actually restored
service libvirtd restart

Iptables rules will be reloaded for certain actions only, but this is sufficient to make it static. Only reload (SIGHUP) of libvirtd will write it's own rules, but it isn't triggered by any system scripts, so will not happen until you type by yourself:

service libvirtd reload

See https://libvirt.org/hooks.html

UPDATE: Recent libvirt versions use its own chains to insert rules and these chains are required to start/stop networks and domains. So the previous way won't work. Here are these chains in iptables-restore format:

*mangle
:LIBVIRT_PRT - [0:0]
-A POSTROUTING -j LIBVIRT_PRT
*filter
:LIBVIRT_FWI - [0:0]
:LIBVIRT_FWO - [0:0]
:LIBVIRT_FWX - [0:0]
:LIBVIRT_INP - [0:0]
:LIBVIRT_OUT - [0:0]
-A INPUT -j LIBVIRT_INP
-A FORWARD -j LIBVIRT_FWX
-A FORWARD -j LIBVIRT_FWI
-A FORWARD -j LIBVIRT_FWO
-A OUTPUT -j LIBVIRT_OUT
*nat
:LIBVIRT_PRT - [0:0]
-A POSTROUTING -j LIBVIRT_PRT

To override libvirtd rules just put your custom rules before the libvirt-jump rule (-j LIBVIRT_XXX). When libvirtd/network/domain starts it only inserts jump-rules if they don't exist. So all you need is load your rules (with all libvirt chains created and libvirt-jump rules correctly placed) before libvirtd starts. From another point of view - you need to restart/reload libvirtd every time after changing and loading your new rules - to let it insert libvirt's ones.

You must log in to answer this question.