Maps: Difference between revisions

From nftables wiki
Jump to navigation Jump to search
(add link to sets)
(Use "snat to" and "dnat to".)
 
(3 intermediate revisions by the same user not shown)
Line 1: Line 1:
Maps are yet another interesting feature that has been in ''nftables'' since the very beginning. You can use a map to look up for data based on some specific key that is used as input. Maps internally use the [[Sets | generic set infrastructure]] and therefore share some of their options and semantics.
An nftables map stores key-value pairs, like [https://en.wikipedia.org/wiki/Associative_array associative arrays / dictionaries / hashes] do in many programming languages. In an nftables rule you can specify a packet field (e.g. ''tcp dport'') and reference a map to search for the map element whose key matches the packet field's value, and return that map element's value (or failure if the map contains no matching element). Some examples below will help clarify this general description.


= Literal maps =
You can think of a map as a [[Sets|set]] that returns a value instead of just an "in set / not in set" result. Behind the scenes both sets and maps use the same generic set infrastructure and therefore share many of the same options and semantics.


The following example shows how the destination TCP port selects the destination IP address to DNAT the packet:
 
= Anonymous maps =
 
The following rule uses a map to [[Performing_Network_Address_Translation_(NAT)|DNAT]] packets to different destination IP addresses depending on the packet's destination tcp port:


<source lang="bash">
<source lang="bash">
% nft add rule ip nat prerouting dnat tcp dport map { 80 : 192.168.1.100, 8888 : 192.168.1.101 }
% nft add rule ip nat prerouting dnat to tcp dport map { 80 : 192.168.1.100, 8888 : 192.168.1.101 }
</source>
</source>


This is how you can express a classical port redirection when the real server are actually located behind the firewall. This can be read as it follows:
This is a very concise and efficient way to perform classical port redirection when the real servers are located behind a firewall. It can be read as it follows:


* If the TCP destination port is 80, then the packet is DNAT'ed to 192.168.1.100.
* If the TCP destination port is 80, then the packet is DNAT'ed to 192.168.1.100.
* If the TCP destination port is 8888, then the packet is DNAT'ed to 192.168.1.101.
* If the TCP destination port is 8888, then the packet is DNAT'ed to 192.168.1.101.


= Map declarations =


You can also declare maps that you can populate in a dynamic fashion, eg.
= Named maps =
 
You can also declare named maps, to which you can then add or delete elements at anytime. For example, with:


<source lang="bash">
<source lang="bash">
Line 23: Line 27:
</source>
</source>


The example above shows that the ''porttoip'' map maintains the corresponde between Internet services (which is the datatype of a TCP destination port) and IP addresses.
we first define a map ''porttoip'' which looks up an IP address based on a UDP or TCP port number, and then add a couple of elements. The map itself only cares about the [[Data_types|data&nbsp;types]] of its keys and values. It is up to us to use meaningful values for both, and to use the map appropriately in rules. In this example we use ''porttoip'' to map tcp destination ports to source IP addresses. Then we can perform [[Performing_Network_Address_Translation_(NAT)|SNAT]] using the rule:
 
Then, you can use it from a rule like:


<source lang="bash">
<source lang="bash">
% nft add rule ip nat postrouting snat tcp dport map @porttoip
% nft add rule ip nat postrouting snat to tcp dport map @porttoip
</source>
</source>


This rules tells that the source IP address that is used for SNAT depends on TCP destination port. The content of the map can be dynamically updated by adding new elements.
Now outgoing packets to TCP/80 use source IP address 192.168.1.100, those to TCP/8888 are SNAT'ed to 192.168.1.101. We can easily adjust our SNAT at anytime simply by adding or deleting elements in ''porttoip''.

Latest revision as of 02:49, 20 April 2021

An nftables map stores key-value pairs, like associative arrays / dictionaries / hashes do in many programming languages. In an nftables rule you can specify a packet field (e.g. tcp dport) and reference a map to search for the map element whose key matches the packet field's value, and return that map element's value (or failure if the map contains no matching element). Some examples below will help clarify this general description.

You can think of a map as a set that returns a value instead of just an "in set / not in set" result. Behind the scenes both sets and maps use the same generic set infrastructure and therefore share many of the same options and semantics.


Anonymous maps

The following rule uses a map to DNAT packets to different destination IP addresses depending on the packet's destination tcp port:

% nft add rule ip nat prerouting dnat to tcp dport map { 80 : 192.168.1.100, 8888 : 192.168.1.101 }

This is a very concise and efficient way to perform classical port redirection when the real servers are located behind a firewall. It can be read as it follows:

  • If the TCP destination port is 80, then the packet is DNAT'ed to 192.168.1.100.
  • If the TCP destination port is 8888, then the packet is DNAT'ed to 192.168.1.101.


Named maps

You can also declare named maps, to which you can then add or delete elements at anytime. For example, with:

% nft add map nat porttoip  { type inet_service: ipv4_addr\; }
% nft add element nat porttoip { 80 : 192.168.1.100, 8888 : 192.168.1.101 }

we first define a map porttoip which looks up an IP address based on a UDP or TCP port number, and then add a couple of elements. The map itself only cares about the data types of its keys and values. It is up to us to use meaningful values for both, and to use the map appropriately in rules. In this example we use porttoip to map tcp destination ports to source IP addresses. Then we can perform SNAT using the rule:

% nft add rule ip nat postrouting snat to tcp dport map @porttoip

Now outgoing packets to TCP/80 use source IP address 192.168.1.100, those to TCP/8888 are SNAT'ed to 192.168.1.101. We can easily adjust our SNAT at anytime simply by adding or deleting elements in porttoip.