gentoo
jwt
d
+
+
+
0x
grafana
+
+
firebase
kali
+
marko
+
+
+
+
+
+
fastapi
+
bundler
+
+
gulp
sql
zorin
choo
stimulus
cypress
+
vb
vercel
+
solid
jax
+
+
0x
riot
+
+
go
alpine
spacy
+
+
+
+
_
r
+
+
โІ
cargo
debian
+
echo
npm
+
dart
+
+
+
+
+
next
+
+
neo4j
+
+
js
+
+
+
aurelia
+
+
nest
esbuild
ada
react
^
+
+
prettier
+
+
Back to Blog
๐Ÿ” AlmaLinux SSH Configuration: Secure Remote Access Guide
almalinux ssh remote-access

๐Ÿ” AlmaLinux SSH Configuration: Secure Remote Access Guide

Published Sep 17, 2025

Master AlmaLinux SSH configuration! Complete guide to secure remote access with key authentication, hardening, and advanced SSH features. Perfect for beginners learning secure system administration.

26 min read
0 views
Table of Contents

๐Ÿ” AlmaLinux SSH Configuration: Secure Remote Access Guide

Ready to access your AlmaLinux system from anywhere securely? ๐ŸŒ SSH (Secure Shell) is the gold standard for remote Linux administration, but default settings leave you vulnerable! This complete guide transforms you from SSH novice to security expert, covering everything from basic connections to advanced hardening techniques. Letโ€™s build an unbreakable remote access system! โšก

๐Ÿค” Why SSH Security Matters?

SSH is your gateway to remote controlโ€”protect it fiercely! ๐ŸŒŸ Hereโ€™s why proper SSH configuration is critical:

  • ๐Ÿ›ก๏ธ Encrypted Communications: All data travels in secure tunnels
  • ๐Ÿ”‘ Strong Authentication: Multiple methods to verify identity
  • ๐ŸŒ Global Access: Manage systems from anywhere safely
  • ๐Ÿšจ Attack Target: SSH is hackersโ€™ favorite entry point
  • ๐Ÿ’ผ Professional Standard: Industry requirement for remote work
  • ๐Ÿ“Š Audit Trail: Complete logging of all access attempts
  • ๐Ÿ”ง Automation Ready: Secure scripting and deployment
  • ๐Ÿ˜Œ Peace of Mind: Know your systems are protected

Over 80% of data breaches involve compromised credentialsโ€”secure SSH stops them! ๐Ÿ†

๐ŸŽฏ What You Need

Letโ€™s prepare for SSH mastery! โœ…

  • โœ… AlmaLinux system with network connectivity
  • โœ… Root or sudo access for configuration
  • โœ… Basic understanding of terminal commands
  • โœ… Client computer (Windows/Mac/Linux) for testing
  • โœ… 45 minutes to master SSH security
  • โœ… IP address or hostname of your server
  • โœ… Willingness to replace passwords with keys
  • โœ… Excitement to become a security expert! ๐ŸŽ‰

Letโ€™s build fortress-level SSH security! ๐ŸŒ

๐Ÿ“ Step 1: SSH Basics and Initial Setup

Master the SSH fundamentals! ๐ŸŽฏ

Understanding SSH Components:

# SSH consists of:
1. SSH Server (sshd) - Runs on AlmaLinux system
2. SSH Client (ssh) - Connects from remote computer
3. Configuration files:
   /etc/ssh/sshd_config - Server configuration
   /etc/ssh/ssh_config - Client configuration
   ~/.ssh/ - User SSH directory

# Check SSH installation:
rpm -qa | grep openssh
# Output should include:
# openssh-server
# openssh-clients
# openssh

# Install if missing:
sudo dnf install openssh-server openssh-clients

Starting and Enabling SSH:

# Start SSH service:
sudo systemctl start sshd

# Enable SSH to start at boot:
sudo systemctl enable sshd

# Check SSH status:
sudo systemctl status sshd
# Should show: Active: active (running)

# Verify SSH is listening:
sudo ss -tuln | grep :22
# Output: tcp LISTEN 0 128 *:22 *:*

# Check firewall allows SSH:
sudo firewall-cmd --list-services | grep ssh
# If not present, add it:
sudo firewall-cmd --add-service=ssh --permanent
sudo firewall-cmd --reload

Basic SSH Connections:

# Connect from client to server:
ssh username@server_ip
# Example:
ssh [email protected]

# Connect with specific port:
ssh -p 2222 username@server_ip

# Connect with verbose output (debugging):
ssh -v username@server_ip

# First connection shows fingerprint:
The authenticity of host '192.168.1.100' can't be established.
ED25519 key fingerprint is SHA256:AbCdEfGhIjKlMnOpQrStUvWxYz123456789.
Are you sure you want to continue connecting (yes/no)? yes

# Execute single command:
ssh username@server_ip "uptime"

# Copy files via SSH (SCP):
scp local_file.txt username@server_ip:/remote/path/
scp username@server_ip:/remote/file.txt ./local_path/

