From 34485828d2de5f731bba5c13cb0079c3f065ec28 Mon Sep 17 00:00:00 2001 From: Tomas Zak Date: Fri, 16 Aug 2024 16:40:49 +0200 Subject: [PATCH] sentinel: nftable fixup For working with dynfw, few neccessary changes were made in sentinel-firewall and haas --- collect/haas-proxy/files/sentinel-firewall.sh | 15 +++-- .../files/init.nftables | 32 +++++----- .../files/common_nftables.sh | 60 +++++++++++++------ .../files/sentinel-firewall-nftables.sh | 2 +- 4 files changed, 71 insertions(+), 38 deletions(-) diff --git a/collect/haas-proxy/files/sentinel-firewall.sh b/collect/haas-proxy/files/sentinel-firewall.sh index 20ad4d3fe..bbc6eec60 100644 --- a/collect/haas-proxy/files/sentinel-firewall.sh +++ b/collect/haas-proxy/files/sentinel-firewall.sh @@ -4,20 +4,25 @@ SF_DIR="${0%/*}" . "$SF_DIR/common.sh" . /lib/functions.sh - config_load "haas" config_get local_port "settings" "local_port" "2525" +# This is simple helper to check for existence of given rule +service_haas_status() { + ubus -S call service list | grep -Eo haas_proxy >/dev/null 2>&1 +} + + port_redirect_zone() { local config_section="$1" local zone enabled config_get zone "$config_section" "name" config_get_bool enabled "$config_section" "haas_proxy" "0" - [ "$enabled" = "1" ] || return 0 - if [ -x /sbin/fw4 ]; then - nftables_set_portfw - fi + [ "$enabled" = "1" ] && service_haas_status || return 0 + if [ -x /sbin/fw4 ]; then + nftables_set_portfw + fi port_redirect "$zone" 22 "$local_port" "HaaS proxy" } diff --git a/collect/sentinel/sentinel-dynfw-c-client/files/init.nftables b/collect/sentinel/sentinel-dynfw-c-client/files/init.nftables index b9c5c8ffc..5ac18d724 100755 --- a/collect/sentinel/sentinel-dynfw-c-client/files/init.nftables +++ b/collect/sentinel/sentinel-dynfw-c-client/files/init.nftables @@ -10,24 +10,26 @@ SET="dynfw" CHAIN="dynfw" setup_firewall() { - nft list tables 2> /dev/null | grep -q " $TABLE" || nft create table inet "$TABLE" - nft delete chain inet "$TABLE" "$SET"-"$TABLE"_input 2> /dev/null - nft add chain inet "$TABLE" "$SET"-"$TABLE"_input '{ type filter hook input priority -5; }' - nft add rule inet "$TABLE" "$SET"-"$TABLE"_input ct state established accept - nft add set inet "$TABLE" "${SET}_4" '{ type ipv4_addr; comment "IPv4 addresses blocked by Turris Sentinel"; }' - nft add rule inet "$TABLE" "$SET"-"$TABLE"_input ip saddr @"$SET"_4 drop - nft add set inet "$TABLE" "${SET}_6" '{ type ipv6_addr; flags interval; comment "IPv6 addresses blocked by Turris Sentinel"; }' - nft add rule inet "$TABLE" "$SET"-"$TABLE"_input ip6 saddr @"$SET"_6 drop - nft delete chain inet "$TABLE" "$SET"-"$TABLE"_forward 2> /dev/null - nft add chain inet "$TABLE" "$SET"-"$TABLE"_forward '{ type filter hook forward priority -5; }' - nft add rule inet "$TABLE" "$SET"-"$TABLE"_forward ct state established accept - nft add rule inet "$TABLE" "$SET"-"$TABLE"_forward ip saddr @"$SET"_4 drop - nft add rule inet "$TABLE" "$SET"-"$TABLE"_forward ip6 saddr @"$SET"_6 drop + nft list table "$TABLE" 2> /dev/null | grep -q " $TABLE" || nft create table inet "$TABLE" + nft delete set inet "$TABLE" "$SET"_4 2> /dev/null + nft delete set inet "$TABLE" "$SET"_6 2> /dev/null + nft add set inet "$TABLE" "$SET"_4 '{ type ipv4_addr; comment "IPv4 addresses blocked by Turris Sentinel" ; }' + nft add set inet "$TABLE" "$SET"_6 '{ type ipv6_addr; flags interval; comment "IPv6 addresses blocked by Turris Sentinel" ; }' + nft delete chain "$TABLE" "$CHAIN"-"$TABLE"_input 2> /dev/null + nft create chain inet "$TABLE" "$CHAIN"-"$TABLE"_input '{ type filter hook input priority -5; }' + nft add rule inet "$TABLE" "$CHAIN"-"$TABLE"_input ct state established accept + nft add rule inet "$TABLE" "$CHAIN"-"$TABLE"_input ip saddr @dynfw_4 drop + nft add rule inet "$TABLE" "$CHAIN"-"$TABLE"_input ip6 saddr @dynfw_6 drop + nft delete chain "$TABLE" "$CHAIN"-"$TABLE"_forward 2> /dev/null + nft create chain inet "$TABLE" "$CHAIN"-"$TABLE"_forward '{ type filter hook input priority -5; }' + nft add rule inet "$TABLE" "$CHAIN"-"$TABLE"_forward ct state established accept + nft add rule inet "$TABLE" "$CHAIN"-"$TABLE"_forward ip saddr @dynfw_4 drop + nft add rule inet "$TABLE" "$CHAIN"-"$TABLE"_forward ip6 saddr @dynfw_6 drop } teardown_firewall() { - nft delete chain inet "$TABLE" "$SET"-"$TABLE"_input 2> /dev/null - nft delete chain inet "$TABLE" "$SET"-"$TABLE"_forward 2> /dev/null + nft delete chain inet "$TABLE" "$CHAIN"-"$TABLE"_input 2> /dev/null + nft delete chain inet "$TABLE" "$CHAIN"-"$TABLE"_forward 2> /dev/null } start_service() { diff --git a/collect/sentinel/sentinel-firewall/files/common_nftables.sh b/collect/sentinel/sentinel-firewall/files/common_nftables.sh index 64d058717..45254e995 100644 --- a/collect/sentinel/sentinel-firewall/files/common_nftables.sh +++ b/collect/sentinel/sentinel-firewall/files/common_nftables.sh @@ -14,6 +14,16 @@ source_if_exists() { [ -f "$1" ] && source "$1" } +# This is simple helper to check for existence of given table +nftables_portfw_table_exists() { + nft list table inet turris-sentinel >/dev/null 2>&1 +} + +# This is simple helper to check for existence of given rule +nftables_portfw_rule_exists() { + nft list chain inet fw4 input_wan | grep "meta mark 0x00000072" >/dev/null 2>&1 +} + # Remove any existing rule # (firewall4 removes only rules in chains it knows so we have to do this to # potentially clean after ourselves) @@ -21,8 +31,10 @@ firewall_cleanup() { local table="" local chain="" local handle="" + local zone="$1" + report_operation "Cleaning up the remnants of the old firewall" - nft -a list ruleset | while read line; do + nft -a list table inet fw4 | while read line; do local new_table="$(echo "$line" | sed -n 's|table inet \(.*\) {.*|\1|p')" if [ -n "$new_table" ]; then table="$new_table" @@ -39,28 +51,42 @@ firewall_cleanup() { [ -n "$handle" ] || continue nft delete rule inet fw4 "$chain" handle "$handle" done - nftables_set_portfw -} -# This is simple helper to check for existence of given chain -nftables_portfw_chain_exists() { - nft list chain inet fw4 input_wan | grep "ct status dnat" >/dev/null 2>&1 + if ! nftables_portfw_rule_exists; then + nft delete chain inet fw4 accept_from_wan_minipots 2> /dev/null + nft delete chain inet turris-sentinel minipots_dstnat 2> /dev/null + nft delete chain inet turris-sentinel minipots_dstnat_wan 2> /dev/null + fi } # Makes sure we have wan forwarding rule nftables_set_portfw() { - local wan_if="$(nft list chain inet fw4 input | sed -n 's|.*iifname \("[^"]*"\) jump input_wan.*|\1|p')" + local wan_if="$(nft list chain inet fw4 input | grep -Eo "iifname .* jump input_wan" | grep -Eo "\".*\"")" + local zone="$1" # recreates it if it is missing. - if ! nftables_portfw_chain_exists; then - nft insert rule inet fw4 input_wan ct status dnat counter accept \ - comment "\"!sentinel: enable port forwarding\"" - - nft add chain inet fw4 dstnat_wan 2> /dev/null || : + if ! nftables_portfw_table_exists; then + nft add table inet turris-sentinel + fi + + # recreates it if it is missing. + if ! nftables_portfw_rule_exists; then + nft add chain inet fw4 accept_from_wan_minipots '{ comment "required for sentinel minipots" ; }' + + nft add rule inet fw4 accept_from_wan_minipots iifname { $wan_if } counter \ + comment "\"!sentinel: minipots packet counter\"" + + nft insert rule inet fw4 input_wan meta mark 114 counter goto accept_from_wan_minipots \ + comment "\"!sentinel: packet redirection for minipots\"" - nft add rule inet fw4 dstnat meta iifname { $wan_if } \ - counter jump dstnat_wan comment \ - "\"!sentinel: forward for interface(s) in wan zone meta packets to dstnat_wan chain\"" + nft add chain inet turris-sentinel minipots_dstnat '{ type nat hook prerouting priority dstnat; policy accept; }' + nft add chain inet turris-sentinel minipots_dstnat_wan + + nft add rule inet turris-sentinel minipots_dstnat iifname { $wan_if } counter jump minipots_dstnat_wan \ + comment "\"!sentinel: port redirection for minipots\"" + + nft add rule inet turris-sentinel minipots_dstnat_wan meta nfproto { ipv4, ipv6 } counter meta mark set 0 \ + comment "\"!sentinel: pass other traffic to static firewall\"" fi } @@ -77,7 +103,7 @@ port_redirect() { nftables_set_portfw report_operation "$description on zone '$zone' ($port -> $local_port)" - nft add rule inet fw4 "dstnat_$zone" meta nfproto { ipv4, ipv6 } counter \ - tcp dport $port redirect to $local_port comment "\"!sentinel: $description port redirect\"" + nft insert rule inet turris-sentinel minipots_dstnat_wan meta nfproto { ipv4, ipv6 } counter meta mark set 114 \ + tcp dport $port redirect to $local_port comment "\"!sentinel: $description port redirect\"" } diff --git a/collect/sentinel/sentinel-fwlogs/files/sentinel-firewall-nftables.sh b/collect/sentinel/sentinel-fwlogs/files/sentinel-firewall-nftables.sh index 9489930ba..65233ea26 100755 --- a/collect/sentinel/sentinel-fwlogs/files/sentinel-firewall-nftables.sh +++ b/collect/sentinel/sentinel-fwlogs/files/sentinel-firewall-nftables.sh @@ -21,7 +21,7 @@ fwlogs_logging() { [ "$enabled" = "1" ] || return 0 report_operation "Logging of zone '$zone'" - nft insert rule inet fw4 "drop_from_${zone}" log group "$nflog_group" queue-threshold "$nflog_threshold" comment "!sentinel: fwlogs" + nft insert rule inet fw4 "reject_from_${zone}" log group "$nflog_group" queue-threshold "$nflog_threshold" comment "\"!sentinel: fwlogs\"" } config_load "firewall"