To configure an isolated network with static IPs and a custom gateway in Libvirt, you must edit the XML definition of your default network or create a new one. The key is using the
<host> tag inside
<dhcp> to assign specific MAC addresses to fixed IP addresses and setting the
<gateway> element to define your custom router. This setup ensures VMs remain disconnected from the host’s external interface while having predictable internal addressing for automation and security testing.
Understanding Libvirt Network Architecture
Libvirt manages virtual networks through XML definitions stored in
/etc/libvirt/qemu/networks/. By default, it creates a NAT-based network named
default that allows VMs to access the internet via the host machine. However, this default configuration often uses dynamic DHCP leases, which makes managing static IPs difficult because the lease times and assigned addresses can change.
For isolated environments where you need precise control over networking, such as building a private cloud or testing sandboxed applications, you should either modify the existing
default network or define a new one. An isolated network typically does not forward traffic to the physical interface of the host, meaning VMs cannot reach the outside world unless explicitly routed. This isolation is crucial for security when handling sensitive data or unstable software.
The core components of this configuration are the bridge interface created by Libvirt (usually
virbr0), the DHCP server running within the Libvirt daemon, and the static IP reservations. You will interact with these components primarily through the
virsh net-edit command, which opens the XML definition in your default text editor. Understanding how these pieces fit together helps prevent common pitfalls like IP conflicts or broken connectivity after rebooting the host.
Editing the Network XML Definition
Begin by listing your available networks to identify the one you wish to modify. Run the following command in your terminal:
virsh net-list --all
If you want to use the default network, select
default. Otherwise, you can create a new network using
virsh net-create or
virsh net-define with a fresh XML template. For this guide, we assume you are editing the
default network. Execute:
virsh net-edit default
This command opens the XML file. You will see sections defining the bridge, IP range, and DHCP settings. Locate the
<dhcp> block. Inside this block, you will add
<host> entries. It is critical to note that earlier versions of tutorials might suggest using
<dhcp-host>, but the correct and valid Libvirt XML schema requires the
<host> tag nested directly within
<dhcp>. Using invalid tags will cause the network to fail to start.
Each
<host> entry requires three attributes:
mac,
ip, and optionally
name. The MAC address must match the virtual NIC of your target VM. The IP address is the static address you wish to assign. For example:
<dhcp>
<range start="192.168.122.100" end="192.168.122.254"/>
<host mac="52:54:00:12:34:56" ip="192.168.122.10" name="webserver"/>
<host mac="52:54:00:78:90:12" ip="192.168.122.11" name="dbserver"/>
</dhcp>
Save the file and exit the editor. Libvirt validates the XML automatically upon saving. If there are syntax errors, it will reject the changes and prompt you to fix them.
Configuring the Custom Gateway
A common misconception is that a custom gateway cannot be set on an isolated network. In reality, the
<gateway> tag defines the IP address that the Libvirt DHCP server hands out as the default route to clients. Even in an isolated network, VMs need a gateway to communicate with each other if routing is involved, or simply to have a consistent network configuration structure.
In the XML, locate the
<ip> tag under the
<network> section. It typically looks like this:
<ip address="192.168.122.1" netmask="255.255.255.0">
<dhcp>...
To set a custom gateway, ensure the
address attribute matches the IP you want to act as the gateway. Usually, this is the first IP in the subnet (e.g.,
192.168.122.1). If you want a different IP to serve as the gateway, change the
address attribute accordingly. For instance, if you want
192.168.122.254 to be the gateway, update the tag:
<ip address="192.168.122.254" netmask="255.255.255.0">
<dhcp>...
After saving, restart the network to apply changes:
virsh net-destroy default
virsh net-start default
Your VMs will now receive the new gateway IP via DHCP. Note that if your VMs were already running, they may retain the old lease. You must renew their network interfaces or reboot them to pick up the new gateway configuration.
Verifying Connectivity and Security
Once configured, verify that the static IPs are correctly assigned. Start a VM and check its IP address using
ip addr or
ifconfig. Ensure it matches the
ip attribute you defined in the XML. Additionally, test connectivity between VMs. Since the network is isolated, they should only be able to ping each other and the gateway, not the host’s external IP or the internet.
If you encounter issues where VMs cannot ping each other, refer to our guide on
Libvirt Guests on Isolated Network Cannot Ping Each Other: Troubleshooting. This article covers firewall rules and bridge configurations that often interfere with inter-VM communication.
Avoid flushing iptables as a troubleshooting step. Flushing iptables removes all firewall rules, including those protecting your host system, which is a significant security risk. Instead, check the Libvirt-specific chains in iptables using
iptables -L -n to ensure traffic is being forwarded correctly between the bridge and the VMs. Properly configuring the XML definition is usually sufficient to resolve connectivity issues without compromising host security.
Frequently Asked Questions
Can I use a custom gateway on an isolated network?
Yes, you can set any IP within the subnet as the gateway by modifying the
address attribute in the
<ip> tag of the network XML. This IP will be distributed to VMs as their default route, even if that route does not lead to the internet.
What happens if I use dhcp-host instead of host?
Using
<dhcp-host> is incorrect for modern Libvirt versions and will cause the network definition to fail validation. Always use
<host> nested inside
<dhcp> to assign static IPs to MAC addresses.
Do I need to restart the host to apply network changes?
No, restarting the host is not required. You only need to destroy and restart the specific Libvirt network using
virsh net-destroy and
virsh net-start. Your running VMs will need to renew their DHCP leases to get the new configuration.
How do I find the MAC address of a VM?
You can find the MAC address by looking at the VM’s XML definition using
virsh dumpxml [vm-name] and searching for the
<mac> tag under the
<interface> section. Alternatively, check inside the guest OS using
ip link show.
Is it safe to flush iptables to fix networking issues?
No, flushing iptables is dangerous as it removes all firewall protections on your host. Instead, inspect the Libvirt-managed chains in iptables or troubleshoot the bridge configuration. Our related article on
Expanding Libvirt VM Storage Using ZFS Volume discusses best practices for maintaining system stability during configuration changes.