From bded42e80e99b8d143a914c8a2a69767323428f5 Mon Sep 17 00:00:00 2001 From: admManuel Date: Wed, 7 May 2025 19:01:29 +0000 Subject: [PATCH] Update Linux/SSH/secure_ssh.sh --- Linux/SSH/secure_ssh.sh | 172 +++++++++++++++++----------------------- 1 file changed, 72 insertions(+), 100 deletions(-) diff --git a/Linux/SSH/secure_ssh.sh b/Linux/SSH/secure_ssh.sh index d5e77fb..aeb7b56 100644 --- a/Linux/SSH/secure_ssh.sh +++ b/Linux/SSH/secure_ssh.sh @@ -1,13 +1,15 @@ #!/usr/bin/env bash # ────────────────────────────────────────────────────────────────────────────── -# Secure-SSH Setup for Modern Linux (2025-edition) -# ------------------------------------------------ -# * Generates hardened OpenSSH configuration (IPv4-only) -# * Installs/updates OpenSSH-server + creates host keys -# * Creates users, adds SSH public keys, restricts login -# * Removes all legacy / deprecated directives -# * Adds post-quantum KEX, rate-limiting, strict auth flow & root lockdown +# Secure‑SSH Setup – Modern Linux (2025‑edition, PAM‑aware) +# ---------------------------------------------------------- +# ✦ Generates hardened OpenSSH config (IPv4‑only) +# ✦ Installs / updates OpenSSH‑server + creates host keys +# ✦ Creates users, adds SSH public keys, restricts login +# ✦ Removes deprecated directives – fully OpenSSH ≥9.x compliant +# ✦ Dynamically omits UsePAM if PAM isn’t present (e.g. Alpine) +# ✦ Adds post‑quantum KEX, minimal cipher suite, strict auth‑flow, +# rate‑limiting & root lockdown # ────────────────────────────────────────────────────────────────────────────── printf "\033c" # clear terminal @@ -19,128 +21,105 @@ ED25519_KEY="/etc/ssh/ssh_host_ed25519_key" ECDSA_KEY="/etc/ssh/ssh_host_ecdsa_key" # ─── ANSI colors ────────────────────────────────────────────────────────────── -RED='\033[1;31m' -GREEN='\033[1;32m' -YELLOW='\033[1;33m' -BLUE='\033[1;34m' -WHITE='\033[1;37m' -RESET='\033[0m' - +RED='\033[1;31m'; GREEN='\033[1;32m'; YELLOW='\033[1;33m'; BLUE='\033[1;34m'; WHITE='\033[1;37m'; RESET='\033[0m' log() { echo -e "${GREEN}$1${RESET}"; } warn() { echo -e "${YELLOW}$1${RESET}"; } error() { echo -e "${RED}$1${RESET}"; } -# ─── Service-Manager detection (systemd │ sysvinit │ openrc) ─────────────────── +# ─── Service‑manager detection ─────────────────────────────────────────────── detect_service_manager() { - if command -v systemctl &>/dev/null; then echo "systemd" - elif command -v service &>/dev/null; then echo "sysvinit" - elif [ -x /sbin/rc-service ]; then echo "openrc" - else echo "unknown"; fi + if command -v systemctl &>/dev/null; then echo systemd + elif command -v rc-service &>/dev/null; then echo openrc # Alpine, Gentoo… + elif command -v service &>/dev/null; then echo sysvinit + else echo unknown; fi } -# ─── SSH service name detection ─────────────────────────────────────────────── +# ─── SSH service‑name detection ─────────────────────────────────────────────── detect_ssh_service() { - local manager=$1 - local services=(sshd ssh openssh-server openssh) + local manager=$1 services=(sshd ssh openssh-server openssh) case $manager in - systemd) for s in "${services[@]}"; do systemctl list-units --type=service | grep -q $s && echo $s && return; done ;; - sysvinit) for s in "${services[@]}"; do service --status-all | grep -q $s && echo $s && return; done ;; - openrc) for s in "${services[@]}"; do rc-service -l | grep -q $s && echo $s && return; done ;; + systemd) + for s in "${services[@]}"; do systemctl list-units --type=service | grep -q "^$s" && { echo $s; return; }; done ;; + openrc) + for s in "${services[@]}"; do rc-service -l | grep -q "^$s$" && { echo $s; return; }; done ;; + sysvinit) + for s in "${services[@]}"; do [ -x "/etc/init.d/$s" ] && { echo $s; return; }; done ;; esac [ -x /usr/sbin/sshd ] && echo sshd || echo unknown } restart_ssh_service() { - local manager=$1 service=$2 - warn "Starte SSH-Dienst ($service) neu…" + local manager=$1 service=$2; warn "Starte SSH‑Dienst ($service) neu…" case $manager in - systemd) sudo systemctl restart "$service" && return 0 ;; - sysvinit) sudo service "$service" restart && return 0 ;; - openrc) sudo rc-service "$service" restart && return 0 ;; + systemd) sudo systemctl restart "$service" && return 0 ;; + openrc) sudo rc-service "$service" restart && return 0 ;; + sysvinit) sudo "/etc/init.d/$service" restart 2>/dev/null && return 0 ;; esac sudo killall -HUP sshd 2>/dev/null && return 0 return 1 } install_package() { - local pkg=$1 - warn "Installiere $pkg…" - if command -v apt &>/dev/null; then sudo apt update -qq && sudo apt install -y $pkg -qq ; - elif command -v dnf &>/dev/null; then sudo dnf install -y $pkg &>/dev/null ; - elif command -v yum &>/dev/null; then sudo yum install -y $pkg &>/dev/null ; - elif command -v apk &>/dev/null; then sudo apk add $pkg &>/dev/null ; - elif command -v pacman&>/dev/null; then sudo pacman -Sy --noconfirm $pkg &>/dev/null ; - elif command -v zypper&>/dev/null; then sudo zypper install -y $pkg &>/dev/null ; - else error "Kein unterstützter Paketmanager – installiere $pkg manuell."; return 1; fi - log "$pkg wurde installiert." + local p=$1; warn "Installiere $p…" + if command -v apt &>/dev/null; then sudo apt update -qq && sudo apt install -y $p -qq + elif command -v dnf &>/dev/null; then sudo dnf install -y $p &>/dev/null + elif command -v yum &>/dev/null; then sudo yum install -y $p &>/dev/null + elif command -v apk &>/dev/null; then sudo apk add $p &>/dev/null + elif command -v pacman &>/dev/null; then sudo pacman -Sy --noconfirm $p &>/dev/null + elif command -v zypper &>/dev/null; then sudo zypper install -y $p &>/dev/null + else error "Paketmanager nicht erkannt – installiere $p manuell."; return 1; fi + log "$p installiert." } -# ─── Setup prerequisites ───────────────────────────────────────────────────── -SERVICE_MANAGER=$(detect_service_manager); log "Service-Manager: $SERVICE_MANAGER" - +# ─── Preparations ───────────────────────────────────────────────────────────── +SERVICE_MANAGER=$(detect_service_manager); log "Service‑Manager: $SERVICE_MANAGER" command -v sudo &>/dev/null || { warn "sudo fehlt – Installation…"; install_package sudo; } command -v sshd &>/dev/null || install_package openssh-server - [ -d "$SSH_CONFIG_DIR" ] || { warn "Erstelle $SSH_CONFIG_DIR"; sudo mkdir -p "$SSH_CONFIG_DIR"; } -# ─── Host keys (ed25519 & ecdsa-p384) ───────────────────────────────────────── -for key in "$ED25519_KEY ed25519" "$ECDSA_KEY ecdsa -b 384"; do - set -- $key; file=$1; shift; args=$*; - [ -f "$file" ] || { - warn "Generiere Host-Schlüssel $(basename $file)…"; - sudo ssh-keygen -t $args -f "$file" -N "" -q && sudo chmod 600 "$file" && log "Schlüssel $(basename $file) erstellt."; - } +# ─── Host keys ──────────────────────────────────────────────────────────────── +for entry in "$ED25519_KEY ed25519" "$ECDSA_KEY ecdsa -b 384"; do + set -- $entry; key=$1; shift; args=$* + [ -f "$key" ] || { warn "Generiere Host-Key $(basename $key)…"; sudo ssh-keygen -t $args -f "$key" -N "" -q && sudo chmod 600 "$key" && log "Key erstellt."; } done # ─── Replace main config with include only ──────────────────────────────────── warn "Setze $SSH_MAIN_CONFIG auf Include…" echo "Include $SSH_CONFIG_DIR/*.conf" | sudo tee "$SSH_MAIN_CONFIG" >/dev/null - -# ─── Remove legacy configs ──────────────────────────────────────────────────── sudo rm -f $SSH_CONFIG_DIR/* -# ─── Collect allowed users + optional creation ─────────────────────────────── +# ─── User handling ──────────────────────────────────────────────────────────── read -rp $'\e[1;34mWelche Benutzer dürfen sich per SSH anmelden? (Leerzeichen-getrennt): \e[0m' SSH_USERS VALID_USERS="" -# distribution-specific sudo group +# distribution‑specific sudo group declare -A distro_sudo=( [ubuntu]=sudo [debian]=sudo [raspbian]=sudo [centos]=wheel [fedora]=wheel [rhel]=wheel [almalinux]=wheel [rocky]=wheel [ol]=wheel [arch]=wheel [manjaro]=wheel [alpine]=wheel ) -SUDO_GROUP="sudo" -[ -f /etc/os-release ] && { . /etc/os-release; SUDO_GROUP=${distro_sudo[$ID]:-sudo}; } +SUDO_GROUP=sudo; [ -f /etc/os-release ] && { . /etc/os-release; SUDO_GROUP=${distro_sudo[$ID]:-sudo}; } log "Benutze sudo-Gruppe: $SUDO_GROUP" -for user in $SSH_USERS; do - if id "$user" &>/dev/null; then - log "Benutzer $user existiert." - VALID_USERS+="$user " - continue - fi - read -rp $'\e[1;34mBenutzer '"$user"$' existiert nicht. Anlegen? [y/N]: \e[0m' CREATE - [[ $CREATE =~ ^[Yy]$ ]] || continue - read -rsp $'\e[1;34mPasswort für '"$user"$': \e[0m' PW; echo - sudo useradd -m -s /bin/bash "$user" && echo "$user:$PW" | sudo chpasswd - sudo usermod -aG "$SUDO_GROUP" "$user" - sudo install -d -m700 -o "$user" -g "$user" "/home/$user/.ssh" - sudo touch "/home/$user/.ssh/authorized_keys" && sudo chmod 600 "/home/$user/.ssh/authorized_keys" && sudo chown "$user":"$user" "/home/$user/.ssh/authorized_keys" - read -rp $'\e[1;34mSSH Public Key für '"$user"$' hinzufügen? [y/N]: \e[0m' ADDKEY - if [[ $ADDKEY =~ ^[Yy]$ ]]; then - read -rp $'\e[1;34mPublic Key: \e[0m' KEY - echo "$KEY" | sudo tee -a "/home/$user/.ssh/authorized_keys" >/dev/null - fi - VALID_USERS+="$user " +for u in $SSH_USERS; do + if id "$u" &>/dev/null; then log "Benutzer $u existiert."; VALID_USERS+="$u "; continue; fi + read -rp $'\e[1;34mBenutzer '"$u"$' anlegen? [y/N]: \e[0m' create; [[ $create =~ ^[Yy]$ ]] || continue + read -rsp $'\e[1;34mPasswort für '"$u"$': \e[0m' pw; echo + sudo useradd -m -s /bin/bash "$u" && echo "$u:$pw" | sudo chpasswd + sudo usermod -aG "$SUDO_GROUP" "$u" + sudo install -d -m700 -o "$u" -g "$u" "/home/$u/.ssh" + sudo touch "/home/$u/.ssh/authorized_keys" && sudo chmod 600 "/home/$u/.ssh/authorized_keys" && sudo chown "$u":"$u" "/home/$u/.ssh/authorized_keys" + read -rp $'\e[1;34mSSH Public Key für '"$u"$' hinzufügen? [y/N]: \e[0m' addkey + if [[ $addkey =~ ^[Yy]$ ]]; then read -rp $'\e[1;34mPublic Key: \e[0m' key; echo "$key" | sudo tee -a "/home/$u/.ssh/authorized_keys" >/dev/null; fi + VALID_USERS+="$u " done -# ─── Determine SFTP-server binary ───────────────────────────────────────────── -for path in /usr/lib/openssh/sftp-server /usr/libexec/openssh/sftp-server /usr/lib/ssh/sftp-server; do [ -x "$path" ] && SFTP_PATH=$path && break; done -SFTP_PATH=${SFTP_PATH:-internal-sftp} -log "SFTP-Pfad: $SFTP_PATH" +# ─── SFTP binary discovery ─────────────────────────────────────────────────── +for p in /usr/lib/openssh/sftp-server /usr/libexec/openssh/sftp-server /usr/lib/ssh/sftp-server; do [ -x "$p" ] && SFTP_PATH=$p && break; done +SFTP_PATH=${SFTP_PATH:-internal-sftp}; log "SFTP-Pfad: $SFTP_PATH" -# ─── Check for PAM ──────────────────────────────────────────────────────────── +# ─── PAM detection ──────────────────────────────────────────────────────────── PAM_AVAILABLE=false [ -d /etc/pam.d ] && { find / -maxdepth 2 -name 'libpam.so*' -quit | grep -q libpam && PAM_AVAILABLE=true; } -$PAM_AVAILABLE && log "PAM verfügbar." || warn "PAM nicht gefunden – UsePAM wird deaktiviert." +$PAM_AVAILABLE && log "PAM verfügbar." || warn "PAM nicht gefunden – UsePAM wird ausgelassen." -# ─── Generate modern, hardened secure.conf ──────────────────────────────────── +# ─── Generate secure.conf ───────────────────────────────────────────────────── warn "Erstelle $SSH_CONFIG_FILE (modern hardened)…" sudo tee "$SSH_CONFIG_FILE" >/dev/null </dev/null </dev/null +fi + +log "Secure‑Config geschrieben." # ─── Validate & restart SSH ────────────────────────────────────────────────── [ -d /run/sshd ] || { sudo mkdir -p /run/sshd; sudo chmod 0755 /run/sshd; }