๐ 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
SSH Banner and Legal Warnings:
# 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 Measure | Configuration | Status |
---|---|---|
Disable Root Login | PermitRootLogin no | โฌ |
Key Authentication | PubkeyAuthentication yes | โฌ |
Disable Passwords | PasswordAuthentication no | โฌ |
Change Default Port | Port 2222 | โฌ |
Limit Users/Groups | AllowUsers or AllowGroups | โฌ |
Two-Factor Auth | Google Authenticator configured | โฌ |
Connection Limits | MaxAuthTries 3 | โฌ |
Idle Timeout | ClientAliveInterval 300 | โฌ |
Strong Ciphers | Modern algorithms only | โฌ |
Fail2ban Protection | Automated 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! ๐