nftables.conf.tmpl 6.8 KB

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