118 lines
3.7 KiB
Django/Jinja
118 lines
3.7 KiB
Django/Jinja
#!/usr/sbin/nft -f
|
|
{% set ifaces_fabric = interfaces | selectattr('name', 'match', '^lan') | map(attribute='name') %}
|
|
|
|
flush ruleset
|
|
|
|
table inet filter {
|
|
include "/etc/nftables.d/interfaces.nft"
|
|
include "/etc/nftables.d/sets.nft*"
|
|
|
|
set link {
|
|
type iface_index
|
|
elements = { {{ ifaces_fabric | product(['2', '4']) | map('join', '.') | join(', ') }} }
|
|
}
|
|
|
|
chain input {
|
|
type filter hook input priority 0; policy drop
|
|
|
|
ct state vmap { established : accept, related : accept, invalid : drop } \
|
|
comment "Accept established streams and drop invalid connections"
|
|
|
|
iif lo accept \
|
|
comment "Accept any localhost traffic"
|
|
|
|
iif mgmt tcp dport ssh accept \
|
|
comment "Accept SSH from management VRF"
|
|
|
|
tcp dport ssh ip saddr {{ hostvars[master]['ansible_host'] }} accept \
|
|
comment "Accept SSH from firewall master"
|
|
|
|
iif @link tcp dport bgp ip6 saddr fe80::/10 accept \
|
|
comment "Accept link-local BGP on fabric links"
|
|
|
|
iif @link udp dport 3784 ip6 saddr fe80::/10 accept \
|
|
comment "Accept link-local BFD on fabric links"
|
|
|
|
iif @outside udp dport 51820 accept \
|
|
comment "Accept WireGuard from outside"
|
|
|
|
iif {{ iface_sync }} ip6 saddr fe80::/10 udp dport 3780 accept \
|
|
comment "Accept connection tracking sync data"
|
|
|
|
tcp dport auth reject with icmpx type port-unreachable \
|
|
comment "Reject AUTH to make it fail fast"
|
|
|
|
# ICMPv4
|
|
ip protocol icmp icmp type {
|
|
echo-request, echo-reply, destination-unreachable,
|
|
parameter-problem, time-exceeded,
|
|
} accept \
|
|
comment "Accept ICMP"
|
|
|
|
# ICMPv6
|
|
ip6 nexthdr icmpv6 icmpv6 type {
|
|
echo-request, echo-reply, destination-unreachable,
|
|
packet-too-big, parameter-problem, time-exceeded,
|
|
} accept \
|
|
comment "Accept basic IPv6 functionality"
|
|
|
|
ip6 nexthdr icmpv6 icmpv6 type {
|
|
nd-neighbor-solicit, nd-neighbor-advert,
|
|
nd-router-solicit, nd-router-advert,
|
|
} ip6 hoplimit 255 accept \
|
|
comment "Allow IPv6 neighbor discovery"
|
|
}
|
|
|
|
chain forward {
|
|
type filter hook forward priority filter; policy drop
|
|
|
|
ct state { established, related } accept \
|
|
comment "Forward all established and related traffic"
|
|
|
|
ct status dnat accept \
|
|
comment "Forward DNAT traffic for servers and suchlike"
|
|
|
|
# Forward IPv4 to/from VPN users in the same network.
|
|
{% for vlan in vlans %}
|
|
iif @inside ip saddr @{{ vlan.name }} ip daddr @{{ vlan.name }} accept
|
|
{% endfor %}
|
|
|
|
# Forward IPv6 to/from VPN users in the same network.
|
|
{% for vlan in vlans %}
|
|
iif @inside ip6 saddr @{{ vlan.name }}/6 ip6 daddr @{{ vlan.name }}/6 accept
|
|
{% endfor %}
|
|
|
|
include "/etc/nftables.d/forward.nft*"
|
|
}
|
|
|
|
chain output {
|
|
type filter hook output priority 0; policy accept
|
|
}
|
|
}
|
|
|
|
table ip nat {
|
|
include "/etc/nftables.d/interfaces.nft"
|
|
include "/etc/nftables.d/sets.nft*"
|
|
include "/etc/nftables.d/netmap.nft*"
|
|
|
|
# Ensure these maps exist even if empty.
|
|
map netmap-in { type ipv4_addr : interval ipv4_addr; flags interval; }
|
|
map netmap-out { type ipv4_addr : interval ipv4_addr; flags interval; }
|
|
|
|
chain postrouting {
|
|
type nat hook postrouting priority srcnat
|
|
|
|
iif @inside oif @outside snat ip prefix to ip saddr map @netmap-out \
|
|
comment "Static source NAT for 1:1 mapped addresses"
|
|
|
|
include "/etc/nftables.d/nat.nft*"
|
|
}
|
|
|
|
chain prerouting {
|
|
type nat hook prerouting priority dstnat
|
|
|
|
dnat ip prefix to ip daddr map @netmap-in \
|
|
comment "Static destination NAT for 1:1 mapped addresses"
|
|
}
|
|
}
|