#!/usr/bin/nft -f # vim:set ts=2 sw=2 et: # IPv4/IPv6 Simple & Safe firewall ruleset. # More examples in /usr/share/nftables/ and /usr/share/doc/nftables/examples/. destroy table inet filter table inet filter { chain input { type filter hook input priority filter policy drop ct state invalid drop comment "early drop of invalid connections" ct state {established, related} accept comment "allow tracked connections" iif lo accept comment "allow from loopback" meta l4proto { icmp, icmpv6 } accept comment "allow icmp" # libvirt's NAT bridge: let guests reach the host's dnsmasq for DHCP+DNS. # libvirt manages its own forward/NAT chains but does NOT touch the input # chain, so without this rule guests get no IP (DHCP packets are dropped # before dnsmasq sees them). iifname "virbr0" udp dport { 53, 67 } accept comment "libvirt: DHCP+DNS from guests" iifname "virbr0" tcp dport 53 accept comment "libvirt: DNS over TCP from guests" # Waydroid's NAT bridge: same pattern as libvirt. The Android container's # DhcpClient broadcasts DHCPDISCOVER on waydroid0; without this rule it's # dropped before dnsmasq sees it and the container never gets an IP. iifname "waydroid0" udp dport { 53, 67 } accept comment "waydroid: DHCP+DNS from container" iifname "waydroid0" tcp dport 53 accept comment "waydroid: DNS over TCP from container" pkttype host limit rate 5/second counter reject with icmpx type admin-prohibited counter } chain forward { type filter hook forward priority filter policy drop # libvirt's NAT bridge: permit guest traffic to be forwarded. libvirt's # own table accepts these explicitly at the same hook+priority, but with # nftables a packet must be accepted by ALL chains at that priority, so # our policy=drop would otherwise block all guest egress and return # traffic. Mirror libvirt's accepts here for the default NAT bridge. # Use iifname/oifname (string match) instead of iif/oif so the rules # load before libvirtd has created virbr0 at boot. iifname "virbr0" accept comment "libvirt: guest egress" oifname "virbr0" ct state established,related accept comment "libvirt: guest return" # Waydroid's NAT bridge: same pattern as libvirt. Waydroid's container # service installs MASQUERADE itself via iptables-nft compat, so no # explicit nat table is needed here -- only the forward-chain accepts. iifname "waydroid0" accept comment "waydroid: guest egress" oifname "waydroid0" ct state established,related accept comment "waydroid: guest return" } }