--- /dev/null
+#!/usr/sbin/nft -f
+#
+# nftables ruleset for an End Node acting as a workstation in a LAN.
+#
+# Copyright (C) 2018 Antonio Ospite <ao2@ao2.it>
+# SPDX-License-Identifier: MIT
+#
+# Based on:
+# https://wiki.nftables.org/wiki-nftables/index.php/Quick_reference-nftables_in_10_minutes#Simple_IP.2FIPv6_Firewall
+# https://wiki.archlinux.org/index.php/Nftables#Workstation
+# https://stosb.com/blog/explaining-my-configs-nftables/
+
+flush ruleset
+
+table inet filter {
+
+ define common_open_ports = {
+ xmpp-client,
+ xmpp-server,
+ 5298, # Link-local XMPP, for backward compatibility, XEP-0174
+ }
+
+ set tcp_open_ports {
+ type inet_service
+ flags interval
+
+ elements = {
+ $common_open_ports,
+ }
+ }
+
+ set udp_open_ports {
+ type inet_service
+ flags interval
+
+ elements = {
+ $common_open_ports,
+ }
+ }
+
+ chain input {
+ type filter hook input priority 0;
+
+ ct state established,related accept
+ ct state invalid drop
+ ct state new jump in-new
+
+ iif lo accept
+
+ ip protocol icmp icmp type {
+ echo-reply,
+ echo-request,
+ time-exceeded,
+ parameter-problem,
+ destination-unreachable
+ } accept
+
+ # ICMPv6 configuration based on:
+ # https://github.com/intel/intel-iot-refkit/blob/master/meta-refkit-core/recipes-security/nftables-settings-default/files/firewall.template
+ ip6 nexthdr ipv6-icmp icmpv6 type {
+ echo-reply,
+ echo-request,
+ time-exceeded,
+ parameter-problem,
+ destination-unreachable,
+ packet-too-big
+ } accept
+
+ # Allow auto configuration support.
+ ip6 nexthdr ipv6-icmp icmpv6 type {
+ nd-router-advert,
+ nd-router-solicit,
+ nd-neighbor-advert,
+ nd-neighbor-solicit
+ } ip6 hoplimit 255 accept
+
+ # Allow multicast listener discovery on link-local addresses.
+ ip6 nexthdr ipv6-icmp icmpv6 type {
+ mld-listener-query,
+ mld-listener-report,
+ mld-listener-reduction
+ } ip6 saddr fe80::/10 accept
+
+ # Allow multicast router discovery messages on link-local addresses (hop limit 1).
+ ip6 nexthdr ipv6-icmp icmpv6 type {
+ nd-router-advert,
+ nd-router-solicit
+ } ip6 hoplimit 1 ip6 saddr fe80::/10 accept
+
+ # Allow IGMPv3 queries.
+ ip protocol igmp ip daddr 224.0.0.1 accept
+
+ # Silently drop other incoming broadcast and multicast traffic.
+ meta pkttype {broadcast, multicast} drop
+
+ limit rate 3/minute burst 10 packets log prefix "[INPUT]: "
+ counter reject
+ }
+
+ chain in-new {
+ # Silently drop DHCPv4 Discover and Request packets from other clients.
+ ip saddr 0.0.0.0 ip daddr 255.255.255.255 udp sport bootpc udp dport bootps drop
+
+ # Silently drop DHCPv6 from other clients.
+ ip6 saddr fe80::/64 ip6 daddr fe80::/64 udp sport dhcpv6-client udp dport dhcpv6-server drop
+
+ # mDNS (ZeroConf/Bonjour)
+ ip daddr 224.0.0.251 udp dport mdns accept
+ ip6 daddr ff02::fb udp dport mdns accept
+
+ # SSDP: https://en.wikipedia.org/wiki/Simple_Service_Discovery_Protocol
+ ip daddr 239.255.255.250 udp dport 1900 accept
+ ip6 daddr {
+ ff02::c,
+ ff05::c,
+ ff08::c,
+ ff0e::c
+ } udp dport 1900 accept
+
+ tcp dport @tcp_open_ports tcp flags & (fin | syn | rst | ack) == syn accept
+ udp dport @udp_open_ports accept
+ }
+
+ chain forward {
+ type filter hook forward priority 0;
+ limit rate 3/minute burst 10 packets log prefix "[FORWARD]: "
+ counter reject
+ }
+
+ chain output {
+ type filter hook output priority 0;
+ counter accept
+ }
+}