WIP: fff-firewall: Switch from ip/ebtables to nftables

Include nftables and appropriate modules. Translate ip- and ebtables
rules to their nftables counterparts. Remove ip/ebtables and modules.

This change intentionally tries to keep structural changes at a minimum
to keep the rule translation comprehensible.

kmod-nft-bridge is not required for fff-node, because it was merged into
a single kernel module since Linux 4.17:
[1] 02c7b25e5f
[2] fbaf48387e

Fixes: #252

Signed-off-by: Fabian Bläse <fabian@blaese.de>
Co-authored-by: Johannes Kimmel <fff@bareminimum.eu>
This commit is contained in:
Fabian Bläse 2022-12-18 13:46:03 +01:00
parent 469f49f795
commit 8be918ad49
23 changed files with 280 additions and 119 deletions

View File

@ -12,8 +12,6 @@ define Package/fff-base
URL:=https://www.freifunk-franken.de
DEFAULT:=y
DEPENDS:= \
+iptables-legacy \
+ip6tables-legacy \
+micrond \
+odhcp6c \
+fff-config \

View File

@ -10,11 +10,7 @@ define Package/$(PKG_NAME)
CATEGORY:=Freifunk
TITLE:=Freifunk-Franken firewall
URL:=https://www.freifunk-franken.de
DEPENDS:=+arptables-legacy \
+ebtables-legacy +ebtables-legacy-utils \
+kmod-ebtables-ipv4 +kmod-ebtables-ipv6 \
+iptables-mod-filter +iptables-mod-ipopt +iptables-mod-conntrack-extra \
+kmod-nf-conntrack6
DEPENDS:=+nftables
endef
define Package/$(PKG_NAME)/description

View File

@ -1,6 +1,3 @@
######## CLEAN UP ############
ebtables -F
ebtables -X
iptables-save | awk '/^[*]/ { print $1 } /^:[A-Z]+ [^-]/ { print $1 " ACCEPT" ; } /COMMIT/ { print $0; }' | iptables-restore
ip6tables-save | awk '/^[*]/ { print $1 } /^:[A-Z]+ [^-]/ { print $1 " ACCEPT" ; } /COMMIT/ { print $0; }' | ip6tables-restore
nft -f - <<__EOF
flush ruleset
__EOF

View File

@ -1,5 +1,15 @@
# Erlaube nur fe80::1 von BATMAN -> CLIENT
ebtables -A FORWARD -p IPv6 --ip6-source fe80::1 -j IN_ONLY
nft -f - <<__EOF
table bridge filter {
chain INPUT {
# Erlaube nur fe80::1 von BATMAN -> CLIENT
# -p IPv6 --ip6-src fe80::1 -j IN_ONLY
ether type ip6 ip6 saddr fe80::1 counter jump IN_ONLY
}
# Erlaube nur fe80::1 von KNOTEN -> CLIENT
ebtables -A INPUT -p IPv6 --ip6-source fe80::1 -j IN_ONLY
chain FORWARD {
# Erlaube nur fe80::1 von KNOTEN -> CLIENT
# -p IPv6 --ip6-src fe80::1 -j IN_ONLY
ether type ip6 ip6 saddr fe80::1 counter jump IN_ONLY
}
}
__EOF

View File

@ -13,7 +13,7 @@ define Package/fff-layer3-snat
DEPENDS:= \
+fff-firewall \
+fff-layer3-config \
+kmod-ipt-nat
+kmod-nft-nat
endef
define Package/fff-layer3-snat/description

View File

@ -1,4 +1,10 @@
if [ "$(uci -q get network.client.fff_snat)" = '1' ]; then
iptables -t mangle -A PREROUTING -i br-client -j MARK --set-mark 0x736e6174
iptables -t nat -A POSTROUTING -m mark --mark 0x736e6174 -j SNAT --to-source $(uci -q get network.client.fff_snat_sourceip)
nft add table ip mangle
nft add chain ip mangle PREROUTING '{ type filter hook prerouting priority mangle; policy accept; }'
nft add table ip nat
nft add chain ip nat POSTROUTING '{ type nat hook postrouting priority srcnat; policy accept; }'
nft add rule ip mangle PREROUTING iifname "br-client" counter mark set 0x736e6174
nft add rule ip nat POSTROUTING meta mark 0x736e6174 counter snat ip to $(uci -q get network.client.fff_snat_sourceip)
fi