# Interactive file transfer (SFTP):
sftp username@server_ip
sftp> ls
sftp> get remote_file.txt
sftp> put local_file.txt
sftp> exit

Perfect! ๐ŸŽ‰ SSH basics mastered!

๐Ÿ”ง Step 2: SSH Key Authentication Setup

Implement strong key-based authentication! ๐Ÿ“ฆ

Generating SSH Keys:

# Generate SSH key pair on CLIENT machine:
ssh-keygen -t ed25519 -C "[email protected]"
# Ed25519 is modern and secure

# Alternative for older systems:
ssh-keygen -t rsa -b 4096 -C "[email protected]"

# Key generation prompts:
Enter file in which to save the key (/home/user/.ssh/id_ed25519): [Press Enter]
Enter passphrase (empty for no passphrase): [Enter strong passphrase]
Enter same passphrase again: [Repeat passphrase]

# Generated files:
~/.ssh/id_ed25519       # Private key (NEVER SHARE!)
~/.ssh/id_ed25519.pub   # Public key (safe to share)

# View your public key:
cat ~/.ssh/id_ed25519.pub
# Example output:
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG... [email protected]

Installing Keys on Server:

# Method 1: ssh-copy-id (easiest):
ssh-copy-id username@server_ip
# Enter password one last time

# Method 2: Manual installation:
# On client, display public key:
cat ~/.ssh/id_ed25519.pub

# On server, add to authorized_keys:
mkdir -p ~/.ssh
chmod 700 ~/.ssh
echo "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG... [email protected]" >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

# Method 3: Copy via existing SSH:
cat ~/.ssh/id_ed25519.pub | ssh username@server_ip "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"

# Test key authentication:
ssh username@server_ip
# Should login without password prompt!

Managing Multiple Keys:

# Create different keys for different purposes:
ssh-keygen -t ed25519 -f ~/.ssh/work_key -C "work"
ssh-keygen -t ed25519 -f ~/.ssh/personal_key -C "personal"

# Configure SSH client (~/.ssh/config):
cat > ~/.ssh/config << 'EOF'
# Work server
Host work-server
    HostName 192.168.1.100
    User john
    Port 22
    IdentityFile ~/.ssh/work_key

# Personal server
Host personal-server
    HostName example.com
    User john
    Port 2222
    IdentityFile ~/.ssh/personal_key

# GitHub
Host github.com
    HostName github.com
    User git
    IdentityFile ~/.ssh/github_key
EOF

chmod 600 ~/.ssh/config

# Now connect with aliases:
ssh work-server
ssh personal-server

SSH Agent for Key Management:

# Start SSH agent:
eval $(ssh-agent -s)

# Add key to agent:
ssh-add ~/.ssh/id_ed25519
# Enter passphrase once per session

# List keys in agent:
ssh-add -l

# Add key with timeout:
ssh-add -t 3600 ~/.ssh/id_ed25519  # 1 hour

# Remove all keys from agent:
ssh-add -D

# Auto-start SSH agent (add to ~/.bashrc):
echo 'eval $(ssh-agent -s) > /dev/null 2>&1' >> ~/.bashrc
echo 'ssh-add ~/.ssh/id_ed25519 2>/dev/null' >> ~/.bashrc

Amazing! ๐ŸŒŸ Key authentication implemented!

๐ŸŒŸ Step 3: SSH Server Hardening

Transform SSH into an impenetrable fortress! โšก

Essential Security Configuration:

# Backup original configuration:
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.backup

# Edit SSH configuration:
sudo nano /etc/ssh/sshd_config

# Essential security settings to modify:
# 1. Disable root login:
PermitRootLogin no

# 2. Disable password authentication (after setting up keys):
PasswordAuthentication no
PubkeyAuthentication yes

# 3. Limit user access:
AllowUsers john alice bob
# OR use groups:
AllowGroups sshusers

# 4. Change default port (optional but effective):
Port 2222  # Choose any port above 1024

# 5. Limit authentication attempts:
MaxAuthTries 3
MaxSessions 10

# 6. Set login grace time:
LoginGraceTime 30

# 7. Disable empty passwords:
PermitEmptyPasswords no

# 8. Use protocol 2 only (should be default):
Protocol 2

# 9. Disable X11 forwarding (unless needed):
X11Forwarding no

# 10. Set client alive checks:
ClientAliveInterval 300
ClientAliveCountMax 2

Advanced Hardening Options:

# Continue editing /etc/ssh/sshd_config:

# Restrict SSH to specific IP addresses:
# Add to sshd_config:
Match Address 192.168.1.0/24
    PermitRootLogin no
    PasswordAuthentication yes

Match Address *
    PasswordAuthentication no

# Enable strict mode:
StrictModes yes

# Limit concurrent connections:
MaxStartups 10:30:60

# Disable host-based authentication:
HostbasedAuthentication no
IgnoreRhosts yes

# Set strong ciphers and algorithms:
Ciphers [email protected],[email protected],[email protected]
MACs [email protected],[email protected]
KexAlgorithms curve25519-sha256,[email protected]

