This issue has been brought up a few times, but I haven't found any real
solution yet. The problem is with the way libvirt adds iptables rules.
I have a KVM Host with 1 public IP address, on which a few virtual
machines run. I want to be able to direct certain ports on the public IP
to certain virtual machine's internal IP.
For example:
allow conneciton to 'public-ip' tcp port: 80 to 'vm1'
Which is possible using following rules:
$ iptables -I FORWARD 1 -d vm1 -p tcp --dport 80 -j ACCEPT
$ iptables -t nat -A PREROUTING -p tcp -d public-ip --dport 80 -j DNAT
--to-destination vm1
However the problem is that libvirt _always_ adds it's rules to the top
of the FORWARD rules, hence it blocks any 'custom' rules to the VM machines.
ie.
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source
destination
39 2964 ACCEPT all -- * virbr0 0.0.0.0/0
192.168.122.0/24 state RELATED,ESTABLISHED
39 2964 ACCEPT all -- virbr0 * 192.168.122.0/24
0.0.0.0/0
2 656 ACCEPT all -- virbr0 virbr0 0.0.0.0/0
0.0.0.0/0
2 120 REJECT all -- * virbr0 0.0.0.0/0
0.0.0.0/0 reject-with icmp-port-unreachable
0 0 REJECT all -- virbr0 * 0.0.0.0/0
0.0.0.0/0 reject-with icmp-port-unreachable
Only established connections are allowed with the libvirt rules, hence
the forwarded connection to port 80 will be rejected by the 4th libvirt
rule.
The only way to make it work is to insert the rule _after_ libvirt has
started the network.. and if the libvirt network ever gets restarted,
the rule will be disabled since libvirt inserts it's rules at the top of
the chain.
Is there a proper way to achieve this with libvirt ?!