iptables and TFTP HOWTO

Reminder to self on iptables and TFTP HOWTO.


iptables on a TFTP server:

iptables -I INPUT -j ACCEPT -p udp -m udp --dport 69

iptables on a TFTP client:

## nf_conntrack_helper = 0 is the default nowadays
## you need CT target for helpers to work
echo 0 > /proc/sys/net/netfilter/nf_conntrack_helper
modprobe nf_conntrack_tftp
iptables -t raw -I OUTPUT -j CT -p udp -m udp --dport 69 --helper tftp

iptables on NAT/router between TFTP client and server; optionally, iptables does NAT for client:

modprobe nf_nat_tftp
iptables -t raw -I PREROUTING -j CT -p udp -m udp --dport 69 --helper tftp

More verbose…

iptables on TFTP server

Exemplary INPUT chain on RHEL 7:

Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
166M 192G ACCEPT all -- * * ctstate RELATED,ESTABLISHED
765K 46M ACCEPT all -- lo *
33M 1962M INPUT_direct all -- * *
33M 1962M INPUT_ZONES_SOURCE all -- * *
33M 1962M INPUT_ZONES all -- * *
288 22872 ACCEPT icmp -- * *
47541 6359K REJECT all -- * * reject-with icmp-host-prohibited

Enable tftp server:
firewall-cmd --zone=$INZONE --enable-service tftp
## OR
## iptables -I INPUT 2 -j ACCEPT -p udp -m udp --dport 69


iptables --list -n -v
## in firewalld this ends up in IN_$INZONE_allow chain
Chain IN_$INZONE_allow (1 references)
pkts bytes target prot opt in out source destination
240 14341 ACCEPT udp -- * * udp dpt:69 ctstate NEW

iptables on TFTP client

Exemplary -t raw OUTPUT chain on RHEL 7:

iptables -t raw --list OUTPUT -n -v
Chain OUTPUT (policy ACCEPT 14196 packets, 1824K bytes)
pkts bytes target prot opt in out source destination
112K 5213K OUTPUT_direct all -- * *

Enable TFTP:

firewall-cmd --direct --add-rule ipv4 raw OUTPUT 0 -j CT -p udp -m udp --dport 69 --helper tftp
## OR
## iptables -t raw -I OUTPUT -j CT -p udp -m udp --dport 69 --helper tftp


## firewalld
# iptables -t raw --list OUTPUT_direct -n -v
Chain OUTPUT_direct (1 references)
pkts bytes target prot opt in out source destination
6 357 CT udp -- * * udp dpt:69 CT helper tftp

# perform a TFTP transaction to view connection/expectation
# is the client; is the server
# conntrack -L | grep ^udp.*
conntrack v1.4.3 (conntrack-tools): 24 flow entries have been shown.

## this is the expectation, setup by tftp helper
udp 17 27 src= dst= sport=43709 dport=47512 src= dst= sport=47512 dport=43709 mark=0 secctx=system_u:object_r:unlabeled_t:s0 use=2

## this is the connection
udp 17 27 src= dst= sport=47512 dport=69 [UNREPLIED] src= dst= sport=69 dport=47512 mark=0 secctx=system_u:object_r:unlabeled_t:s0 helper=tftp use=2

iptables on NAT/router between TFTP client and server

  • Server:
  • NAT/router: ##configure iptables here
  • Client:

Exemplary -t raw PREROUTING chain in RHEL 7:

# iptables -t raw --list PREROUTING -n -v
Chain PREROUTING (policy ACCEPT 17541 packets, 19M bytes)
pkts bytes target prot opt in out source destination
477K 176M PREROUTING_direct all -- * *
477K 176M PREROUTING_ZONES all -- * *

Enable TFTP:

## we assume there are already rules for FORWARD/MASQUERADE
firewall-cmd --zone=internal --enable-service tftp-client
## OR
## iptables -t raw -I PREROUTING -j CT -p udp -m udp --dport 69 --helper tftp


# firewalld: the client is on the internal zone
# iptables -t raw --list PRE_internal_allow -n -v
Chain PRE_internal_allow (1 references)
pkts bytes target prot opt in out source destination
0 0 CT udp -- * * udp dpt:69 CT helper tftp

## perform a TFTP transaction...then
# conntrack -L | grep ^udp.*
conntrack v1.4.3 (conntrack-tools): 21 flow entries have been shown.
## this is the connection through the NAT+router
udp 17 27 src= dst= sport=52718 dport=69 [UNREPLIED] src= dst= sport=69 dport=52718 mark=0 secctx=system_u:object_r:unlabeled_t:s0 helper=tftp use=2
## this is the expectation setup by tftp helper
udp 17 27 src= dst= sport=59356 dport=52718 src= dst= sport=52718 dport=59356 mark=0 secctx=system_u:object_r:unlabeled_t:s0 use=1

  • Expectations are installed in the reverse direction from the connection (that caused them)
  • TFTP Expectation dport = TFTP Connection sport
  • Recall that in TFTP the server makes a new connection from a random source port to the client port that was used to start the session to the server (69/udp)

Fedora 19 and GRUB2

