Skip to content

Instantly share code, notes, and snippets.

@jesussuarz
Last active May 5, 2024 04:03
Show Gist options
  • Save jesussuarz/a2806db341a699ac04e65b0a17fa4c7a to your computer and use it in GitHub Desktop.
Save jesussuarz/a2806db341a699ac04e65b0a17fa4c7a to your computer and use it in GitHub Desktop.
Advanced SSH Configuration Script for Dynamic Port Assignment and Enhanced Security

Advanced SSH Configuration Script for Dynamic Port Assignment and Enhanced Security

Introduction:

This Bash script automates the configuration of SSH services on Oracle Linux 8.9, including dynamic port assignment based on IP address input, SELinux and firewall adjustments, and SSH key pair generation with enhanced security measures.

Functionality:

The script starts by verifying the presence of an IP address as input. It then parses the IP address to construct a unique SSH port number based on predefined rules: the port number starts with a '6', followed by the first digit of the first IP octet, and the last digits of the remaining three octets.

Key Features:

  • Dynamic SSH Port Configuration: Automatically updates the SSH port in the sshd_config file based on the IP address provided, enhancing security by avoiding default port usage.
  • SELinux and Firewall Integration: Installs necessary tools and configures SELinux to allow the new SSH port, and updates the firewall rules to permit traffic on the new port, ensuring the server remains protected.
  • SSH Key Pair Generation: Generates a strong RSA key pair secured with a randomly generated password, stored securely on the system. This step enhances user authentication practices.
  • Environmental Checks and Preparations: Checks for the existence of the .ssh directory and creates it if missing, setting the appropriate permissions to maintain security standards.

Code:

#!/bin/bash

# Validate that an IP address has been provided as an argument
if [ -z "$1" ]; then
  echo "Please provide an IP address as an argument."
  exit 1
fi

# Extract the octets from the IP address
IFS='.' read -ra ADDR <<< "$1"

