#!/usr/bin/env nft -f # The home-server project produces a multi-purpose setup using Ansible. # Copyright © 2018–2023 Y. Gablin, under the GPL-3.0-or-later license. # Full licensing information in the LICENSE file, or gnu.org/licences/gpl-3.0.txt if the file is missing. flush ruleset table arp RateLimiter { chain ArpIn { type filter hook input priority 0 policy accept meta iif if_isp limit rate 2/second burst 10 packets accept } chain ArpOut { type filter hook output priority 0 policy accept } } {% for V in ['4', '6'] %} {% set v = V | replace('4', '') %} {% macro trust(list) %} {% for net in list.split(' ') %} {% if not net is match('127(?:\.\d{1,3}){3}(?:/\d+)?|::1|^$') %} {% if (net is match('\d{1,3}(?:\.\d{1,3}){3}(?:/\d+)?') and V == '4') or (net is search(':') and V == '6') %} {{caller(net)}} {% endif %} {% endif %} {% endfor %} {% endmacro %} table ip{{v}} Inet{{V}} { set ssdp_out { type inet_service timeout 5s } chain FilterIn { type filter hook input priority 0 policy drop # early drop of invalid connections ct state invalid drop # allow icmp {% if V == '4' %} icmp type { echo-reply, destination-unreachable, router-advertisement, time-exceeded, parameter-problem } accept icmp type { source-quench, redirect, info-request, info-reply, address-mask-request, address-mask-reply } drop meta l4proto icmp limit rate 2/second burst 4 packets accept {% else %} icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, echo-reply, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } accept meta l4proto ipv6-icmp limit rate 2/second burst 4 packets accept {% endif %} # allow established/related connections ct state {established, related} accept # allow from loopback {% if V == '4' %} meta iif lo ip saddr != 127.0.0.0/8 drop {% else %} meta iif lo ip6 saddr != ::1/128 drop {% endif %} meta iif lo accept # allow ssdp replies udp dport @ssdp_out accept # zeroconf {% call(net) trust(net_trusted_ranges) %} udp dport 5353 ip{{v}} saddr {{net}} accept {% endcall %} # transmission tcp dport {{transmission_bt_port}} accept udp dport {{transmission_bt_port}} accept } chain FilterOut { type filter hook output priority 0 policy drop {% if V == '4' %} icmp type { echo-reply, destination-unreachable, router-advertisement, time-exceeded, parameter-problem } accept icmp type { source-quench, redirect, info-request, info-reply, address-mask-request, address-mask-reply } drop meta l4proto icmp limit rate 2/second burst 4 packets accept {% else %} icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, echo-reply, nd-router-solicit, nd-neighbor-solicit, nd-neighbor-advert } accept meta l4proto ipv6-icmp limit rate 2/second burst 4 packets accept {% endif %} ct state {established, related} accept meta oif lo accept meta oif if_isp udp dport 1900 set add udp sport @ssdp_out accept {% call(net) trust(SafeZone_IP + ' ' + dns_hosts + ' ' + allowed_domains_ip + ' ' + ntp_hosts) %} ip{{v}} daddr {{net}} accept {% endcall %} meta skuid transmission tcp dport 443 accept meta skuid transmission udp dport 443 accept meta skuid transmission tcp dport > 1024 accept meta skuid transmission udp dport > 1024 accept } } {% endfor %}