Fedora 19 has removed box characters from the GRUB2 menu. This caught me by surprise and I thought it was a bug.

The release notes mentioned something about better GRUB2 visual integration but it was too vague.


I decided to do some more testing this time with upstream GRUB2.

GRUB2 UEFI PXE booting works too: unlike Fedora-GRUB2. GRUB2 only looks for grub.cfg in $prefix; it does not seem to look at the directory where core.efi is located. Standard GRUB2 does not do name mangling while looking for the configuration file. It is a purer implementation, but may not be so useful for Cobbler-like provisioning.

Standard GRUB2 also sets a whole slew of variables just like in i386-pc; when I looked at this more than a year ago the network stuff was quite broken: couldn’t get efinet tftp to work. It is great to see what progress has been made. Kudos to the GNU GRUB2 team!

## GRUB2 UEFI PXE environment; BUG ALERT: Fedora 19-GRUB2 leaves some of these blank

net_efinet1_boot_file=BOOTX64.efi (actually copied from $prefix/x86_64-efi/core.efi)


GRUB2 UEFI & PXE — Cobbler ready!

Note: my experience with GRUB2 is the heavily hacked version from Fedora 19. I don’t think upstream behaves this way (TODO testing on upstream).

GRUB2 on UEFI/PXE seems to have matured enough that it might be usable in Cobbler to replace grub-legacy. It has network support now and it searches for its grub.cfg in creative ways from the TFTP server by using name-mangling just like PXELINUX and grub-legacy (UEFI/PXE)

Recap: PXELINUX boot will try to find its config by constructing  a filename from the mac address, IP address-digit-striping. E.g.,01-88-99-aa-bb-cc-dd  C000025B C000025

Cobbler makes use of this for per-system installation configs. For UEFI/PXE systems: grub-legacy 0.97 that comes with Red Hat-like systems emulates PXELINUX behaviour. When grub-legacy is booted using UEFI/PXE it will reach back to the TFTP server and pull its config with filenames constructed from  UUID, mac address, IP address-digit-striping.

Unfortunately, grub-legacy UEFI/PXE + RHEL6.x installer gives me problems on Dell PowerEdge servers. On some boots I cannot get console graphics, as if the UEFI-GOP is not initialised correctly.  The installer works because I am able to use the serial console and anaconda over vnc. I have hit this on M910, R715 and a whole assortment of PowerEdge servers. The funny thing is that when the installation completes, I have no problems booting the system with grub-legacy and seeing the Linux penguin icons at the top of the boot messages. Perhaps the installer initialises the video in a more conservative fashion.

E.g., CentOS 6.4 installer ISO on UEFI — no console during installation but serial console and vnc both work.

I was hoping to move to GRUB2 as I have had it boot the OS installer (RHEL6.x type)  without fail on Dell PowerEdge in UEFI mode. Dell’s own OpenManage Deployment Toolkit v4.3 (Linux) has also switched to GRUB2; it touts UEFI-support and I’m guessing the move to GRUB2 is due to the rather fragile grub-legacy/UEFI behaviour.

However GRUB2/UEFI/PXE as a Cobbler grub-legacy replacement component depends on a working PXE stack and config file search algorithm. That day has arrived!

Prepared a PXE/UEFI-aware GRUB2 image (from Fedora 19) using:

grub2-mkstandalone –net-directory /var/lib/tftpboot  –subdir grub2-efi

The resulting core.efi bootloader has efinet, tftp and other essential network modules loaded; the variables root and prefix are set correctly so that grub2 can find its modules and config file. In fact, before loading the config file, the bootloader immediately reaches back to the TFTP server and pulls some modules.

Here is the full list of files that GRUB2/UEFI/PXE pulled down. You can see the search algorithm.

BOOTX64.efi <– copied /grub2-efi/x86_64-efi/core.efi here


Now to see when Cobbler incorporates this as an alternate bootloader.

One weirdness of Fedora 19-GRUB2 is that some variables don’t seem to be populated. Bug, much?


Hmmmm…… why all the blank variables? Shouldn’t they be copied from net_efinet1_XX? The missing *_server variables look fishy. P.S. Further testing show that upstream GRUB2 fills in all the aforementioned vars.

Fedora 19 Fixes for VM behaviour

Fedora 19 had problems as VM host for my Windows 7 64-bit guest: two kernel oops that I encountered:

These bugs caused oops’ing when the guest shuts down or uses the network, in a certain way, e.g, CIFS.

A recent kernel update 3.10.3-300.fc19.x86_64 has fixed this.

Kudos to the Fedora kernel team and now to test Windows guests properly.

Singapore DVB-T

LinuxTV: this stuff is all working on a noname DVB-T stick with RTL2832U and R820T tuner.
For Fedora kernels you have to use the LinuxTV media_build backport drivers to support the R820T tuner

