I have
table ip nat {
chain Redirect_to_local {
limit rate 3/minute burst 10 packets log prefix "[nft.ip.dnat.8080]: "
redirect to :8080
}
chain PREROUTING {
type nat hook prerouting priority dstnat; policy accept;
iifname != { "lo", "ISP*" } fib daddr type != { local, multicast, broadcast } udp dport == 8000 counter jump Redirect_to_local
}
}
and it's incorrect because transport protocol mapping is only valid after transport protocol match
. But why? It DID match, but not directly there.
If I add udp dport == 8000
before redirect it will be accepted as correct, despite duplication of rule (which is annoying).
Is there a way to overcome this? Or did I misunderstand this?
ip protocol udp
(from packet's content) ormeta l4proto udp
(from measured packet's properties. Usually this is automatically implied when writing for exampleudp dport 8000
) is the way to tell it's UDP without specifying again the port. Without this piece of information that is only single-rule-wide, the NAT statement will accept to alter only layer 3 (here: IPv4) and leave alone the layer 4: it would accept to change the address but not the port. Asredirect
is usually meant to change the port (But not required. A single rule line consisting only ofredirect
is valid), then stating the protocol usually has to be done.So you can replace:
with either:
or:
Note: for IPv6, using
meta l4proto udp
is the only correct choice, becauseip6 nexthdr udp
(which would be the equivalent toip protocol udp
) would fail in presence of IPv6 options, since the IPv6 fixed header doesn't provide the final transport header protocol, but only the next header, which could be an option header and thus differ.