About Hooks and Chains

Hooks are points in a system where packets can be intercepted for processing. These hooks are where nftables applies chains and rules that decide what happens to a packet. Different hooks are available depending on the address family applied to a table.

The following table shows the hooks available to each address family.

Address Family Hook Description

IP, IPv6, inet / Bridge

prerouting

Processes all incoming packets before routing decisions.

input

Handles packets destined for the local system.

forward

Manages packets being forwarded to another host.

output

Processes packets originating from the local system.

postrouting

Deals with all outgoing packets after routing.

ingress

Manages incoming packets before the prerouting, available from Linux kernel 5.10 for inet family.

ARP

input

Processes packets for the local system.

output

Handles packets sent from the local system.

Netdev

ingress

Processes incoming packets after network taps, such as tcpdump, before layer 3 handling.

egress

Manages outgoing packets after layer 3 handling but before final network exit.

Base chains are attached to hooks. When a packet arrives at a hook, configured with a base chain, the packet then traverses the chain, and each rule in the chain is evaluated in order until a rule matches, or the end of the chain is reached. nftables includes the following chain types:
  • Base Chains: These are chains directly built on a hook. For example, a base chain named myinput might be linked to the inet input hook for IPv4 or IPv6 packets arriving at the local system.
  • Regular Chains: These are chains that jump from base chains or other regular chains. They aren't built directly at a hook but can be part of the decision-making process within a base chain.
Base chains must include the base chain type, hook, and priority parameters. Chain types include:
  • filter: Primarily used for packet filtering, such as whether to permit or block packets based on various criteria such as source and destination IP, ports, protocols, and so on. This chain type works with all address families and their hooks.
  • nat: Primarily used to change IP addresses, ports, or both in packet headers for NAT operations. This includes changes to Source NAT (SNAT) for outgoing traffic and Destination NAT (DNAT) for incoming traffic. This chain type can be configured with ip, ipv6, and inet address families and can take the prerouting, input, output, and postrouting hooks.
  • route: Primarily used for routing decisions such as altering a routing table or marking packets for specific routing policies. This chain type can be used with ip and ipv6 address families and can take the output hook only.

When using the ingress or egress hooks, specify a network interface name as a string with the device parameter. Any ingress or egress chains only filters traffic from the interface specified in the device parameter.

The priority parameter uses a signed integer or a standard priority name to determine the order in which chains with the same hook are processed. Chains process from lower priority values or names to higher priority values or names.

The following table shows priority names and values for each associated address family and hook type.

Name Value Family Hooks

raw

-300

ip, ip6, inet all

mangle

-150

ip, ip6, inet all

dsnat

-100

ip, ip6, inet prerouting

filter

0

ip, ip6, inet, arp, netdev all

security

50

ip, ip6, inet all

srcnat

100

ip, ip6, inet postrouting

The following table shows priority names and values for the bridge address family and hook type.

Name Value Hooks

dsnat

-300

prerouting

filter

-200

all

out

100

output

srcnat

300

postrouting

You can also choose to set a policy on a chain that defines whether to accept or drop a packet when none of the rules defined on the chain matches the packet. By default, base chains accept all packets. However, setting a policy to drop all traffic not explicitly allowed by a chain is good practice for security reasons.

Creating Base Chains

To create nftable base chains in memory, do the following:
  1. Create a chain for a specific address family type and table using the following syntax:

    sudo nft add chain <address_family> <table_name> <chain_name>{ type <chain_type> hook <hook_type> device <network_interface_name> priority <priority> policy <policy> comment <comment> ; }
    
    In the previous,
    • <address_family> can be ip, ip6, inet, arp, bridge, or netdev. All nftables objects are in one of these address family. For more information about these address families, see the nft(8) manual page.
    • <table_name> is the name of the table. Tables are containers for chains, which in turn are containers for rules.
    • <chain_name> is an arbitrary name for the chain. People migrating from iptables based firewalls often use traditional iptables naming.
    • <chain_type> is the chain type. Valid values for base chains are filter, nat, and route. For more information, see About Hooks and Chains.
    • <hook_type> is the hook type. Possible values depend on the selected address family and chain type. For more information, see About Hooks and Chains.
    • <network_interface_name> is the network interface name for the device parameter. This parameter is only required when using the ingress or egress hooks.
    • <priority> is the priority value or name for the chain. Priority depends on the selected address family and hook type. For more information, see About Hooks and Chains.
    • <policy> is the action taken if all rules defined on the chain fail to match the packet. Valid values are accept or drop. If not specified, the default value is accept.
    For example, the following command creates a chain in the mytable table called mychain with the inet family. The chain type is filter, the hook is input, and the priority is 0. Finally, the policy is set to drop all packets that don't match a rule:
    sudo nft add chain inet mytable mychain "{ type filter hook input priority 0 ; policy drop ; }"
  2. Do the following:
    • To view all chains, do the following:
      sudo nft list chains
    • To view a single chain, do the following:
      sudo nft list chain <address_family> <table_name> <chain_name>