344 lines
8.8 KiB
Bash
344 lines
8.8 KiB
Bash
![]() |
#!/usr/bin/env bash
|
||
|
# SSH Server Setup and Hardening Script
|
||
|
|
||
|
set -euo pipefail
|
||
|
|
||
|
# Load environment variables
|
||
|
source /tmp/env-desktop
|
||
|
|
||
|
log() {
|
||
|
echo "[$(date +'%Y-%m-%d %H:%M:%S')] SSH: $1"
|
||
|
}
|
||
|
|
||
|
error() {
|
||
|
echo "[$(date +'%Y-%m-%d %H:%M:%S')] SSH ERROR: $1" >&2
|
||
|
exit 1
|
||
|
}
|
||
|
|
||
|
# Detect OS
|
||
|
detect_os() {
|
||
|
if [[ -f /etc/os-release ]]; then
|
||
|
. /etc/os-release
|
||
|
OS=$ID
|
||
|
VERSION=$VERSION_ID
|
||
|
else
|
||
|
error "Cannot detect OS"
|
||
|
fi
|
||
|
log "Detected OS: $OS $VERSION"
|
||
|
}
|
||
|
|
||
|
# Install SSH server
|
||
|
install_ssh_server() {
|
||
|
log "Installing SSH server..."
|
||
|
|
||
|
case $OS in
|
||
|
ubuntu|debian)
|
||
|
apt-get update
|
||
|
apt-get install -y openssh-server openssh-client
|
||
|
;;
|
||
|
centos|rhel|fedora)
|
||
|
if command -v dnf >/dev/null 2>&1; then
|
||
|
dnf install -y openssh-server openssh-clients
|
||
|
else
|
||
|
yum install -y openssh-server openssh-clients
|
||
|
fi
|
||
|
;;
|
||
|
*)
|
||
|
error "Unsupported OS for SSH installation: $OS"
|
||
|
;;
|
||
|
esac
|
||
|
|
||
|
log "SSH server installed"
|
||
|
}
|
||
|
|
||
|
# Configure SSH server
|
||
|
configure_ssh_server() {
|
||
|
log "Configuring SSH server..."
|
||
|
|
||
|
local ssh_port="${SSH_PORT:-22}"
|
||
|
local password_auth="${SSH_PASSWORD_AUTH:-yes}"
|
||
|
local key_auth="${SSH_KEY_AUTH:-yes}"
|
||
|
local root_login="${SSH_ROOT_LOGIN:-prohibit-password}"
|
||
|
local max_auth_tries="${SSH_MAX_AUTH_TRIES:-3}"
|
||
|
local client_alive_interval="${SSH_CLIENT_ALIVE_INTERVAL:-300}"
|
||
|
local client_alive_count_max="${SSH_CLIENT_ALIVE_COUNT_MAX:-2}"
|
||
|
|
||
|
# Backup original config
|
||
|
cp /etc/ssh/sshd_config /etc/ssh/sshd_config.backup.$(date +%Y%m%d_%H%M%S)
|
||
|
|
||
|
# Create new SSH configuration
|
||
|
cat > /etc/ssh/sshd_config << EOF
|
||
|
# SSH Configuration for Desktop Environment
|
||
|
# Generated by provisioning system
|
||
|
|
||
|
# Connection settings
|
||
|
Port $ssh_port
|
||
|
AddressFamily any
|
||
|
ListenAddress 0.0.0.0
|
||
|
ListenAddress ::
|
||
|
|
||
|
# Host keys
|
||
|
HostKey /etc/ssh/ssh_host_rsa_key
|
||
|
HostKey /etc/ssh/ssh_host_ecdsa_key
|
||
|
HostKey /etc/ssh/ssh_host_ed25519_key
|
||
|
|
||
|
# Ciphers and keying
|
||
|
RekeyLimit default none
|
||
|
|
||
|
# Logging
|
||
|
SyslogFacility AUTH
|
||
|
LogLevel INFO
|
||
|
|
||
|
# Authentication
|
||
|
LoginGraceTime 2m
|
||
|
PermitRootLogin $root_login
|
||
|
StrictModes yes
|
||
|
MaxAuthTries $max_auth_tries
|
||
|
MaxSessions 10
|
||
|
|
||
|
PubkeyAuthentication $key_auth
|
||
|
AuthorizedKeysFile .ssh/authorized_keys .ssh/authorized_keys2
|
||
|
|
||
|
# Password authentication
|
||
|
PasswordAuthentication $password_auth
|
||
|
PermitEmptyPasswords no
|
||
|
ChallengeResponseAuthentication no
|
||
|
|
||
|
# Kerberos and GSSAPI (disabled for security)
|
||
|
KerberosAuthentication no
|
||
|
GSSAPIAuthentication no
|
||
|
|
||
|
# Connection timeouts
|
||
|
ClientAliveInterval $client_alive_interval
|
||
|
ClientAliveCountMax $client_alive_count_max
|
||
|
TCPKeepAlive yes
|
||
|
|
||
|
# Compression
|
||
|
Compression delayed
|
||
|
|
||
|
# Environment
|
||
|
AcceptEnv LANG LC_*
|
||
|
AcceptEnv XMODIFIERS
|
||
|
|
||
|
# X11 forwarding (enabled for desktop environment)
|
||
|
X11Forwarding yes
|
||
|
X11DisplayOffset 10
|
||
|
X11UseLocalhost yes
|
||
|
|
||
|
# Agent forwarding (be careful with security)
|
||
|
AllowAgentForwarding yes
|
||
|
|
||
|
# TCP forwarding
|
||
|
AllowTcpForwarding yes
|
||
|
GatewayPorts no
|
||
|
|
||
|
# Tunnel device forwarding
|
||
|
PermitTunnel no
|
||
|
|
||
|
# chroot directory
|
||
|
ChrootDirectory none
|
||
|
|
||
|
# Banner
|
||
|
Banner none
|
||
|
|
||
|
# Subsystem
|
||
|
Subsystem sftp /usr/lib/openssh/sftp-server
|
||
|
|
||
|
# User/Group restrictions
|
||
|
EOF
|
||
|
|
||
|
# Add user restrictions if specified
|
||
|
if [[ -n "${SSH_ALLOWED_USERS:-}" ]]; then
|
||
|
echo "AllowUsers $SSH_ALLOWED_USERS" >> /etc/ssh/sshd_config
|
||
|
log "SSH access restricted to users: $SSH_ALLOWED_USERS"
|
||
|
fi
|
||
|
|
||
|
if [[ -n "${SSH_DENIED_USERS:-}" ]]; then
|
||
|
echo "DenyUsers $SSH_DENIED_USERS" >> /etc/ssh/sshd_config
|
||
|
log "SSH access denied for users: $SSH_DENIED_USERS"
|
||
|
fi
|
||
|
|
||
|
# Fix sftp-server path for different distributions
|
||
|
case $OS in
|
||
|
ubuntu|debian)
|
||
|
sed -i 's|/usr/lib/openssh/sftp-server|/usr/lib/openssh/sftp-server|' /etc/ssh/sshd_config
|
||
|
;;
|
||
|
centos|rhel|fedora)
|
||
|
sed -i 's|/usr/lib/openssh/sftp-server|/usr/libexec/openssh/sftp-server|' /etc/ssh/sshd_config
|
||
|
;;
|
||
|
esac
|
||
|
|
||
|
# Test SSH configuration
|
||
|
sshd -t || error "SSH configuration is invalid"
|
||
|
|
||
|
log "SSH server configured"
|
||
|
}
|
||
|
|
||
|
# Setup SSH keys for desktop user
|
||
|
setup_ssh_keys() {
|
||
|
local desktop_user="${DESKTOP_USER:-desktop}"
|
||
|
local desktop_home="${DESKTOP_HOME:-/home/$desktop_user}"
|
||
|
|
||
|
log "Setting up SSH keys for user $desktop_user"
|
||
|
|
||
|
# Create user if not exists
|
||
|
if ! id "$desktop_user" &>/dev/null; then
|
||
|
useradd -m -s /bin/bash "$desktop_user"
|
||
|
log "Created user $desktop_user"
|
||
|
fi
|
||
|
|
||
|
# Create .ssh directory
|
||
|
sudo -u "$desktop_user" mkdir -p "$desktop_home/.ssh"
|
||
|
chmod 700 "$desktop_home/.ssh"
|
||
|
|
||
|
# Generate SSH key pair if not exists
|
||
|
if [[ ! -f "$desktop_home/.ssh/id_rsa" ]]; then
|
||
|
log "Generating SSH key pair for $desktop_user"
|
||
|
sudo -u "$desktop_user" ssh-keygen -t rsa -b 4096 -f "$desktop_home/.ssh/id_rsa" -N "" -C "$desktop_user@$(hostname)"
|
||
|
log "SSH key pair generated"
|
||
|
fi
|
||
|
|
||
|
# Create authorized_keys file
|
||
|
sudo -u "$desktop_user" touch "$desktop_home/.ssh/authorized_keys"
|
||
|
chmod 600 "$desktop_home/.ssh/authorized_keys"
|
||
|
|
||
|
# Set proper ownership
|
||
|
chown -R "$desktop_user:$desktop_user" "$desktop_home/.ssh"
|
||
|
|
||
|
log "SSH keys setup completed for $desktop_user"
|
||
|
}
|
||
|
|
||
|
# Setup fail2ban for SSH protection
|
||
|
setup_fail2ban() {
|
||
|
log "Setting up fail2ban for SSH protection..."
|
||
|
|
||
|
case $OS in
|
||
|
ubuntu|debian)
|
||
|
apt-get install -y fail2ban
|
||
|
;;
|
||
|
centos|rhel|fedora)
|
||
|
if command -v dnf >/dev/null 2>&1; then
|
||
|
dnf install -y fail2ban
|
||
|
else
|
||
|
yum install -y fail2ban
|
||
|
fi
|
||
|
;;
|
||
|
esac
|
||
|
|
||
|
# Create fail2ban configuration for SSH
|
||
|
cat > /etc/fail2ban/jail.local << EOF
|
||
|
[DEFAULT]
|
||
|
# Ban time in seconds (10 minutes)
|
||
|
bantime = 600
|
||
|
|
||
|
# Find time window (10 minutes)
|
||
|
findtime = 600
|
||
|
|
||
|
# Max retry attempts
|
||
|
maxretry = 3
|
||
|
|
||
|
[sshd]
|
||
|
enabled = true
|
||
|
port = ${SSH_PORT:-22}
|
||
|
filter = sshd
|
||
|
logpath = /var/log/auth.log
|
||
|
maxretry = ${SSH_MAX_AUTH_TRIES:-3}
|
||
|
bantime = 3600
|
||
|
EOF
|
||
|
|
||
|
# Start and enable fail2ban
|
||
|
systemctl enable fail2ban
|
||
|
systemctl start fail2ban
|
||
|
|
||
|
log "fail2ban configured and started"
|
||
|
}
|
||
|
|
||
|
# Setup firewall rules for SSH
|
||
|
setup_firewall() {
|
||
|
log "Setting up firewall rules for SSH"
|
||
|
|
||
|
local ssh_port="${SSH_PORT:-22}"
|
||
|
|
||
|
# Try different firewall tools
|
||
|
if command -v ufw >/dev/null 2>&1; then
|
||
|
ufw allow "$ssh_port/tcp" comment "SSH"
|
||
|
log "UFW rule added for SSH port $ssh_port"
|
||
|
elif command -v firewall-cmd >/dev/null 2>&1; then
|
||
|
if [[ "$ssh_port" != "22" ]]; then
|
||
|
firewall-cmd --permanent --add-port="$ssh_port/tcp"
|
||
|
else
|
||
|
firewall-cmd --permanent --add-service=ssh
|
||
|
fi
|
||
|
firewall-cmd --reload
|
||
|
log "FirewallD rule added for SSH port $ssh_port"
|
||
|
else
|
||
|
log "WARNING: No supported firewall tool found. Manual firewall configuration may be needed."
|
||
|
fi
|
||
|
}
|
||
|
|
||
|
# Start and enable SSH service
|
||
|
start_ssh_service() {
|
||
|
log "Starting SSH service..."
|
||
|
|
||
|
# Enable and start SSH service
|
||
|
systemctl enable ssh sshd 2>/dev/null || systemctl enable sshd
|
||
|
systemctl restart ssh sshd 2>/dev/null || systemctl restart sshd
|
||
|
|
||
|
# Check service status
|
||
|
if systemctl is-active --quiet ssh || systemctl is-active --quiet sshd; then
|
||
|
log "SSH service is running"
|
||
|
else
|
||
|
error "Failed to start SSH service"
|
||
|
fi
|
||
|
|
||
|
log "SSH service started and enabled"
|
||
|
}
|
||
|
|
||
|
# Display connection information
|
||
|
display_connection_info() {
|
||
|
local desktop_user="${DESKTOP_USER:-desktop}"
|
||
|
local ssh_port="${SSH_PORT:-22}"
|
||
|
local server_ip=$(ip route get 1.1.1.1 | grep -oP 'src \K\S+' 2>/dev/null || echo "$(hostname -I | awk '{print $1}')")
|
||
|
|
||
|
log "SSH setup completed!"
|
||
|
log ""
|
||
|
log "SSH Connection Information:"
|
||
|
log " Server IP: $server_ip"
|
||
|
log " SSH Port: $ssh_port"
|
||
|
log " Desktop User: $desktop_user"
|
||
|
log ""
|
||
|
log "Connect via SSH:"
|
||
|
log " ssh $desktop_user@$server_ip -p $ssh_port"
|
||
|
log ""
|
||
|
log "Public key location (for key-based auth):"
|
||
|
log " /home/$desktop_user/.ssh/id_rsa.pub"
|
||
|
log ""
|
||
|
log "To copy your public key to another machine:"
|
||
|
log " ssh-copy-id -i /home/$desktop_user/.ssh/id_rsa.pub user@remote-host"
|
||
|
}
|
||
|
|
||
|
# Main installation function
|
||
|
main() {
|
||
|
if [[ "${SSH_ENABLED:-true}" != "true" ]]; then
|
||
|
log "SSH is disabled, skipping installation"
|
||
|
return 0
|
||
|
fi
|
||
|
|
||
|
log "Starting SSH server installation and configuration..."
|
||
|
|
||
|
detect_os
|
||
|
install_ssh_server
|
||
|
configure_ssh_server
|
||
|
setup_ssh_keys
|
||
|
setup_fail2ban
|
||
|
setup_firewall
|
||
|
start_ssh_service
|
||
|
display_connection_info
|
||
|
|
||
|
log "SSH setup completed successfully!"
|
||
|
}
|
||
|
|
||
|
# Run main function if script is executed directly
|
||
|
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
||
|
main "$@"
|
||
|
fi
|