nftables.conf.tmpl 6.8 KB

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