3

When I clear IPtables and then add the following rules, incoming connections can connect to my KVM VM on port 1234 without any problems.

-A PREROUTING -i br0 -p tcp -m tcp --dport 1234 -j DNAT --to-destination 192.168.122.194:1234
-A FORWARD -d 192.168.122.194/32 -p tcp -m state --state NEW,RELATED,ESTABLISHED -m tcp --dport 1234 -j ACCEPT
-A FORWARD -s 192.168.122.194/32 -p tcp -m tcp --sport 1234 -j ACCEPT
-A FORWARD -d 192.168.122.194/32 -p tcp -m tcp --dport 1234 -j ACCEPT

But I also want NAT to work inside my KVM VM's. By default libvirt sets up some rules that provide my VM's with NAT. However when I try sending SIGHUP to libvirt (that's how you ask it to add it's rules to iptables), it adds the following rules to iptables that breaks my port forwarding that I have specified above.

-A FORWARD -d 192.168.122.0/24 -o virbr0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -s 192.168.122.0/24 -i virbr0 -j ACCEPT
-A FORWARD -i virbr0 -o virbr0 -j ACCEPT
-A FORWARD -o virbr0 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -i virbr0 -j REJECT --reject-with icmp-port-unreachable
-A OUTPUT -o virbr0 -p udp -m udp --dport 68 -j ACCEPT

-A POSTROUTING -s 192.168.122.0/24 -d 224.0.0.0/24 -j RETURN
-A POSTROUTING -s 192.168.122.0/24 -d 255.255.255.255/32 -j RETURN
-A POSTROUTING -s 192.168.122.0/24 ! -d 192.168.122.0/24 -p tcp -j MASQUERADE --to-ports 1024-65535
-A POSTROUTING -s 192.168.122.0/24 ! -d 192.168.122.0/24 -p udp -j MASQUERADE --to-ports 1024-65535
-A POSTROUTING -s 192.168.122.0/24 ! -d 192.168.122.0/24 -j MASQUERADE

I've tried running these commands manually. I can run all of the FORWARD and OUTPUT commands and they do not break my port forwarding. However I can't run any of the POSTROUTING commands manually. I get an error saying: "No chain/target/match by that name."

*These libvirt iptables rules in the last grey section above were obtained by running iptables-save and confirming port forwarding was working, then sending SIGHUP to libvirt, confirming port forwarding was broken, then running iptables-save again and running a diff on the two outputs to find which new iptables rules were added by libvirt.

user1862165
  • 119
  • 1
  • 8

1 Answers1

1

I just enabled NAT with my own rules. I didn't bother with any of the default libvirt rules.

Adding NAT is as simple as 3 iptables commands. (where br0 is your internet facing adapter (it could be ppp0 or whatever))

iptables -t nat -A POSTROUTING -o br0 -j MASQUERADE
iptables -A FORWARD -i br0 -o virbr0 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i virbr0 -o br0 -j ACCEPT
user1862165
  • 119
  • 1
  • 8
  • 2
    Once again I've learned not to bother using StackOverflow or it's sister sites. So many unkind people on big ego-trips with their empty points looking to abuse people. My question got downvoted 4 points, no comments or answers. Once again, as always I've solved my problem myself. All I get out of StackOverflow is abuse. It's pathetic. I'm posting this answer here for the benefit of others. I'm not going to post any more questions here. Bye StackOverflow. – user1862165 Jun 05 '15 at 12:59
  • The problem with your solution is, that libvirt/KVM/qemu often (if not always) destroys iptables as soon it does something. I did not find any way to prevent libvirt/KVM/qemu from changing rules. Also the manual on libvirt.org is completely incomprehensible. Things which are easy and well known for ages seem to become complex tasks, involving editing of XML with arbitrary semantics, with no documentation whatsoever. My solution is a script, which checks iptables each minute and does `iptables-restore` if needed, based on a calculated connection matrix for all local and remote VMs. – Tino Sep 25 '16 at 14:04