Red Hat Training

A Red Hat training course is available for Red Hat Enterprise Linux

6.5. Using verdict maps in nftables commands

Verdict maps, which are also known as dictionaries, enable nft to perform an action based on packet information by mapping match criteria to an action.

6.5.1. Using anonymous maps in nftables

An anonymous map is a { match_criteria : action } statement that you use directly in a rule. The statement can contain multiple comma-separated mappings.
The drawback of an anonymous map is that if you want to change the map, you must replace the rule. For a dynamic solution, use named maps as described in Section 6.5.2, “Using named maps in nftables”.
The example describes how to use an anonymous map to route both TCP and UDP packets of the IPv4 and IPv6 protocol to different chains to count incoming TCP and UDP packets separately.

Procedure 6.15. Using anonymous maps in nftables

  1. Create the example_table:
    # nft add table inet example_table
  2. Create the tcp_packets chain in example_table:
    # nft add chain inet example_table tcp_packets
  3. Add a rule to tcp_packets that counts the traffic in this chain:
    # nft add rule inet example_table tcp_packets counter
  4. Create the udp_packets chain in example_table:
    # nft add chain inet example_table udp_packets
  5. Add a rule to udp_packets that counts the traffic in this chain:
    # nft add rule inet example_table udp_packets counter
  6. Create a chain for incoming traffic. For example, to create a chain named incoming_traffic in example_table that filters incoming traffic:
    # nft add chain inet example_table incoming_traffic { type filter hook input priority 0 \; }
  7. Add a rule with an anonymous map to incoming_traffic:
    # nft add rule inet example_table incoming_traffic ip protocol vmap { tcp : jump tcp_packets, udp : jump udp_packets }
    The anonymous map distinguishes the packets and sends them to the different counter chains based on their protocol.
  8. To list the traffic counters, display example_table:
    # nft list table inet example_table
    table inet example_table {
      chain tcp_packets {
        counter packets 36379 bytes 2103816
      }
    
      chain udp_packets {
        counter packets 10 bytes 1559
      }
    
      chain incoming_traffic {
        type filter hook input priority filter; policy accept;
        ip protocol vmap { tcp : jump tcp_packets, udp : jump udp_packets }
      }
    }
    
    The counters in the tcp_packets and udp_packets chain display both the number of received packets and bytes.

6.5.2. Using named maps in nftables

The nftables framework supports named maps. You can use these maps in multiple rules within a table. Another benefit over anonymous maps is that you can update a named map without replacing the rules that use it.
When you create a named map, you must specify the type of elements:
  • ipv4_addr for a map whose match part contains an IPv4 address, such as 192.0.2.1.
  • ipv6_addr for a map whose match part contains an IPv6 address, such as 2001:db8:1::1.
  • ether_addr for a map whose match part contains a media access control (MAC) address, such as 52:54:00:6b:66:42.
  • inet_proto for a map whose match part contains an Internet protocol type, such as tcp.
  • inet_service for a map whose match part contains an Internet services name port number, such as ssh or 22.
  • mark for a map whose match part contains a packet mark. A packet mark can be any positive 32-bit integer value (0 to 2147483647).
  • counter for a map whose match part contains a counter value. The counter value can be any positive 64-bit integer value.
  • quota for a map whose match part contains a quota value. The quota value can be any positive 64-bit integer value.
The example describes how to allow or drop incoming packets based on their source IP address. Using a named map, you require only a single rule to configure this scenario while the IP addresses and actions are dynamically stored in the map. The procedure also describes how to add and remove entries from the map.

Procedure 6.16. Using named maps in nftables

  1. Create a table. For example, to create a table named example_table that processes IPv4 packets:
    # nft add table ip example_table
  2. Create a chain. For example, to create a chain named example_chain in example_table:
    # nft add chain ip example_table example_chain { type filter hook input priority 0 \; }

    Important

    To avoid that the shell interprets the semicolons as the end of the command, you must escape the semicolons with a backslash.
  3. Create an empty map. For example, to create a map for IPv4 addresses:
    # nft add map ip example_table example_map { type ipv4_addr : verdict \; }
  4. Create rules that use the map. For example, the following command adds a rule to example_chain in example_table that applies actions to IPv4 addresses which are both defined in example_map:
    # nft add rule example_table example_chain ip saddr vmap @example_map
  5. Add IPv4 addresses and corresponding actions to example_map:
    # nft add element ip example_table example_map { 192.0.2.1 : accept, 192.0.2.2 : drop }
    This example defines the mappings of IPv4 addresses to actions. In combination with the rule created above, the firewall accepts packet from 192.0.2.1 and drops packets from 192.0.2.2.
  6. Optionally, enhance the map by adding another IP address and action statement:
    # nft add element ip example_table example_map { 192.0.2.3 : accept }
  7. Optionally, remove an entry from the map:
    # nft delete element ip example_table example_map { 192.0.2.1 }
  8. Optionally, display the rule set:
    # nft list ruleset
    table ip example_table {
      map example_map {
        type ipv4_addr : verdict
        elements = { 192.0.2.2 : drop, 192.0.2.3 : accept }
      }
    
      chain example_chain {
        type filter hook input priority filter; policy accept;
        ip saddr vmap @example_map
      }
    }
    

6.5.3. Related information

For further details about verdict maps, see the Maps section in the nft(8) man page.