default-rules.nix (7654B)
1 let 2 drop = expr: "${expr} drop"; 3 accept = expr: "${expr} accept"; 4 mcast-scope = 8; 5 allow-incoming = false; 6 in 7 { 8 bogons-ip6 = { 9 type = "filter"; 10 family = "ip6"; 11 policy = "accept"; 12 hook = "prerouting"; 13 rules = [ 14 (drop "ip6 saddr ff00::/8") # multicast saddr is illegal 15 16 (drop "ip6 saddr ::/128") # unspecified address 17 (drop "ip6 daddr ::/128") 18 (drop "ip6 saddr 2001:db8::/32") # documentation addresses 19 (drop "ip6 daddr 2001:db8::/32") 20 21 # Reverse path filtering: drop packet if it's not coming from 22 # the same interface that we'd use to send a reply. Works by 23 # doing a lookup in the FIB to find how we'd route a packet _to_ 24 # saddr through iif, and then checking the output interface 25 # returned by the lookup. if oif is 0, that means no route was 26 # found for that address with that interface, so the packet can 27 # be dropped 28 # 29 # https://wiki.nftables.org/wiki-nftables/index.php/Matching_routing_information#fib 30 # https://thr3ads.net/netfilter-buglog/2018/01/2843000-Bug-1220-New-Reverse-path-filtering-using-fib-needs-better-documentation 31 (drop "fib saddr . iif oif eq 0") 32 33 (drop "icmpv6 type router-renumbering") 34 (drop "icmpv6 type 139") # Node Information Query 35 (drop "icmpv6 type 140") # Node Information Response 36 (drop "icmpv6 type 100") 37 (drop "icmpv6 type 101") 38 (drop "icmpv6 type 200") 39 (drop "icmpv6 type 201") 40 (drop "icmpv6 type 127") 41 (drop "icmpv6 type 255") 42 (drop "icmpv6 type destination-unreachable ct state invalid,untracked") 43 ]; 44 }; 45 46 forward-ip6 = { 47 type = "filter"; 48 family = "ip6"; 49 policy = "drop"; 50 hook = "forward"; 51 rules = [ 52 (drop "ip6 saddr ::1/128") # loopback address [RFC4291] 53 (drop "ip6 daddr ::1/128") 54 (drop "ip6 saddr ::FFFF:0:0/96") # IPv4-mapped addresses 55 (drop "ip6 daddr ::FFFF:0:0/96") 56 (drop "ip6 saddr fe80::/10") # link-local unicast 57 (drop "ip6 daddr fe80::/10") 58 (drop "ip6 saddr 2001:10::/28") # ORCHID [RFC4843]. 59 (drop "ip6 daddr 2001:10::/28") 60 61 (drop "ip6 saddr fc00::/7") # unique local source 62 (drop "ip6 daddr fc00::/7") # and/or dst addresses [RFC4193] 63 64 # multicast with wrong scopes 65 (drop 66 # dest addr first byte 0xff, low nibble of second byte <= scope 67 # https://www.mankier.com/8/nft#Payload_Expressions-Raw_Payload_Expression 68 "@nh,192,8 eq 0xff @nh,204,4 le ${toString mcast-scope}" 69 ) 70 71 (accept "oifname @lan iifname @wan meta l4proto udp ct state established,related") 72 (accept "iifname @lan oifname @wan meta l4proto udp") 73 74 (accept "meta l4proto icmpv6") 75 (accept "meta l4proto ah") 76 (accept "meta l4proto esp") 77 78 # does this ever get used or does the preceding general udp accept 79 # already grab anything that might get here? 80 (accept "oifname @wan udp dport 500") # IKE Protocol [RFC5996]. haha zyxel 81 (accept "ip6 nexthdr 139") # Host Identity Protocol 82 83 ## FIXME no support yet for recs 27-30 Mobility Header 84 85 (accept "oifname @lan iifname @wan meta l4proto tcp ct state established,related") 86 (accept "iifname @lan oifname @wan meta l4proto tcp") 87 88 (accept "oifname @lan iifname @wan meta l4proto sctp ct state established,related") 89 (accept "iifname @lan oifname @wan meta l4proto sctp") 90 91 (accept "oifname @lan iifname @wan meta l4proto dccp ct state established,related") 92 (accept "iifname @lan oifname @wan meta l4proto dccp") 93 94 # we can allow all reasonable inbound, or we can use an explicit 95 # allowlist to enumerate the endpoints that are allowed to 96 # accept inbound from the WAN 97 ( 98 if allow-incoming then 99 accept "oifname @lan iifname @wan" 100 else 101 "iifname @wan jump incoming-allowed-ip6" 102 ) 103 # allow all outbound and any inbound that's part of a 104 # recognised (outbound-initiated) flow 105 (accept "oifname @lan iifname @wan ct state established,related") 106 (accept "iifname @lan oifname @wan ") 107 108 "log prefix \"DENIED CHAIN=forward-ip6 \"" 109 ]; 110 }; 111 112 input-ip6-lan = { 113 type = "filter"; 114 family = "ip6"; 115 116 rules = [ 117 (accept "udp dport 547") # dhcp, could restrict to daddr ff02::1:2 118 (accept "udp dport 53") # dns 119 (accept "tcp dport 22") 120 ]; 121 }; 122 123 input-ip6-wan = { 124 type = "filter"; 125 family = "ip6"; 126 127 rules = [ 128 (accept "udp dport 546") # dhcp client, needed for prefix delegation 129 ]; 130 }; 131 132 input-ip6 = { 133 type = "filter"; 134 family = "ip6"; 135 policy = "drop"; 136 hook = "input"; 137 rules = [ 138 (accept "meta l4proto icmpv6") 139 "iifname @lan jump input-ip6-lan" 140 "iifname @wan jump input-ip6-wan" 141 (if allow-incoming then accept "iifname @wan" else "iifname @wan jump incoming-allowed-ip6") 142 # how does this even make sense in an input chain? 143 (accept "iifname @wan ct state established,related") 144 (accept "iifname @lan ") 145 "log prefix \"DENIED CHAIN=input-ip6 \"" 146 ]; 147 }; 148 149 incoming-allowed-ip6 = { 150 type = "filter"; 151 family = "ip6"; 152 rules = [ 153 # this is where you put permitted incoming connections 154 # "oifname @lan ip6 daddr 2001:8b0:de3a:40de::e9d tcp dport 22" 155 ]; 156 }; 157 158 nat-tx = { 159 type = "nat"; 160 hook = "postrouting"; 161 priority = "100"; 162 policy = "accept"; 163 family = "ip"; 164 rules = [ 165 "oifname @wan masquerade" 166 ]; 167 }; 168 169 nat-rx = { 170 type = "nat"; 171 hook = "prerouting"; 172 priority = "-100"; 173 family = "ip"; 174 policy = "accept"; 175 rules = [ 176 # per https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/security_guide/sec-configuring_nat_using_nftables: 177 # "Even if you do not add a rule to the prerouting chain, the 178 # nftables framework requires this chain to match incoming 179 # packet replies. " 180 ]; 181 }; 182 183 # these chains are for rules that have to be present for things to 184 # basically work at all: for example, the router won't issue DHCP 185 # unless it's allowed to receive DHCP requests. For "site policy" 186 # rules you may prefer to use incoming-allowed-ip[46] instead 187 188 input-ip4-lan = { 189 type = "filter"; 190 family = "ip"; 191 192 rules = [ 193 (accept "udp dport 67") # dhcp 194 (accept "udp dport 53") # dns 195 (accept "tcp dport 22") # ssh 196 ]; 197 }; 198 199 input-ip4-wan = { 200 type = "filter"; 201 family = "ip"; 202 203 rules = [ ]; 204 }; 205 206 input-ip4 = { 207 type = "filter"; 208 family = "ip"; 209 policy = "drop"; 210 hook = "input"; 211 rules = [ 212 "iifname lo accept" 213 "icmp type { echo-request, echo-reply } accept" 214 "iifname @lan jump input-ip4-lan" 215 "iifname @wan jump input-ip4-wan" 216 "iifname @wan jump incoming-allowed-ip4" 217 "ct state established,related accept" 218 "log prefix \"DENIED CHAIN=input-ip4 \"" 219 ]; 220 }; 221 222 forward-ip4 = { 223 type = "filter"; 224 family = "ip"; 225 policy = "drop"; 226 hook = "forward"; 227 rules = [ 228 "iifname @lan accept" 229 "ct state established,related accept" 230 "oifname @lan iifname @wan jump incoming-allowed-ip4" 231 "log prefix \"DENIED CHAIN=forward-ip4 \"" 232 ]; 233 }; 234 235 incoming-allowed-ip4 = { 236 type = "filter"; 237 family = "ip"; 238 rules = [ 239 # This is where you put permitted incoming connections. If 240 # you're using NAT and want to forward a port from outside to 241 # devices on the LAN, then you need a DNAT rule in nat-rx chain 242 # *and* to accept the packet in this chain (specifying the 243 # internal (RFC1918) address). 244 ]; 245 }; 246 247 }