# Enable logging:
LogLevel VERBOSE
SyslogFacility AUTH

# Use privilege separation:
UsePrivilegeSeparation yes

# DNS settings:
UseDNS no  # Speeds up connections

# Apply changes:
sudo sshd -t  # Test configuration
sudo systemctl restart sshd

Two-Factor Authentication (2FA):

# Install Google Authenticator:
sudo dnf install epel-release
sudo dnf install google-authenticator

# Configure for user:
google-authenticator

# Answer prompts:
Do you want authentication tokens to be time-based? y
# Scan QR code with authenticator app
Do you want me to update your "~/.google_authenticator" file? y
Do you want to disallow multiple uses? y
Do you want to increase the time window? n
Do you want to enable rate-limiting? y

# Configure SSH for 2FA:
sudo nano /etc/ssh/sshd_config
# Add:
ChallengeResponseAuthentication yes

# Edit PAM configuration:
sudo nano /etc/pam.d/sshd
# Add at top (for 2FA + password):
auth required pam_google_authenticator.so

# OR for 2FA + key (more secure):
# Comment out:
#auth substack password-auth
# Add:
auth required pam_google_authenticator.so

# Restart SSH:
sudo systemctl restart sshd

# Test 2FA login:
ssh username@server_ip
# Enter verification code from app
# Create warning banner:
sudo cat > /etc/ssh/banner << 'EOF'
****************************************************************************
                            AUTHORIZED ACCESS ONLY
Unauthorized access to this system is forbidden and will be prosecuted
by law. By accessing this system, you agree that your actions may be
monitored and recorded. Disconnect immediately if you are not authorized.
****************************************************************************
EOF

# Enable banner in SSH:
sudo nano /etc/ssh/sshd_config
# Add or uncomment:
Banner /etc/ssh/banner

# Create detailed MOTD (Message of the Day):
sudo cat > /etc/motd << 'EOF'
================================================================================
Welcome to AlmaLinux SSH Server

System Information:
- Hostname: $(hostname)
- IP Address: $(ip -4 addr show | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | head -1)
- Kernel: $(uname -r)
- Uptime: $(uptime -p)

Security Reminders:
1. All connections are logged and monitored
2. Report suspicious activity to [email protected]
3. Use strong passwords and SSH keys
4. Keep your client software updated
================================================================================
EOF

sudo systemctl restart sshd

Excellent! โšก SSH server hardened to maximum security!

โœ… Step 4: Advanced SSH Features and Tunneling

Master professional SSH techniques! ๐Ÿ”ง

SSH Tunneling and Port Forwarding:

# Local port forwarding (access remote service locally):
# Access remote MySQL through local port 3307:
ssh -L 3307:localhost:3306 username@server_ip
# Now connect to localhost:3307 to access remote MySQL

# Multiple port forwards:
ssh -L 8080:localhost:80 -L 3307:localhost:3306 username@server_ip

# Remote port forwarding (expose local service to remote):
# Make local web server available on remote port 8080:
ssh -R 8080:localhost:80 username@server_ip

# Dynamic port forwarding (SOCKS proxy):
ssh -D 8888 username@server_ip
# Configure browser to use SOCKS proxy: localhost:8888

# Background tunnels with auto-reconnect:
ssh -fN -L 3307:localhost:3306 username@server_ip
# -f: Background after authentication
# -N: Don't execute remote command

SSH Jump Hosts (Bastion):

# Connect through jump host (bastion):
ssh -J jump_user@jump_host target_user@target_host

# Multiple jumps:
ssh -J user1@host1,user2@host2 target_user@target_host

# Configure in ~/.ssh/config:
Host target-server
    HostName 10.0.0.100
    User admin
    ProxyJump [email protected]

# With different ports:
Host jump-server
    HostName jump.example.com
    Port 2222
    User jumpuser

Host internal-server
    HostName 192.168.1.100
    User admin
    ProxyJump jump-server

# Now simply:
ssh internal-server

SSH Multiplexing for Performance:

# Configure connection multiplexing (~/.ssh/config):
Host *
    ControlMaster auto
    ControlPath ~/.ssh/control-%h-%p-%r
    ControlPersist 10m

# Benefits:
# - Reuse existing connections
# - Faster subsequent connections
# - Reduced authentication overhead

# Check active connections:
ssh -O check server_ip

# Close master connection:
ssh -O stop server_ip

# Forward port on existing connection:
ssh -O forward -L 8080:localhost:80 server_ip

SSH Escape Sequences:

# During SSH session, type ~ followed by:
~.   # Disconnect
~^Z  # Suspend SSH
~#   # List forwarded connections
~&   # Background SSH (logout possible)
~?   # Show escape sequences
~C   # Open command line (for port forwarding)
~R   # Request rekey

# Add port forward to existing session:
# Press Enter, then ~C
ssh> -L 8080:localhost:80
Forwarding port.

Automated SSH with Expect:

# Install expect:
sudo dnf install expect