View File

@ -23,21 +23,13 @@ define Package/fff-layer3
+fff-ra \
+fff-web-mqtt \
+fff-wireguard \
+arptables-legacy \
+bmon \
+ebtables-legacy \
+ebtables-legacy-utils \
+kmod-ebtables-ipv4 \
+kmod-ebtables-ipv6 \
+kmod-sched-cake \
+gre \
+@PACKAGE_grev4 \
+@PACKAGE_grev6 \
+iperf3 \
+ip-full \
+iptables-mod-filter \
+iptables-mod-ipopt \
+iptables-mod-conntrack-extra \
+mtr \
+nftables \
+snmp-utils \

View File

@ -1,5 +1,10 @@
# Ensure nothing is forwarded onto WAN interface
if [ -n "$IF_WAN" ]; then
iptables -A FORWARD -o $IF_WAN -j REJECT --reject-with icmp-net-unreachable
ip6tables -A FORWARD -o $IF_WAN -j REJECT --reject-with no-route
nft add table ip filter
nft add chain ip filter FORWARD '{ type filter hook forward priority filter; policy accept; }'
nft add table ip6 filter
nft add chain ip6 filter FORWARD '{ type filter hook forward priority filter; policy accept; }'
nft add rule ip filter FORWARD oifname "$IF_WAN" counter reject with icmp net-unreachable
nft add rule ip6 filter FORWARD oifname "$IF_WAN" counter reject with icmpv6 no-route
fi

View File

@ -1,34 +1,44 @@
######## IN_ONLY ############
ebtables -N IN_ONLY -P RETURN
nft -f - <<__EOF
table bridge filter {
# IN_ONLY wird angesprungen, wenn dieses Paket nur
# vom Gateway (also vom BATMAN) kommen darf.
chain IN_ONLY {
# -i ! bat0 --logical-in br-client -j DROP
iifname != "bat0" counter drop
counter
}
# Daten aus dem BATMAN werden erlaubt
# Alles ausser Daten von BATMAN werden DROP'ed
ebtables -A IN_ONLY -i ! bat0 --logical-in br-client -j DROP
# OUT_ONLY wird angesprungen, wenn dieses Paket nur
# in Richtung Gateway (also ins BATMAN) gesendet werden darf.
chain OUT_ONLY {
# --logical-out br-client -o ! bat0 -j DROP
oifname != "bat0" counter drop
counter
}
######## OUT_ONLY ############
ebtables -N OUT_ONLY -P RETURN
# MULTICAST_OUT filtert/reduziert Multicast-Frames, die ins BATMAN gesendet werden.
chain MULTICAST_OUT {
}
# Daten ins BATMAN werden erlaubt
# Alles ausser Daten ins BATMAN werden DROP'ed
ebtables -A OUT_ONLY --logical-out br-client -o ! bat0 -j DROP
chain INPUT {
type filter hook input priority filter; policy accept;
######## MULTICAST_OUT ############
ebtables -N MULTICAST_OUT -P DROP
# -d Multicast -i ! bat0 --logical-in br-client -j ACCEPT
iifname != "bat0" ether daddr & 01:00:00:00:00:00 == 01:00:00:00:00:00 counter packets 0 bytes 0 accept
}
######## INPUT ############
ebtables -P INPUT ACCEPT
chain FORWARD {
type filter hook forward priority filter; policy accept;
# Regelt alles was an Multicast/Broadcast von CLIENT -> KNOTEN geht bei MULTICAST_OUT
ebtables -A INPUT -d Multicast --logical-in br-client -i ! bat0 -j ACCEPT
# -d Multicast --logical-out br-client -o bat0 -j MULTICAST_OUT
oifname "bat0" ether daddr & 01:00:00:00:00:00 == 01:00:00:00:00:00 counter packets 0 bytes 0 jump MULTICAST_OUT
}
######## FORWARD ############
ebtables -P FORWARD ACCEPT
chain OUTPUT {
type filter hook output priority filter; policy accept;
# Regelt alles was an Multicast/Broadcast von CLIENT -> BATMAN geht bei MULTICAST_OUT
ebtables -A FORWARD -d Multicast --logical-out br-client -o bat0 -j MULTICAST_OUT
######## OUTPUT ############
ebtables -P OUTPUT ACCEPT
# Regelt alles was an Multicast/Broadcast von KNOTEN -> BATMAN geht bei MULTICAST_OUT
ebtables -A OUTPUT -d Multicast --logical-out br-client -o bat0 -j MULTICAST_OUT
# -d Multicast --logical-out br-client -o bat0 -j MULTICAST_OUT
oifname "bat0" ether daddr & 01:00:00:00:00:00 == 01:00:00:00:00:00 counter jump MULTICAST_OUT
}
}
__EOF

