I found the networking configured by libvirt
(KVM) did not allow me to firewall the network as I desired. I use Shorewall for firewalling, and DNSMasq for internal DNS and DHCP. After a little experimentation, I found that I could configure Ubuntu to create the network. This allows me to get a reliable firewall configuration with a virtual DMZ.
The virtual hosts are assigned to a bridge, and only have connectivity to other networks as defined in the Shorewall configuration. A single DNSMasq server provides DSN and DHCP services for all virtual servers, as well as the network the server is connected to. The network and firewall configuration remains consistent even as servers are cycled up and down. An additional bridge was created to support virtual servers in the DMZ zone.
This page has been updated in 2019 to reflect changes in the tools.
Disabling the Existing Network
The command virsh net-list --all
will list all the existing networks. Disable auto-start for each network current marked for auto-start. To disable the default network use the command virsh net-autostart default --disable
. Replace default with the name of the network to be disabled.
It is possible to change from a network interface to a bridge interface. This may require restarting the network interface on the virtual servers after the bridge is restarted. Depending on the existing virtual server configuration, this may be as simple as changing the interface type from network
to bridge
. This gives a block similar to this:
<interface type='bridge'> <mac address='52:54:00:ee:b5:b1'/> <source bridge='br0'/> <target dev='vnet0'/> <model type='virtio'/> <alias name='net0'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> </interface>
You may want to edit the existing networks using the virsh net-edit
command. Record the information being deleted if you want to replicate it into your new configuration. The example below is the definition for a test network using a bridge named virbr2.
<network> <name>test</name> <uuid>91ae6378-841c-89d1-cf48-2d66a212e807</uuid> <bridge name='virbr2' stp='off' delay='0' /> </network>
You can use the above example to define new networks. Remove the UUID line, and replace the names with appropriate new values.
Defining the Bridges
The existing Ubuntu network scripts can be used to create the bridges when the network starts. This is done in the /etc/network/interfaces
script. The following example creates a bridged for the default using a bridge name virbr0. In order to bring up a bridge, it is now necessary to connect an interface. This configuration creates a dummy device to be the interface as it is not bridged to the ethernet interface. If the bridge_ports include an existing device, the pre-up
and post-down
lines can be omitted.
auto virbr0 iface virbr0 inet static bridge_ports virbr0-nic address 192.0.2.1 netmask 255.255.255.0 pre-up ip link add virbr0-nic type dummy || true post-down ip link del virbr0-nic || true
The old network tools did not support creating and deleting interfaces.
auto virbr0 iface virbr0 inet static address 192.0.2.1 netmask 255.255.255.0 pre-up brctl addbr virbr0 post-down brctl delbr virbr0
The address used is an example and will need to be edited appropriately. Additional bridges can be defined using this example as a template. The address and bridge name needs to be unique for each network. To handle a DMZ I added a bridge named virbr1
.
The libvrt.org wiki shows how to build a bridge configuration attached to an interface. This will create a network outage. You may want to replicate the eth0
configuration as the br0
configuration. Copy and update all appropriate configurations before switching from eth0 to br0 and disable automatic start-up for eth0.
Configuring Shorewall
The sample configurations are a good starting point for configuration. I used the three interface examples to handle my DMZ. The default fw, dmz, loc, and net zones are used as-is. An additional virt
zone was added to handle virtual servers that are not in the DMZ. The Shorewall documentation provides documentation for a simpler setup such as might be used on a laptop.
Edit shorewall.conf
to ensure IP forwarding is enabled. This is done with the line IP_FORWARDING=Yes
. Review this file to see if you want to change anything else.
My loc
zone supporting the LAN is routed over eth0
as is the net
zone. A firewall between the Internet and the LAN is used to prevent spoofing of LAN addresses from the Internet. If this were also the Internet firewall, then the loc
zone should be on a different Ethernet adapter.
The interfaces
file lists each network interface and bridge. Servers in the dmz
zone are expected to have static addresses so DHCP is disabled. DHCP is enabled on the net interface enabling DNSMasq to provide addresses to the LAN. It would also be enabled if the net interface got its address via DHCP. DHCP is optional for the virt
zone, but may be required for prepackaged virtual servers. The routeback
option may be required on the bridge zones if servers on the bridge need to talk to each other.
net eth0 detect tcpflags,routefilter,nosmurfs,logmartians,blacklist,dhcp virt virbr0 detect tcpflags,routefilter,nosmurfs,logmartians,routeback,dhcp dmz virbr1 detect tcpflags,routefilter,nosmurfs,logmartians,routeback
My configuration uses the same NIC to connect to the internet and local network. A single line in the hosts
file handles defining the loc
zone. The LAN uses a private address range so it is relatively easy to secure from spoofing from the Internet. Public IP addresses would be more difficult to secure.
loc eth0:192.168.10.0/24
The policy file contains an unusable policy allowing full access from loc to net. This should be disabled or changed to allow access from virt to the net. Diagnosing problems may be simpler if you define a policy for each local zone to all
with logging enabled. I replicate the all
to all
policy, and change the origin.
The masq
file is deleted. It is not required in our configuration. For hosts directly connected to the Internet, the provided file is likely sufficient and should be kept.
The routestopped
file needs to be edited if used. It is a good idea to have some sort of access when the firewall is stopped. This file is used to define access.
The rules
file may need to be tailored significantly. Many of the rules applying to the loc
zone may be applicable to the virt
zone. Consider which protocols each zone needs to accept, or connect to. These must be permitted between the appropriate zones. Rules may be built that limit access for a particular host or hosts. These are some basic items that should be considered.
- ICMP must be enabled everywhere. Pings from the Internet (net zone) are blocked in the default ruleset.
- NTP should not be run on the virtual servers. It should be run on the firewall.
- DNS should be allowed to the appropriate zone(s).
- SSH should be allowed between appropriate zones.
- HTTP and/or HTTPS may need to be allowed between appropriate zones.
- Services available on or required by the virtual servers should be available from the appropriate zones.
- DNAT (Destination NAT) may be used to provide access to the DMZ from the Internet (net).
- Policy rules may be used to provide unlimited access from one zone to other zones. (This makes securing access more difficult.)
Configuring DNSMasq
Installing libvirt
will have installed the dnsmasq
binaries. If you haven’t already done so, install the dnsmasq
package to install the init scripts. Install your configuration changes as files in the /etc/dnsmasq.d
directory.
The dhcp-range
option can be used to assign network-ids to the various interfaces. This is done by matching the address of the interface to the address range. Network-ids can then be used to send different DHCP parameters to clients in different address ranges. The following example provides network-ids matching the Shorewall zones.
dhcp-range=loc,192.168.10.200,192.168.5.250,255.255.255.0,192.168.5.255,120h dhcp-range=virt,192.168.11.200,192.168.6.250,255.255.255.0,192.168.6.255,120h dhcp-range=dmz,192.168.32.200,static,255.255.255.0,192.168.32.255,240h
You can then supply zone-specific parameters as in the following example defining DNS networks.
dhcp-option=15,example.com # Default dhcp-option=virt,15,virt.example.com dhcp-o ption=dmz,15,dmz.example.com
Hosts that provide their name should be given the appropriate static address as defined in the /etc/hosts
file. Static addresses can also be defined in the /etc/ethers
file. Enable this file by adding the read-ethers
option to your dnsmasq configuration. The mac address for the virtual servers can be obtained using the virsh dumpxml
command. If the host has a DHCP lease, its mac address will be recorded in /var/lib/misc/dnsmasq.leases
. The /etc/host
s and /etc/ethers
files can be used to document your network.
Review the dnsmasq man page for additional options you may want to set. The /usr/share/doc/dnsmasq/setup.html
file provides good setup information. The documentation set can be found in /usr/share/doc/dnsmasq
or /usr/share/doc/dnsmasq-base
.