| 1 |
# Mountaineer baseline firewall — IPv4 and IPv6 |
| 2 |
# |
| 3 |
# Drop inbound by default, allow established/related, allow SSH with rate |
| 4 |
# limiting, allow ICMP/ICMPv6 sane filtering, log dropped. |
| 5 |
# |
| 6 |
# Per-workload allow rules belong in additional files in /etc/nftables.d/ |
| 7 |
# (e.g. 10-web.nft for Caddy ports). The baseline is what every Mountaineer |
| 8 |
# host runs and is loaded by the s6-rc nftables service at boot. |
| 9 |
|
| 10 |
flush ruleset |
| 11 |
|
| 12 |
table inet filter { |
| 13 |
set ssh_offenders { |
| 14 |
type ipv4_addr |
| 15 |
flags timeout |
| 16 |
timeout 1h |
| 17 |
} |
| 18 |
|
| 19 |
chain input { |
| 20 |
type filter hook input priority filter; policy drop; |
| 21 |
|
| 22 |
# Loopback always allowed. |
| 23 |
iif lo accept |
| 24 |
|
| 25 |
# Reject invalid early. |
| 26 |
ct state invalid drop |
| 27 |
|
| 28 |
# Established and related conversations. |
| 29 |
ct state { established, related } accept |
| 30 |
|
| 31 |
# ICMPv4 — echo, destination-unreachable, time-exceeded, parameter-problem. |
| 32 |
ip protocol icmp icmp type { |
| 33 |
echo-request, |
| 34 |
destination-unreachable, |
| 35 |
time-exceeded, |
| 36 |
parameter-problem |
| 37 |
} limit rate 10/second accept |
| 38 |
|
| 39 |
# ICMPv6 — required for IPv6 to function (NDP, MLD, etc.) plus echo. |
| 40 |
ip6 nexthdr ipv6-icmp icmpv6 type { |
| 41 |
destination-unreachable, |
| 42 |
packet-too-big, |
| 43 |
time-exceeded, |
| 44 |
parameter-problem, |
| 45 |
echo-request, |
| 46 |
nd-router-advert, |
| 47 |
nd-neighbor-solicit, |
| 48 |
nd-neighbor-advert, |
| 49 |
mld-listener-query, |
| 50 |
mld-listener-report, |
| 51 |
mld-listener-done, |
| 52 |
mld2-listener-report |
| 53 |
} accept |
| 54 |
|
| 55 |
# SSH — soft rate limit; offenders into a timeout set for one hour. |
| 56 |
tcp dport 22 ct state new ip saddr @ssh_offenders drop |
| 57 |
tcp dport 22 ct state new limit rate 4/minute burst 6 packets accept |
| 58 |
tcp dport 22 ct state new add @ssh_offenders { ip saddr timeout 1h } drop |
| 59 |
|
| 60 |
# Log everything else dropped, rate-limited so the log doesn't flood. |
| 61 |
limit rate 5/minute log prefix "nft drop: " level info |
| 62 |
} |
| 63 |
|
| 64 |
chain forward { |
| 65 |
type filter hook forward priority filter; policy drop; |
| 66 |
# Mountaineer hosts do not forward by default. Workloads that need |
| 67 |
# forwarding (a podman network, a wireguard bridge) add a chain or |
| 68 |
# rule in their own .nft file. |
| 69 |
} |
| 70 |
|
| 71 |
chain output { |
| 72 |
type filter hook output priority filter; policy accept; |
| 73 |
} |
| 74 |
} |
| 75 |
|