Configuring and Securing SSH Server with sshd.sh: A Guide for Reliable Setup

The sshd.sh script is crafted to automate the configuration of sshd settings, applying essential security options, checking for user privileges, and streamlining the SSH setup for administrators. The sshd.sh script available in my Git Hub repository.

Configuring and Securing SSH Server with sshd.sh: A Guide for Reliable Setup

When setting up SSH on a Linux server, ensuring secure access is critical. The sshd.sh script is crafted to automate the configuration of sshd settings, applying essential security options, checking for user privileges, and streamlining the SSH setup for administrators. This post dives into the details of the sshd.sh script available in my Git Hub repository, crafted for setting up a secure SSH server configuration. Feel free to access, review, and use the script as you like—it's there to make your SSH setup smoother and more secure!

1. Overview of the sshd.sh Script

This script configures SSH server (sshd) settings, making it a suitable starting point for anyone wanting to secure remote access on a Linux system. Key objectives include:

  • Verifying if the script is executed with root permissions.
  • Applying secure SSH configurations.
  • Disabling features like password login and empty passwords to prioritize SSH keys.
  • Checking if a specific user (vagrant) or another user that you can provide to the script is available and adjusting privileges if necessary.
  • Restarting the SSH service to apply changes.

2. Breaking Down the Script

Let’s explore the code and functionality, line by line.

#!/bin/bash -ex

The shebang (#!/bin/bash -ex) specifies that this script should be executed with bash. The -e flag stops the script if any command fails, and -x enables debugging, printing each command as it's executed.

3. Ensuring Root Privileges

check_root() {
    if [[ $EUID -ne 0 ]]; then
        echo "This script must be run as root" 
        exit 1
    fi
}

The check_root function verifies if the script is run as the root user (required for modifying SSH settings and other system configurations). The EUID variable is the effective user ID; a non-zero ID means the user is not root. If not run as root, the script exits with an error message.

Usage:

check_root

This command is placed at the start of the script to ensure all further commands run with the necessary privileges.

4. Core Function for SSHD Configuration

configure_sshd() {
    local option="$1"
    local value="$2"
    local config_file="/etc/ssh/sshd_config"

    # Check if option exists; if so, replace it; otherwise, add it.
    if grep -q "^$option" "$config_file"; then
        sed -i "s/^$option.*/$option $value/" "$config_file"
    else
        echo "$option $value" | sudo tee -a "$config_file"
    fi
}

The configure_sshd function adds or updates SSH configuration options. It takes two arguments:

  • option: The configuration setting (e.g., PermitRootLogin).
  • value: The desired value for that option (e.g., no).

The function checks if the specified configuration option is already in /etc/ssh/sshd_config. If it exists, it uses sed to replace the line with the new setting. If not, it appends the option and value to the file.

Example Call:

configure_sshd "UseDNS" "no"

5. Secure SSH Settings Applied by the Script

# Basic SSH Server Configuration
configure_sshd "UseDNS" "no"
configure_sshd "GSSAPIAuthentication" "no"
configure_sshd "PermitRootLogin" "no"  # Disable root login for security
configure_sshd "PasswordAuthentication" "no"  # Disable password-based login, recommend SSH keys
configure_sshd "PermitEmptyPasswords" "no"  # Disallow empty passwords
configure_sshd "AllowTcpForwarding" "no"  # Disable TCP forwarding by default

Each configure_sshd call updates the sshd_config file with secure options. Here’s what each setting does:

  1. UseDNS no: Disables DNS lookups during login, which reduces login delays.
  2. GSSAPIAuthentication no: Disables GSSAPI, a network authentication protocol often unnecessary outside enterprise environments, to speed up login.
  3. PermitRootLogin no: Disables SSH login as the root user, minimizing unauthorized access risks.
  4. PasswordAuthentication no: Disables password authentication, encouraging SSH key use, which is more secure.
  5. PermitEmptyPasswords no: Prevents login with empty passwords, ensuring no accounts are accessible without a password.
  6. AllowTcpForwarding no: Disables TCP forwarding, reducing exposure to port forwarding risks.

6. Conditional Configuration for Additional User

if id "${ADD_USER}" &>/dev/null; then
    cp /etc/sudoers /etc/sudoers.backup
    echo "Defaults:${ADD_USER} !requiretty" | sudo tee -a /etc/sudoers
fi

This section of the script checks if the ${ADD_USER} contains user name that already exists. If so, it adjusts the /etc/sudoers file to prevent SSH login issues by appending the Defaults:ADD_USER !requiretty setting. This change allows this user to execute commands without a terminal (requiretty), a common configuration needed for automation tools like Vagrant.

7. Reloading the SSH Service

if command -v systemctl &>/dev/null; then
    systemctl restart sshd
else
    service ssh restart
fi

This section restarts the SSH service to apply all changes. It checks if systemctl (used in systemd environments) is available and uses it to restart sshd. If systemctl isn’t available, it falls back on the older service command. This ensures compatibility with a wide range of Linux distributions.

8. Final Output

echo "SSH server configuration is complete and secure."

A simple echo statement indicating that the SSH server is now configured and secure.

9. Complete Script Listing

Here is the entire sshd.sh script:

#!/bin/bash -ex

# sshd.sh         - Set up SSHD configurations for secure access.

# Function to check if running as root
check_root() {
    if [[ $EUID -ne 0 ]]; then
        echo "This script must be run as root" 
        exit 1
    fi
}

# Function to add or replace configuration in sshd_config
configure_sshd() {
    local option="$1"
    local value="$2"
    local config_file="/etc/ssh/sshd_config"

    # Check if option exists; if so, replace it; otherwise, add it.
    if grep -q "^$option" "$config_file"; then
        sed -i "s/^$option.*/$option $value/" "$config_file"
    else
        echo "$option $value" | sudo tee -a "$config_file"
    fi
}

check_root

# Basic SSH Server Configuration
configure_sshd "UseDNS" "no"
configure_sshd "GSSAPIAuthentication" "no"
configure_sshd "PermitRootLogin" "no"  # Disable root login for security
configure_sshd "PasswordAuthentication" "no"  # Disable password-based login, recommend SSH keys
configure_sshd "PermitEmptyPasswords" "no"  # Disallow empty passwords
configure_sshd "AllowTcpForwarding" "no"  # Disable TCP forwarding by default

# Conditional setup for vagrant user, if it exists
if id "vagrant" &>/dev/null; then
    cp /etc/sudoers /etc/sudoers.backup
    echo "Defaults:vagrant !requiretty" | sudo tee -a /etc/sudoers
fi

# Reload SSH service to apply changes
if command -v systemctl &>/dev/null; then
    systemctl restart sshd
else
    service ssh restart
fi

echo "SSH server configuration is complete and secure."

Conclusion

The sshd.sh script automates SSH security configurations, enforcing best practices and ensuring your SSH server is hardened against unauthorized access. By leveraging conditionals and backup practices, this script works across Linux distributions, providing administrators with a flexible and secure SSH setup. This guide helps you understand the reasoning behind each command, allowing you to adapt and expand the script as needed for your specific environment.

Read next

Automating GRUB Configuration Across Linux Distributions

In this post, we’re going to explore the grub.sh script, which is designed to handle the configuration and hardening of GRUB across various Linux distributions. We’ll go over each line of the script to understand what it does and how it contributes to the overall configuration.

The NVLink Bridge Saga: Attempt Number Four

What started as a busy evening and a casual SMS turned into the most successful NVLink install I’ve ever had. After three failures, the fourth attempt finally worked — quietly, instantly, and without demanding my soul.