nftables is a packet filtering framework that can be used to implement a firewall. The input chain is responsible for filtering incoming network traffic destined for the server itself. Securing this chain is critical to prevent unauthorized access and protect your server from various network-based attacks.
Here’s how to configure and secure your nftables input chain for a typical server scenario.
The Core Idea: Default Deny
The most robust security posture is to deny all incoming traffic by default and then explicitly allow only what is necessary. This is often referred to as a "default deny" or "whitelisting" approach.
Setting Up the Table and Chain
First, ensure you have nftables installed. Then, create a table and the input chain.
sudo nft add table ip filter
sudo nft add chain ip filter input { type filter hook input priority 0 \; policy drop \; }
sudo nft add table ip filter: This creates a new table namedfilterfor IPv4 packets.sudo nft add chain ip filter input { ... }: This creates a chain namedinputwithin thefiltertable.type filter: Specifies this is a filtering chain.hook input: Attaches this chain to theinputhook, meaning it processes packets destined for the local system.priority 0: Sets the priority of the hook. Lower numbers are processed earlier.policy drop: This is the crucial part. It sets the default policy for the chain todrop, meaning any packet that doesn’t match an explicitacceptrule will be discarded.
Allowing Essential Loopback Traffic
Your server needs to communicate with itself. The loopback interface (lo) is used for this.
sudo nft add rule ip filter input iif lo accept
iif lo: Matches packets arriving on the loopback interface.accept: Allows these packets to pass.
Allowing Established and Related Connections
To allow return traffic for connections initiated from your server, you need to track connection states.
sudo nft add rule ip filter input ct state established,related accept
ct state established,related: This matches packets that are part of an already established connection or are related to one (like ICMP errors for an established TCP connection). This is essential for most network services to function correctly.
Allowing SSH Access (Port 22)
You’ll likely need SSH access to manage your server.
sudo nft add rule ip filter input tcp dport 22 accept
tcp dport 22: Matches TCP packets destined for port 22 (the default SSH port).accept: Allows these connections.
Important: If you are managing this server remotely via SSH, ensure this rule is in place BEFORE setting the policy drop. Otherwise, you will lock yourself out.
Allowing HTTP/HTTPS (Ports 80 and 443)
If your server hosts a website, you need to allow incoming traffic on ports 80 (HTTP) and 443 (HTTPS).
sudo nft add rule ip filter input tcp dport { 80, 443 } accept
tcp dport { 80, 443 }: Matches TCP packets destined for either port 80 or port 443.
Allowing ICMP (Ping)
Allowing ICMP echo requests (ping) can be useful for network diagnostics.
sudo nft add rule ip filter input icmp type echo-request accept
icmp type echo-request: Matches ICMP packets that are of the "echo request" type.
Logging Dropped Packets (Optional but Recommended)
To understand what traffic is being blocked, you can add a logging rule before the final drop policy (which is implicit if no rule matches and the policy is drop).
sudo nft add rule ip filter input counter log prefix "nft-drop: " accept
This rule will match any packet that reaches it. The counter adds a packet and byte counter to the rule, which you can inspect later. The log prefix "nft-drop: " sends a message to the system log (e.g., /var/log/syslog or via journalctl) for each packet that matches, prefixed with nft-drop: . The accept here is a bit of a trick; it makes the packet pass this logging rule, but since it’s the last rule before the implicit drop policy, any packet that reaches this point and isn’t explicitly accepted by a prior rule will still be dropped.
If you want to log and then drop explicitly:
sudo nft add rule ip filter input counter log prefix "nft-drop: " drop
Place this rule as the very last rule in your chain. Any packet that reaches this rule will be logged and then dropped.
Saving Your Rules
nftables rules are ephemeral by default and will be lost on reboot. You need to save them. The method varies slightly by distribution, but common approaches include:
Systemd-based systems (most modern Linux):
sudo systemctl enable nftables.service
sudo nft list ruleset > /etc/nftables.conf
Other systems or manual configuration:
You might need to add nft -f /etc/nftables.conf to a startup script.
A More Comprehensive Example Ruleset
Here’s a more complete example for a web server, including IPv6:
#!/sbin/nft -f
flush ruleset
table ip filter {
chain input {
type filter hook input priority 0; policy drop;
# Allow loopback traffic
iif lo accept
# Allow established/related connections
ct state established,related accept
# Allow SSH
tcp dport 22 accept
# Allow HTTP/HTTPS
tcp dport { 80, 443 } accept
# Allow ICMP echo-request (ping)
icmp type echo-request accept
# Log and drop everything else
counter log prefix "nft-drop: "
# The 'drop' is implicit due to policy drop, but can be explicit
# drop
}
}
table ip6 filter {
chain input {
type filter hook input priority 0; policy drop;
# Allow loopback traffic
iif lo accept
# Allow established/related connections
ct state established,related accept
# Allow SSH
tcp dport 22 accept
# Allow HTTP/HTTPS
tcp dport { 80, 443 } accept
# Allow ICMPv6 echo-request (ping)
icmpv6 type echo-request accept
# Log and drop everything else
counter log prefix "nft-drop: "
# drop
}
}
To apply this from a file (e.g., my_nftables.conf):
sudo nft -f my_nftables.conf
And to save it:
sudo nft list ruleset > /etc/nftables.conf
sudo systemctl enable nftables.service
By following the "default deny" principle and explicitly allowing only necessary traffic, you significantly harden your server’s attack surface.