Linux SSH: Secure Shell Configuration and Usage

SSH (Secure Shell) is the standard protocol for secure remote access to Linux and Unix systems. It replaced insecure protocols like Telnet and FTP by encrypting all traffic between client and server,...

Key Insights

  • SSH key-based authentication is non-negotiable for production systems—disable password authentication entirely and use Ed25519 keys for the best security-to-performance ratio.
  • Client-side SSH configuration (~/.ssh/config) eliminates repetitive typing and enforces connection standards across your infrastructure, making it essential for anyone managing more than two servers.
  • SSH port forwarding transforms your secure shell into a versatile tunneling tool that can expose remote services locally, bypass restrictive firewalls, and secure otherwise unencrypted protocols.

Introduction to SSH

SSH (Secure Shell) is the standard protocol for secure remote access to Linux and Unix systems. It replaced insecure protocols like Telnet and FTP by encrypting all traffic between client and server, including authentication credentials, commands, and data transfers.

You’ll use SSH daily for server administration, automated deployments, secure file transfers, and creating encrypted tunnels for services that lack native encryption. Understanding SSH configuration isn’t optional—it’s fundamental to managing modern infrastructure securely.

Basic SSH Usage and Connection Methods

The simplest SSH connection requires just a username and hostname:

ssh username@192.168.1.100
ssh username@example.com

If you’re connecting as the same username on both systems, you can omit it:

ssh example.com

When SSH runs on a non-standard port (anything other than 22), specify it with -p:

ssh -p 2222 username@example.com

For key-based authentication with a specific private key:

ssh -i ~/.ssh/id_ed25519_work username@example.com

On your first connection to a new host, SSH displays the server’s fingerprint and asks for verification:

The authenticity of host 'example.com (203.0.113.1)' can't be established.
ED25519 key fingerprint is SHA256:7K9pB2XQ3mF8nR5tL1vH4jW6sP9dY2cN8xM3kV7bZ1Q.
Are you sure you want to continue connecting (yes/no/[fingerprint])?

Type yes to accept and add the host to ~/.ssh/known_hosts. This prevents man-in-the-middle attacks on subsequent connections. If the fingerprint changes later, SSH will refuse to connect—which usually indicates a security issue or server reinstallation.

SSH Key-Based Authentication

Password authentication is vulnerable to brute force attacks and doesn’t scale for automation. SSH keys solve both problems by using public-key cryptography.

Generate a new SSH key pair with Ed25519 (preferred over RSA for better security and performance):

ssh-keygen -t ed25519 -C "work-laptop-2024"

You’ll be prompted for a file location (default: ~/.ssh/id_ed25519) and a passphrase. Use a strong passphrase—it encrypts your private key on disk, so even if someone steals your laptop, they can’t use your keys without it.

The command creates two files:

  • ~/.ssh/id_ed25519 (private key—never share this)
  • ~/.ssh/id_ed25519.pub (public key—safe to distribute)

Copy your public key to the remote server:

ssh-copy-id username@example.com

This appends your public key to ~/.ssh/authorized_keys on the remote server. If ssh-copy-id isn’t available, do it manually:

cat ~/.ssh/id_ed25519.pub | ssh username@example.com "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"

Set correct permissions on the remote server:

chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys

Test your key-based login:

ssh username@example.com

You should connect without entering your remote password (though you’ll need your key passphrase if you set one).

SSH Server Configuration

The SSH daemon configuration file lives at /etc/ssh/sshd_config. Always backup before editing:

sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.backup

Essential security settings:

# Disable password authentication (keys only)
PasswordAuthentication no
PubkeyAuthentication yes

# Disable root login entirely
PermitRootLogin no

# Change default port to reduce automated attacks
Port 2222

# Restrict which users can connect
AllowUsers alice bob charlie

# Disable empty passwords
PermitEmptyPasswords no

# Limit authentication attempts
MaxAuthTries 3

# Set idle timeout (5 minutes)
ClientAliveInterval 300
ClientAliveCountMax 0

After modifying sshd_config, test the configuration syntax:

sudo sshd -t

If no errors appear, restart the SSH service:

# On systemd systems (Ubuntu, Debian, RHEL 7+, Arch)
sudo systemctl restart sshd

# On older systems
sudo service ssh restart

