nftables.conf.tmpl 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. #!/usr/sbin/nft -f
  2. #
  3. # /etc/nftables.conf - FFHO packet filter configuration
  4. #
  5. {%- set node_config = salt['pillar.get']('nodes:' ~ grains['id']) %}
  6. {%- set nf_cc = node_config.get ('nftables', {}) %}
  7. {%- set roles = node_config.get ('roles', []) %}
  8. {%- set services = node_config.get ('services', []) %}
  9. {%- set fw_policy = salt['pillar.get']('firewall:policy', {}) %}
  10. {%- set acls = salt['pillar.get']('firewall:acls') %}
  11. {%- set admin_access = salt['pillar.get']('firewall:admin_access') %}
  12. {%- set ssh = salt['pillar.get']("firewall:ssh") %}
  13. {%- set icinga2_queriers = salt['pillar.get']('monitoring:icinga2:queriers', []) %}
  14. {%- set nms_list = salt['pillar.get']('globals:snmp:nms_list', []) %}
  15. {%- set forward = salt['ffho_netfilter.generate_forward_policy'](fw_policy, roles, nf_cc) %}
  16. {%- set nat_policy = salt['ffho_netfilter.generate_nat_policy'](roles, nf_cc) %}
  17. {%- set urpf = salt['ffho_netfilter.generate_urpf_policy'](node_config['ifaces']) %}
  18. flush ruleset
  19. table ip filter {
  20. set ibgp-peers {
  21. type ipv4_addr
  22. elements = {
  23. 10.132.255.1, # cr01.in.ffho.net
  24. 10.132.255.2, # cr02.in.ffho.net
  25. 10.132.255.3, # cr03.in.ffho.net
  26. }
  27. }
  28. chain input {
  29. type filter hook input priority 0; policy drop;
  30. iifname "lo" counter accept
  31. ip protocol icmp counter jump icmp_chain
  32. udp dport 0 counter drop
  33. tcp dport 7 counter drop comment "Ignore echo protocol queries"
  34. ct state invalid counter drop
  35. counter jump admin_access
  36. counter jump monitoring
  37. tcp dport 22 counter jump ssh
  38. {%- if 'router' in roles %}
  39. ip daddr { 224.0.0.5, 224.0.0.6 } meta l4proto ospf accept
  40. tcp dport 179 counter jump bgp
  41. {%- endif %}
  42. ct state related,established counter accept
  43. counter jump services
  44. limit rate 1/second burst 3 packets counter log prefix "nf input: "
  45. limit rate 1/second burst 3 packets counter reject with icmp type admin-prohibited
  46. counter drop
  47. }
  48. chain forward {
  49. type filter hook forward priority 0; policy {{ forward['policy'] }}; # {{ forward['policy_reason'] }}
  50. {#- custom rules #}
  51. {%- for rule in forward['rules'].get ('4', []) %}
  52. {{ rule }}
  53. {%- endfor %}
  54. {#- uRPF #}
  55. {%- for iface_cfg in urpf %}
  56. {%- if loop.first %}
  57. # uRPF
  58. {%- endif %}
  59. {%- for pfx in iface_cfg[4] %}
  60. iif {{ iface_cfg['iface'] }} ip saddr {{ pfx }} accept
  61. {%- endfor %}
  62. iif {{ iface_cfg['iface'] }} counter drop
  63. {%- endfor %}
  64. {%- if forward['policy'] == 'drop' %}
  65. limit rate 1/second burst 3 packets counter log prefix "nf forward: "
  66. limit rate 1/second burst 3 packets counter reject with icmp type admin-prohibited
  67. {%- endif %}
  68. }
  69. chain icmp_chain {
  70. icmp type { echo-request, destination-unreachable, time-exceeded } counter accept
  71. }
  72. chain admin_access {
  73. {%- for pfx in admin_access[4].keys()|sort %}
  74. {%- set comment = admin_access[4][pfx] %}
  75. ip saddr {{ pfx }} counter accept comment "{{ comment }}"
  76. {%- endfor %}
  77. }
  78. {%- if 'router' in roles %}
  79. chain bgp {
  80. ip saddr @ibgp-peers counter accept comment "iBGP peers"
  81. # TODO: Add external BGP peers, if any
  82. }
  83. {%- endif %}
  84. chain monitoring {
  85. {%- for ip in icinga2_queriers if not ":" in ip %}
  86. ip saddr {{ ip }} counter accept comment "Icinga2"
  87. {%- endfor %}
  88. {%- for ip in nms_list if not ":" in ip %}
  89. ip saddr {{ ip }} udp dport 161 counter accept comment "NMS"
  90. {%- endfor %}
  91. }
  92. chain ssh {
  93. {%- for pfx in ssh[4].keys()|sort %}
  94. {%- set comment = ssh[4][pfx] %}
  95. ip saddr {{ pfx }} counter accept comment "{{ comment }}"
  96. {%- endfor %}
  97. }
  98. chain services {
  99. {%- for rule in salt['ffho_netfilter.generate_service_rules'](services, acls, 4) %}
  100. {{ rule }}
  101. {%- endfor %}
  102. }
  103. chain log-drop {
  104. limit rate 1/second burst 3 packets counter log prefix "netfilter: "
  105. counter drop
  106. }
  107. chain log-reject {
  108. limit rate 1/second burst 3 packets counter log prefix "netfilter: "
  109. limit rate 1/second burst 3 packets counter reject with icmp type admin-prohibited
  110. counter drop
  111. }
  112. }
  113. table ip6 filter {
  114. set ibgp-peers {
  115. type ipv6_addr
  116. elements = {
  117. 2a03:2260:2342:ffff::1, # cr01.in.ffho.net
  118. 2a03:2260:2342:ffff::2, # cr02.in.ffho.net
  119. 2a03:2260:2342:ffff::3, # cr03.in.ffho.net
  120. }
  121. }
  122. chain input {
  123. type filter hook input priority 0; policy drop;
  124. iifname "lo" counter accept
  125. ip6 nexthdr icmpv6 counter jump icmp_chain
  126. tcp dport 7 counter drop comment "Ignore echo protocol queries"
  127. ct state invalid counter drop comment "Drop packets that do not make sense."
  128. counter jump admin_access
  129. counter jump monitoring
  130. tcp dport 22 counter jump ssh
  131. {%- if 'router' in roles %}
  132. ip6 saddr fe80::/64 ip6 daddr { fe80::/10, ff02::5, ff02::6 } meta l4proto ospf accept
  133. tcp dport 179 counter jump bgp
  134. {%- endif %}
  135. ct state related,established counter accept comment "Allow established connections."
  136. counter jump services
  137. limit rate 1/second burst 3 packets counter log prefix "netfilter: "
  138. limit rate 1/second burst 3 packets counter reject with icmpv6 type admin-prohibited
  139. counter drop
  140. }
  141. chain forward {
  142. type filter hook forward priority 0; policy {{ forward['policy'] }}; # {{ forward['policy_reason'] }}
  143. {#- custom rules #}
  144. {%- for rule in forward['rules'].get ('6', []) %}
  145. {{ rule }}
  146. {%- endfor %}
  147. {#- uRPF #}
  148. {%- for iface_cfg in urpf %}
  149. {%- if loop.first %}
  150. # uRPF
  151. {%- endif %}
  152. {%- for pfx in iface_cfg[6] %}
  153. iif {{ iface_cfg['iface'] }} ip6 saddr {{ pfx }} accept
  154. {%- endfor %}
  155. iif {{ iface_cfg['iface'] }} counter drop
  156. {%- endfor %}
  157. {%- if forward['policy'] == 'drop' %}
  158. limit rate 1/second burst 3 packets counter log prefix "nf forward: "
  159. limit rate 1/second burst 3 packets counter reject with icmp type admin-prohibited
  160. {%- endif %}
  161. }
  162. chain icmp_chain {
  163. icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, echo-request, echo-reply } counter accept
  164. 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
  165. }
  166. chain admin_access {
  167. {%- for pfx in admin_access[6].keys()|sort %}
  168. {%- set comment = admin_access[6][pfx] %}
  169. ip6 saddr {{ pfx }} counter accept comment "{{ comment }}"
  170. {%- endfor %}
  171. }
  172. {%- if 'router' in roles %}
  173. chain bgp {
  174. ip6 saddr @ibgp-peers counter accept comment "iBGP peers"
  175. # TODO: Add external BGP peers, if any
  176. }
  177. {%- endif %}
  178. chain monitoring {
  179. {%- for ip in icinga2_queriers if ":" in ip %}
  180. ip6 saddr {{ ip }} counter accept comment "Icinga2"
  181. {%- endfor %}
  182. {%- for ip in nms_list if ":" in ip %}
  183. ip6 saddr {{ ip }} udp dport 161 counter accept comment "NMS"
  184. {%- endfor %}
  185. }
  186. chain ssh {
  187. {%- for pfx in ssh[6].keys()|sort %}
  188. {%- set comment = ssh[6][pfx] %}
  189. ip6 saddr {{ pfx }} counter accept comment "{{ comment }}"
  190. {%- endfor %}
  191. }
  192. chain services {
  193. {%- for rule in salt['ffho_netfilter.generate_service_rules'](services, acls, 6) %}
  194. {{ rule }}
  195. {%- endfor %}
  196. }
  197. chain log-drop {
  198. limit rate 1/second burst 3 packets counter log prefix "netfilter: "
  199. counter drop
  200. }
  201. chain log-reject {
  202. limit rate 1/second burst 3 packets counter log prefix "netfilter: "
  203. limit rate 1/second burst 3 packets counter reject with icmpv6 type admin-prohibited
  204. counter drop
  205. }
  206. }
  207. {#-
  208. # NAT
  209. #}
  210. {%- for af in [ 4, 6 ] %}
  211. {%- if nat_policy[af] %}
  212. {%- set af_name = "ip" if af == 4 else "ip6" %}
  213. table {{ af_name }} nat {
  214. {%- for chain in ['output', 'prerouting', 'postrouting'] if chain in nat_policy[af] %}
  215. chain {{ chain }} {
  216. type nat hook {{ chain }} priority 0; policy accept;
  217. {%- for rule in nat_policy[af][chain] %}
  218. {{ rule }}
  219. {%- endfor %}
  220. }
  221. {%- endfor %}
  222. }
  223. {%- endif %}
  224. {%- endfor %}