6

Is it possible to have an nftables map which maps port to ipv4_addr:port, where port and ipv4_addr:port have different TCP port numbers? For example, I want to dnat all incoming packets on port 80 to a container running a web server on port 8080 (purely with nftables). This is possible using two maps and two map lookups, as below:

table ip dnatTable {
  chain dnatChain {
    type nat hook prerouting priority dstnat; policy accept;
    dnat to tcp dport map { 80 : 172.17.0.3 }:tcp dport map { 80 : 8080 }
  }
}

However, I was wondering if it is possible with only a single map lookup?

Thanks

1 Answer 1

4

As usual nftables is a moving target. This feature appeared in nftables 0.9.4 released on 2020-04-01:

  • NAT mappings with concatenations. This allows you to specify the address and port to be used in the NAT mangling from maps, eg.

    nft add rule ip nat pre dnat ip addr . port to ip saddr map { 1.1.1.1 : 2.2.2.2 . 30 }
    

    You can also use this new feature with named sets:

    nft add map ip nat destinations { type ipv4_addr . inet_service : ipv4_addr . inet_service \; }
    nft add rule ip nat pre dnat ip addr . port to ip saddr . tcp dport map @destinations
    

So in OP's case that would be:

nft add ip dnatTable dnatChain 'dnat ip addr . port to tcp dport map { 80 : 172.17.0.3 . 8080 }'

Just for information, nftables 1.0.0 released on 2021-08-19 has a simplified syntax:

  • Simplify syntax for NAT mappings. You can specify an IP range:

[...]

Or a specific IP and port.

... dnat to ip saddr map { 10.141.11.4 : 192.168.2.3 . 80 }

So OP's case can then be shortened to (and previous rule will be displayed as):

nft add ip dnatTable dnatChain 'dnat to tcp dport map { 80 : 172.17.0.3 . 8080 }'

Using a named map can help to separate rules from data. This would work too instead (using 0.9.4 syntax):

nft add map ip dnatTable portToIpPort '{ type inet_service : ipv4_addr . inet_service ; }'
nft add rule ip dnatTable dnatChain dnat ip addr . port to tcp dport map @portToIpPort

and then at any convenient time:

nft add element ip dnatTable portToIpPort '{ 80 : 172.17.0.3 . 8080 }'
3
  • Just to make sure, what is the exact syntax for the simplified command? It says dnat to ip saddr map { 10.141.11.4 : 192.168.2.3 . 80 }. Does that mean it maps the source IP to the combination of daddr:dport? So if I wanted to map dports to the same thing I'd have to replace ip saddr with tcp dport and adjust the map accodringly?
    – Lithimlin
    Commented Oct 8, 2021 at 10:54
  • @Lithimlin Use the complete syntax version: i your nftables version supports it, it will display back the simplified version. The kernel side receives exactly the same in both cases.
    – A.B
    Commented Oct 8, 2021 at 11:34
  • @Lithimlin Beside what you want to do was exactly what OP wanted to do: it's in the answer already.
    – A.B
    Commented Oct 8, 2021 at 11:56

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .