diff --git a/miscellaneous/secure_ssh.sh b/miscellaneous/secure_ssh.sh index 3e0eb6f..2f4cce3 100644 --- a/miscellaneous/secure_ssh.sh +++ b/miscellaneous/secure_ssh.sh @@ -1,101 +1,232 @@ #!/bin/bash -# Warning: Before running this script, make sure you have created a user and an SSH key in the authorized_keys file. - -# This script is designed to configure the SSH server on a Linux system according to Mozilla's security best practices. -# It enhances the security of SSH connections by enforcing modern encryption standards, disabling insecure protocols, and restricting root access. -# The script backs up the original SSH configuration file, applies a new set of secure settings, and then restarts the SSH service to apply the changes. -# These settings include disabling password authentication, limiting access to strong ciphers and key exchange methods, and enhancing brute-force protection. -# These recommendations are based on Mozilla's guidelines, which can be found here: https://infosec.mozilla.org/guidelines/openssh +# This script configures the SSH server according to Mozilla's best security practices. +# It backs up the original SSH configuration file, generates a new secure configuration file, +# and then restarts the SSH service to apply the changes. # Usage: -# To run this script, save it as "secure_ssh.sh" and make it executable by running the command: `chmod +x secure_ssh.sh`. -# After that, execute it with root privileges using: `sudo ./secure_ssh.sh`. -# The script will automatically apply the recommended configuration changes and restart the SSH service. - -# Check if the script is run as root -if [[ "$EUID" -ne 0 ]]; then - echo "This script must be run as root. Please use sudo to execute it." - exit 1 -fi +# 1. Save this script as "secure_ssh.sh". +# 2. Make it executable with: `chmod +x secure_ssh.sh`. +# 3. Run it with root privileges using: `sudo ./secure_ssh.sh`. # Variables SSHD_CONFIG="/etc/ssh/sshd_config" -BACKUP_FILE="${SSHD_CONFIG}_$(date +'%Y%m%d_%H%M%S').bak" # Backup with date and time +BACKUP_DIR="/etc/ssh/backup_sshd_config" +DATE_STR=$(date +"%Y%m%d_%H%M%S") +SSHD_SERVICE="" -# Backup the old configuration with a timestamp -cp "$SSHD_CONFIG" "$BACKUP_FILE" +# Function to validate an IP address +validate_ip() { + local ip=$1 + local stat=1 -# Ask user if they want to restrict SSH access to a single IP -read -p "Do you want to restrict SSH access to a single IP? (yes/no): " restrict_ip + if [[ $ip =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then + OIFS=$IFS + IFS='.' + ip=($ip) + IFS=$OIFS + if [[ ${ip[0]} -le 255 && ${ip[1]} -le 255 && ${ip[2]} -le 255 && ${ip[3]} -le 255 ]]; then + stat=0 + fi + fi -if [[ "$restrict_ip" == "yes" ]]; then - read -p "Enter the IP address to allow SSH access: " allowed_ip - allow_users="AllowUsers *@${allowed_ip}" -else - allow_users="# AllowUsers configuration not set" -fi + return $stat +} -# Ask user if they want to change the SSH port -read -p "Do you want to change the SSH port? (yes/no): " change_port -if [[ "$change_port" == "yes" ]]; then - read -p "Enter the new SSH port: " new_port - port_setting="Port $new_port" -else - port_setting="# Port configuration not changed" -fi +# Function to validate the SSH port +validate_ssh_port() { + local port=$1 + local stat=1 -# Ask user if they want to use password or key-based authentication -read -p "Do you want to use password or key-based authentication? (password/key): " auth_method -if [[ "$auth_method" == "password" ]]; then - password_auth="PasswordAuthentication yes" - key_auth="# PasswordAuthentication no" -else - password_auth="# PasswordAuthentication no" - key_auth="PubkeyAuthentication yes" -fi + if [[ "$port" =~ ^[0-9]+$ ]] && [[ "$port" -gt 0 && "$port" -le 65535 ]]; then + stat=0 + fi -# Modify the sshd_config file -cat < "$SSHD_CONFIG" -# Mozilla SSH Security Recommendations + return $stat +} + +# Detect the name of the SSH service +detect_sshd_service() { + if systemctl list-units --type=service | grep -q 'sshd'; then + echo "sshd" + elif systemctl list-units --type=service | grep -q 'ssh'; then + echo "ssh" + else + echo "" + fi +} + +# Function to restart the SSH service +restart_sshd() { + local service=$1 + systemctl restart "$service" + return $? +} + +# Create a backup of the SSH configuration file +backup_sshd_config() { + mkdir -p "$BACKUP_DIR" + BACKUP_FILE="${BACKUP_DIR}/sshd_config.${DATE_STR}.bak" + cp "$SSHD_CONFIG" "$BACKUP_FILE" + if [[ $? -ne 0 ]]; then + echo "Error creating backup of the SSH configuration file." + exit 1 + fi + echo "SSH configuration backup created: $BACKUP_FILE" +} + +# Prompt for the SSH port +prompt_ssh_port() { + while true; do + read -p "Please enter the SSH port (default 22): " SSH_PORT + SSH_PORT=${SSH_PORT:-22} + if validate_ssh_port "$SSH_PORT"; then + echo "SSH port used: $SSH_PORT" + break + else + echo "Invalid port. The port must be an integer between 1 and 65535." + fi + done +} + +# Prompt to restrict SSH access to specific IP addresses +prompt_allowed_ips() { + read -p "Do you want to restrict SSH access to specific IP addresses? (yes/no): " RESTRICT_ACCESS + ALLOWED_IPS="" + if [[ "$RESTRICT_ACCESS" =~ ^([oO]ui|[yY]es)$ ]]; then + while true; do + read -p "Enter a comma-separated list of allowed IP addresses (e.g. 192.168.1.1,10.0.0.1): " ALLOWED_IPS_INPUT + IFS=',' read -ra IP_ARRAY <<< "$ALLOWED_IPS_INPUT" + VALID=true + ALLOWED_IPS_CLEAN="" + for ip in "${IP_ARRAY[@]}"; do + ip=$(echo "$ip" | xargs) # Remove spaces + if ! validate_ip "$ip"; then + echo "Invalid IP address: $ip" + VALID=false + break + fi + ALLOWED_IPS_CLEAN+="$ip " + done + if $VALID; then + ALLOWED_IPS="${ALLOWED_IPS_CLEAN% }" # Remove trailing space + echo "SSH access allowed from: $ALLOWED_IPS" + break + else + echo "Please enter valid IP addresses." + fi + done + else + echo "SSH access allowed from all IP addresses." + fi +} + +# Generate a new SSH configuration file +generate_new_sshd_config() { + cat < "$SSHD_CONFIG" +# Secure SSH configuration according to Mozilla's recommendations + +# Protocol version Protocol 2 -# Enable only secure ciphers + +# Secure ciphers Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr -# Enable only secure key exchange algorithms + +# Secure key exchange algorithms KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256 -# Enable only secure MAC algorithms + +# Secure MAC algorithms MACs hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha2-256,hmac-sha2-512 -# Authentication method based on user input -$password_auth -$key_auth +# Disable password authentication +PasswordAuthentication no -# Disable old host keys +# Secure host keys (make sure they exist) HostKey /etc/ssh/ssh_host_ed25519_key HostKey /etc/ssh/ssh_host_rsa_key # Restrict root access PermitRootLogin no -# Strict connection policy +# Strict login policy MaxAuthTries 3 LoginGraceTime 30 -# Additional security recommendations +# Specified SSH port +Port $SSH_PORT + +# Other recommended configurations +PermitEmptyPasswords no +ChallengeResponseAuthentication no +UsePAM yes AllowTcpForwarding no -MaxSessions 2 -LogLevel VERBOSE -ClientAliveInterval 300 -ClientAliveCountMax 2 +X11Forwarding no -# IP restriction based on user input -$allow_users - -# SSH port based on user input -$port_setting +# IP address access restrictions (if specified) EOL -# Restart the SSH service -systemctl restart sshd + if [[ -n "$ALLOWED_IPS" ]]; then + echo "" >> "$SSHD_CONFIG" + echo "# IP address access restriction" >> "$SSHD_CONFIG" + echo "Match Address $(echo "$ALLOWED_IPS" | tr ' ' ',')" >> "$SSHD_CONFIG" + echo " AllowUsers *" >> "$SSHD_CONFIG" + fi +} -echo "SSH configuration has been updated and backed up to $BACKUP_FILE according to Mozilla's security recommendations." \ No newline at end of file +# Test the syntax of the new SSH configuration +test_sshd_config() { + sshd -t + return $? +} + +# Detect the SSH service in use +detect_service() { + SSHD_SERVICE=$(detect_sshd_service) + if [[ -z "$SSHD_SERVICE" ]]; then + echo "Error: Unable to detect the SSH service (sshd or ssh)." + exit 1 + fi +} + +# Main process +main() { + # Detect the SSH service + detect_service + + # Backup current configuration + backup_sshd_config + + # Prompt for the SSH port + prompt_ssh_port + + # Prompt for allowed IP addresses + prompt_allowed_ips + + # Generate the new configuration file + generate_new_sshd_config + echo "New SSH configuration file generated." + + # Test the syntax of the new configuration + if test_sshd_config; then + echo "The new SSH configuration is valid." + else + echo "Error: The new SSH configuration contains errors. Restoring original configuration." + cp "$BACKUP_FILE" "$SSHD_CONFIG" + restart_sshd "$SSHD_SERVICE" + exit 1 + fi + + # Restart the SSH service + if restart_sshd "$SSHD_SERVICE"; then + echo "The SSH service has been restarted successfully." + echo "The SSH configuration has been updated according to Mozilla's security recommendations." + else + echo "Error: Failed to restart the SSH service. Restoring original configuration." + cp "$BACKUP_FILE" "$SSHD_CONFIG" + restart_sshd "$SSHD_SERVICE" + exit 1 + fi +} + +# Execute the main process +main \ No newline at end of file