usb 2-1.6: dvb_usb_v2: found a 'Realtek RTL2832U reference design' in warm state
usbcore: registered new interface driver dvb_usb_rtl28xxu
usb 2-1.6: dvb_usb_v2: will pass the complete MPEG2 transport stream to the software demuxer
DVB: registering new adapter (Realtek RTL2832U reference design)
usb 2-1.6: DVB: registering adapter 0 frontend 0 (Realtek RTL2832 (DVB-T))...
r820t 9-001a: creating new instance
r820t 9-001a: Rafael Micro r820t successfully identified
Registered IR keymap rc-empty
input: Realtek RTL2832U reference design as /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.6/rc/rc1/input20
rc1: Realtek RTL2832U reference design as /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.6/rc/rc1
input: MCE IR Keyboard/Mouse (dvb_usb_rtl28xxu) as /devices/virtual/input/input21
rc rc1: lirc_dev: driver ir-lirc-codec (dvb_usb_rtl28xxu) registered at minor = 0
usb 2-1.6: dvb_usb_v2: schedule remote query interval to 400 msecs
usb 2-1.6: dvb_usb_v2: 'Realtek RTL2832U reference design' successfully initialized and connected

This will be history when Singapore switches to DVB-T2 at the end of 2013.

But for the record…

    For services at 610MHz:

  • Digital 8
  • Digital 5
  • Digital CNA
  • MediaCorp HD5

The ‘MediaCorp HD5’ service uses H.264 AVC and this is misidentified by mplayer as a MPEG2TS. Found a workaround here: https://bbs.archlinux.org/viewtopic.php?id=159744
mplayer dvb://'MediaCorp HD5' -demuxer lavf

There is reference to an old channel at 538MHz, but this is unused now.

Initial DVB-T scan file:

# T freq bw fec_hi fec_lo mod transmission-mode guard-interval hierarchy
T 610000000 8MHz 2/3 NONE QAM64 8k 1/8 NONE

    Attached (as PDF) are an scandvb initial scan file and tzap channels file. The tzap file works with mplayer & vlc:

  • sg-MediaCorp (initial scan file)
  • channels (tzap file, suitable for mplayer,vlc etc)

Stable Windows 7 Pro in KVM: virtio & qxl drivers

Update: 2013-08-14. Latest Fedora drivers virtio-win-0.1-65 brings all drivers up to 6/19/2013

Update: 2013-07-22. Finally got round to testing spice-guest-tools-0.59.exe on Windows XP 32-bits. The “signedness” of QXL is moot as anything goes here.

QXL — dated 10/15/2012

VirtIO — dated 4/17/2013

Everything is working including audio/Spice. Strange, I don’t seem to have balloon here.

Update: 2013-07-22. RedHat has virtio-win-1.6.5-6.el6_4 on RHN.

Update: 2013-06-18. The “KVM — The Linux Kernel-Based Virtual Machine” site links to current verions of qemu, Fedora virtio iso, and Spice guest tools.


Update: 2013-05-11. I am now running with all Fedora virtio drivers v on two Win7 Pro guests. Fingers-crossed — they are running stable. One is using standard VGA and the other is using the signed RedHat QXL GPU driver from virtio-win-1.6.3-3.

I have Spice (instead of VNC) running in the guests for audio; sound from Win7Pro guest — what’s not to like!

In short:

  • host is KVM/Fedora 18
  • guest drivers: virtio from Fedora for Serial, Storage, Net, Balloon
  • guest drivers: qxl from RedHat for Display
  • vdservice.exe and vdagent.exe running from spice-guest-tools
  • audio is working using Spice

Previously: I was having a really hard time getting Windows 7 Pro, Windows Server 2008R2  KVM guests stable using virtio and qxl drivers.


  1. Drivers everywhere: Spice guest tools: http://spice-space.org/download/binaries/spice-guest-tools/.  Very obscure set of tools. Comes with lots of virtio drivers. Encountered problem with unsigned QXL drivers. When you install this you must manually stop the vdservice service, otherwise the files are locked.
  2. Fedora alternative http://alt.fedoraproject.org/pub/alt/virtio-win/. Very recent versions as of 4/17/2013: but no QXL.
  3. RedHat virtio-win-1.6.3-3.el6.noarch. The RedHat package has versions equal or slightly older than Fedora alternative. The QXL drivers are not in the ISO image but unpacked to /usr/share/virtio BUT the QXL driver is signed.

However, things seem to be coming together, albeit slowly:

  1. Windows 7 Pro guest is now stable with all the RedHat drivers.
  2. Windows 2008 R2 Standard KVM guest is stable with all drivers and QXL.
  3. The signed Red Hat QXL GPU driver that works is: version 10/15/2012

By stable I mean: in Windows Device Manager none of the devices has the dreaded exclamation icon and the VM does not randomly reboot or BSOD.

Now to tackle Windows 2012 server guests!!!!!!

FIXME: Update vdagent.exe/vdservice.exe to latest from Spice Guest tools 0.52 — DONE!

FIXME: I have qemu-ga: QEMU guest agent running; no idea how crucial this is to life and limb: http://wiki.libvirt.org/page/Qemu_guest_agent

FIXME: can one get sound using VNC?

Generally, RedHat have done well with the 1.6.3 release!!

Take away: KVM virtio drivers are not easy to find. The best sources are Fedora alternative (everything but QXL), and RedHat RHEL 6 Supplementary Channel ($$$$) with signed QXL . The jury is out on spice-guest-tools.