315 lines
7.8 KiB
Text
315 lines
7.8 KiB
Text
#!/usr/bin/env nft -f
|
|
|
|
table inet fw {
|
|
include "./conf.def"
|
|
include "./log.nft"
|
|
|
|
# invalid packets
|
|
counter ct-invalid { packets 0 bytes 0 }
|
|
# !(tcp|udp) protocol packets dropped
|
|
counter catchall { packets 0 bytes 0 }
|
|
# iifgroup != IIFGROUP_ETHERNET | IIFGROUP_VPN
|
|
counter iif-other { packets 0 bytes 0 }
|
|
# non-unicast
|
|
counter non-unicast { packets 0 bytes 0 }
|
|
# no reverse path
|
|
counter no-reverse-path { packets 0 bytes 0 }
|
|
# ipv6 type 0 routing headers
|
|
counter type0-header { packets 0 bytes 0 }
|
|
# dropped icmp packets
|
|
counter unwanted-icmp { packets 0 bytes 0 }
|
|
counter unwanted-icmpv6 { packets 0 bytes 0 }
|
|
# dropped blocklist packets
|
|
counter block-static { packets 0 bytes 0 }
|
|
counter block-dynamic { packets 0 bytes 0 }
|
|
# reject total
|
|
counter reject-total { packets 0 bytes 0 }
|
|
# dropped total
|
|
counter drop-total { packets 0 bytes 0 }
|
|
# zone traversal statistics
|
|
counter zone-default { packets 0 bytes 0 }
|
|
counter zone-forward { packets 0 bytes 0 }
|
|
counter zone-output { packets 0 bytes 0 }
|
|
counter zone-private { packets 0 bytes 0 }
|
|
counter zone-public { packets 0 bytes 0 }
|
|
counter zone-vpn { packets 0 bytes 0 }
|
|
|
|
define NET_V6_LINK_LOCAL = fe80::/10
|
|
|
|
set set_private_net_v4 {
|
|
type ipv4_addr
|
|
flags constant,interval
|
|
elements = {
|
|
10.0.0.0/8,
|
|
169.254.0.0/16,
|
|
172.16.0.0/12,
|
|
192.168.0.0/16
|
|
}
|
|
}
|
|
|
|
set set_private_net_v6 {
|
|
type ipv6_addr
|
|
flags constant,interval
|
|
elements = {
|
|
$NET_V6_LINK_LOCAL,
|
|
$NET_V6_UNIQUE_LOCAL
|
|
}
|
|
}
|
|
|
|
set set_icmp_v4 {
|
|
type icmp_type
|
|
flags constant
|
|
elements = $SET_ALLOW_ICMP_V4
|
|
}
|
|
|
|
set set_icmp_v6 {
|
|
type icmpv6_type
|
|
flags constant
|
|
elements = $SET_ALLOW_ICMP_V6
|
|
}
|
|
|
|
# static list, primarily for scanner networks
|
|
set set_allow_static_v4 {
|
|
type ipv4_addr
|
|
flags constant,interval
|
|
auto-merge
|
|
elements = $SET_STATIC_ALLOW_V4
|
|
}
|
|
|
|
set set_drop_static_v4 {
|
|
type ipv4_addr
|
|
flags constant,interval
|
|
auto-merge
|
|
elements = $SET_STATIC_DROP_V4
|
|
}
|
|
|
|
set set_allow_static_v6 {
|
|
type ipv6_addr
|
|
flags constant,interval
|
|
auto-merge
|
|
elements = $SET_STATIC_ALLOW_V6
|
|
}
|
|
|
|
set set_drop_static_v6 {
|
|
type ipv6_addr
|
|
flags constant,interval
|
|
auto-merge
|
|
elements = $SET_STATIC_DROP_V6
|
|
}
|
|
|
|
# dynamic lists with timeout
|
|
set set_allow_dyn_v4 {
|
|
type ipv4_addr
|
|
flags interval,timeout
|
|
timeout 1d
|
|
gc-interval 1m
|
|
auto-merge
|
|
elements = $SET_ALLOW_NETS_V4
|
|
}
|
|
|
|
set set_block_dyn_v4 {
|
|
type ipv4_addr
|
|
flags interval,timeout
|
|
timeout 1d
|
|
gc-interval 1m
|
|
auto-merge
|
|
elements = $SET_BLOCK_NETS_V4
|
|
}
|
|
|
|
set set_allow_dyn_v6 {
|
|
type ipv6_addr
|
|
flags interval,timeout
|
|
timeout 1d
|
|
gc-interval 1m
|
|
auto-merge
|
|
elements = $SET_ALLOW_NETS_V6
|
|
}
|
|
|
|
set set_block_dyn_v6 {
|
|
type ipv6_addr
|
|
flags interval,timeout
|
|
timeout 1d
|
|
gc-interval 1m
|
|
auto-merge
|
|
elements = $SET_BLOCK_NETS_V6
|
|
}
|
|
|
|
chain iif-dispatch {
|
|
type filter hook input priority $HOOK_FILTER_PRIORITY; policy drop;
|
|
iif "lo" accept
|
|
jump ct-filter-bypass
|
|
|
|
iifgroup vmap {
|
|
$IIFGROUP_ETHERNET : goto input-zone-dispatch,
|
|
$IIFGROUP_VPN : goto vpn,
|
|
"default" : goto default
|
|
}
|
|
|
|
# basic filtering of unhandled iifgroups
|
|
counter name "iif-other" jump proto-filter
|
|
goto $DEFAULT_VERDICT
|
|
}
|
|
|
|
chain input-zone-dispatch {
|
|
ip saddr @set_private_net_v4 goto private
|
|
ip6 saddr @set_private_net_v6 goto private
|
|
goto public
|
|
}
|
|
|
|
chain xlist-lookup {
|
|
ip saddr @set_allow_static_v4 accept
|
|
ip6 saddr @set_allow_static_v6 accept
|
|
ip saddr @set_allow_dyn_v4 accept
|
|
ip6 saddr @set_allow_dyn_v6 accept
|
|
# packets from static blocklists are always dropped
|
|
ip saddr @set_drop_static_v4 counter name "block-static" \
|
|
goto $CHAIN_LOG_DISPATCH_DROP
|
|
ip6 saddr @set_drop_static_v6 counter name "block-static" \
|
|
goto $CHAIN_LOG_DISPATCH_DROP
|
|
# packets from dynamic blocklists respect chosen block mode
|
|
ip saddr @set_block_dyn_v4 counter name "block-dynamic" \
|
|
goto $LIST_BLOCK_MODE
|
|
ip6 saddr @set_block_dyn_v6 counter name "block-dynamic" \
|
|
goto $LIST_BLOCK_MODE
|
|
}
|
|
|
|
chain proto-filter {
|
|
# `vmap` causes segfault
|
|
ip protocol icmp goto icmpv4-filter
|
|
ip6 nexthdr ipv6-icmp goto icmpv6-filter
|
|
ip protocol igmp goto $CHAIN_LOG_DISPATCH_DROP
|
|
# drop unsolicited broadcast/multicast
|
|
meta pkttype { broadcast, multicast } counter name "non-unicast" goto $CHAIN_LOG_DISPATCH_DROP
|
|
# disallow ipv6 type 0 routing headers
|
|
rt type 0 counter name "type0-header" goto log6-reject-addr-unreachable
|
|
}
|
|
|
|
chain ct-filter-bypass {
|
|
ct state established,related accept
|
|
ct state invalid counter name "ct-invalid" goto $CHAIN_LOG_DISPATCH_DROP
|
|
# accept marked connections
|
|
ct mark $MARK_FASTPATH_ID accept
|
|
# accept marked packets
|
|
meta mark $MARK_FASTPATH_ID accept
|
|
}
|
|
|
|
chain rp-filter {
|
|
# reverse path filter for ipv6
|
|
type filter hook prerouting priority raw; policy drop;
|
|
fib saddr . iif oif exists accept
|
|
counter name "no-reverse-path" goto $CHAIN_LOG_DISPATCH_DROP
|
|
}
|
|
|
|
chain icmpv6-filter {
|
|
# allow configured types
|
|
icmpv6 type @set_icmp_v6 accept
|
|
# and all essential types according to rfc4890
|
|
jump rfc4890
|
|
counter name "unwanted-icmpv6" goto $CHAIN_LOG_DISPATCH_DROP
|
|
}
|
|
|
|
chain icmpv4-filter {
|
|
icmp type @set_icmp_v4 accept
|
|
counter name "unwanted-icmp" goto $CHAIN_LOG_DISPATCH_DROP
|
|
}
|
|
|
|
chain rfc4890 {
|
|
# https://tools.ietf.org/html/rfc4890
|
|
# https://github.com/intel/intel-iot-refkit/blob/master/meta-refkit-core/recipes-security/nftables-settings-default/files/firewall.template
|
|
|
|
# allow basic IPv6 functionality.
|
|
icmpv6 type {
|
|
destination-unreachable,
|
|
packet-too-big,
|
|
time-exceeded,
|
|
parameter-problem,
|
|
echo-request,
|
|
echo-reply
|
|
} accept;
|
|
|
|
# allow auto configuration support.
|
|
icmpv6 type {
|
|
nd-neighbor-solicit,
|
|
nd-neighbor-advert,
|
|
nd-router-advert,
|
|
nd-router-solicit
|
|
} ip6 hoplimit 255 accept;
|
|
|
|
# allow multicast listener discovery on link-local addresses.
|
|
icmpv6 type {
|
|
mld-listener-query,
|
|
mld-listener-report,
|
|
mld-listener-reduction
|
|
} ip6 saddr $NET_V6_LINK_LOCAL accept;
|
|
|
|
# allow multicast router discovery messages on link-local
|
|
# addresses (hop limit 1).
|
|
icmpv6 type {
|
|
nd-router-advert,
|
|
nd-router-solicit
|
|
} ip6 hoplimit 1 ip6 saddr $NET_V6_LINK_LOCAL accept;
|
|
}
|
|
|
|
chain reject-verdict {
|
|
meta l4proto vmap {
|
|
udp : goto logx-reject-port-unreachable,
|
|
tcp : goto logx-reject-tcp-reset
|
|
}
|
|
counter name "catchall" goto logx-reject-port-unreachable
|
|
}
|
|
|
|
chain drop-verdict {
|
|
# prefer calling CHAIN_LOG_DISPATCH_DROP directly
|
|
goto $CHAIN_LOG_DISPATCH_DROP
|
|
}
|
|
|
|
chain log6-reject-addr-unreachable {
|
|
jump $CHAIN_LOG_DISPATCH_REJECT
|
|
reject with icmpv6 type addr-unreachable comment "icmpv6 addr-unreachable"
|
|
# end of rule traversal
|
|
}
|
|
|
|
chain logx-reject-port-unreachable {
|
|
jump $CHAIN_LOG_DISPATCH_REJECT
|
|
reject comment "icmpx port-unreachable"
|
|
# end of rule traversal
|
|
}
|
|
|
|
chain logx-reject-tcp-reset {
|
|
jump $CHAIN_LOG_DISPATCH_REJECT
|
|
reject with tcp reset comment "icmpx tcp reset"
|
|
# end of rule traversal
|
|
}
|
|
|
|
chain forward-zone-dispatch {
|
|
type filter hook forward priority $HOOK_FILTER_PRIORITY; policy drop;
|
|
jump ct-filter-bypass
|
|
jump forward
|
|
}
|
|
|
|
chain output-zone-dispatch {
|
|
type filter hook output priority $HOOK_FILTER_PRIORITY; policy drop;
|
|
jump ct-filter-bypass
|
|
jump output
|
|
}
|
|
|
|
# reusable service jump targets
|
|
chain vpn-zone-svc { include "./services/vpn.zone.d/*.nft"; }
|
|
chain private-zone-svc { include "./services/private.zone.d/*.nft"; }
|
|
chain public-zone-svc { include "./services/public.zone.d/*.nft"; }
|
|
chain forward-zone-svc { include "./services/forward.zone.d/*.nft"; }
|
|
chain output-zone-svc { include "./services/output.zone.d/*.nft"; }
|
|
chain default-zone-svc { include "./services/default.zone.d/*.nft"; }
|
|
|
|
# zones
|
|
include "./zones/vpn.nft"
|
|
include "./zones/private.nft"
|
|
include "./zones/public.nft"
|
|
include "./zones/forward.nft"
|
|
include "./zones/output.nft"
|
|
include "./zones/default.nft"
|
|
|
|
# custom rules
|
|
include "./global/*.def"
|
|
include "./global/*.nft"
|
|
}
|