Libvirt Forwarding
13 Aug 2016The KVM virtual machine could be managed by libvirt. If the virtual network is set to NAT, the virtual machine could not be accessed from outside the host. Incoming connections to the VM are only allowd from host and other virtual machines on this host.
If you would like to provide services (like ssh or http) from the VM,
port forwarding could be setup with iptables on the host.
This article takes libvirt network wiki as reference.
Disable firewalld
There are conflicts between firewalld and libvirtd on CentOS 7.
firewalld must be disabled first.
$ sudo systemctl stop firewalld.service
$ sudo systemctl disable firewalld.serviceAllow ip forward
Add option to /etc/sysctl.conf to allow ip forward:
net.ipv4.ip_forward = 1It will not take effect until reboot. Use sysctl command
to make it take effect immediately.
$ sudo sysctl -piptables forwarding rules
What we need now is to forward the traffic from HOST_IP on HOST_PORT
to specified virtual machine’s GUEST_IP:GUEST_PORT.
Run the following iptables commands on host:
$ sudo iptables -I FORWARD -o virbr0 -d $GUEST_IP --dport $GUEST_PORT -j ACCEPT
$ sudo iptables -t nat -I PREROUTING -p tcp --dport $HOST_PORT -j DNAT --to $GUEST_IP:$GUEST_PORTThen the virtual machine could be connected from HOST_IP:HOST_PORT.
Using these commands is not very convenient, especially when there are a lot of VMs and ports.
Automation with hook script
When VMs are started by virsh start or shutdown, the hook script
/etc/libvirt/hooks/qemu will run automatically. We could use
this script to add and delete the rules of iptables.
In order to simplify the configuration of port forwarding, I wrote libvirt-forward. It works well on CentOS 6/7.
This program supports json and yaml configuration. In case you
are going to use yaml, please install PyYAML first:
$ sudo yum install PyYAMLCopy qemu-hook to /etc/libvirt/hooks directory and create symbolic
link:
$ sudo cp libvirt-forward/qemu-hook /etc/libvirt/hooks/qemu-hook
$ sudo ln -s qemu-hook qemuCreate configuration directory:
$ sudo mkdir -p /etc/libvirt/hooks/config
$ sudo cp libvirt-forward/config/config.yaml.example /etc/libvirt/hooks/config/config.yamlEdit config.yaml:
public_ip: 222.222.222.222
local_range: 192.168.122.0/24
domain:
MySQL:
private_ip: 192.168.122.20
local_range: 192.168.122.0/25
port_map:
tcp:
- [10022, 22]
- 3306
Apache:
private_ip: 192.168.122.30
port_map:
tcp:
- [20022, 22]
- 80
- 443public_ip is the ip address of host.
The forward rules for each VM are configured under domain.
The domain name must be the same as the libvirt VM name,
which could be found by virsh list --all.
private_ip is the ip address of VM.
port_map includes the list of ports to be forwarded.
If the port number is the same for both the host and guest,
only one number is needed, or specify [HOST_PORT, GUEST_PORT].
After the modification of configuration,
please shutdown the VM, and use virsh start VMNAME to start the VM,
then the rules are automatically added.
After shutdown the VM, these rules will be deleted.