The mgmt VRF might not exist yet when nftables rules are loaded, so use iifname instead of iif for dynamic interface lookup.
		
			
				
	
	
		
			80 lines
		
	
	
	
		
			2.6 KiB
		
	
	
	
		
			Django/Jinja
		
	
	
	
	
	
			
		
		
	
	
			80 lines
		
	
	
	
		
			2.6 KiB
		
	
	
	
		
			Django/Jinja
		
	
	
	
	
	
#!/usr/sbin/nft -f
 | 
						|
 | 
						|
flush ruleset
 | 
						|
 | 
						|
table inet filter {
 | 
						|
    set cluster {
 | 
						|
        type ipv4_addr; flags interval; auto-merge
 | 
						|
        elements = {
 | 
						|
{{ nodes | map('device_address') | flatten | selectattr('family.value', '==', 4) | map(attribute='address') | join(',\n') | indent(12, first=True) }}
 | 
						|
        }
 | 
						|
    }
 | 
						|
    set cluster/6 {
 | 
						|
        type ipv6_addr; flags interval; auto-merge
 | 
						|
        elements = {
 | 
						|
{{ nodes | map('device_address') | flatten | selectattr('family.value', '==', 6) | map(attribute='address') | join(',\n') | indent(12, first=True) }}
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    # Just a temporary filter until we get our shit together policy-wise.
 | 
						|
    set allowed {
 | 
						|
        type ipv4_addr; flags interval
 | 
						|
        elements = { 10.32.0.0/14, 193.2.76.176/24, 192.168.251.0/24, 88.200.23.0/24 }
 | 
						|
    }
 | 
						|
    set allowed/6 {
 | 
						|
        type ipv6_addr; flags interval
 | 
						|
        elements = { 2001:1470:fffd:3432::/64, 2001:1470:fffd:a000::/64 }
 | 
						|
    }
 | 
						|
 | 
						|
    chain input {
 | 
						|
        type filter hook input priority filter; policy drop
 | 
						|
 | 
						|
        ct state vmap { invalid : drop, established : accept, related : accept }
 | 
						|
        iif lo accept
 | 
						|
 | 
						|
        ip protocol icmp icmp type {
 | 
						|
            echo-request, echo-reply, destination-unreachable,
 | 
						|
            parameter-problem, time-exceeded,
 | 
						|
        } accept comment "accept some ICMPv4"
 | 
						|
 | 
						|
        ip6 nexthdr icmpv6 icmpv6 type {
 | 
						|
            echo-request, echo-reply, destination-unreachable,
 | 
						|
            packet-too-big, parameter-problem, time-exceeded,
 | 
						|
        } accept comment "accept some ICMPv6"
 | 
						|
 | 
						|
        # BGP / BFD sessions
 | 
						|
        iif lan0 ip6 saddr fe80::/64 accept
 | 
						|
        iif lan1 ip6 saddr fe80::/64 accept
 | 
						|
 | 
						|
        ip saddr @cluster accept comment "accept connections from other nodes"
 | 
						|
        ip6 saddr @cluster/6 accept comment "accept connections from other nodes"
 | 
						|
 | 
						|
{% for service in services %}
 | 
						|
{% set prefixes = service | allowed_prefixes %}
 | 
						|
{% set prefixes4 = prefixes | selectattr('family.value', '==', 4) | map('string') %}
 | 
						|
{% set prefixes6 = prefixes | selectattr('family.value', '==', 6) | map('string') %}
 | 
						|
{% set ports = service.ports | compact_numlist %}
 | 
						|
        # service {{ service.name }}
 | 
						|
{% if prefixes4 %}
 | 
						|
        ip saddr { {{ prefixes4 | join(', ') }} } tcp dport { {{ ports }} } accept
 | 
						|
{% endif %}
 | 
						|
{% if prefixes6 %}
 | 
						|
        ip6 saddr { {{ prefixes6 | join(', ') }} } tcp dport { {{ ports }} } accept
 | 
						|
{% endif %}
 | 
						|
 | 
						|
{% endfor %}
 | 
						|
 | 
						|
        iifname mgmt accept comment "management access"
 | 
						|
 | 
						|
        ip saddr @allowed accept
 | 
						|
        ip6 saddr @allowed/6 accept
 | 
						|
    }
 | 
						|
 | 
						|
    chain forward {
 | 
						|
        type filter hook forward priority filter; policy accept
 | 
						|
    }
 | 
						|
 | 
						|
    chain output {
 | 
						|
        type filter hook output priority filter; policy accept
 | 
						|
    }
 | 
						|
}
 |