nftables.conf.tmpl 8.0 KB

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