View File

@ -1,2 +1,12 @@
/usr/sbin/iptables -P FORWARD DROP
/usr/sbin/ip6tables -P FORWARD DROP
nft -f - <<__EOF
table ip filter {
chain FORWARD {
type filter hook forward priority filter; policy drop;
}
}
table ip6 filter {
chain FORWARD {
type filter hook forward priority filter; policy drop;
}
}
__EOF

View File

@ -1,8 +1,19 @@
# Erlaube DHCP Requests
ebtables -A MULTICAST_OUT -p IPv4 --ip-proto udp --ip-dport 67 -j RETURN
nft -f - <<__EOF
table bridge filter {
chain MULTICAST_OUT {
# Erlaube DHCP Requests
# -p IPv4 --ip-proto udp --ip-dport 67 -j RETURN
ether type ip udp dport 67 counter return
}
# Erlaube nur DHCP Request von CLIENT -> BATMAN
ebtables -A FORWARD -p IPv4 --ip-proto udp --ip-dport 67 -j OUT_ONLY
chain FORWARD {
# Erlaube nur DHCP Request von CLIENT -> BATMAN
# -p IPv4 --ip-proto udp --ip-dport 67 -j OUT_ONLY
ether type ip udp dport 67 counter jump OUT_ONLY
# Erlaube nur DHCP Antworten von BATMAN -> CLIENT
ebtables -A FORWARD -p IPv4 --ip-proto udp --ip-dport 68 -j IN_ONLY
# Erlaube nur DHCP Antworten von BATMAN -> CLIENT
# -p IPv4 --ip-proto udp --ip-dport 68 -j IN_ONLY
ether type ip udp dport 68 counter jump IN_ONLY
}
}
__EOF

View File

@ -1,8 +1,19 @@
# Erlaube DHCPv6 Requests
ebtables -A MULTICAST_OUT -p IPv6 --ip6-proto udp --ip6-dport 547 -j RETURN
nft -f - <<__EOF
table bridge filter {
chain MULTICAST_OUT {
# Erlaube DHCPv6 Requests
# -p IPv6 --ip6-proto udp --ip6-dport 547 -j RETURN
ether type ip6 udp dport 547 counter return
}
# Erlaube nur DHCPv6 Request von CLIENT -> BATMAN
ebtables -A FORWARD -p IPv6 --ip6-proto udp --ip6-dport 547 -j OUT_ONLY
chain FORWARD {
# Erlaube nur DHCPv6 Request von CLIENT -> BATMAN
# -p IPv6 --ip6-proto udp --ip6-dport 547 -j OUT_ONLY
ether type ip6 udp dport 547 counter jump OUT_ONLY
# Erlaube nur DHCPv6 Antworten von BATMAN -> CLIENT
ebtables -A FORWARD -p IPv6 --ip6-proto udp --ip6-dport 546 -j IN_ONLY
# Erlaube nur DHCPv6 Antworten von BATMAN -> CLIENT
# -p IPv6 --ip6-proto udp --ip6-dport 546 -j IN_ONLY
ether type ip6 udp dport 546 counter jump IN_ONLY
}
}
__EOF