# Create automated SSH script:
cat > auto_ssh.exp << 'EOF'
#!/usr/bin/expect -f
set timeout 10
set host [lindex $argv 0]
set user [lindex $argv 1]
set password [lindex $argv 2]

spawn ssh $user@$host
expect {
    "password:" {
        send "$password\r"
        expect "$ "
    }
    "$ " {
        # Already logged in
    }
}

# Execute commands
send "uptime\r"
expect "$ "
send "df -h\r"
expect "$ "
send "exit\r"
expect eof
EOF

chmod +x auto_ssh.exp
# Usage: ./auto_ssh.exp server_ip username password

Perfect! ๐Ÿ† Advanced SSH features mastered!

๐ŸŽฎ Quick Examples

Real-world SSH configuration scenarios! ๐ŸŽฏ

Example 1: Secure Development Environment Access

# Scenario: Setup secure SSH for development team
# Solution: Key authentication + restricted access + monitoring

#!/bin/bash
# Development SSH setup script

echo "Setting up secure development SSH access..."

# 1. Create development group
sudo groupadd developers

# 2. Configure SSH for developers only
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.dev-backup

cat | sudo tee /etc/ssh/sshd_config.d/10-developers.conf << 'EOF'
# Development team SSH configuration
Port 2222
Protocol 2

# Authentication
PermitRootLogin no
PubkeyAuthentication yes
PasswordAuthentication no
ChallengeResponseAuthentication no

# Access control
AllowGroups developers
DenyGroups root

# Security
MaxAuthTries 3
MaxSessions 5
LoginGraceTime 60
StrictModes yes

# Idle timeout
ClientAliveInterval 600
ClientAliveCountMax 3

# Logging
LogLevel VERBOSE

# Development features
X11Forwarding yes
AllowTcpForwarding yes
PermitTunnel yes

# SFTP subsystem
Subsystem sftp internal-sftp

# Development environment specifics
Match Group developers
    ForceCommand /usr/local/bin/dev-shell
    X11Forwarding yes
    AllowTcpForwarding yes
EOF

# 3. Create developer shell wrapper
cat | sudo tee /usr/local/bin/dev-shell << 'EOF'
#!/bin/bash
# Developer shell with logging

LOG_DIR="/var/log/ssh-audit"
mkdir -p "$LOG_DIR"
LOG_FILE="$LOG_DIR/dev-$(date +%Y%m%d)-$USER.log"

echo "[$(date '+%Y-%m-%d %H:%M:%S')] SSH session started for $USER from $SSH_CLIENT" >> "$LOG_FILE"

# Start shell with logging
script -q -a "$LOG_FILE" /bin/bash

echo "[$(date '+%Y-%m-%d %H:%M:%S')] SSH session ended for $USER" >> "$LOG_FILE"
EOF

sudo chmod +x /usr/local/bin/dev-shell

# 4. Setup key management
for user in alice bob charlie; do
    sudo useradd -m -G developers $user
    sudo -u $user mkdir -p /home/$user/.ssh
    sudo -u $user ssh-keygen -t ed25519 -f /home/$user/.ssh/id_ed25519 -N ""
    echo "User $user created with SSH key"
done

# 5. Configure firewall
sudo firewall-cmd --add-port=2222/tcp --permanent
sudo firewall-cmd --reload

# 6. Setup monitoring
cat | sudo tee /usr/local/bin/ssh-monitor.sh << 'EOF'
#!/bin/bash
# Monitor SSH connections

echo "=== Current SSH Sessions ==="
w -h | grep pts

echo -e "\n=== Recent SSH Logins ==="
last -n 10 | grep "pts\|still logged"

echo -e "\n=== Failed SSH Attempts ==="
sudo grep "Failed password\|Invalid user" /var/log/secure | tail -5

echo -e "\n=== SSH Port Connections ==="
ss -tan | grep :2222
EOF

sudo chmod +x /usr/local/bin/ssh-monitor.sh

# 7. Restart SSH service
sudo systemctl restart sshd

echo "Development SSH setup complete!"
echo "SSH Port: 2222"
echo "Users created: alice, bob, charlie"
echo "Monitor with: sudo /usr/local/bin/ssh-monitor.sh"

Example 2: Automated Backup Server Access

# Scenario: Secure automated backup system with SSH
# Solution: Dedicated backup user with restricted commands

#!/bin/bash
# Backup server SSH configuration

echo "Configuring SSH for automated backups..."

# 1. Create backup user with limited shell
sudo useradd -m -s /bin/rbash backup-user
sudo mkdir -p /home/backup-user/bin

# 2. Generate SSH key for backup (no passphrase for automation)
sudo -u backup-user ssh-keygen -t ed25519 -f /home/backup-user/.ssh/id_ed25519 -N ""

# 3. Configure restricted commands
cat | sudo tee /home/backup-user/.ssh/authorized_keys << 'EOF'
command="/usr/local/bin/backup-handler",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-ed25519 AAAAC3NzaC1... backup@client
EOF

# 4. Create backup handler script
cat | sudo tee /usr/local/bin/backup-handler << 'EOF'
#!/bin/bash
# Restricted backup command handler

