TC-NAT(8)

๐Ÿ“ฆ
version 7.3.0 ยท 2 versions
  • 7.3.0 ยท alpine 3.22, alpine 3.23, alpine 3.24, arch rolling, centos-stream 10, centos-stream 9, debian bookworm, debian trixie, fedora 43, fedora 44, nixos 26.05, nixpkgs unstable, opensuse-leap 16.0, ubuntu noble, ubuntu questing, ubuntu resolute, ubuntu stonking (latest)
  • 5.15.0 ยท ubuntu jammy
, in alpine 3.22, alpine 3.23, alpine 3.24, arch rolling, centos-stream 10, centos-stream 9, debian bookworm, debian trixie, fedora 43, fedora 44, nixos 26.05, nixpkgs unstable, opensuse-leap 16.0, ubuntu noble, ubuntu questing, ubuntu resolute, ubuntu stonking

๐Ÿ’– NAT action in tc(8) ๐Ÿ’–

Okay bestie, this is the page for the nat action in tc(8). Its whole name is nat - stateless native address translation action ๐Ÿฆ‹ It's the NAT action that goes in tc, and it's stateless, which means it doesn't keep track of connections.

โœจ NAME โœจ

nat - stateless native address translation action ๐ŸŽ€

๐ŸŒธ SYNOPSIS ๐ŸŒธ

tc ... action nat DIRECTION OLD NEW

DIRECTION := { ingress | egress }

OLD := IPV4_ADDR_SPEC

NEW := IPV4_ADDR_SPEC

IPV4_ADDR_SPEC := { default | any | all | in_addr[/{prefix|netmask}]

๐Ÿงš DESCRIPTION ๐Ÿงš

Okay so the nat action lets you do NAT without the overhead of conntrack ๐Ÿ™ˆ That's super useful when you've got a huge number of flows or addresses to translate, bestie. Like, it's giving efficiency. ๐Ÿ’… It works best when you pair it with the u32 filter, because then you can look up a big pile of stateless NAT rules in constant time. Iconic. ๐Ÿ”ฅ

๐Ÿ“ OPTIONS ๐Ÿ“

  • ingress โ€” Translates destination addresses, aka DNAT ๐Ÿ’œ
  • egress โ€” Translates source addresses, aka SNAT โœจ
  • OLD โ€” Says which addresses should get translated ๐ŸŒˆ
  • NEW โ€” Says which addresses OLD should be translated into ๐Ÿฆ‹

๐Ÿ’… NOTES ๐Ÿ’…

The address format for OLD and NEW is seriously flexible, no cap ๐Ÿซถ You can use one of the keywords default, any or all, which all mean the all-zero IP address. Or you can do an IP address plus a netmask or prefix length, separated by a slash (/). Either way, the mask (or prefix length) from OLD gets used for NEW too, so you always get a one-to-one mapping of addresses. Periodt. ๐Ÿ’–

Address translation is done with a combo of binary operations ๐Ÿง  First, the original address (source or destination) gets matched against OLD. If it fits, the new address is built by taking the leading bits from NEW (defined by the netmask of OLD) and taking the remaining bits from the original address. It's giving math magic. โœจ

Heads up: there's only rudimental support for upper layer protocols, namely TCP, UDP and ICMP ๐Ÿ˜ญ For TCP and UDP, the action only recalculates the checksum. For ICMP, it also takes care of embedded IP headers inside ICMP packets and translates the addresses in there too. ๐Ÿ™ˆ

๐Ÿฆ‹ SEE ALSO ๐Ÿฆ‹

tc(8) ๐Ÿ’œ


Bye bestie, that's the whole page! ๐Ÿซถ This one's from the iproute2 package, dated 12 Jan 2015, and it's filed under NAT action in tc(8) ๐Ÿ’–โœจ

๐Ÿ“ฆ where this page comes from