View File

@ -1,5 +1,13 @@
# Erlaube nur Router-Solicitation von CLIENT -> BATMAN
ebtables -A FORWARD -p IPv6 --ip6-proto ipv6-icmp --ip6-icmp-type router-solicitation -j OUT_ONLY
nft -f - <<__EOF
table bridge filter {
chain FORWARD {
# Erlaube nur Router-Solicitation von CLIENT -> BATMAN
# -p IPv6 --ip6-proto ipv6-icmp --ip6-icmp-type router-solicitation -j OUT_ONLY
ether type ip6 icmpv6 type nd-router-solicit counter jump OUT_ONLY
# Erlaube nur Router-Advertisment von BATMAN -> CLIENT
ebtables -A FORWARD -p IPv6 --ip6-proto ipv6-icmp --ip6-icmp-type router-advertisement -j IN_ONLY
# Erlaube nur Router-Advertisment von BATMAN -> CLIENT
# -p IPv6 --ip6-proto ipv6-icmp --ip6-icmp-type router-advertisement -j IN_ONLY
ether type ip6 icmpv6 type nd-router-advert counter jump IN_ONLY
}
}
__EOF

View File

@ -1,5 +1,15 @@
# Erlaube nur DHCP Antworten von BATMAN -> KNOTEN
ebtables -A INPUT -p IPv4 --ip-proto udp --ip-dport 68 -j IN_ONLY
nft -f - <<__EOF
table bridge filter {
chain INPUT {
# Erlaube nur DHCP Antworten von BATMAN -> KNOTEN
# -p IPv4 --ip-proto udp --ip-dport 68 -j IN_ONLY
ether type ip udp dport 68 counter jump IN_ONLY
}
# Erlaube nur DHCP Request von KNOTEN -> BATMAN
ebtables -A OUTPUT -p IPv4 --ip-proto udp --ip-dport 67 -j OUT_ONLY
chain OUTPUT {
# Erlaube nur DHCP Request von KNOTEN -> BATMAN
# -p IPv4 --ip-proto udp --ip-dport 67 -j OUT_ONLY
ether type ip udp dport 67 counter jump OUT_ONLY
}
}
__EOF

View File

@ -1,5 +1,15 @@
# Erlaube nur DHCPv6 Antworten von BATMAN -> KNOTEN
ebtables -A INPUT -p IPv6 --ip6-proto udp --ip6-dport 546 -j IN_ONLY
nft -f - <<__EOF
table bridge filter {
chain INPUT {
# Erlaube nur DHCPv6 Antworten von BATMAN -> KNOTEN
# -p IPv6 --ip6-proto udp --ip6-dport 546 -j IN_ONLY
ether type ip6 udp dport 546 counter jump IN_ONLY
}
# Erlaube nur DHCPv6 Request von KNOTEN -> BATMAN
ebtables -A OUTPUT -p IPv6 --ip6-proto udp --ip6-dport 547 -j OUT_ONLY
chain OUTPUT {
# Erlaube nur DHCPv6 Request von KNOTEN -> BATMAN
# -p IPv6 --ip6-proto udp --ip6-dport 547 -j OUT_ONLY
ether type ip6 udp dport 547 counter jump OUT_ONLY
}
}
__EOF

View File

