123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315 |
- #!/usr/sbin/nft -f
- #
- # /etc/nftables.conf - FFHO packet filter configuration
- #
- {%- set node_config = salt['pillar.get']('nodes:' ~ grains['id']) %}
- {%- set roles = node_config.get ('roles', []) %}
- {%- set fw_config = salt['pillar.get']('firewall', {}) %}
- {%- set admin_access = fw_config.get ('admin_access') %}
- {%- set ssh = fw_config.get ('ssh') %}
- {%- set prometheus_hosts = salt['pillar.get']('firewall:acls:prometheus') %}
- {%- set icinga2_queriers = salt['pillar.get']('monitoring:icinga2:queriers', []) %}
- {%- set nms_list = salt['pillar.get']('globals:snmp:nms_list', []) %}
- {%- set services = salt['ffho_netfilter.generate_service_rules'](fw_config, node_config) %}
- {%- set forward = salt['ffho_netfilter.generate_forward_policy'](fw_config, node_config) %}
- {%- set nat_policy = salt['ffho_netfilter.generate_nat_policy'](node_config) %}
- {%- set mgmt_config = salt['ffho_netfilter.generate_mgmt_config'](fw_config, node_config) %}
- {%- set urpf = salt['ffho_netfilter.generate_urpf_policy'](node_config) %}
- {%- set ospf_ifaces = salt['ffho_netfilter.get_ospf_active_interface'](node_config) %}
- {%- set vxlan_ifaces = salt['ffho_netfilter.get_vxlan_interfaces'](node_config['ifaces']) %}
- flush ruleset
- table ip filter {
- set ibgp-peers {
- type ipv4_addr
- elements = {
- 10.132.255.1, # cr01.in.ffho.net
- 10.132.255.2, # cr02.in.ffho.net
- 10.132.255.3, # cr03.in.ffho.net
- }
- }
- chain input {
- type filter hook input priority 0; policy drop;
- iifname "lo" counter accept
- udp dport 0 counter drop
- tcp dport 7 counter drop comment "Ignore echo protocol queries"
- {%- if vxlan_ifaces %}
- udp dport 4789 jump vxlan
- {%- endif %}
- {%- if urpf %}
- jump urpf
- {%- endif %}
- ip protocol icmp jump icmp_chain
- ct state invalid counter drop
- jump admin_access
- jump monitoring
- tcp dport 22 counter jump ssh
- {%- if ospf_ifaces %}
- {#- ifname sets are introduced in nftables 2.11 #}
- meta l4proto ospf iifname { {{ ospf_ifaces|join(', ') }} } counter accept
- {%- endif %}
- {%- if 'router' in roles %}
- tcp dport 179 counter jump bgp
- {%- endif %}
- ct state related,established counter accept
- jump services
- meta pkttype broadcast counter drop comment "Drop broadcasts before logging"
- limit rate 1/second burst 3 packets counter log prefix "nf input: "
- limit rate 1/second burst 3 packets counter reject with icmp type admin-prohibited
- counter drop
- }
- chain forward {
- type filter hook forward priority 0; policy {{ forward['policy'] }}; # {{ forward['policy_reason'] }}
- {%- if urpf %}
- jump urpf
- {%- endif %}
- {%- if mgmt_config and mgmt_config['prefixes'][4] %}
- ip daddr { {{ mgmt_config['prefixes'][4]|join(', ') }} } oifname { {{ mgmt_config['ifaces']|join(', ') }} } jump mgmt
- {%- endif %}
- {%- for rule in forward['rules'].get ('4', []) %}
- {{ rule }}
- {%- endfor %}
- {%- if forward['policy'] == 'drop' %}
- limit rate 1/second burst 3 packets counter log prefix "nf forward: "
- limit rate 1/second burst 3 packets counter reject with icmp type admin-prohibited
- {%- endif %}
- }
- chain icmp_chain {
- icmp type { echo-request, destination-unreachable, time-exceeded } counter accept
- }
- chain admin_access {
- {%- for pfx in admin_access[4].keys()|sort %}
- {%- set comment = admin_access[4][pfx] %}
- ip saddr {{ pfx }} counter accept comment "{{ comment }}"
- {%- endfor %}
- }
- {%- if 'router' in roles %}
- chain bgp {
- ip saddr @ibgp-peers counter accept comment "iBGP peers"
- # TODO: Add external BGP peers, if any
- }
- {%- endif %}
- {%- if mgmt_config %}
- chain mgmt {
- ct state related,established counter accept
- jump admin_access
- jump icmp_chain
- jump monitoring
- jump log-reject
- }
- {%- endif %}
- chain monitoring {
- ip saddr { {{ prometheus_hosts[4]|join(", ") }} } tcp dport 9100 counter accept comment "prometheus"
- {%- for ip in icinga2_queriers if not ":" in ip %}
- ip saddr {{ ip }} counter accept comment "Icinga2"
- {%- endfor %}
- {%- for ip in nms_list if not ":" in ip %}
- ip saddr {{ ip }} udp dport 161 counter accept comment "NMS"
- {%- endfor %}
- }
- chain ssh {
- {%- for pfx in ssh[4].keys()|sort %}
- {%- set comment = ssh[4][pfx] %}
- ip saddr {{ pfx }} counter accept comment "{{ comment }}"
- {%- endfor %}
- }
- chain services {
- {%- for rule in services[4] %}
- {{ rule }}
- {%- endfor %}
- }
- {%- if urpf %}
- chain urpf {
- {%- for iface_cfg in urpf %}
- {%- for pfx in iface_cfg[4] %}
- iifname {{ iface_cfg['iface'] }} ip saddr {{ pfx }} return
- {%- endfor %}
- iifname {{ iface_cfg['iface'] }} counter drop
- {%- endfor %}
- }
- {%- endif %}
- {%- if vxlan_ifaces %}
- chain vxlan {
- {%- for iface in vxlan_ifaces %}
- iifname {{ iface }} accept
- {%- endfor %}
- counter drop
- }
- {%- endif %}
- chain log-drop {
- limit rate 1/second burst 3 packets counter log prefix "netfilter: "
- counter drop
- }
- chain log-reject {
- limit rate 1/second burst 3 packets counter log prefix "netfilter: "
- limit rate 1/second burst 3 packets counter reject with icmp type admin-prohibited
- counter drop
- }
- }
- table ip6 filter {
- set ibgp-peers {
- type ipv6_addr
- elements = {
- 2a03:2260:2342:ffff::1, # cr01.in.ffho.net
- 2a03:2260:2342:ffff::2, # cr02.in.ffho.net
- 2a03:2260:2342:ffff::3, # cr03.in.ffho.net
- }
- }
- chain input {
- type filter hook input priority 0; policy drop;
- iifname "lo" counter accept
- tcp dport 7 counter drop comment "Ignore echo protocol queries"
- {%- if vxlan_ifaces %}
- udp dport 4789 jump vxlan
- {%- endif %}
- {%- if urpf %}
- jump urpf
- {%- endif %}
- meta l4proto icmpv6 jump icmp_chain
- ct state invalid counter drop
- jump admin_access
- jump monitoring
- tcp dport 22 counter jump ssh
- {%- if ospf_ifaces %}
- {#- ifname sets are introduced in nftables 2.11 #}
- meta l4proto ospf iifname { {{ ospf_ifaces|join(', ') }} } counter accept
- {%- endif %}
- {%- if 'router' in roles %}
- tcp dport 179 counter jump bgp
- {%- endif %}
- ct state related,established counter accept
- counter jump services
- limit rate 1/second burst 3 packets counter log prefix "netfilter: "
- limit rate 1/second burst 3 packets counter reject with icmpv6 type admin-prohibited
- counter drop
- }
- chain forward {
- type filter hook forward priority 0; policy {{ forward['policy'] }}; # {{ forward['policy_reason'] }}
- {%- if urpf %}
- jump urpf
- {%- endif %}
- {%- for rule in forward['rules'].get ('6', []) %}
- {{ rule }}
- {%- endfor %}
- {%- if forward['policy'] == 'drop' %}
- limit rate 1/second burst 3 packets counter log prefix "nf forward: "
- limit rate 1/second burst 3 packets counter reject with icmpv6 type admin-prohibited
- {%- endif %}
- }
- chain icmp_chain {
- icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, echo-request, echo-reply } counter accept
- icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert, ind-neighbor-solicit, ind-neighbor-advert } ip6 hoplimit 255 counter accept
- icmpv6 type { mld-listener-query, mld-listener-report, mld-listener-reduction } ip6 saddr fe80::/64 counter accept
- }
- chain admin_access {
- {%- for pfx in admin_access[6].keys()|sort %}
- {%- set comment = admin_access[6][pfx] %}
- ip6 saddr {{ pfx }} counter accept comment "{{ comment }}"
- {%- endfor %}
- }
- {%- if 'router' in roles %}
- chain bgp {
- ip6 saddr @ibgp-peers counter accept comment "iBGP peers"
- # TODO: Add external BGP peers, if any
- }
- {%- endif %}
- chain monitoring {
- ip6 saddr { {{ prometheus_hosts[6]|join(", ") }} } tcp dport 9100 counter accept comment "prometheus"
- {%- for ip in icinga2_queriers if ":" in ip %}
- ip6 saddr {{ ip }} counter accept comment "Icinga2"
- {%- endfor %}
- {%- for ip in nms_list if ":" in ip %}
- ip6 saddr {{ ip }} udp dport 161 counter accept comment "NMS"
- {%- endfor %}
- }
- chain ssh {
- {%- for pfx in ssh[6].keys()|sort %}
- {%- set comment = ssh[6][pfx] %}
- ip6 saddr {{ pfx }} counter accept comment "{{ comment }}"
- {%- endfor %}
- }
- chain services {
- {%- for rule in services[6] %}
- {{ rule }}
- {%- endfor %}
- }
- {%- if urpf %}
- chain urpf {
- ip6 saddr fe80::/64 return
- {%- for iface_cfg in urpf %}
- {%- for pfx in iface_cfg[6] %}
- iifname {{ iface_cfg['iface'] }} ip6 saddr {{ pfx }} return
- {%- endfor %}
- iifname {{ iface_cfg['iface'] }} counter drop
- {%- endfor %}
- }
- {%- endif %}
- {%- if vxlan_ifaces %}
- chain vxlan {
- {%- for iface in vxlan_ifaces %}
- iifname {{ iface }} accept
- {%- endfor %}
- counter drop
- }
- {%- endif %}
- chain log-drop {
- limit rate 1/second burst 3 packets counter log prefix "netfilter: "
- counter drop
- }
- chain log-reject {
- limit rate 1/second burst 3 packets counter log prefix "netfilter: "
- limit rate 1/second burst 3 packets counter reject with icmpv6 type admin-prohibited
- counter drop
- }
- }
- {#-
- # NAT
- #}
- {%- for af in [ 4, 6 ] %}
- {%- if nat_policy[af] %}
- {%- set af_name = "ip" if af == 4 else "ip6" %}
- table {{ af_name }} nat {
- {%- for chain in ['output', 'prerouting', 'postrouting'] if chain in nat_policy[af] %}
- chain {{ chain }} {
- type nat hook {{ chain }} priority 0; policy accept;
- {%- for rule in nat_policy[af][chain] %}
- {{ rule }}
- {%- endfor %}
- }
- {%- endfor %}
- }
- {%- endif %}
- {%- endfor %}
|