106 lines
3.8 KiB
Django/Jinja
106 lines
3.8 KiB
Django/Jinja
#!/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 %}
|