@ -1,11 +1,23 @@
# Erlaube nur Router-Advertisment von BATMAN -> KNOTEN
ebtables -A INPUT -p IPv6 --ip6-proto ipv6-icmp --ip6-icmp-type router-advertisement -j IN_ONLY
nft -f - <<__EOF
table bridge filter {
chain INPUT {
# Erlaube nur Router-Advertisment von BATMAN -> KNOTEN
# -p IPv6 --ip6-proto ipv6-icmp --ip6-icmp-type router-advertisement -j IN_ONLY
ether type ip6 ip6 nexthdr icmpv6 icmpv6 type nd-router-advert counter jump IN_ONLY
# Verbiete Router-Solicitation von BATMAN -> KNOTEN
ebtables -A INPUT -p IPv6 -i bat0 --ip6-proto ipv6-icmp --ip6-icmp-type router-solicitation -j DROP
# Verbiete Router-Solicitation von BATMAN -> KNOTEN
# -p IPv6 -i bat0 --ip6-proto ipv6-icmp --ip6-icmp-type router-solicitation -j DROP
iifname "bat0" ether type ip6 ip6 nexthdr icmpv6 icmpv6 type nd-router-solicit counter drop
}
# Erlaube nur Router-Solicitation von KNOTEN -> BATMAN
ebtables -A OUTPUT -p IPv6 --ip6-proto ipv6-icmp --ip6-icmp-type router-solicitation -j OUT_ONLY
chain OUTPUT {
# Erlaube nur Router-Solicitation von KNOTEN -> BATMAN
# -p IPv6 --ip6-proto ipv6-icmp --ip6-icmp-type router-solicitation -j OUT_ONLY
ether type ip6 icmpv6 type nd-router-solicit counter jump OUT_ONLY
# Verbiete Router-Advertisment von KNOTEN -> BATMAN
ebtables -A OUTPUT -p IPv6 -o bat0 --ip6-proto ipv6-icmp --ip6-icmp-type router-advertisement -j DROP
# Verbiete Router-Advertisment von KNOTEN -> BATMAN
# -p IPv6 -o bat0 --ip6-proto ipv6-icmp --ip6-icmp-type router-advertisement -j DROP
oifname "bat0" ether type ip6 icmpv6 type nd-router-advert counter drop
}
}
__EOF

View File

@ -1,6 +1,13 @@
# Erlaube alles was nicht IP ?? ist " hop-by-hop " ??
ebtables -A MULTICAST_OUT -p IPv6 --ip6-proto 0 -j RETURN
# Erlaube Organisation der Multicast Gruppen
ebtables -A MULTICAST_OUT -p IPv4 --ip-proto igmp -j RETURN
nft -f - <<__EOF
table bridge filter {
chain MULTICAST_OUT {
# Erlaube alles was nicht IP ?? ist " hop-by-hop " ??
# -p IPv6 --ip6-proto ip -j RETURN
ether type ip6 ip6 nexthdr 0 counter return
# Erlaube Organisation der Multicast Gruppen
# -p IPv4 --ip-proto igmp -j RETURN
ether type ip meta l4proto igmp counter return
}
}
__EOF

View File

@ -1,8 +1,17 @@
# Verbiete ARP Antworten an alle
ebtables -A MULTICAST_OUT -p ARP --arp-op Reply --arp-ip-src 0.0.0.0 -j DROP
nft -f - <<__EOF
table bridge filter {
chain MULTICAST_OUT {
# Verbiete ARP Antworten an alle
# -p ARP --arp-op Reply --arp-ip-src 0.0.0.0 -j DROP
ether type arp arp operation reply arp daddr ip 0.0.0.0 counter drop
# Verbiete ARP Requests an alle
ebtables -A MULTICAST_OUT -p ARP --arp-op Request --arp-ip-dst 0.0.0.0 -j DROP
# Verbiete ARP Requests an alle
# -p ARP --arp-op Request --arp-ip-dst 0.0.0.0 -j DROP
ether type arp arp operation request arp daddr ip 0.0.0.0 counter drop
# Erlaube alle anderen ARP's
ebtables -A MULTICAST_OUT -p ARP -j RETURN
# Erlaube alle anderen ARP's
# -p ARP -j RETURN
ether type arp counter return
}
}
__EOF

View File

@ -1,6 +1,13 @@
# Erlaube PING
ebtables -A MULTICAST_OUT -p IPv4 --ip-proto icmp -j RETURN
# Erlaube PINGv6
ebtables -A MULTICAST_OUT -p IPv6 --ip6-proto ipv6-icmp -j RETURN
nft -f - <<__EOF
table bridge filter {
chain MULTICAST_OUT {
# Erlaube PING
# -p IPv4 --ip-proto icmp -j RETURN
ether type ip meta l4proto icmp counter return
# Erlaube PINGv6
# -p IPv6 --ip6-proto ipv6-icmp -j RETURN
ether type ip6 meta l4proto icmpv6 counter return
}
}
__EOF

