Udp port forwarding not working but tcp does

I'm trying to do UDP port forwarding from WAN to LAN using OpenWrt 23.05.3 to no avail. TCP is working as it should.

This is my firewall config:

config redirect
	option target 'DNAT'
	option name 'E11_udp'
	option family 'ipv4'
	option src 'wan'
	option src_ip '212.X.X.X'
	option src_dport '4271'
	option proto 'udp'
	option dest 'lan'
	option dest_ip '192.168.5.143'
	option dest_port '4277'

This is the created fw4 rule:

chain dstnat_wan {                                                                                                     
        ip saddr 212.X.X.X udp dport 4271 counter dnat 192.168.5.143:4277 comment "!fw4: E11_udp"
}

This is the result:

17:36:10.373518 eth0  In  IP 212.X.X.X.4270 > 212.Y.Y.Y.4271: UDP, length 90
17:36:10.373683 eth0  Out IP 212.Y.Y.Y > 212.X.X.X: ICMP 212.Y.Y.Y udp port 4271 unreachable, length 126

If I do exactly the same using tcp, everything works and the SYN packet is forwarded to br-lan instead of ICMP unreachable.

Any ideas?

Are firewall rules in place to allow UDP traffic on that port to the 192.168.5.x network, not just the specific host?

What sort of device is this being forwarded to?
does the host-based firewall of the target allow UDP?

The 192.168.5.x network is the LAN network and I have no specific firewall rules. Everything is by default allowed on LAN:

config zone
	option name 'lan'
	list network 'lan'
	option input 'ACCEPT'
	option output 'ACCEPT'
	option forward 'ACCEPT'

As the output packet never leaves the OpenWrt router it's irrelevant what the target is. It's a Raspberry Pi 5 and it allows UDP. It has a specific listener on the destination port that works locally.

The odd thing is that exactly the same config works for TCP.

This may be a question for @psherman if he is able.

What is the service on the forwarded host (192.168.5.143)? Is it listening on UDP port 4277?

How have you verified this? What is the host's OS?

Hi @pfassberg,

it looks fine from what I can see based on your configuration, both the /etc/config/firewall snippet, as well as the nft rule that it generated.

Some more questions:

  • does the counter in the dstnat rule actually increment if you look at nft list ruleset ?
  • the tcpdump snippet you provided was presumably using -i any so we are sure the ICMP is generated by your OpenWRT router/firewall, and not by the end host?
  • does the behaviour change if you run a local process on the OpenWRT box which binds to udp port 4271? If yes, this would mean that a) your firewall rules permit the port, and b) the DNAT is not actually performed and the packets end up on the local host

Thank you both for your comments.

The OS was Raspberry Os and yes, it was a service listening on that port. I have verified it by sending UDP packets locally from OpenWrt using socat.

No, the dstnat rule did not increment (reject was incremented).

Yes, tcpdump -i any.

I haven't checked with a local process, I will do that.

I have used similar configurations on older versions of OpenWrt without any problems. I will do some more testing.