This has taken me all day to work out, so I thought I would get this recorded here!
I have a LibVirt host with NAT instead of bridging for the hosted virtual machines, using the default IPTables rules constructed by LibVirt when installed. I could install an OS using a virtual CD, then get full Internet connectivity, but due to the more complex nature of TFTP* for PXE boot, the masquerading wasn't seeming to pass the TFTP replies back to the VMs.
I could see the following packet sequence from various instances of tcpdump:
- VM udp/ephemeral to LibVirt host udp/69 requesting file
- LibVirt host udp/ephemeral to TFTP server udp/69 requesting file
- TFTP server udp/ephemeral2 to LibVirt host udp/ephemeral
At this point nothing further passed and the VM tftp client timed out.
I tried using the kernel modules ip_conntrack_tftp/nf_conntrack_tftp and ip_nat_tftp/nf_nat_tftp, but this didn't help.
* Although the initial request from client to server is on udp/69, the reply from server to client originates from a pseudo-random ephemeral port.
I had the exact same problem as you and ended up finding your post.
On my side, loading the
nf_nat_tftp
on the Libvirt host was enough to make it work. Thanks for this hint!Finally, I found an article about VMWare that had a similar problem and tried switching the type of the network interface in LibVirt from virtio to e1000. Instant success!