View File

@ -0,0 +1,8 @@
nft -f - <<__EOF
table bridge filter {
chain MULTICAST_OUT {
# policy: DROP
counter drop
}
}
__EOF

View File

@ -1,11 +1,30 @@
# No input from/to local node ip from batman
ebtables -A INPUT --logical-in br-client -i bat0 -p IPv6 --ip6-source fdff::1/128 -j DROP
ebtables -A INPUT --logical-in br-client -i bat0 -p IPv6 --ip6-destination fdff::1/128 -j DROP
nft -f - <<__EOF
table bridge filter {
chain INPUT {
# No input from/to local node ip from batman
# Do not forward local node ip
ebtables -A FORWARD --logical-out br-client -o bat0 -p IPv6 --ip6-destination fdff::1/128 -j DROP
ebtables -A FORWARD --logical-out br-client -o bat0 -p IPv6 --ip6-source fdff::1/128 -j DROP
# -p IPv6 -i bat0 --logical-in br-client --ip6-src fdff::1 -j DROP
iifname "bat0" ether type ip6 ip6 saddr fdff::1 counter drop
# -p IPv6 -i bat0 --logical-in br-client --ip6-dst fdff::1 -j DROP
iifname "bat0" ether type ip6 ip6 daddr fdff::1 counter drop
}
# Do not output local node ip to batman
ebtables -A OUTPUT --logical-out br-client -o bat0 -p IPv6 --ip6-destination fdff::1/128 -j DROP
ebtables -A OUTPUT --logical-out br-client -o bat0 -p IPv6 --ip6-source fdff::1/128 -j DROP
chain FORWARD {
# Do not forward local node ip
# -p IPv6 --logical-out br-client -o bat0 --ip6-dst fdff::1 -j DROP
oifname "bat0" ether type ip6 ip6 daddr fdff::1 counter drop
# -p IPv6 --logical-out br-client -o bat0 --ip6-src fdff::1 -j DROP
oifname "bat0" ether type ip6 ip6 saddr fdff::1 counter drop
}
chain OUTPUT {
# Do not output local node ip to batman
# -p IPv6 --logical-out br-client -o bat0 --ip6-dst fdff::1 -j DROP
oifname "bat0" ether type ip6 ip6 daddr fdff::1 counter drop
# -p IPv6 --logical-out br-client -o bat0 --ip6-src fdff::1 -j DROP
oifname "bat0" ether type ip6 ip6 saddr fdff::1 counter drop
}
}
__EOF

View File

@ -0,0 +1,15 @@
nft -f - <<__EOF
table bridge filter {
chain INPUT {
counter
}
chain FORWARD {
counter
}
chain OUTPUT {
counter
}
}
__EOF

View File

@ -1,5 +1,15 @@
# Erlaube router solicitation von client zu knoten
ebtables -A INPUT -p IPv6 -i ! bat0 --ip6-proto ipv6-icmp --ip6-icmp-type router-solicitation -j ACCEPT
nft -f - <<__EOF
table bridge filter {
chain INPUT {
# Erlaube router solicitation von client zu knoten
# -p IPv6 -i ! bat0 --ip6-proto ipv6-icmp --ip6-icmp-type router-solicitation -j ACCEPT
iifname != "bat0" ether type ip6 ip6 nexthdr icmpv6 icmpv6 type nd-router-solicit counter accept
}
# Erlaube router advertisment von knoten zu client
ebtables -A OUTPUT -p IPv6 -o ! bat0 --ip6-proto ipv6-icmp --ip6-icmp-type router-advertisement -j ACCEPT
chain OUTPUT {
# Erlaube router advertisment von knoten zu client
# -p IPv6 -o ! bat0 --ip6-proto ipv6-icmp --ip6-icmp-type router-advertisement -j ACCEPT
oifname != "bat0" ether type ip6 icmpv6 type nd-router-advert counter accept
}
}
__EOF