BACKUP_DIR="/backup/remote"
LOG_FILE="/var/log/backup-ssh.log"

log_message() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "$LOG_FILE"
}

case "$SSH_ORIGINAL_COMMAND" in
    "rsync --server"*)
        log_message "Backup started from $SSH_CLIENT"
        $SSH_ORIGINAL_COMMAND
        log_message "Backup completed from $SSH_CLIENT"
        ;;
    "test")
        echo "Backup connection test successful"
        log_message "Connection test from $SSH_CLIENT"
        ;;
    *)
        log_message "Rejected command from $SSH_CLIENT: $SSH_ORIGINAL_COMMAND"
        echo "Command not allowed"
        exit 1
        ;;
esac
EOF

sudo chmod +x /usr/local/bin/backup-handler

# 5. Setup backup directories
sudo mkdir -p /backup/remote
sudo chown backup-user:backup-user /backup/remote

# 6. Configure SSH daemon for backup user
cat | sudo tee /etc/ssh/sshd_config.d/20-backup.conf << 'EOF'
Match User backup-user
    PasswordAuthentication no
    PubkeyAuthentication yes
    X11Forwarding no
    AllowTcpForwarding no
    PermitTunnel no
    ForceCommand /usr/local/bin/backup-handler
    ChrootDirectory /backup
EOF

# 7. Client-side backup script
cat > /tmp/client_backup.sh << 'EOF'
#!/bin/bash
# Client backup script using SSH

BACKUP_SERVER="backup-server"
BACKUP_USER="backup-user"
SOURCE_DIR="/important/data"
SSH_KEY="/home/client/.ssh/backup_key"

# Test connection
ssh -i "$SSH_KEY" "$BACKUP_USER@$BACKUP_SERVER" test

# Perform backup
rsync -avz --delete \
    -e "ssh -i $SSH_KEY" \
    "$SOURCE_DIR/" \
    "$BACKUP_USER@$BACKUP_SERVER:remote/$(hostname)/"

echo "Backup completed to $BACKUP_SERVER"
EOF

echo "Backup SSH configuration complete!"
echo "Backup user: backup-user"
echo "Backup directory: /backup/remote"
echo "Client script: /tmp/client_backup.sh"

Example 3: Multi-Server Management System

# Scenario: Manage multiple servers from central location
# Solution: SSH config with jump hosts and automation

#!/bin/bash
# Multi-server SSH management setup

echo "Setting up multi-server SSH management..."

# 1. Create comprehensive SSH config
cat > ~/.ssh/config << 'EOF'
# Global settings
Host *
    ServerAliveInterval 60
    ServerAliveCountMax 3
    TCPKeepAlive yes
    Compression yes
    ControlMaster auto
    ControlPath ~/.ssh/control-%h-%p-%r
    ControlPersist 10m

# Jump/Bastion host
Host bastion
    HostName bastion.company.com
    User admin
    Port 2222
    IdentityFile ~/.ssh/bastion_key
    ForwardAgent yes

# Production servers (through bastion)
Host prod-web-*
    User webadmin
    ProxyJump bastion
    IdentityFile ~/.ssh/prod_key
    StrictHostKeyChecking yes

Host prod-web-01
    HostName 10.0.1.10

Host prod-web-02
    HostName 10.0.1.11

Host prod-db-*
    User dbadmin
    ProxyJump bastion
    IdentityFile ~/.ssh/prod_db_key
    LocalForward 3307 localhost:3306

Host prod-db-01
    HostName 10.0.2.10

Host prod-db-02
    HostName 10.0.2.11

# Development servers (direct access)
Host dev-*
    User developer
    Port 22
    IdentityFile ~/.ssh/dev_key

Host dev-01
    HostName 192.168.1.100

Host dev-02
    HostName 192.168.1.101

# Staging environment
Host stage-*
    User deploy
    ProxyJump bastion
    IdentityFile ~/.ssh/stage_key

Host stage-app
    HostName 10.0.3.10
    LocalForward 8080 localhost:8080

Host stage-db
    HostName 10.0.3.11
    LocalForward 5433 localhost:5432
EOF

# 2. Create server management script
cat > ~/bin/manage-servers.sh << 'EOF'
#!/bin/bash
# Multi-server management tool

ACTION=$1
TARGET=$2

show_menu() {
    echo "Server Management Tool"
    echo "====================="
    echo "1. Check server status"
    echo "2. Update all servers"
    echo "3. Backup configurations"
    echo "4. View logs"
    echo "5. Deploy application"
    echo "6. Run custom command"
    echo "0. Exit"
}

check_status() {
    SERVERS=${1:-"prod-web-01 prod-web-02 prod-db-01 dev-01"}
    echo "Checking server status..."

    for server in $SERVERS; do
        echo -n "$server: "
        if ssh -q -o ConnectTimeout=5 $server exit; then
            UPTIME=$(ssh $server uptime | awk -F'up' '{print $2}' | awk -F',' '{print $1}')
            echo "โœ… Online (up$UPTIME)"
        else
            echo "โŒ Offline or unreachable"
        fi
    done
}

