WebsiteTemplate/cheatsheets/nftables.html
2026-01-25 11:33:37 -04:00

406 lines
12 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'; style-src 'self'; font-src 'self' data:; img-src 'self' data:; connect-src 'self'; base-uri 'self'; form-action 'self' https://defcon.social https://bsky.app;">
<meta http-equiv="X-Content-Type-Options" content="nosniff">
<link rel="stylesheet" href="../assets/css/style.css">
<link rel="icon" type="image/x-icon" href="../favicon.ico">
<script>
// Apply theme immediately to prevent flash
(function() {
const theme = localStorage.getItem('theme') ||
(window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
document.documentElement.setAttribute('data-theme', theme);
})();
</script>
<title>nftables Cheatsheet - Cheatsheets - Launch Pad</title>
</head>
<body>
<button class="theme-toggle" id="themeToggle" aria-label="Toggle dark mode">
<svg class="theme-icon theme-icon-moon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path></svg>
<svg class="theme-icon theme-icon-sun" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display: none;"><circle cx="12" cy="12" r="5"></circle><line x1="12" y1="1" x2="12" y2="3"></line><line x1="12" y1="21" x2="12" y2="23"></line><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line><line x1="1" y1="12" x2="3" y2="12"></line><line x1="21" y1="12" x2="23" y2="12"></line><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line></svg>
</button>
<br/><br/>
<div class="name">
__ _______________________ _________._________________________
\_ _____/ \______ \ / _ \ / _____/ / _____/ | | \_ _____/
| __) | _/ / /_\ \ / \ ___ / \ ___ | | | __)_
| \ | | \ / | \ \ \_\ \ \ \_\ \ | |___ | \
\___ / |____|_ / \____|__ / \______ / \______ / |_______ \ /_______ /
\/ \/ \/ \/ \/ \/ \/
</div>
<div class="blog-page-header">
<div class="blog-header-content">
<a href="/cheatsheets" class="back-link" title="Back to Cheatsheets">
<svg xmlns="http://www.w3.org/2000/svg" width="42" height="42" viewBox="0 0 24 24" class="home-icon"><path fill="currentColor" d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"/></svg>
</a>
<h1 class="blog-page-title">nftables Cheatsheet</h1>
</div>
</div>
<div class="blog-post-container">
<div class="blog-posts-container" style="max-width: 900px; margin: 0 auto;">
<div class="blog-post">
<div class="blog-post-content">
<p><a href="index.html">← Back to cheatsheets</a></p>
<p><a href="../index.html">← Home</a></p>
<hr>
<p>nftables is the modern Linux firewall framework, replacing iptables. It provides a unified interface for IPv4, IPv6, ARP, and bridge filtering with improved performance and syntax.</p>
<hr>
<h2>Basic Commands</h2>
<ul>
<li>nft list ruleset - List all rules</li>
</ul>
<ul>
<li>nft list tables - List all tables</li>
</ul>
<ul>
<li>nft list table &lt;family&gt; &lt;name&gt; - List specific table</li>
</ul>
<ul>
<li>nft list chain &lt;family&gt; &lt;table&gt; &lt;chain&gt; - List specific chain</li>
</ul>
<ul>
<li>nft flush ruleset - Clear all rules</li>
</ul>
<ul>
<li>nft flush table &lt;family&gt; &lt;name&gt; - Clear specific table</li>
</ul>
<ul>
<li>nft -s list ruleset - List with handle numbers</li>
</ul>
<ul>
<li>nft monitor - Watch for rule changes in real-time</li>
</ul>
<hr>
<h2>Address Families</h2>
<ul>
<li>ip - IPv4 (default)</li>
</ul>
<ul>
<li>ip6 - IPv6</li>
</ul>
<ul>
<li>inet - IPv4 and IPv6 combined</li>
</ul>
<ul>
<li>arp - ARP</li>
</ul>
<ul>
<li>bridge - Bridge filtering</li>
</ul>
<ul>
<li>netdev - Ingress filtering</li>
</ul>
<hr>
<h2>Tables</h2>
<h3>Create Table</h3>
<pre><code>nft add table inet filter
nft add table ip nat</code></pre>
<h3>Delete Table</h3>
<pre><code>nft delete table inet filter</code></pre>
<hr>
<h2>Chains</h2>
<h3>Chain Types</h3>
<ul>
<li>filter - Packet filtering</li>
</ul>
<ul>
<li>route - Rerouting packets</li>
</ul>
<ul>
<li>nat - Network address translation</li>
</ul>
<h3>Chain Hooks</h3>
<ul>
<li>prerouting - Before routing decision</li>
</ul>
<ul>
<li>input - Incoming packets to local</li>
</ul>
<ul>
<li>forward - Forwarded packets</li>
</ul>
<ul>
<li>output - Outgoing packets from local</li>
</ul>
<ul>
<li>postrouting - After routing decision</li>
</ul>
<ul>
<li>ingress - Earliest hook (netdev only)</li>
</ul>
<h3>Create Chain</h3>
<pre><code>nft add chain inet filter input { type filter hook input priority 0 \; policy drop \; }
nft add chain inet filter output { type filter hook output priority 0 \; policy accept \; }
nft add chain inet filter forward { type filter hook forward priority 0 \; policy drop \; }</code></pre>
<h3>Delete Chain</h3>
<pre><code>nft delete chain inet filter input</code></pre>
<hr>
<h2>Adding Rules</h2>
<ul>
<li>nft add rule &lt;family&gt; &lt;table&gt; &lt;chain&gt; &lt;rule&gt; - Append rule</li>
</ul>
<ul>
<li>nft insert rule &lt;family&gt; &lt;table&gt; &lt;chain&gt; &lt;rule&gt; - Insert at beginning</li>
</ul>
<ul>
<li>nft add rule &lt;family&gt; &lt;table&gt; &lt;chain&gt; position &lt;handle&gt; &lt;rule&gt; - Add after handle</li>
</ul>
<ul>
<li>nft delete rule &lt;family&gt; &lt;table&gt; &lt;chain&gt; handle &lt;handle&gt; - Delete by handle</li>
</ul>
<hr>
<h2>Rule Matching</h2>
<h3>Interface Matching</h3>
<ul>
<li>iifname "eth0" - Input interface name</li>
</ul>
<ul>
<li>oifname "eth0" - Output interface name</li>
</ul>
<ul>
<li>iif eth0 - Input interface (faster, index-based)</li>
</ul>
<ul>
<li>oif eth0 - Output interface (faster, index-based)</li>
</ul>
<h3>Address Matching</h3>
<ul>
<li>ip saddr 192.168.1.0/24 - Source IPv4 address</li>
</ul>
<ul>
<li>ip daddr 10.0.0.1 - Destination IPv4 address</li>
</ul>
<ul>
<li>ip6 saddr fe80::/10 - Source IPv6 address</li>
</ul>
<ul>
<li>ip6 daddr ::1 - Destination IPv6 address</li>
</ul>
<h3>Protocol Matching</h3>
<ul>
<li>ip protocol tcp - TCP protocol</li>
</ul>
<ul>
<li>ip protocol udp - UDP protocol</li>
</ul>
<ul>
<li>ip protocol icmp - ICMP protocol</li>
</ul>
<ul>
<li>meta l4proto tcp - Layer 4 protocol (works with inet)</li>
</ul>
<h3>Port Matching</h3>
<ul>
<li>tcp sport 22 - TCP source port</li>
</ul>
<ul>
<li>tcp dport 80 - TCP destination port</li>
</ul>
<ul>
<li>udp dport 53 - UDP destination port</li>
</ul>
<ul>
<li>tcp dport { 22, 80, 443 } - Multiple ports</li>
</ul>
<ul>
<li>tcp dport 1024-65535 - Port range</li>
</ul>
<hr>
<h2>Verdicts (Actions)</h2>
<ul>
<li>accept - Accept the packet</li>
</ul>
<ul>
<li>drop - Drop silently</li>
</ul>
<ul>
<li>reject - Reject with error</li>
</ul>
<ul>
<li>queue - Send to userspace</li>
</ul>
<ul>
<li>continue - Continue rule processing</li>
</ul>
<ul>
<li>return - Return to calling chain</li>
</ul>
<ul>
<li>jump &lt;chain&gt; - Jump to another chain</li>
</ul>
<ul>
<li>goto &lt;chain&gt; - Go to chain without returning</li>
</ul>
<hr>
<h2>Connection Tracking</h2>
<ul>
<li>ct state new - New connections</li>
</ul>
<ul>
<li>ct state established - Established connections</li>
</ul>
<ul>
<li>ct state related - Related connections</li>
</ul>
<ul>
<li>ct state invalid - Invalid packets</li>
</ul>
<ul>
<li>ct state { established, related } - Multiple states</li>
</ul>
<hr>
<h2>Common Examples</h2>
<h3>Allow SSH</h3>
<pre><code>nft add rule inet filter input tcp dport 22 accept</code></pre>
<h3>Allow Established Connections</h3>
<pre><code>nft add rule inet filter input ct state established,related accept</code></pre>
<h3>Block IP Address</h3>
<pre><code>nft add rule inet filter input ip saddr 192.168.1.100 drop</code></pre>
<h3>Allow HTTP/HTTPS</h3>
<pre><code>nft add rule inet filter input tcp dport { 80, 443 } accept</code></pre>
<h3>Allow Loopback</h3>
<pre><code>nft add rule inet filter input iifname "lo" accept</code></pre>
<h3>Log and Drop</h3>
<pre><code>nft add rule inet filter input log prefix "nftables-dropped: " drop</code></pre>
<hr>
<h2>NAT Configuration</h2>
<h3>Masquerading (SNAT)</h3>
<pre><code>nft add table ip nat
nft add chain ip nat postrouting { type nat hook postrouting priority 100 \; }
nft add rule ip nat postrouting oifname "eth0" masquerade</code></pre>
<h3>Port Forwarding (DNAT)</h3>
<pre><code>nft add chain ip nat prerouting { type nat hook prerouting priority -100 \; }
nft add rule ip nat prerouting iifname "eth0" tcp dport 8080 dnat to 192.168.1.10:80</code></pre>
<hr>
<h2>Complete Firewall Example</h2>
<pre><code>#!/usr/sbin/nft -f
flush ruleset
table inet filter {
chain input {
type filter hook input priority 0; policy drop;
# Allow loopback
iifname "lo" accept
# Allow established/related
ct state established,related accept
# Drop invalid
ct state invalid drop
# Allow ICMP
ip protocol icmp accept
ip6 nexthdr icmpv6 accept
# Allow SSH
tcp dport 22 accept
# Allow HTTP/HTTPS
tcp dport { 80, 443 } accept
}
chain forward {
type filter hook forward priority 0; policy drop;
}
chain output {
type filter hook output priority 0; policy accept;
}
}</code></pre>
<hr>
<h2>Sets and Maps</h2>
<h3>Named Set</h3>
<pre><code>nft add set inet filter allowed_ips { type ipv4_addr \; }
nft add element inet filter allowed_ips { 192.168.1.1, 192.168.1.2 }
nft add rule inet filter input ip saddr @allowed_ips accept</code></pre>
<h3>Anonymous Set</h3>
<pre><code>nft add rule inet filter input ip saddr { 192.168.1.1, 192.168.1.2 } accept</code></pre>
<h3>Port Set</h3>
<pre><code>nft add set inet filter allowed_ports { type inet_service \; }
nft add element inet filter allowed_ports { 22, 80, 443 }
nft add rule inet filter input tcp dport @allowed_ports accept</code></pre>
<hr>
<h2>Rate Limiting</h2>
<pre><code># Limit to 10 packets per second
nft add rule inet filter input tcp dport 22 limit rate 10/second accept
# Limit with burst
nft add rule inet filter input tcp dport 22 limit rate over 10/second burst 5 packets drop</code></pre>
<hr>
<h2>Saving and Loading</h2>
<ul>
<li>nft list ruleset &gt; /etc/nftables.conf - Save rules</li>
</ul>
<ul>
<li>nft -f /etc/nftables.conf - Load rules from file</li>
</ul>
<ul>
<li>systemctl enable nftables - Enable at boot</li>
</ul>
<ul>
<li>systemctl start nftables - Start nftables service</li>
</ul>
<hr>
<h2>Migration from iptables</h2>
<ul>
<li>iptables-translate - Convert iptables rule to nft syntax</li>
</ul>
<ul>
<li>iptables-restore-translate - Convert iptables-save output to nft</li>
</ul>
<ul>
<li>iptables-nft - iptables compatibility layer using nftables backend</li>
</ul>
<pre><code># Translate a single rule
iptables-translate -A INPUT -p tcp --dport 22 -j ACCEPT
# Translate saved rules
iptables-save | iptables-restore-translate</code></pre>
<hr>
<h2>Tips</h2>
<ul>
<li>Use inet family for combined IPv4/IPv6 rules</li>
</ul>
<ul>
<li>Use sets for multiple addresses or ports (more efficient)</li>
</ul>
<ul>
<li>Use iifname/oifname for dynamic interfaces, iif/oif for static</li>
</ul>
<ul>
<li>Chain priority determines order (lower = earlier)</li>
</ul>
<ul>
<li>Use handles (-a flag) to identify rules for deletion</li>
</ul>
<ul>
<li>nft monitor is useful for debugging rule changes</li>
</ul>
<ul>
<li>Put rules in /etc/nftables.conf for persistence</li>
</ul>
<ul>
<li>Use flush ruleset carefully - it removes everything</li>
</ul>
<ul>
<li>Escape semicolons with backslash in shell commands</li>
</ul>
<ul>
<li>nftables is the future - iptables is in maintenance mode</li>
</ul>
<hr>
<p><a href="index.html">← Back to cheatsheets</a></p>
<p><a href="../index.html">← Home</a></p>
</div>
</div>
</div>
</div>
<script async type="text/javascript" src="../blog/analytics.js"></script>
<script src="../theme.js"></script>
</body>
</html>