strom/nft-simple-fw
Archived
1
0
Fork 0
This repository has been archived on 2024-03-30. You can view files and clone it, but cannot push or open issues or pull requests.
nft-simple-fw/fw.nft

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"
}