update_servers() {
    SERVERS=${1:-"prod-web-01 prod-web-02 dev-01"}
    echo "Updating servers..."

    for server in $SERVERS; do
        echo "Updating $server..."
        ssh $server "sudo dnf update -y && sudo systemctl restart httpd"
    done
}

backup_configs() {
    BACKUP_DIR="$HOME/server-backups/$(date +%Y%m%d)"
    mkdir -p "$BACKUP_DIR"

    SERVERS="prod-web-01 prod-web-02 prod-db-01"
    for server in $SERVERS; do
        echo "Backing up $server..."
        ssh $server "sudo tar -czf - /etc" > "$BACKUP_DIR/$server-etc.tar.gz"
    done

    echo "Backups saved to $BACKUP_DIR"
}

run_command() {
    read -p "Enter command to run: " CMD
    read -p "Enter servers (space-separated): " SERVERS

    for server in $SERVERS; do
        echo "=== $server ==="
        ssh $server "$CMD"
        echo ""
    done
}

# Main menu
if [ -z "$ACTION" ]; then
    show_menu
    read -p "Select option: " choice

    case $choice in
        1) check_status ;;
        2) update_servers ;;
        3) backup_configs ;;
        4) view_logs ;;
        5) deploy_app ;;
        6) run_command ;;
        0) exit 0 ;;
        *) echo "Invalid option" ;;
    esac
fi
EOF

chmod +x ~/bin/manage-servers.sh

# 3. Create SSH key deployment script
cat > ~/bin/deploy-keys.sh << 'EOF'
#!/bin/bash
# Deploy SSH keys to multiple servers

SERVERS="prod-web-01 prod-web-02 prod-db-01 dev-01 dev-02"
KEY_FILE="${1:-$HOME/.ssh/id_ed25519.pub}"

if [ ! -f "$KEY_FILE" ]; then
    echo "Key file not found: $KEY_FILE"
    exit 1
fi

KEY_CONTENT=$(cat "$KEY_FILE")

for server in $SERVERS; do
    echo "Deploying key to $server..."
    ssh $server "mkdir -p ~/.ssh && echo '$KEY_CONTENT' >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
done

echo "SSH keys deployed successfully!"
EOF

chmod +x ~/bin/deploy-keys.sh

echo "Multi-server management system configured!"
echo "Use: ~/bin/manage-servers.sh"
echo "SSH to servers: ssh prod-web-01"

Example 4: SSH Honeypot and Monitoring

# Scenario: Detect and monitor SSH attacks
# Solution: SSH honeypot with comprehensive logging

#!/bin/bash
# SSH honeypot and monitoring setup

echo "Setting up SSH honeypot and monitoring..."

# 1. Configure fake SSH on port 22 (honeypot)
cat | sudo tee /etc/ssh/sshd_config_honeypot << 'EOF'
Port 22
Protocol 2
PermitRootLogin yes
PasswordAuthentication yes
PubkeyAuthentication no
MaxAuthTries 10
LoginGraceTime 120
LogLevel DEBUG3
SyslogFacility LOCAL0
Banner /etc/ssh/honeypot_banner
EOF

# 2. Create honeypot banner
cat | sudo tee /etc/ssh/honeypot_banner << 'EOF'
****************************************************************************
                         SYSTEM SECURITY WARNING
This is a honeypot system. All access attempts are logged and monitored.
Your IP address and activities have been recorded for security analysis.
****************************************************************************
EOF

# 3. Real SSH on alternative port
sudo sed -i 's/^Port 22/Port 2222/' /etc/ssh/sshd_config

# 4. Create monitoring script
cat | sudo tee /usr/local/bin/ssh-attack-monitor.sh << 'EOF'
#!/bin/bash
# SSH attack monitoring and analysis

LOG_FILE="/var/log/secure"
ATTACK_LOG="/var/log/ssh_attacks.log"
BLOCK_LIST="/etc/ssh/blocked_ips.txt"
ALERT_EMAIL="[email protected]"

# Function to analyze attacks
analyze_attacks() {
    echo "=== SSH Attack Analysis $(date) ===" >> "$ATTACK_LOG"

    # Failed login attempts
    echo "Top 10 attacking IPs:" >> "$ATTACK_LOG"
    grep "Failed password" "$LOG_FILE" | \
        grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" | \
        sort | uniq -c | sort -rn | head -10 >> "$ATTACK_LOG"

    # Invalid usernames attempted
    echo -e "\nInvalid usernames attempted:" >> "$ATTACK_LOG"
    grep "Invalid user" "$LOG_FILE" | \
        awk '{print $(NF-2)}' | sort | uniq -c | sort -rn | head -10 >> "$ATTACK_LOG"

    # Attack patterns by hour
    echo -e "\nAttacks by hour:" >> "$ATTACK_LOG"
    grep "Failed password" "$LOG_FILE" | \
        awk '{print substr($3,1,2)}' | sort | uniq -c >> "$ATTACK_LOG"
}

