#!/bin/bash # SPDX-Version: 3.0 # SPDX-CreationInfo: 2025-05-05; WEIDNER, Marc S.; # SPDX-ExternalRef: GIT https://git.coresecret.dev/msw/CISS.debian.live.builder.git # SPDX-FileContributor: WEIDNER, Marc S.; Centurion Intelligence Consulting Agency # SPDX-FileCopyrightText: 2024-2025; WEIDNER, Marc S.; # SPDX-FileType: SOURCE # SPDX-License-Identifier: EUPL-1.2 OR LicenseRef-CCLA-1.0 # SPDX-LicenseComment: This file is part of the CISS.debian.installer.secure framework. # SPDX-PackageName: CISS.debian.live.builder # SPDX-Security-Contact: security@coresecret.eu ####################################### # Wrapper for accompanying all CISS.debian.hardening features into the Live ISO image. # Globals: # ARY_HANDLER_JUMPHOST # ARY_HANDLER_JUMPHOST_UNIQUE # VAR_ARCHITECTURE # VAR_HANDLER_BUILD_DIR # VAR_SSHPORT # VAR_SSHPUBKEY # VAR_WORKDIR # Arguments: # None ####################################### hardening_ultra() { # shellcheck disable=SC2164 cd "${VAR_WORKDIR}" printf "\e[95m++++ ++++ ++++ ++++ ++++ ++++ ++ ๐Ÿงช Copying ./config/bootloaders ... \e[0m\n" if [[ ! -d "${VAR_HANDLER_BUILD_DIR}/config/bootloaders" ]]; then mkdir -p "${VAR_HANDLER_BUILD_DIR}/config/bootloaders" cp -af ./config/bootloaders "${VAR_HANDLER_BUILD_DIR}/config" else cp -af ./config/bootloaders "${VAR_HANDLER_BUILD_DIR}/config" fi printf "\e[92m++++ ++++ ++++ ++++ ++++ ++++ ++ โœ… Copying ./config/bootloaders done.\e[0m\n" printf "\e[95m++++ ++++ ++++ ++++ ++++ ++++ ++ ๐Ÿงช Copying ./config/includes.binary ... \e[0m\n" if [[ ! -d "${VAR_HANDLER_BUILD_DIR}/config/includes.binary/boot/grub" ]]; then mkdir -p "${VAR_HANDLER_BUILD_DIR}/config/includes.binary/boot/grub" cp -af ./config/includes.binary "${VAR_HANDLER_BUILD_DIR}/config" else cp -af ./config/includes.binary "${VAR_HANDLER_BUILD_DIR}/config" fi printf "\e[92m++++ ++++ ++++ ++++ ++++ ++++ ++ โœ… Copying ./config/includes.binary done.\e[0m\n" printf "\e[95m++++ ++++ ++++ ++++ ++++ ++++ ++ ๐Ÿงช Copying ./config/hooks/live ... \e[0m\n" if [[ ! -d "${VAR_HANDLER_BUILD_DIR}/config/hooks/live" ]]; then mkdir -p "${VAR_HANDLER_BUILD_DIR}/config/hooks/live" cp -af ./config/hooks/live "${VAR_HANDLER_BUILD_DIR}/config/hooks" else cp -af ./config/hooks/live "${VAR_HANDLER_BUILD_DIR}/config/hooks" fi printf "\e[92m++++ ++++ ++++ ++++ ++++ ++++ ++ โœ… Copying ./config/hooks/live done.\e[0m\n" if [[ -d "${VAR_WORKDIR}/config/hooks/early" ]]; then printf "\e[95m++++ ++++ ++++ ++++ ++++ ++++ ++ ๐Ÿงช Copying ./config/hooks/early ... \e[0m\n" if [[ ! -d "${VAR_HANDLER_BUILD_DIR}/config/hooks/early" ]]; then mkdir -p "${VAR_HANDLER_BUILD_DIR}/config/hooks/early" cp -af ./config/hooks/early "${VAR_HANDLER_BUILD_DIR}/config/hooks" else cp -af ./config/hooks/early "${VAR_HANDLER_BUILD_DIR}/config/hooks" fi printf "\e[92m++++ ++++ ++++ ++++ ++++ ++++ ++ โœ… Copying ./config/hooks/early done.\e[0m\n" fi printf "\e[95m++++ ++++ ++++ ++++ ++++ ++++ ++ ๐Ÿงช Copying ./config/includes.chroot ... \e[0m\n" if [[ ! -d "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot" ]]; then mkdir -p "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot" cp -af ./config/includes.chroot "${VAR_HANDLER_BUILD_DIR}/config" else cp -af ./config/includes.chroot "${VAR_HANDLER_BUILD_DIR}/config" fi printf "\e[92m++++ ++++ ++++ ++++ ++++ ++++ ++ โœ… Copying ./config/includes.chroot done.\e[0m\n" printf "\e[95m++++ ++++ ++++ ++++ ++++ ++++ ++ ๐Ÿงช Copying ./config/package-lists ... \e[0m\n" if [[ ! -d "${VAR_HANDLER_BUILD_DIR}/config/package-lists" ]]; then mkdir -p "${VAR_HANDLER_BUILD_DIR}/config/package-lists" fi cp -af ./config/package-lists/live.list.common.chroot "${VAR_HANDLER_BUILD_DIR}/config/package-lists/live.list.chroot" case "${VAR_ARCHITECTURE}" in amd64) declare arch_list="./config/package-lists/live.list.amd64.chroot" declare arch_comment="# amd64 specific packages" ;; arm64) declare arch_list="./config/package-lists/live.list.arm64.chroot" declare arch_comment="# arm64 specific packages" ;; *) printf "\e[91m++++ ++++ ++++ ++++ ++++ ++++ ++ โŒ Unsupported architecture '%s'.\e[0m\n" "${VAR_ARCHITECTURE}" exit 1 ;; esac declare pkgs mapfile -t pkgs < <( grep -v '^\s*#' "${arch_list}" | sed '/^\s*$/d' ) awk -v comment="${arch_comment}" -v n_pkgs="${#pkgs[@]}" -v pkgs="$(printf '%s\n' "${pkgs[@]}")" ' BEGIN { split(pkgs, pkg_arr, "\n") inserted = 0 } { # Detect the vim-modeline (last line marker) if ($0 ~ /^# vim:.*$/ && !inserted) { print comment for (i = 1; i <= length(pkg_arr); i++) { print pkg_arr[i] } inserted = 1 } print } ' "${VAR_HANDLER_BUILD_DIR}/config/package-lists/live.list.chroot" > temp && mv temp "${VAR_HANDLER_BUILD_DIR}/config/package-lists/live.list.chroot" printf "\e[92m++++ ++++ ++++ ++++ ++++ ++++ ++ โœ… Copying ./config/package-lists done.\e[0m\n" printf "\e[95m++++ ++++ ++++ ++++ ++++ ++++ ++ ๐Ÿงช Updating SSH Keys, Ports ... \e[0m\n" if [[ ! -d "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/root/.ssh" ]]; then mkdir -p "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/root/.ssh" cp -af "${VAR_SSHPUBKEY}/authorized_keys" "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/root/.ssh" chmod 0600 "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/root/.ssh/authorized_keys" chown root:root "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/root/.ssh/authorized_keys" declare -r sshport="${VAR_SSHPORT:-22}" sed -i "s|^port = MUST_BE_SET|port = ${sshport}|" "${VAR_HANDLER_BUILD_DIR}/config/hooks/live/9950_fail2ban_hardening.chroot" sed -i "s|^declare -r SSHPORT=\"MUST_BE_SET\"|declare -r SSHPORT=\"${sshport}\"|" "${VAR_HANDLER_BUILD_DIR}/config/hooks/live/0900_ufw_setup.chroot" sed -i "s|^Port MUST_BE_CHANGED|Port ${sshport}|" "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/etc/ssh/sshd_config" if [[ ${#ARY_HANDLER_JUMPHOST[@]} -gt 0 ]]; then declare file="${VAR_HANDLER_BUILD_DIR}/config/hooks/live/0900_ufw_setup.chroot" sed -i "/^ufw allow in \"\${SSHPORT}\"\/tcp comment 'Incoming SSH (Custom-Port)'$/d" "${file}" declare line line=$(grep -n '^ufw default deny forward$' "${file}" | cut -d: -f1) if [[ -z "${line}" ]]; then printf "\e[91m++++ ++++ ++++ ++++ ++++ ++++ ++ โŒ'ufw default deny forward' not found in: '%s'\e[0m\n" "${file}" >&2 exit 1 fi declare host for host in "${ARY_HANDLER_JUMPHOST_UNIQUE[@]}"; do ((line++)) sed -i "${line}a ufw allow from ${host} to any port ${sshport} proto tcp comment \"Incoming SSH ([${host}]:${sshport})\"" "$file" done fi else cp -af "${VAR_SSHPUBKEY}/authorized_keys" "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/root/.ssh" chmod 0600 "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/root/.ssh/authorized_keys" chown root:root "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/root/.ssh/authorized_keys" declare -r sshport="${VAR_SSHPORT:-22}" sed -i "s|^port = MUST_BE_SET|port = ${sshport}|" "${VAR_HANDLER_BUILD_DIR}/config/hooks/live/9950_fail2ban_hardening.chroot" sed -i "s|^declare -r SSHPORT=\"MUST_BE_SET\"|declare -r SSHPORT=\"$sshport\"|" "${VAR_HANDLER_BUILD_DIR}/config/hooks/live/0900_ufw_setup.chroot" sed -i "s|^Port MUST_BE_CHANGED|Port ${sshport}|" "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/etc/ssh/sshd_config" if [[ ${#ARY_HANDLER_JUMPHOST_UNIQUE[@]} -gt 0 ]]; then declare file="${VAR_HANDLER_BUILD_DIR}/config/hooks/live/0900_ufw_setup.chroot" sed -i "/^ufw allow in \"\${SSHPORT}\"\/tcp comment 'Incoming SSH (Custom-Port)'$/d" "${file}" declare line line=$(grep -n '^ufw default deny forward$' "${file}" | cut -d: -f1) if [[ -z "${line}" ]]; then printf "\e[91mโŒ Error: 'ufw default deny forward' not found in: '%s'\e[0m\n" "${file}" >&2 exit 1 fi declare host for host in "${ARY_HANDLER_JUMPHOST_UNIQUE[@]}"; do ((line++)) sed -i "${line}a ufw allow from ${host} to any port ${sshport} proto tcp comment \"Incoming SSH ([${host}]:${sshport})\"" "$file" done fi fi printf "\e[92m++++ ++++ ++++ ++++ ++++ ++++ ++ โœ… Updating SSH Keys, Ports done. \e[0m\n" if [[ -f "${VAR_WORKDIR}/hosts.allow" ]]; then printf "\e[95m++++ ++++ ++++ ++++ ++++ ++++ ++ ๐Ÿงช SSH Hardening Ultra ... \e[0m\n" cp -af "${VAR_WORKDIR}/hosts.allow" "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/etc" cp -af "${VAR_WORKDIR}/hosts.deny" "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/etc" chmod 0644 "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/etc/hosts.allow" chmod 0644 "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/etc/hosts.deny" rm -f "${VAR_WORKDIR}/hosts.allow" rm -f "${VAR_WORKDIR}/hosts.deny" printf "\e[92m++++ ++++ ++++ ++++ ++++ ++++ ++ โœ… SSH Hardening Ultra done.\e[0m\n" fi if ((${#ARY_HANDLER_JUMPHOST[@]} > 0)); then printf "\e[95m++++ ++++ ++++ ++++ ++++ ++++ ++ ๐Ÿงช Updating fail2ban Jumphosts IPs ... \e[0m\n" # Join array entries with spaces, preserving any newlines declare ips="${ARY_HANDLER_JUMPHOST[*]}" # Flatten to a single line and strip literal brackets [] declare flat_ips flat_ips=$(printf "%s" "${ips}" | tr '\n' ' ' | tr -d '[]') # flat_ips now contains e.g., "123.128.111.42 2a03:ffff:0815:4711:... 2a03:.../64" # Perform an in-place replacement of MUST_BE_SET with the cleaned list sed -i -e "s|^\(ignoreip[[:space:]]*=[[:space:]]*127\.0\.0\.0/8 ::1[[:space:]]*\)MUST_BE_SET|\1${flat_ips}|" \ "${VAR_HANDLER_BUILD_DIR}/config/hooks/live/9950_fail2ban_hardening.chroot" printf "\e[92m++++ ++++ ++++ ++++ ++++ ++++ ++ โœ… Updating fail2ban Jumphosts IPs done. \e[0m\n" else printf "\e[93m++++ ++++ ++++ ++++ ++++ ++++ ++ ๐Ÿงช No jump hosts configured, removing placeholder ... \e[0m\n" sed -i \ -e "s|^\(ignoreip[[:space:]]*=[[:space:]]*127\.0\.0\.0/8 ::1\)[[:space:]]*MUST_BE_SET|\1|" \ -e "s|\(ignoreip[[:space:]]*=[[:space:]]*127\.0\.0\.0/8 ::1\)[[:space:]]*$|\1|" \ "${VAR_HANDLER_BUILD_DIR}/config/hooks/live/9950_fail2ban_hardening.chroot" printf "\e[92m++++ ++++ ++++ ++++ ++++ ++++ ++ โœ… Placeholder removed. \e[0m\n" fi } # vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh