rules.j2 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  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. set tailscale4 {
  58. type ipv4_addr;
  59. flags interval;
  60. elements = { 100.64.0.0/10 }
  61. }
  62. set tailscale6 {
  63. type ipv6_addr;
  64. flags interval;
  65. elements = { fd7a:115c:a1e0::/96 }
  66. }
  67. chain dnet_forward {
  68. meta protocol != ip6 counter drop;
  69. # Reject own network from peers
  70. {% for ct in crazytrace %}
  71. ip6 saddr @own_nets6 ip6 saddr {{ ct.prefix }}/64 iifname "{{ ct.interface }}" accept;
  72. {% endfor %}
  73. meta protocol ip6 ip6 saddr @own_nets6 counter drop;
  74. # Reject non-crxn addresses from peers
  75. meta protocol ip6 ip6 saddr != @dnet_ipv6 \
  76. log prefix "[nftables][dnet] Someone tried to forward with non-dnet source address: " counter reject;
  77. meta protocol ip6 ip6 daddr != @dnet_ipv6 \
  78. log prefix "[nftables][dnet] Someone tried to forward with non-dnet destination address: " counter reject;
  79. # Gather some statistics about possible attacks in the crxn
  80. tcp flags & (fin|psh|urg) == fin|psh|urg \
  81. log prefix "[nftables][dnet] Forward XMAS: " counter;
  82. tcp flags & (fin|syn|rst|psh|ack|urg) == 0x0 \
  83. log prefix "[nftables][dnet] Forward TCP null package: " counter;
  84. tcp flags syn \
  85. tcp option maxseg size 1-535 \
  86. log prefix "[nftables][dnet] Forward invalid TCP MSS: " counter;
  87. meta nfproto ipv4 @nh,48,8 & 0x80 == 0x80 \
  88. log prefix "[nftables] Forward evil bit: " counter;
  89. counter accept;
  90. }
  91. chain dnet_input {
  92. {% for ct in crazytrace %}
  93. ip6 saddr @own_nets6 ip6 saddr {{ ct.prefix }}/64 iifname "{{ ct.interface }}" accept;
  94. {% endfor %}
  95. ip6 saddr @own_nets6 \
  96. log prefix "[nftables][dnet] Hjacking of the own network: " counter drop;
  97. ip6 saddr != @dnet_ipv6 ip6 saddr != fe80::/10 \
  98. log prefix "[nftables][dnet] Invalid source address: " counter drop;
  99. ip6 saddr fe80::/64 udp dport 6696 accept;
  100. }
  101. chain drop_evil_ct {
  102. # CT INVALID
  103. ct state invalid counter drop;
  104. # If a TCP is New and has no Syn Flag:
  105. tcp flags & (fin|syn|rst|ack) != syn ct state new counter drop;
  106. }
  107. chain drop_evil {
  108. meta nfproto ipv4 @nh,48,8 & 0x80 == 0x80 \
  109. log prefix "[nftables] Evil bit: " counter;
  110. tcp flags & (fin|psh|urg) == fin|psh|urg \
  111. log prefix "[nftables] XMAS: " counter drop;
  112. tcp flags & (fin|syn|rst|psh|ack|urg) == 0x0 \
  113. log prefix "[nftables] TCP null package: " counter drop;
  114. tcp flags syn \
  115. tcp option maxseg size 1-535 \
  116. log prefix "[nftables] Invalid TCP MSS: " counter drop;
  117. {% if firewall.tailscale is defined and firewall.tailscale %}
  118. iifname != "tailscale0" ip saddr @tailscale4 drop;
  119. iifname != "tailscale0" ip6 saddr @tailscale6 drop;
  120. {% endif %}
  121. iifname != @dnet_interfaces iifname != "lo"{% if firewall.tailscale is defined and firewall.tailscale %} iifname != "tailscale0"{% endif %} ip6 saddr @dnet_ipv6 \
  122. log prefix "[nftables] Dnet packet on non-dnet interface: " counter drop;
  123. }
  124. chain input {
  125. type filter hook input priority 0;
  126. policy drop;
  127. jump drop_evil;
  128. jump drop_evil_ct;
  129. # Anti-lockout
  130. tcp dport 22 accept;
  131. # Filter dnet connections
  132. iifname @dnet_interfaces jump dnet_input;
  133. ct state { established, related } accept;
  134. icmp type . icmp code @icmp4 accept;
  135. icmpv6 type . icmpv6 code @icmp6 accept;
  136. {% if firewall.alfis is defined %}
  137. tcp dport 4244 accept;
  138. {% endif %}
  139. {% if firewall.http is defined %}
  140. tcp dport 80 accept;
  141. {% endif %}
  142. {% if firewall.https is defined %}
  143. tcp dport 443 accept;
  144. {% endif %}
  145. {% if firewall.tailscale is defined and firewall.tailscale %}
  146. udp dport 41641 counter accept;
  147. {% endif %}
  148. # WireGuard
  149. {% set wg_peers = [] %}
  150. {% for peer in peers %}{% if peer.type == "wg" %}
  151. {% set _ = wg_peers.append(peer.wg.port) %}
  152. {% endif %}{% endfor %}
  153. {% if wg_peers %}
  154. udp dport { {{ wg_peers | join(",") }} } accept;
  155. {% endif %}
  156. # fastd
  157. {% set fastd_peers = [] %}
  158. {% for peer in peers %}{% if peer.type == "fastd" %}
  159. {% set _ = fastd_peers.append(peer.fastd.port) %}
  160. {% endif %}{% endfor %}
  161. {% if fastd_peers %}
  162. udp dport { {{ fastd_peers | join(",") }} } accept;
  163. {% endif %}
  164. # OpenVPN
  165. {% set openvpn_peers = [] %}
  166. {% for peer in peers %}{% if peer.type == "openvpn" %}
  167. {% set _ = openvpn_peers.append(peer.openvpn.port) %}
  168. {% endif %}{% endfor %}
  169. {% if openvpn_peers %}
  170. udp dport { {{ openvpn_peers | join(",") }} } accept;
  171. {% endif %}
  172. {% if babelweb2.nginx.telnet_proxy is defined and babelweb2.nginx.telnet_proxy %}
  173. # babelweb2 proxy
  174. tcp dport 33321 accept;
  175. {% endif %}
  176. {% if yggdrasil.listen is defined %}
  177. {% for item in yggdrasil.listen %}
  178. tcp dport {{ item.port }} accept;
  179. {% endfor %}
  180. {% endif %}
  181. {% if yggdrasil.multicast_discovery is defined %}
  182. {% for item in yggdrasil.multicast_discovery %}
  183. udp dport 9001 ip6 daddr ff02::114 iifname {{ item.interface }} accept;
  184. {% endfor %}
  185. {% endif %}
  186. {% for peer in peers if peer.type == "gre" %}
  187. ip protocol gre ip{% if ":" in peer.gre.endpoint %}:{% endif %} saddr {{ peer.gre.endpoint }} accept;
  188. {% endfor %}
  189. {% if firewall.rules is defined %}{% for rule in firewall.rules %}
  190. {{ rule }};
  191. {% endfor %}{% endif %}
  192. # UDP traceroute
  193. udp dport 33424-33689 ip6 saddr @dnet_ipv6 counter reject;
  194. # Accept all link local connections
  195. iifname lo ip daddr 127.0.0.1/8 counter accept;
  196. iifname lo ip6 daddr ::1/128 counter accept;
  197. # Log attempts from peers
  198. ip6 saddr fe80::/10 \
  199. log prefix "[nftables] Violation from peer: " counter;
  200. }
  201. chain forward {
  202. type filter hook forward priority 0;
  203. policy drop;
  204. iifname @dnet_interfaces oifname @dnet_interfaces goto dnet_forward;
  205. }
  206. chain output {
  207. type filter hook output priority 0;
  208. }
  209. }