# Ensure that the IP has exactly four octets
if [ ${#ADDR[@]} -ne 4 ]; then
  echo "The provided IP address is invalid."
  exit 1
fi

# Construct the port number
# The first number is always 6
# The second number is the first number of the first octet
# The next three numbers are the last number from each of the last three octets
port="6${ADDR[0]:0:1}${ADDR[1]: -1}${ADDR[2]: -1}${ADDR[3]: -1}"

# Display the port
echo "The calculated SSH port for IP $1 is: $port"

# Ensure the ~/.ssh directory exists
if [ ! -d ~/.ssh ]; then
  mkdir ~/.ssh
  chmod 700 ~/.ssh
fi

# Update SSH port in the sshd_config file
if ! grep -q "^Port" /etc/ssh/sshd_config; then
  echo "Port $port" >> /etc/ssh/sshd_config
else
  sed -i "s/^Port .*/Port $port/" /etc/ssh/sshd_config
fi

# Install SELinux management tool
yum install -y policycoreutils-python-utils

# Add the port to SELinux policy
semanage port -a -t ssh_port_t -p tcp $port

# Allow the port through the firewall
firewall-cmd --permanent --zone=public --add-port=$port/tcp
firewall-cmd --reload

# Check if key files exist and delete them if they do
for file in id_rsa id_rsa.pub key_password.txt; do
  if [ -f "/root/.ssh/$file" ]; then
    rm "/root/.ssh/$file"
    echo "Deleted existing file: /root/.ssh/$file"
  fi
done

# Generate a random password for SSH key
password=$(openssl rand -base64 32)

# Generate SSH key pair
ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa -N "$password" -C "key-for-$1"
echo "SSH key pair generated with a random password."

# Output the generated password to a secure location
echo $password > ~/.ssh/key_password.txt
chmod 600 ~/.ssh/key_password.txt
echo "Password for SSH key pair stored securely."

# Check if the public key already exists in authorized_keys
if grep -qFf ~/.ssh/id_rsa.pub ~/.ssh/authorized_keys; then
  echo "Public key already exists in authorized_keys."
else
  cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
  chmod 600 ~/.ssh/authorized_keys
  echo "Public SSH key added to authorized keys for authentication."
fi

# Restart SSH service to apply changes
systemctl restart sshd.service
if [ $? -eq 0 ]; then
    echo "SSH service has been restarted successfully."
else
    echo "Failed to restart SSH service. Please check for errors."
    exit 1
fi

Download Command:

wget https://gist.githubusercontent.com/jesussuarz/a2806db341a699ac04e65b0a17fa4c7a/raw/f9d561441ffe1f79e75b5128e114974a9fc87073/SSH-Dynamic-Port-and-Security-Setup.sh -O SSH-Dynamic-Port-and-Security-Setup.sh

Usage:

The script must be run as a superuser to modify system configuration files and manage services. It is designed for systems administrators who need to dynamically assign SSH ports based on IP addresses and enhance server security through automated configurations.

chmod +x SSH-Dynamic-Port-and-Security-Setup.sh
hostname -I
./SSH-Dynamic-Port-and-Security-Setup.sh Your_Public_Server_IP 
# Example: ./SSH-Dynamic-Port-and-Security-Setup.sh 192.168.0.1
#Download Private Key and Password Key:
cat ~/.ssh/id_rsa
cat ~/.ssh/key_password.txt

Please be aware that to prevent this script from potentially locking you out of your server, you must manually enable public key authentication. Follow the steps below to properly set up this feature:

Edit the

nano /etc/ssh/sshd_config 

file so that it has the following configuration:

# Authentication:

PermitRootLogin without-password #Force use SSH Key with Login Root
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys

PasswordAuthentication no
ChallengeResponseAuthentication no

UsePAM no

GSSAPIAuthentication no

Explanation:

  • PermitRootLogin yes: Allows root user access. You can change this to without-password to enforce the exclusive use of public keys for the root user.
  • PubkeyAuthentication yes: Ensures that public key authentication is enabled.
  • AuthorizedKeysFile .ssh/authorized_keys: Specifies the location of the file that contains the authorized public keys.
  • PasswordAuthentication no: Disables password authentication, enforcing the use of keys.
  • ChallengeResponseAuthentication no: Disables challenge-response authentication, which is another form of password-based authentication.
  • UsePAM no: Disables PAM (Pluggable Authentication Module), which can allow password-based authentication methods depending on its configuration.
  • GSSAPIAuthentication no: Disables GSSAPI authentication, which is primarily used in environments implementing Kerberos.

after:

cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
systemctl restart sshd

Please remember to download your private key for future access to your server. You can find it in the /root/.ssh folder, along with the key_password.txt file that contains the key's password.

Be aware that the private key is not directly compatible with PuTTY. To use it with this software, you will need to convert it to the PPK format. This conversion can be performed on a Windows machine equipped with the Windows Subsystem for Linux (WSL) and PuTTY installed:

Redhat/Centos/AlmaLinux

sudo yum install putty

Ubuntu/Debian

sudo apt update
sudo apt install putty-tools

Go to the directory where you downloaded your private key and run:

puttygen id_rsa -o id_rsa.ppk -O private

Conclusion:

This script is a powerful tool for managing SSH configurations in dynamic IP environments. By automating the port assignment, SELinux and firewall settings, and key pair generation, it significantly reduces manual configuration errors and strengthens the security posture of the server. Suitable for both new installations and existing setups looking to improve their security with minimal manual intervention.

Note: If you only want to generate the dynamic port for SSH you can use the following bash script: https://gist.github.com/jesussuarz/4e29438a55ea41061da34b8355d4a52c

If you encounter any issues with the code or its usage, please leave a comment, and I will respond as soon as possible.

#!/bin/bash
# Validate that an IP address has been provided as an argument
if [ -z "$1" ]; then
echo "Please provide an IP address as an argument."
exit 1
fi
# Extract the octets from the IP address
IFS='.' read -ra ADDR <<< "$1"
# Ensure that the IP has exactly four octets
if [ ${#ADDR[@]} -ne 4 ]; then
echo "The provided IP address is invalid."
exit 1
fi
# Construct the port number
# The first number is always 6
# The second number is the first number of the first octet
# The next three numbers are the last number from each of the last three octets
port="6${ADDR[0]:0:1}${ADDR[1]: -1}${ADDR[2]: -1}${ADDR[3]: -1}"
# Display the port
echo "The calculated SSH port for IP $1 is: $port"
# Ensure the ~/.ssh directory exists
if [ ! -d ~/.ssh ]; then
mkdir ~/.ssh
chmod 700 ~/.ssh
fi
# Update SSH port in the sshd_config file
if ! grep -q "^Port" /etc/ssh/sshd_config; then
echo "Port $port" >> /etc/ssh/sshd_config
else
sed -i "s/^Port .*/Port $port/" /etc/ssh/sshd_config
fi
# Install SELinux management tool
yum install -y policycoreutils-python-utils
# Add the port to SELinux policy
semanage port -a -t ssh_port_t -p tcp $port
# Allow the port through the firewall
firewall-cmd --permanent --zone=public --add-port=$port/tcp
firewall-cmd --reload
# Check if key files exist and delete them if they do
for file in id_rsa id_rsa.pub key_password.txt; do
if [ -f "/root/.ssh/$file" ]; then
rm "/root/.ssh/$file"
echo "Deleted existing file: /root/.ssh/$file"
fi
done
# Generate a random password for SSH key
password=$(openssl rand -base64 32)
# Generate SSH key pair
ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa -N "$password" -C "key-for-$1"
echo "SSH key pair generated with a random password."
# Output the generated password to a secure location
echo $password > ~/.ssh/key_password.txt
chmod 600 ~/.ssh/key_password.txt
echo "Password for SSH key pair stored securely."
# Check if the public key already exists in authorized_keys
if grep -qFf ~/.ssh/id_rsa.pub ~/.ssh/authorized_keys; then
echo "Public key already exists in authorized_keys."
else
cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
echo "Public SSH key added to authorized keys for authentication."
fi
# Restart SSH service to apply changes
systemctl restart sshd.service
if [ $? -eq 0 ]; then
echo "SSH service has been restarted successfully."
else
echo "Failed to restart SSH service. Please check for errors."
exit 1
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment