rules.j2 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. #!/usr/sbin/nft -f
  2. flush ruleset
  3. table inet filter {
  4. set icmp4 {
  5. type icmp_type . icmp_code;
  6. flags interval;
  7. elements = {
  8. echo-request . 0,
  9. echo-reply . 0,
  10. destination-unreachable . 0-15,
  11. time-exceeded . 0-1
  12. };
  13. }
  14. set icmp6 {
  15. type icmpv6_type . icmpv6_code;
  16. flags interval;
  17. elements = {
  18. destination-unreachable . 0-7,
  19. packet-too-big . 0,
  20. time-exceeded . 0-1,
  21. parameter-problem . 0-2,
  22. echo-request . 0,
  23. echo-reply . 0,
  24. nd-router-solicit . 0,
  25. nd-router-advert . 0,
  26. nd-neighbor-solicit . 0,
  27. nd-neighbor-advert . 0,
  28. ind-neighbor-solicit . 0,
  29. ind-neighbor-advert . 0
  30. };
  31. }
  32. set dnet_interfaces {
  33. type ifname;
  34. elements = {
  35. {% if peers is defined %}{% for peer in peers %}
  36. "{{ peer.interface }}",
  37. {% endfor %}{% endif %}
  38. {% for ct in crazytrace %}
  39. "{{ ct.interface }}",
  40. {% endfor %}
  41. };
  42. }
  43. set dnet_ipv6 {
  44. type ipv6_addr;
  45. flags interval;
  46. elements = {
  47. fd00::/8
  48. };
  49. }
  50. set own_nets6 {
  51. type ipv6_addr;
  52. flags interval;
  53. elements = {
  54. {{ routing.ownnet }}
  55. }
  56. }
  57. chain dnet_forward {
  58. meta protocol != ip6 counter drop;
  59. # Reject own network from peers
  60. {% for ct in crazytrace %}
  61. ip6 saddr @own_nets6 ip6 saddr {{ ct.prefix }}/64 iifname "{{ ct.interface }}" accept;
  62. {% endfor %}
  63. meta protocol ip6 ip6 saddr @own_nets6 counter drop;
  64. # Reject non-crxn addresses from peers
  65. meta protocol ip6 ip6 saddr != @dnet_ipv6 \
  66. log prefix "[nftables][dnet] Someone tried to forward with non-dnet source address: " counter reject;
  67. meta protocol ip6 ip6 daddr != @dnet_ipv6 \
  68. log prefix "[nftables][dnet] Someone tried to forward with non-dnet destination address: " counter reject;
  69. # Gather some statistics about possible attacks in the crxn
  70. tcp flags & (fin|psh|urg) == fin|psh|urg \
  71. log prefix "[nftables][dnet] Forward XMAS: " counter;
  72. tcp flags & (fin|syn|rst|psh|ack|urg) == 0x0 \
  73. log prefix "[nftables][dnet] Forward TCP null package: " counter;
  74. tcp flags syn \
  75. tcp option maxseg size 1-535 \
  76. log prefix "[nftables][dnet] Forward invalid TCP MSS: " counter;
  77. meta nfproto ipv4 @nh,48,8 & 0x80 == 0x80 \
  78. log prefix "[nftables] Forward evil bit: " counter;
  79. counter accept;
  80. }
  81. chain dnet_input {
  82. {% for ct in crazytrace %}
  83. ip6 saddr @own_nets6 ip6 saddr {{ ct.prefix }}/64 iifname "{{ ct.interface }}" accept;
  84. {% endfor %}
  85. ip6 saddr @own_nets6 \
  86. log prefix "[nftables][dnet] Hjacking of the own network: " counter drop;
  87. ip6 saddr != @dnet_ipv6 ip6 saddr != fe80::/10 \
  88. log prefix "[nftables][dnet] Invalid source address: " counter drop;
  89. ip6 saddr fe80::/64 udp dport 6696 accept;
  90. }
  91. chain drop_evil_ct {
  92. # CT INVALID
  93. ct state invalid counter drop;
  94. # If a TCP is New and has no Syn Flag:
  95. tcp flags & (fin|syn|rst|ack) != syn ct state new counter drop;
  96. }
  97. chain drop_evil {
  98. meta nfproto ipv4 @nh,48,8 & 0x80 == 0x80 \
  99. log prefix "[nftables] Evil bit: " counter;
  100. tcp flags & (fin|psh|urg) == fin|psh|urg \
  101. log prefix "[nftables] XMAS: " counter drop;
  102. tcp flags & (fin|syn|rst|psh|ack|urg) == 0x0 \
  103. log prefix "[nftables] TCP null package: " counter drop;
  104. tcp flags syn \
  105. tcp option maxseg size 1-535 \
  106. log prefix "[nftables] Invalid TCP MSS: " counter drop;
  107. iifname != @dnet_interfaces iifname != "lo" ip6 saddr @dnet_ipv6 \
  108. log prefix "[nftables] Dnet packet on non-dnet interface: " counter drop;
  109. }
  110. chain common_input {
  111. }
  112. chain input {
  113. type filter hook input priority 0;
  114. policy drop;
  115. jump drop_evil;
  116. jump drop_evil_ct;
  117. # Anti-lockout
  118. tcp dport 22 accept;
  119. # Filter dnet connections
  120. iifname @dnet_interfaces jump dnet_input;
  121. ct state { established, related } accept;
  122. icmp type . icmp code @icmp4 accept;
  123. icmpv6 type . icmpv6 code @icmp6 accept;
  124. {% if firewall.alfis is defined %}
  125. tcp dport 4244 accept;
  126. {% endif %}
  127. {% if firewall.http is defined %}
  128. tcp dport 80 accept;
  129. {% endif %}
  130. {% if firewall.https is defined %}
  131. tcp dport 443 accept;
  132. {% endif %}
  133. # WireGuard
  134. {% set wg_peers = [] %}
  135. {% for peer in peers %}{% if peer.type == "wg" %}
  136. {% set _ = wg_peers.append(peer.wg.port) %}
  137. {% endif %}{% endfor %}
  138. {% if wg_peers %}
  139. udp dport { {{ wg_peers | join(",") }} } accept;
  140. {% endif %}
  141. # fastd
  142. {% set fastd_peers = [] %}
  143. {% for peer in peers %}{% if peer.type == "fastd" %}
  144. {% set _ = fastd_peers.append(peer.fastd.port) %}
  145. {% endif %}{% endfor %}
  146. {% if fastd_peers %}
  147. udp dport { {{ fastd_peers | join(",") }} } accept;
  148. {% endif %}
  149. # OpenVPN
  150. {% set openvpn_peers = [] %}
  151. {% for peer in peers %}{% if peer.type == "openvpn" %}
  152. {% set _ = openvpn_peers.append(peer.openvpn.port) %}
  153. {% endif %}{% endfor %}
  154. {% if openvpn_peers %}
  155. udp dport { {{ openvpn_peers | join(",") }} } accept;
  156. {% endif %}
  157. {% if babelweb2.nginx.telnet_proxy is defined and babelweb2.nginx.telnet_proxy %}
  158. # babelweb2 proxy
  159. tcp dport 33321 accept;
  160. {% endif %}
  161. {% if yggdrasil.listen is defined %}
  162. {% for item in yggdrasil.listen %}
  163. tcp dport {{ item.port }} accept;
  164. {% endfor %}
  165. {% endif %}
  166. {% if yggdrasil.multicast_discovery is defined %}
  167. {% for item in yggdrasil.multicast_discovery %}
  168. udp dport 9001 ip6 daddr ff02::114 iifname {{ item.interface }} accept;
  169. {% endfor %}
  170. {% endif %}
  171. {% for peer in peers if peer.type == "gre" %}
  172. ip protocol gre ip{% if ":" in peer.gre.endpoint %}:{% endif %} saddr {{ peer.gre.endpoint }} accept;
  173. {% endfor %}
  174. {% if firewall.rules is defined %}{% for rule in firewall.rules %}
  175. {{ rule }};
  176. {% endfor %}{% endif %}
  177. # UDP traceroute
  178. udp dport 33424-33689 ip6 saddr @dnet_ipv6 counter reject;
  179. # Accept all link local connections
  180. iifname lo ip daddr 127.0.0.1/8 counter accept;
  181. iifname lo ip6 daddr ::1/128 counter accept;
  182. # Log attempts from peers
  183. ip6 saddr fe80::/10 \
  184. log prefix "[nftables] Violation from peer: " counter;
  185. }
  186. chain forward {
  187. type filter hook forward priority 0;
  188. policy drop;
  189. iifname @dnet_interfaces oifname @dnet_interfaces goto dnet_forward;
  190. }
  191. chain output {
  192. type filter hook output priority 0;
  193. }
  194. }