Solved Gateway, NAT (PAT). Cannot use external TFTP due to UDP port "unreachable"

Hi there,

I am trying to solve a problem with my gateway setup.
My FreeBSD machine is basically a gateway RaspberryPI which has two NIC: ue0 (Connected to external network, let's call it Internet) and ue1 (is an interface for internal LAN, dhcpd and dnsmasq spinning on it).

My current setup is using ipfw and nat in order to gain internet access for the lan clients, however, when I am trying to reach TFTP (10.1.1.33) server on external network from any of the clients, I can see that request is passing through, however, when the server replying to the client, the gateway (12.1.1.15) seems to be dropping the packets and replying that the port is unreachable.

Code:
IP 10.1.1.33.49137 > 12.1.1.15.44798: UDP, length 516
IP 12.1.1.15 > 10.1.1.33: ICMP 12.1.1.15 udp port 44798 unreachable, length 552

So it seems to me that I am missing some sort of simple keep-state rule that I am too ignorant in firewalls to realize.
Code:
WAN=ue0
ADD='ipfw add'
ipfw -q flush
ipfw nat 1 config if $WAN
$ADD 00010 allow ip from any to any via ue1
$ADD 00020 allow ip from any to any via lo0

$ADD 00100 nat 1 log ip from any to any in via $WAN in
$ADD 00105 check-state
$ADD 00110 skipto 1000 tcp from any to any in via $WAN setup keep-state
$ADD 00111 skipto 1000 udp from any to any in via $WAN keep-state
$ADD 00114 skipto 1000 tcp from any to any out via $WAN setup keep-state
$ADD 00115 skipto 1000 udp from any to any out via $WAN keep-state
$ADD 00900 allow tcp from any to me via $WAN in setup keep-state
$ADD 01000 nat 1 ip from any to any via $WAN out
$ADD 65000 pass all from any to any
net.inet.ip.fw.one_pass=0

What am I missing?

Thank you in advance
 
tftp server negotiate on port 69 with the client then send a random upper port for data transfer similar as active mode in ftp so when the server reply on this random upper port your firewall doesn't allows it because it doesn't know what the client and server negotiate. Your option is to allow all udp ports from the server ip to any inside ip addresses or find some tftp proxy (if any) to punch the hole in your firewall for returning data traffic.

Edit:
there's tftp proxy but it's for pf firewall not ipfw.

Edit2:
on a second thought it won't work because your NAT will not have the translation for the data traffic even if you allow all udp incoming traffic. Your best option is to switch to pf.
 
tftp server negotiate on port 69 with the client then send a random upper port for data transfer similar as active mode in ftp so when the server reply on this random upper port your firewall doesn't allows it because it doesn't know what the client and server negotiate. Your option is to allow all udp ports from the server ip to any inside ip addresses or find some tftp proxy (if any) to punch the hole in your firewall for returning data traffic.
The server IP is static so I guess I can add a udp rule to allow any traffic from it

so basically something like this?
Code:
$ADD 00120 allow udp from 10.1.1.33 to any via $WAN

Upd: oh man, so there is no other way except setting up tftp proxy? I was thinking that it should be possible and I just don’t know exactly how. Regular routers have no problems passing the traffic like this. Or is this just a problem with ipfw particularly?
 
The regular cisco router have protocol inspection which monitor (sniff) the traffic inside the handshake on tftp port 69 looking for read/write request (rrq, wrq) and errors then it creates a dynamic port address translation (PAT) for the data returning traffic which allow the communication to continue to the client behind the router. It's similar as the tftp-proxy which redirect and establish all request to the router itself. So even if you allow all incoming traffic from the tftp server ip address to the router the router will not know to which client ip address to forward it inside on the LAN as there will be no PAT record.
There's other similar protocols where the negotiation/handshake is happen on standard port and then the data traffic is switched to different high port. Such example are the SIP, rtsp protocols.
 
The regular cisco router have protocol inspection which monitor (sniff) the traffic inside the handshake on tftp port 69 looking for read/write request (rrq, wrq) and errors then it creates a dynamic port address translation (PAT) for the data returning traffic which allow the communication to continue to the client behind the router. It's similar as the tftp-proxy which redirect and establish all request to the router itself. So even if you allow all incoming traffic from the tftp server ip address to the router the router will not know to which client ip address to forward it inside on the LAN as there will be no PAT record.
There's other similar protocols where the negotiation/handshake is happen on standard port and then the data traffic is switched to different high port. Such example are the SIP, rtsp protocols.
Thank you, that is very helpful! I guess I have to switch to pf in this case. Will mark it as solved.

unfortunately libalias has no module for tftp but you may create one
see libalias(3)
I wish I was anywhere close in my knowledge to be able to do that. I will look at it anyway, good way to learn is to first break something, haha
 
Back
Top