I have a TFTP server (Machine & # 39; S & # 39;) and a TFTP client (Machine & # 39; C & # 39; C & # 39; C) in different subnets. They are connected through a router (Machine & # 39; R & # 39;). The 3 machines are Debian 9 / Stretch. The router is running iptables and is configured to mask connections from the client's network to the server's network. I have configured iptables to use the TFTP helper from Netfilter for the tftp connections that go to the TFTP server.
The problem I have is that the TFTP helper sets an expectation for the return tftp connection (as expected) but specifies
sport = 69 from the server. This is not how the TFTP communication is supposed to work in accordance with RFC1350. The server must choose a port of random origin for its communication and direct it to the port that the client originally used as a source port (although …).
The result is that the NAT router connects from the client to the server, establishes a translation rule for the return connection, and happily waits for a return packet from the server with the source port = 69 that never arrives.
The directions are made for clarity:
Iptables in the router have the following rules. All tables have a default ACCEPT policy:
======== RAW Table ======== PREROUTING of the chain (policy ACCEPT 464K packets, 432M bytes) pkts bytes target prot choose in the destination of origin 59 2504 CT udp - * * 0.0.0.0/0 0.0.0.0/0 udp dpt: 69 CT helper tftp DEPART chain (policy ACCEPTS 280K packs, 36M bytes) pkts bytes target prot choose in the destination of origin ======== NAT table ======== POSTROUTING string (ACCEPT policy 398 packets, 40794 bytes) pkts bytes target prot choose in the destination of origin 5678 349K MASQUERADE all - * enp1s0 0.0.0.0/0 0.0.0.0/0
Once the TFTP client is trying to connect,
conntrack -L shows the following:
udp 17 28 src = 18.104.22.168 dst = 22.214.171.124 sport = 45084 dport = 69 [UNREPLIED] src = 126.96.36.199 dst = 188.8.131.52 sport = 69 dport = 45084 mark = 0 helper = tftp use = 1
conntrack -L WAIT:
298 proto = 17 src = 184.108.40.206 dst = 220.127.116.11 sport = 0 dport = 45084 mask-src = 255.255.255.255 mask-dst = 255.255.255.255 sport = 0 dport = 65535 master-src = 18.104.22.168 master-dst = 22.214.171.124 sport = 45084 dport = 69 class = 0 helper = tftp
As you can see, the TFTP help rule works correctly and is activated once the client tries to connect. As you can also see, the expectation created in the EXPECT table has the port of origin 0, which I suppose means "any port". But, as you will see, the connection is only routed back to the client if the port of origin of the server is port 69! Why is this? This is not the correct behavior for what I can say.
I will not mess up this publication if I can avoid it, but what is shown in
tcpdump udp and host 126.96.36.199 confirm exactly what iptables and conntrack are showing me.
I run a netcat listener on the TFTP server on port 69 with
nc -l -u -p 69 and then I connect to it from the TFTP client with
nc -u 188.8.131.52 69. Once I send some data from the client to the server, the TFTP assistant configures an expectation, just as before. However, when I send some data from the server, that's it! the
[UNREPLIED] It disappears from the entry of the connection table and the client receives the data I sent. The connection is working correctly. I am sure that if I go a little further, I can even imitate the full TFTP transaction using
The traffic looks like:
08: 19: 28.285749 IP 184.108.40.206.60704> 220.127.116.11.tftp: 10 tftp- # 25967 08: 19: 31.676846 IP 18.104.22.168.tftp> 22.214.171.124.60704: 2 tftp- # 25610
I made this same configuration in various Debian 8 / Jessie configurations about a year ago and the TFTP helper worked as expected and I never had any problems. Can someone help me find out if I'm doing something wrong? Is it the problem with the TFTP helper? Why would he have changed his Debian 8 / Jessie behavior?