From 1ef795b90e4d87f58553afbcf5928728ffb86e1b Mon Sep 17 00:00:00 2001 From: "William A. Kennington III" Date: Wed, 10 Mar 2021 18:59:12 -0800 Subject: meta-google: gbmc-ncsi-config: Restrict NCSI input packets Break down packets by their incoming address and ensure that we don't allow packets to unintended destinations. Right now this is effectively a no-op, but it will be necessary for BMC public addressing. Change-Id: I39c16c3b9cd4c293df42b928674e39677d7834e9 Signed-off-by: William A. Kennington III --- .../ncsi/files/50-gbmc-ncsi.rules.in | 13 +++ .../recipes-google/ncsi/files/gbmc-ncsi-nft.sh.in | 95 ++++++++++++++++++++++ .../recipes-google/ncsi/gbmc-ncsi-config.bb | 17 +++- 3 files changed, 122 insertions(+), 3 deletions(-) create mode 100644 meta-google/recipes-google/ncsi/files/gbmc-ncsi-nft.sh.in (limited to 'meta-google') diff --git a/meta-google/recipes-google/ncsi/files/50-gbmc-ncsi.rules.in b/meta-google/recipes-google/ncsi/files/50-gbmc-ncsi.rules.in index 33031f0db7..4ebe351281 100644 --- a/meta-google/recipes-google/ncsi/files/50-gbmc-ncsi.rules.in +++ b/meta-google/recipes-google/ncsi/files/50-gbmc-ncsi.rules.in @@ -3,10 +3,23 @@ table inet filter { type filter hook input priority 0; policy drop; iifname != @NCSI_IF@ accept ct state established accept + ip6 daddr ff00::/8 goto ncsi_brd_input + ip6 daddr fe80::/64 goto ncsi_legacy_input + } + chain ncsi_gbmc_br_pub_input { + jump gbmc_br_pub_input + reject + } + chain gbmc_br_pub_input { + } + chain ncsi_legacy_input { + jump ncsi_brd_input tcp dport 3959 accept udp dport 3959 accept tcp dport 3967 accept udp dport 3967 accept + } + chain ncsi_brd_input { icmpv6 type nd-neighbor-advert accept icmpv6 type nd-neighbor-solicit accept icmpv6 type nd-router-advert accept diff --git a/meta-google/recipes-google/ncsi/files/gbmc-ncsi-nft.sh.in b/meta-google/recipes-google/ncsi/files/gbmc-ncsi-nft.sh.in new file mode 100644 index 0000000000..34ca4e52ff --- /dev/null +++ b/meta-google/recipes-google/ncsi/files/gbmc-ncsi-nft.sh.in @@ -0,0 +1,95 @@ +# Copyright 2021 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +[ -z "${gbmc_ncsi_nft_lib-}" ] || return + +gbmc_ncsi_nft_init= +gbmc_ncsi_nft_lastip4= +gbmc_ncsi_nft_lastip6= + +gbmc_ncsi_nft_update() { + [ -n "$gbmc_ncsi_nft_init" ] || return + + printf 'NCSI firewall for IPv4(%s) IPv6(%s)\n' \ + "${gbmc_ncsi_nft_lastip4:-(deleted)}" \ + "${gbmc_ncsi_nft_lastip6:-(deleted)}" >&2 + + local contents= + contents+='table inet filter {'$'\n' + contents+=' chain ncsi_input {'$'\n' + + local ip4="$gbmc_ncsi_nft_lastip4" + if [ -n "$ip4" ]; then + contents+=" ip daddr $ip4 goto ncsi_legacy_input"$'\n' + fi + + local ip6="$gbmc_ncsi_nft_lastip6" + if [ -n "$ip6" ]; then + contents+=" ip6 daddr $ip6/128 goto ncsi_legacy_input"$'\n' + + # Pad out to 4 hextets with no trailing semicolons + local pfx= + pfx="${ip6%::}" + while true; do + # Count `:` in `pfx` by removing them and diffing their lengths + local nos="${pfx//:/}" + (( ${#pfx} - ${#nos} >= 3 )) && break + pfx+=":0" + done + + # If our address has enough spare bits for appending the BMC suffix + # then we add a rule that allows the BMC subnet. That is, we need a /64 + # as input. + if (( ${#pfx} - ${#nos} == 3 )); then + contents+=" ip6 saddr != ${pfx}:fd00::/72 ip6 daddr" + contents+=" ${pfx}:fd00::/72 goto ncsi_gbmc_br_pub_input"$'\n' + fi + fi + + contents+=' }'$'\n' + contents+='}'$'\n' + + local rfile=/run/nftables/40-gbmc-ncsi-in.rules + mkdir -p -m 755 "$(dirname "$rfile")" + printf '%s' "$contents" >"$rfile" + + echo 'Restarting nftables' >&2 + systemctl reset-failed nftables + systemctl --no-block restart nftables +} + +gbmc_ncsi_nft_hook() { + if [ "$change" = 'init' ]; then + gbmc_ncsi_nft_init=1 + gbmc_ncsi_nft_update + elif [ "$change" = 'addr' -a "$intf" = '@NCSI_IF@' -a "$scope" = 'global' ]; then + if [ "$fam" = 'inet6' ]; then + local -n lastip='gbmc_ncsi_nft_lastip6' + else + local -n lastip='gbmc_ncsi_nft_lastip4' + fi + if [ "$action" = 'add' -a "$ip" != "$lastip" ]; then + lastip="$ip" + gbmc_ncsi_nft_update + fi + if [ "$action" = 'del' -a "$ip" = "$lastip" ]; then + lastip= + gbmc_ncsi_nft_update + fi + fi +} + +GBMC_IP_MONITOR_HOOKS+=(gbmc_ncsi_nft_hook) + +gbmc_ncsi_nft_lib=1 diff --git a/meta-google/recipes-google/ncsi/gbmc-ncsi-config.bb b/meta-google/recipes-google/ncsi/gbmc-ncsi-config.bb index ecdda2cb60..b833810f15 100644 --- a/meta-google/recipes-google/ncsi/gbmc-ncsi-config.bb +++ b/meta-google/recipes-google/ncsi/gbmc-ncsi-config.bb @@ -9,17 +9,22 @@ SRC_URI += " \ file://50-gbmc-ncsi.rules.in \ file://gbmc-ncsi-sslh.socket.in \ file://gbmc-ncsi-sslh.service \ + file://gbmc-ncsi-nft.sh.in \ " S = "${WORKDIR}" RDEPENDS_${PN} += " \ + gbmc-ip-monitor \ ncsid \ nftables-systemd \ sslh \ " -FILES_${PN} += "${systemd_unitdir}" +FILES_${PN} += " \ + ${datadir}/gbmc-ip-monitor \ + ${systemd_unitdir} \ + " SYSTEMD_SERVICE_${PN} += " \ gbmc-ncsi-sslh.service \ @@ -50,7 +55,7 @@ do_install_append() { nftdir=${D}${sysconfdir}/nftables install -d -m0755 "$nftdir" - sed "s,@NCSI_IF@,$if_name," ${WORKDIR}/50-gbmc-ncsi.rules.in \ + sed "s,@NCSI_IF@,$if_name,g" ${WORKDIR}/50-gbmc-ncsi.rules.in \ >"$nftdir"/50-gbmc-ncsi.rules wantdir=${D}${systemd_system_unitdir}/multi-user.target.wants @@ -58,6 +63,12 @@ do_install_append() { ln -sv ../ncsid@.service "$wantdir"/ncsid@$if_name.service install -m 0644 ${WORKDIR}/gbmc-ncsi-sslh.service ${D}${systemd_system_unitdir} - sed "s,@NCSI_IF@,$if_name," ${WORKDIR}/gbmc-ncsi-sslh.socket.in \ + sed "s,@NCSI_IF@,$if_name,g" ${WORKDIR}/gbmc-ncsi-sslh.socket.in \ >${D}${systemd_system_unitdir}/gbmc-ncsi-sslh.socket + + mondir=${D}${datadir}/gbmc-ip-monitor/ + install -d -m0755 $mondir + sed "s,@NCSI_IF@,$if_name,g" ${WORKDIR}/gbmc-ncsi-nft.sh.in \ + >${WORKDIR}/gbmc-ncsi-nft.sh + install -m644 ${WORKDIR}/gbmc-ncsi-nft.sh $mondir } -- cgit v1.2.3