nftables.conf.tmpl 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  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 roles = node_config.get ('roles', []) %}
  7. {%- set fw_config = salt['pillar.get']('firewall', {}) %}
  8. {%- set admin_access = fw_config.get ('admin_access') %}
  9. {%- set ssh = fw_config.get ('ssh') %}
  10. {%- set icinga2_queriers = salt['pillar.get']('monitoring:icinga2:queriers', []) %}
  11. {%- set nms_list = salt['pillar.get']('globals:snmp:nms_list', []) %}
  12. {%- set services = salt['ffho_netfilter.generate_service_rules'](fw_config, node_config) %}
  13. {%- set forward = salt['ffho_netfilter.generate_forward_policy'](fw_config, node_config) %}
  14. {%- set nat_policy = salt['ffho_netfilter.generate_nat_policy'](node_config) %}
  15. {%- set urpf = salt['ffho_netfilter.generate_urpf_policy'](node_config['ifaces']) %}
  16. {%- set ospf_ifaces = salt['ffho_netfilter.get_ospf_active_interface'](node_config) %}
  17. {%- set vxlan_ifaces = salt['ffho_netfilter.get_vxlan_interfaces'](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. udp dport 0 counter drop
  32. tcp dport 7 counter drop comment "Ignore echo protocol queries"
  33. {%- if vxlan_ifaces %}
  34. udp dport 4789 jump vxlan
  35. {%- endif %}
  36. jump urpf
  37. ip protocol icmp jump icmp_chain
  38. ct state invalid counter drop
  39. jump admin_access
  40. jump monitoring
  41. tcp dport 22 counter jump ssh
  42. {%- if ospf_ifaces %}
  43. {#- ifname sets are introduced in nftables 2.11 #}
  44. meta l4proto ospf iif { {{ ospf_ifaces|join(', ') }} } counter accept
  45. {%- endif %}
  46. {%- if 'router' in roles %}
  47. tcp dport 179 counter jump bgp
  48. {%- endif %}
  49. ct state related,established counter accept
  50. jump services
  51. meta pkttype broadcast counter drop comment "Drop broadcasts before logging"
  52. limit rate 1/second burst 3 packets counter log prefix "nf input: "
  53. limit rate 1/second burst 3 packets counter reject with icmp type admin-prohibited
  54. counter drop
  55. }
  56. chain forward {
  57. type filter hook forward priority 0; policy {{ forward['policy'] }}; # {{ forward['policy_reason'] }}
  58. jump urpf
  59. {%- for rule in forward['rules'].get ('4', []) %}
  60. {{ rule }}
  61. {%- endfor %}
  62. {%- if forward['policy'] == 'drop' %}
  63. limit rate 1/second burst 3 packets counter log prefix "nf forward: "
  64. limit rate 1/second burst 3 packets counter reject with icmp type admin-prohibited
  65. {%- endif %}
  66. }
  67. chain icmp_chain {
  68. icmp type { echo-request, destination-unreachable, time-exceeded } counter accept
  69. }
  70. chain admin_access {
  71. {%- for pfx in admin_access[4].keys()|sort %}
  72. {%- set comment = admin_access[4][pfx] %}
  73. ip saddr {{ pfx }} counter accept comment "{{ comment }}"
  74. {%- endfor %}
  75. }
  76. {%- if 'router' in roles %}
  77. chain bgp {
  78. ip saddr @ibgp-peers counter accept comment "iBGP peers"
  79. # TODO: Add external BGP peers, if any
  80. }
  81. {%- endif %}
  82. chain monitoring {
  83. {%- for ip in icinga2_queriers if not ":" in ip %}
  84. ip saddr {{ ip }} counter accept comment "Icinga2"
  85. {%- endfor %}
  86. {%- for ip in nms_list if not ":" in ip %}
  87. ip saddr {{ ip }} udp dport 161 counter accept comment "NMS"
  88. {%- endfor %}
  89. }
  90. chain ssh {
  91. {%- for pfx in ssh[4].keys()|sort %}
  92. {%- set comment = ssh[4][pfx] %}
  93. ip saddr {{ pfx }} counter accept comment "{{ comment }}"
  94. {%- endfor %}
  95. }
  96. chain services {
  97. {%- for rule in services[4] %}
  98. {{ rule }}
  99. {%- endfor %}
  100. }
  101. chain urpf {
  102. {%- for iface_cfg in urpf %}
  103. {%- for pfx in iface_cfg[4] %}
  104. iif {{ iface_cfg['iface'] }} ip saddr {{ pfx }} return
  105. {%- endfor %}
  106. iif {{ iface_cfg['iface'] }} counter drop
  107. {%- endfor %}
  108. }
  109. {%- if vxlan_ifaces %}
  110. chain vxlan {
  111. {%- for iface in vxlan_ifaces %}
  112. iif {{ iface }} accept
  113. {%- endfor %}
  114. counter drop
  115. }
  116. {%- endif %}
  117. chain log-drop {
  118. limit rate 1/second burst 3 packets counter log prefix "netfilter: "
  119. counter drop
  120. }
  121. chain log-reject {
  122. limit rate 1/second burst 3 packets counter log prefix "netfilter: "
  123. limit rate 1/second burst 3 packets counter reject with icmp type admin-prohibited
  124. counter drop
  125. }
  126. }
  127. table ip6 filter {
  128. set ibgp-peers {
  129. type ipv6_addr
  130. elements = {
  131. 2a03:2260:2342:ffff::1, # cr01.in.ffho.net
  132. 2a03:2260:2342:ffff::2, # cr02.in.ffho.net
  133. 2a03:2260:2342:ffff::3, # cr03.in.ffho.net
  134. }
  135. }
  136. chain input {
  137. type filter hook input priority 0; policy drop;
  138. iifname "lo" counter accept
  139. tcp dport 7 counter drop comment "Ignore echo protocol queries"
  140. {%- if vxlan_ifaces %}
  141. udp dport 4789 jump vxlan
  142. {%- endif %}
  143. jump urpf
  144. meta l4proto icmpv6 jump icmp_chain
  145. ct state invalid counter drop
  146. jump admin_access
  147. jump monitoring
  148. tcp dport 22 counter jump ssh
  149. {%- if ospf_ifaces %}
  150. {#- ifname sets are introduced in nftables 2.11 #}
  151. meta l4proto ospf iif { {{ ospf_ifaces|join(', ') }} } counter accept
  152. {%- endif %}
  153. {%- if 'router' in roles %}
  154. tcp dport 179 counter jump bgp
  155. {%- endif %}
  156. ct state related,established counter accept
  157. counter jump services
  158. limit rate 1/second burst 3 packets counter log prefix "netfilter: "
  159. limit rate 1/second burst 3 packets counter reject with icmpv6 type admin-prohibited
  160. counter drop
  161. }
  162. chain forward {
  163. type filter hook forward priority 0; policy {{ forward['policy'] }}; # {{ forward['policy_reason'] }}
  164. jump urpf
  165. {%- for rule in forward['rules'].get ('6', []) %}
  166. {{ rule }}
  167. {%- endfor %}
  168. {%- if forward['policy'] == 'drop' %}
  169. limit rate 1/second burst 3 packets counter log prefix "nf forward: "
  170. limit rate 1/second burst 3 packets counter reject with icmp type admin-prohibited
  171. {%- endif %}
  172. }
  173. chain icmp_chain {
  174. icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, echo-request, echo-reply } counter accept
  175. 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
  176. icmpv6 type { mld-listener-query, mld-listener-report, mld-listener-reduction } ip6 saddr fe80::/64 counter accept
  177. }
  178. chain admin_access {
  179. {%- for pfx in admin_access[6].keys()|sort %}
  180. {%- set comment = admin_access[6][pfx] %}
  181. ip6 saddr {{ pfx }} counter accept comment "{{ comment }}"
  182. {%- endfor %}
  183. }
  184. {%- if 'router' in roles %}
  185. chain bgp {
  186. ip6 saddr @ibgp-peers counter accept comment "iBGP peers"
  187. # TODO: Add external BGP peers, if any
  188. }
  189. {%- endif %}
  190. chain monitoring {
  191. {%- for ip in icinga2_queriers if ":" in ip %}
  192. ip6 saddr {{ ip }} counter accept comment "Icinga2"
  193. {%- endfor %}
  194. {%- for ip in nms_list if ":" in ip %}
  195. ip6 saddr {{ ip }} udp dport 161 counter accept comment "NMS"
  196. {%- endfor %}
  197. }
  198. chain ssh {
  199. {%- for pfx in ssh[6].keys()|sort %}
  200. {%- set comment = ssh[6][pfx] %}
  201. ip6 saddr {{ pfx }} counter accept comment "{{ comment }}"
  202. {%- endfor %}
  203. }
  204. chain services {
  205. {%- for rule in services[6] %}
  206. {{ rule }}
  207. {%- endfor %}
  208. }
  209. chain urpf {
  210. ip6 saddr fe80::/64 return
  211. {%- for iface_cfg in urpf %}
  212. {%- for pfx in iface_cfg[6] %}
  213. iif {{ iface_cfg['iface'] }} ip6 saddr {{ pfx }} return
  214. {%- endfor %}
  215. iif {{ iface_cfg['iface'] }} counter drop
  216. {%- endfor %}
  217. }
  218. {%- if vxlan_ifaces %}
  219. chain vxlan {
  220. {%- for iface in vxlan_ifaces %}
  221. iif {{ iface }} accept
  222. {%- endfor %}
  223. counter drop
  224. }
  225. {%- endif %}
  226. chain log-drop {
  227. limit rate 1/second burst 3 packets counter log prefix "netfilter: "
  228. counter drop
  229. }
  230. chain log-reject {
  231. limit rate 1/second burst 3 packets counter log prefix "netfilter: "
  232. limit rate 1/second burst 3 packets counter reject with icmpv6 type admin-prohibited
  233. counter drop
  234. }
  235. }
  236. {#-
  237. # NAT
  238. #}
  239. {%- for af in [ 4, 6 ] %}
  240. {%- if nat_policy[af] %}
  241. {%- set af_name = "ip" if af == 4 else "ip6" %}
  242. table {{ af_name }} nat {
  243. {%- for chain in ['output', 'prerouting', 'postrouting'] if chain in nat_policy[af] %}
  244. chain {{ chain }} {
  245. type nat hook {{ chain }} priority 0; policy accept;
  246. {%- for rule in nat_policy[af][chain] %}
  247. {{ rule }}
  248. {%- endfor %}
  249. }
  250. {%- endfor %}
  251. }
  252. {%- endif %}
  253. {%- endfor %}