Critical warning: Before disabling password authentication, verify that key-based authentication works from a separate terminal session. Don’t close your existing SSH connection until you’ve confirmed the new configuration works.

SSH Client Configuration

The client configuration file ~/.ssh/config eliminates repetitive command-line options and enforces consistent connection parameters.

Create or edit ~/.ssh/config:

# Production web server
Host prod-web
    HostName 203.0.113.50
    User deploy
    Port 2222
    IdentityFile ~/.ssh/id_ed25519_production
    ServerAliveInterval 60

# Development database server
Host dev-db
    HostName dev-database.internal.example.com
    User admin
    IdentityFile ~/.ssh/id_ed25519_dev
    LocalForward 5432 localhost:5432

# Bastion host configuration
Host bastion
    HostName bastion.example.com
    User jump
    IdentityFile ~/.ssh/id_ed25519_bastion

# Internal server via bastion
Host internal-app
    HostName 10.0.1.50
    User appuser
    ProxyJump bastion
    IdentityFile ~/.ssh/id_ed25519_internal

# Default settings for all hosts
Host *
    ServerAliveInterval 60
    ServerAliveCountMax 3
    Compression yes

With this configuration, connect using simple aliases:

ssh prod-web
ssh dev-db
ssh internal-app

The ProxyJump directive automatically routes connections through a bastion host, essential for accessing servers in private networks.

Advanced SSH Features

SSH provides powerful tunneling capabilities beyond basic remote access.

Local port forwarding makes a remote service available on your local machine:

ssh -L 8080:localhost:80 username@webserver.com

Now accessing http://localhost:8080 on your machine connects to port 80 on the remote server through an encrypted tunnel. This is invaluable for accessing web interfaces on servers without exposing them to the internet.

Remote port forwarding exposes your local service to the remote server:

ssh -R 9000:localhost:3000 username@server.com

The remote server can now access your local service on port 3000 by connecting to its own port 9000. Useful for demonstrating local development work to remote colleagues.

Dynamic port forwarding creates a SOCKS proxy:

ssh -D 8080 username@server.com

Configure your browser to use localhost:8080 as a SOCKS5 proxy, and all traffic routes through the SSH server—perfect for bypassing restrictive networks or encrypting traffic on untrusted WiFi.

Secure file transfers with SCP:

# Copy local file to remote server
scp document.pdf username@server.com:/home/username/

# Copy remote file to local machine
scp username@server.com:/var/log/app.log ./

# Copy entire directory recursively
scp -r /local/directory username@server.com:/remote/path/

SFTP provides an interactive file transfer session:

sftp username@server.com

Common SFTP commands:

put localfile.txt          # Upload file
get remotefile.txt         # Download file
ls                         # List remote directory
lls                        # List local directory
cd /remote/path           # Change remote directory
lcd /local/path           # Change local directory

Security Best Practices and Troubleshooting

Enable verbose output to diagnose connection problems:

ssh -vvv username@server.com

This shows detailed information about key exchange, authentication attempts, and where connections fail.

Check SSH service status on the server:

sudo systemctl status sshd

Review authentication logs:

# Ubuntu/Debian
sudo tail -f /var/log/auth.log

# RHEL/CentOS/Fedora
sudo tail -f /var/log/secure

Install and configure Fail2ban to automatically block brute force attacks:

sudo apt install fail2ban

# Create local configuration
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

Edit /etc/fail2ban/jail.local:

[sshd]
enabled = true
port = 2222
maxretry = 3
bantime = 3600
findtime = 600

Restart Fail2ban:

sudo systemctl restart fail2ban
sudo fail2ban-client status sshd

Additional security recommendations:

  • Use SSH keys exclusively—disable password authentication
  • Implement two-factor authentication with Google Authenticator PAM module
  • Run SSH on a non-standard port to reduce log noise from automated scanners
  • Use AllowUsers or AllowGroups to restrict access
  • Keep SSH updated—security vulnerabilities are discovered regularly
  • Monitor authentication logs for suspicious activity
  • Consider using certificate-based authentication for large deployments
  • Implement network-level restrictions with firewall rules

SSH is the foundation of secure remote administration. Master its configuration, use key-based authentication religiously, and leverage client configuration files to streamline your workflow. The time invested in proper SSH setup pays dividends in security, efficiency, and peace of mind.

Liked this? There's more.

Every week: one practical technique, explained simply, with code you can use immediately.