# Function to block aggressive IPs
block_attackers() {
    # Find IPs with >10 failed attempts
    ATTACKERS=$(grep "Failed password" "$LOG_FILE" | \
        grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" | \
        sort | uniq -c | awk '$1 > 10 {print $2}')

    for ip in $ATTACKERS; do
        if ! grep -q "$ip" "$BLOCK_LIST"; then
            echo "$ip" >> "$BLOCK_LIST"
            sudo firewall-cmd --add-rich-rule="rule family='ipv4' source address='$ip' drop"
            echo "$(date): Blocked $ip for excessive failed attempts" >> "$ATTACK_LOG"
        fi
    done
}

# Function to send alerts
send_alerts() {
    HIGH_RISK_COUNT=$(grep -c "Failed password for root" "$LOG_FILE")

    if [ "$HIGH_RISK_COUNT" -gt 50 ]; then
        echo "High risk alert: $HIGH_RISK_COUNT root login attempts" | \
            mail -s "SSH Security Alert" "$ALERT_EMAIL"
    fi
}

# Main monitoring loop
while true; do
    analyze_attacks
    block_attackers
    send_alerts
    sleep 300  # Run every 5 minutes
done
EOF

sudo chmod +x /usr/local/bin/ssh-attack-monitor.sh

# 5. Create systemd service for monitor
cat | sudo tee /etc/systemd/system/ssh-monitor.service << 'EOF'
[Unit]
Description=SSH Attack Monitor
After=network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/ssh-attack-monitor.sh
Restart=always
User=root

[Install]
WantedBy=multi-user.target
EOF

# 6. Enable services
sudo systemctl enable ssh-monitor
sudo systemctl start ssh-monitor

echo "SSH honeypot and monitoring configured!"
echo "Real SSH port: 2222"
echo "Honeypot port: 22"
echo "Monitor logs: /var/log/ssh_attacks.log"

๐Ÿšจ Fix Common Problems

SSH troubleshooting and problem resolution! ๐Ÿ”ง

Problem 1: Cannot Connect to SSH Server

Solution:

# Diagnose connection issues:
# 1. Check if SSH service is running
sudo systemctl status sshd
sudo systemctl start sshd
sudo systemctl enable sshd

# 2. Verify SSH is listening
sudo ss -tuln | grep :22
sudo netstat -tuln | grep :22

# 3. Check firewall rules
sudo firewall-cmd --list-all | grep ssh
sudo firewall-cmd --add-service=ssh --permanent
sudo firewall-cmd --reload

# 4. Test with verbose output
ssh -vvv username@server_ip

# 5. Check SELinux (often the culprit)
sudo sestatus
sudo semanage port -l | grep ssh
# If using custom port:
sudo semanage port -a -t ssh_port_t -p tcp 2222

# 6. Verify network connectivity
ping server_ip
traceroute server_ip
telnet server_ip 22

# 7. Check hosts.deny and hosts.allow
cat /etc/hosts.deny
cat /etc/hosts.allow
# Remove blocking entries or add allowing entries

# 8. Verify SSH configuration syntax
sudo sshd -t
# Fix any reported errors in /etc/ssh/sshd_config

Problem 2: SSH Key Authentication Not Working

Solution:

# Debug key authentication issues:
# 1. Check key permissions (CRITICAL!)
# On client:
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519
chmod 644 ~/.ssh/id_ed25519.pub
chmod 600 ~/.ssh/config

# On server:
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys

# 2. Verify key is in authorized_keys
cat ~/.ssh/authorized_keys
# Ensure public key is on ONE line

# 3. Check SSH config allows keys
sudo grep PubkeyAuthentication /etc/ssh/sshd_config
# Should be: PubkeyAuthentication yes

# 4. Test with specific key
ssh -i ~/.ssh/specific_key username@server_ip

# 5. Check for SSH agent issues
ssh-add -l  # List keys in agent
ssh-add ~/.ssh/id_ed25519  # Add key to agent

# 6. SELinux context for .ssh directory
restorecon -R -v ~/.ssh

# 7. Debug with verbose output
ssh -vvv username@server_ip
# Look for:
# - Offering public key
# - Server accepts key
# - Authentication succeeded

# 8. Check authorized_keys format
# Each key should be on one line:
ssh-ed25519 AAAA...xyz user@host

Problem 3: SSH Connection Drops or Times Out

Solution:

# Fix connection stability issues:
# 1. Configure keep-alive settings
# Client side (~/.ssh/config):
Host *
    ServerAliveInterval 60
    ServerAliveCountMax 3
    TCPKeepAlive yes

# Server side (/etc/ssh/sshd_config):
ClientAliveInterval 60
ClientAliveCountMax 3
TCPKeepAlive yes

# 2. Check network MTU issues
ping -M do -s 1472 server_ip
# If fails, reduce packet size until it works
# Then set MTU accordingly:
sudo ip link set dev eth0 mtu 1400

# 3. Disable SSH timeout
# In /etc/ssh/sshd_config:
ClientAliveInterval 120
ClientAliveCountMax 720  # 24 hours

# 4. Check for rate limiting
sudo iptables -L -n | grep ssh
sudo firewall-cmd --list-rich-rules

# 5. Increase SSH connection limits
# In /etc/ssh/sshd_config:
MaxStartups 10:30:100
MaxSessions 100

# 6. Fix DNS issues
# In /etc/ssh/sshd_config:
UseDNS no

# 7. Check system resources
free -h  # Memory
df -h    # Disk space
top      # CPU usage

# Restart SSH after changes:
sudo systemctl restart sshd

Problem 4: SSH Security Breach or Suspicious Activity

Solution:

# Respond to security incidents:
# 1. Check current connections
w
who
ss -tan | grep :22

# 2. Review authentication logs
sudo grep "Accepted" /var/log/secure | tail -20
sudo grep "Failed password" /var/log/secure | tail -50
sudo journalctl -u sshd --since "1 hour ago"

# 3. Identify attack patterns
sudo grep "Failed password" /var/log/secure | \
    grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" | \
    sort | uniq -c | sort -rn

# 4. Emergency lockdown
# Block all SSH except from specific IP:
sudo firewall-cmd --remove-service=ssh
sudo firewall-cmd --add-rich-rule='rule family="ipv4" source address="trusted_ip" service name="ssh" accept'

# 5. Kill suspicious sessions
# Find session PID:
ps aux | grep sshd
# Kill specific session:
sudo kill -9 PID

# 6. Change all passwords
sudo passwd username
# Force password change on next login:
sudo chage -d 0 username

# 7. Regenerate SSH host keys
sudo rm /etc/ssh/ssh_host_*
sudo ssh-keygen -A
sudo systemctl restart sshd

# 8. Audit user accounts
sudo lastlog  # Last login times
sudo last     # Login history
sudo lastb    # Failed login attempts

# 9. Install fail2ban for protection
sudo dnf install fail2ban
sudo systemctl enable fail2ban
sudo systemctl start fail2ban

๐Ÿ“‹ SSH Security Checklist

Security MeasureConfigurationStatus
Disable Root LoginPermitRootLogin noโฌœ
Key AuthenticationPubkeyAuthentication yesโฌœ
Disable PasswordsPasswordAuthentication noโฌœ
Change Default PortPort 2222โฌœ
Limit Users/GroupsAllowUsers or AllowGroupsโฌœ
Two-Factor AuthGoogle Authenticator configuredโฌœ
Connection LimitsMaxAuthTries 3โฌœ
Idle TimeoutClientAliveInterval 300โฌœ
Strong CiphersModern algorithms onlyโฌœ
Fail2ban ProtectionAutomated IP blockingโฌœ

๐Ÿ’ก Tips for Success

Master SSH security like a professional! ๐ŸŒŸ

  • ๐Ÿ”‘ Always Use Keys: Never rely on passwords alone
  • ๐Ÿ“ Document Access: Keep records of who has SSH access
  • ๐Ÿ”„ Rotate Keys Regularly: Change SSH keys quarterly
  • ๐Ÿ“Š Monitor Logs Daily: Check for suspicious activity
  • ๐Ÿ›ก๏ธ Defense in Depth: Layer multiple security controls
  • โšก Keep Updated: Apply SSH security patches promptly
  • ๐ŸŽฏ Principle of Least Privilege: Limit access strictly
  • ๐Ÿงช Test Changes: Verify configuration before logging out
  • ๐Ÿ“ฑ Backup Access Method: Keep console access available
  • ๐Ÿค Team Training: Ensure everyone understands SSH security

๐Ÿ† What You Learned

Congratulations! Youโ€™re now an SSH security expert! ๐ŸŽ‰

  • โœ… Mastered SSH fundamentals and initial setup
  • โœ… Implemented strong key-based authentication
  • โœ… Hardened SSH server to maximum security
  • โœ… Configured advanced features like tunneling and jump hosts
  • โœ… Built real-world SSH management systems
  • โœ… Solved common SSH connection problems
  • โœ… Learned incident response for security breaches
  • โœ… Gained professional remote access management skills

๐ŸŽฏ Why This Matters

Your SSH expertise enables secure global system management! ๐Ÿš€

  • ๐ŸŒ Remote Work: Access systems from anywhere securely
  • ๐Ÿ›ก๏ธ Security Foundation: First line of defense against attacks
  • ๐Ÿ’ผ Professional Requirement: Essential skill for IT careers
  • ๐Ÿ”ง Automation Enabler: Secure scripting and deployment
  • ๐Ÿ“Š Compliance: Meet security audit requirements
  • ๐ŸŽฏ Problem Solving: Diagnose and fix access issues
  • ๐ŸŒŸ Career Growth: Advanced system administration skill
  • ๐Ÿ’ฐ Cost Savings: Reduce need for physical access

You now control secure access to any Linux system worldwide! ๐Ÿ†

Connect securely, manage confidently! ๐Ÿ™Œ