From f086d2dbd9de3d46436195f4142f33b7a30bc028 Mon Sep 17 00:00:00 2001 From: Ali Date: Mon, 30 Jun 2025 21:10:35 +0100 Subject: [PATCH] fixing SSH roll back --- du_setup.sh | 220 ++++++++++++++++++++-------------------------------- 1 file changed, 83 insertions(+), 137 deletions(-) diff --git a/du_setup.sh b/du_setup.sh index aabc5ab..e3cfe43 100644 --- a/du_setup.sh +++ b/du_setup.sh @@ -1,7 +1,7 @@ #!/bin/bash # Debian 12 and Ubuntu Server Hardening Interactive Script -# Version: 0.52-rc3 | 2025-06-30 +# Version: 0.52-rc4 | 2025-06-30 # Changelog: # - v0.51: corrected repo links # - v0.50: versioning format change and repo name change @@ -90,7 +90,7 @@ print_header() { echo -e "${CYAN}╔═════════════════════════════════════════════════════════════════╗${NC}" echo -e "${CYAN}║ ║${NC}" echo -e "${CYAN}║ DEBIAN/UBUNTU SERVER SETUP AND HARDENING SCRIPT ║${NC}" - echo -e "${CYAN}║ v0.52-rc3 | 2025-06-30 ║${NC}" + echo -e "${CYAN}║ v0.52-rc4 | 2025-06-30 ║${NC}" echo -e "${CYAN}║ ║${NC}" echo -e "${CYAN}╚═════════════════════════════════════════════════════════════════╝${NC}" echo @@ -503,17 +503,31 @@ configure_system() { log "System configuration completed." } +cleanup_and_exit() { + local exit_code=$? + if [[ $exit_code -ne 0 && $(type -t rollback_ssh_changes) == "function" ]]; then + print_error "An error occurred. Rolling back SSH changes to port $PREVIOUS_SSH_PORT..." + rollback_ssh_changes + if [[ $? -ne 0 ]]; then + print_error "Rollback failed. SSH may not be accessible. Please check 'systemctl status $SSH_SERVICE' and 'journalctl -u $SSH_SERVICE'." + fi + fi + exit $exit_code +} + configure_ssh() { + trap cleanup_and_exit ERR + print_section "SSH Hardening" - local CURRENT_SSH_PORT USER_HOME SSH_DIR SSH_KEY AUTH_KEYS NEW_SSH_CONFIG + local CURRENT_SSH_PORT USER_HOME SSH_DIR SSH_KEY AUTH_KEYS NEW_SSH_CONFIG PREVIOUS_SSH_PORT # Ensure openssh-server is installed if ! dpkg -l openssh-server | grep -q ^ii; then - print_error "openssh-server package is not installed. Please ensure it is installed." - exit 1 + print_error "openssh-server package is not installed." + return 1 fi - # Detect SSH service name, prefer socket activation on Ubuntu if active + # Detect SSH service name if [[ $ID == "ubuntu" ]] && systemctl is-active ssh.socket >/dev/null 2>&1; then SSH_SERVICE="ssh.socket" print_info "Using SSH socket activation: $SSH_SERVICE" @@ -521,115 +535,58 @@ configure_ssh() { SSH_SERVICE="ssh.service" elif systemctl is-enabled sshd.service >/dev/null 2>&1 || systemctl is-active sshd.service >/dev/null 2>&1; then SSH_SERVICE="sshd.service" - elif ps aux | grep -q "[s]shd"; then - print_warning "SSH daemon running but no standard service detected." - SSH_SERVICE="ssh.service" # Default for Debian - if ! systemctl enable --now "$SSH_SERVICE" >/dev/null 2>&1; then - print_error "Failed to enable and start $SSH_SERVICE. Attempting manual start..." - if ! /usr/sbin/sshd; then - print_error "Failed to start SSH daemon manually." - exit 1 - fi - print_success "SSH daemon started manually." - fi else - print_error "No SSH service or daemon detected. Please verify openssh-server installation and daemon status." - exit 1 + print_error "No SSH service or daemon detected." + return 1 fi print_info "Using SSH service: $SSH_SERVICE" log "Detected SSH service: $SSH_SERVICE" - # Ensure SSH service is enabled and running - if ! systemctl is-enabled "$SSH_SERVICE" >/dev/null 2>&1; then - if ! systemctl enable "$SSH_SERVICE" >/dev/null 2>&1; then - print_error "Failed to enable $SSH_SERVICE. Please check service status." - exit 1 - fi - print_success "SSH service enabled: $SSH_SERVICE" - fi - if ! systemctl is-active "$SSH_SERVICE" >/dev/null 2>&1; then - if ! systemctl start "$SSH_SERVICE" >/dev/null 2>&1; then - print_error "Failed to start $SSH_SERVICE. Attempting manual start..." - if ! /usr/sbin/sshd; then - print_error "Failed to start SSH daemon manually." - exit 1 - fi - print_success "SSH daemon started manually." - fi - fi - - CURRENT_SSH_PORT=$(ss -tuln | grep -E ":(22|.*$SSH_SERVICE.*)" | awk '{print $5}' | cut -d':' -f2 | head -n1 || echo "22") + # Store the current active port as the previous port + PREVIOUS_SSH_PORT=$(ss -tuln | grep -E ":(22|.*$SSH_SERVICE.*)" | awk '{print $5}' | cut -d':' -f2 | head -n1 || echo "22") + CURRENT_SSH_PORT=$PREVIOUS_SSH_PORT USER_HOME=$(getent passwd "$USERNAME" | cut -d: -f6) SSH_DIR="$USER_HOME/.ssh" - SSH_KEY="$SSH_DIR/id_ed25519" AUTH_KEYS="$SSH_DIR/authorized_keys" if [[ $LOCAL_KEY_ADDED == false ]] && [[ ! -s "$AUTH_KEYS" ]]; then - print_info "No local key provided and no existing keys found. Generating new SSH key..." - mkdir -p "$SSH_DIR" - chmod 700 "$SSH_DIR" - sudo -u "$USERNAME" ssh-keygen -t ed25519 -f "$SSH_KEY" -N "" -q - cat "$SSH_KEY.pub" >> "$AUTH_KEYS" - chmod 600 "$AUTH_KEYS" - chown -R "$USERNAME:$USERNAME" "$SSH_DIR" + print_info "No local key provided. Generating new SSH key..." + mkdir -p "$SSH_DIR"; chmod 700 "$SSH_DIR" + sudo -u "$USERNAME" ssh-keygen -t ed25519 -f "$SSH_DIR/id_ed25519" -N "" -q + cat "$SSH_DIR/id_ed25519.pub" >> "$AUTH_KEYS" + chmod 600 "$AUTH_KEYS"; chown -R "$USERNAME:$USERNAME" "$SSH_DIR" print_success "SSH key generated." - echo -e "${YELLOW}Public key for remote access:${NC}" - cat "$SSH_KEY.pub" | tee -a "$LOG_FILE" - echo -e "${YELLOW}Copy this key to your local ~/.ssh/authorized_keys or use 'ssh-copy-id -p $CURRENT_SSH_PORT $USERNAME@$SERVER_IP' from your local machine.${NC}" - else - print_info "SSH key(s) already present or added. Skipping key generation." + echo -e "${YELLOW}Public key for remote access:${NC}"; cat "$SSH_DIR/id_ed25519.pub" fi print_warning "SSH Key Authentication Required for Next Steps!" echo -e "${CYAN}Test SSH access from a SEPARATE terminal now: ssh -p $CURRENT_SSH_PORT $USERNAME@$SERVER_IP${NC}" - if ! confirm "Can you successfully log in using your SSH key?"; then - print_error "SSH key authentication is mandatory to proceed. Please fix and re-run." - exit 1 + print_error "SSH key authentication is mandatory to proceed." + return 1 fi print_info "Backing up original SSH config..." SSHD_BACKUP_FILE="$BACKUP_DIR/sshd_config.backup_$(date +%Y%m%d_%H%M%S)" cp /etc/ssh/sshd_config "$SSHD_BACKUP_FILE" - # Update SSH port in sshd_config for Ubuntu 24.04+ socket activation + # Apply port override if [[ $ID == "ubuntu" ]] && dpkg --compare-versions "$(lsb_release -rs)" ge "24.04"; then - print_info "Updating SSH port in /etc/ssh/sshd_config for Ubuntu 24.04+ socket activation..." - if ! grep -q "^Port" /etc/ssh/sshd_config; then - echo "Port $SSH_PORT" >> /etc/ssh/sshd_config - else - sed -i "s/^Port .*/Port $SSH_PORT/" /etc/ssh/sshd_config - fi + print_info "Updating SSH port in /etc/ssh/sshd_config for Ubuntu 24.04+..." + if ! grep -q "^Port" /etc/ssh/sshd_config; then echo "Port $SSH_PORT" >> /etc/ssh/sshd_config; else sed -i "s/^Port .*/Port $SSH_PORT/" /etc/ssh/sshd_config; fi + elif [[ "$SSH_SERVICE" == "ssh.socket" ]]; then + print_info "Configuring SSH socket to listen on port $SSH_PORT..." + mkdir -p /etc/systemd/system/ssh.socket.d + echo -e "[Socket]\nListenStream=\nListenStream=$SSH_PORT" > /etc/systemd/system/ssh.socket.d/override.conf else - # Fallback for older versions or non-Ubuntu - if [[ "$SSH_SERVICE" == "ssh.socket" ]]; then - print_info "Configuring SSH socket to listen on port $SSH_PORT..." - NEW_SSH_CONFIG=$(mktemp) - tee "$NEW_SSH_CONFIG" > /dev/null < /dev/null < /etc/systemd/system/${SSH_SERVICE}.d/override.conf fi - # Apply additional hardening via sshd_config.d - NEW_SSH_CONFIG=$(mktemp) - tee "$NEW_SSH_CONFIG" > /dev/null < /dev/null < /dev/null <<'EOF' + tee /etc/issue.net > /dev/null <<'EOF' ****************************************************************************** 🔒AUTHORIZED ACCESS ONLY ════ all attempts are logged and reviewed ════ ****************************************************************************** EOF - fi print_info "Reloading systemd and restarting SSH service..." systemctl daemon-reload - if [[ $SSH_SERVICE == "ssh.socket" ]]; then - if ! systemctl restart "$SSH_SERVICE"; then - print_error "SSH socket failed to restart! Reverting changes..." - rollback_ssh_changes - exit 1 - fi - else - if ! systemctl restart "$SSH_SERVICE"; then - print_error "SSH service failed to restart! Reverting changes..." - rollback_ssh_changes - exit 1 - fi - fi - # Wait and verify port binding + systemctl restart "$SSH_SERVICE" sleep 5 if ! ss -tuln | grep -q ":$SSH_PORT"; then - print_error "SSH not listening on port $SSH_PORT after restart! Reverting changes..." - rollback_ssh_changes - exit 1 + print_error "SSH not listening on port $SSH_PORT after restart!" + return 1 fi print_success "SSH service restarted on port $SSH_PORT." # Verify root SSH is disabled print_info "Verifying root SSH login is disabled..." - if ssh -p "$SSH_PORT" -o BatchMode=yes -o ConnectTimeout=5 root@localhost true 2>/dev/null; then - print_error "Root SSH login is still possible! Check SSH configuration." - rollback_ssh_changes - exit 1 + if ssh -p "$SSH_PORT" -o BatchMode=yes -o StrictHostKeyChecking=no -o ConnectTimeout=5 root@localhost true 2>/dev/null; then + print_error "Root SSH login is still possible! Check configuration." + return 1 else print_success "Confirmed: Root SSH login is disabled." fi print_warning "CRITICAL: Test new SSH connection in a SEPARATE terminal NOW!" print_info "Use: ssh -p $SSH_PORT $USERNAME@$SERVER_IP" - print_info "If login fails, ensure client uses the new port and check server logs (e.g., journalctl -u $SSH_SERVICE)." # Retry loop for SSH connection test local retry_count=0 local max_retries=3 while (( retry_count < max_retries )); do if confirm "Was the new SSH connection successful?"; then + print_success "SSH hardening confirmed and finalized." break else (( retry_count++ )) @@ -705,44 +638,57 @@ EOF print_info "Retrying SSH connection test ($retry_count/$max_retries)..." sleep 5 else - print_error "Aborting. Initiating rollback to original configuration..." + print_error "All retries failed. Initiating rollback to port $PREVIOUS_SSH_PORT..." rollback_ssh_changes - if ss -tuln | grep -q ":$CURRENT_SSH_PORT"; then - print_success "Rollback successful. SSH restored on original port $CURRENT_SSH_PORT." + if ! ss -tuln | grep -q ":$PREVIOUS_SSH_PORT"; then + print_error "Rollback failed. SSH not restored on original port $PREVIOUS_SSH_PORT." else - print_error "Rollback failed. SSH may not be accessible. Please investigate manually." + print_success "Rollback successful. SSH restored on original port $PREVIOUS_SSH_PORT." fi - exit 1 + return 1 fi fi done + + trap - ERR log "SSH hardening completed." } rollback_ssh_changes() { - print_info "Rolling back SSH configuration changes..." - print_info "Removing override and hardening files..." + print_info "Rolling back SSH configuration changes to port $PREVIOUS_SSH_PORT..." rm -f /etc/systemd/system/ssh.service.d/override.conf rm -f /etc/systemd/system/ssh.socket.d/override.conf - print_info "Restoring original sshd_config from $SSHD_BACKUP_FILE..." + rm -f /etc/ssh/sshd_config.d/99-hardening.conf if [[ -f "$SSHD_BACKUP_FILE" ]]; then cp "$SSHD_BACKUP_FILE" /etc/ssh/sshd_config - rm -f /etc/ssh/sshd_config.d/99-hardening.conf + print_info "Restored original sshd_config from $SSHD_BACKUP_FILE." else - print_error "Backup file $SSHD_BACKUP_FILE not found. Rollback incomplete." - exit 1 + print_error "Backup file not found. Could not restore sshd_config." + return 1 fi + print_info "Reloading systemd and restarting $SSH_SERVICE..." systemctl daemon-reload if ! systemctl restart "$SSH_SERVICE"; then print_warning "Failed to restart $SSH_SERVICE after rollback. Attempting manual start..." /usr/sbin/sshd || true fi - sleep 10 - if ! ss -tuln | grep -q ":$CURRENT_SSH_PORT"; then - print_error "Rollback failed. SSH not restored on original port $CURRENT_SSH_PORT. Please check logs." - else - print_success "Rollback successful. SSH restored on original port $CURRENT_SSH_PORT." + + local rollback_verified=false + print_info "Verifying SSH rollback to port $PREVIOUS_SSH_PORT..." + for ((i=1; i<=10; i++)); do + if ss -tuln | grep -q ":$PREVIOUS_SSH_PORT"; then + print_success "Rollback successful. SSH is now listening on port $PREVIOUS_SSH_PORT." + rollback_verified=true + break + fi + sleep 1 + done + + if [[ $rollback_verified == false ]]; then + print_error "Rollback failed. SSH service is not listening on port $PREVIOUS_SSH_PORT." + print_info "Please check service status manually with 'systemctl status $SSH_SERVICE' and 'journalctl -u $SSH_SERVICE'." + return 1 fi }