6  Secure Shell (SSH)

6.1 Introduction

SSH (Secure Shell) protocol enables encrypted communication between two systems over an unsecured network. It’s primarily employed for command-line sessions and remote command execution.

SSH Key Pair Mechanism

SSH uses a public key cryptography model, consisting of:

  • Private Key: It remains confidential and is stored on the client side.
  • Public Key: Shared openly and placed on the remote server.

The public key encrypts data, and its corresponding private key decrypts it. When you give someone your public key, you are saying - I permit you to use this key to create a lock on your system that can be opened with a key that I will not allow you to have. You are guaranteed to be the only person to access that system through the lock, and the system owner can revoke your access at any point.

Generating an SSH Key Pair

Generate a new SSH key pair with:

ssh-keygen -t rsa -b 4096

This creates two files in ~/.ssh:

  • id_rsa: The private key
  • id_rsa.pub: The public key

Adding the Public Key to the Remote Server

For password-less login for additional keys beyond your default key file, add the public key to ~/.ssh/authorized_keys. If you have ever passed a public key to Github or Gitlab for you to pull your code using SSH instead of HTTPS, they are doing this step on their end for you.

echo 'YOUR_PUBLIC_KEY' >> ~/.ssh/authorized_keys

The SSH Command Breakdown

The general SSH command structure is:

ssh [options] [user@]hostname

Where:

  • user: Username on the remote server.
  • hostname: Address or IP of the remote server.

To connect as user john to a server with IP 192.168.1.100:

ssh john@192.168.1.100

Ports

SSH defaults to port 22. For a different port, use -p:

ssh -p PORT_NUMBER john@192.168.1.100

Key-Based Authentication

To authenticate using a specific private key:

ssh -i ~/.ssh/privatekey john@192.168.1.100

Underlying Mechanism of SSH

  • The client requests the server’s public key.
  • The server sends its public key.
  • The client sends back data encrypted with this public key.
  • The server decrypts this with its private key, verifying its identity.
  • Both derive a symmetric key for the session.

6.2 SSH Configuration

Customize SSH client with vim ~/.ssh/config (client)

For instance, to set defaults for my_server:

Host my_server
  Port 2222
  IdentityFile /path/to/my_key

Then, connect simply with:

ssh john@my_server

SSH Security

Key-Based Authentication Over Passwords and Disable Root Login Over SSH

To enhance the security of SSH connections, it’s advisable to use SSH keys instead of password-based authentication. Additionally, disabling root login over SSH further strengthens security. Here’s how you can configure these settings:

  1. Edit the SSH Configuration File:

    Open the SSH configuration file using a text editor or the ndexr console.

    sudo vim /etc/ssh/sshd_config
  2. Configure Key-Based Authentication:

    To disable password authentication and enforce key-based authentication, ensure the following line is in your sshd_config:

    PasswordAuthentication no

    This setting disables password-based logins for all users, requiring them to use SSH keys.

  3. Disable Root Login Over SSH:

    To prevent the root user from logging in via SSH, include:

    PermitRootLogin no

    This setting ensures that the root account cannot be accessed directly over SSH, which is a critical security measure.

  4. Configure Gateway Ports (Optional):

    If your setup involves SSH tunneling or port forwarding, consider the GatewayPorts setting:

    • GatewayPorts no: Only allows forwarded ports to be accessed from the localhost, offering a more secure setup.
    • GatewayPorts yes: Allows forwarded ports to be accessed from any remote machine, which is less secure and should be used cautiously.
    • GatewayPorts clientspecified: Offers a balance by allowing the SSH client to specify the bind address for the forwarded port, providing flexibility while maintaining control over port accessibility.

    Choose the GatewayPorts setting that best fits your security needs and operational requirements.

  5. Restart SSH Service:

    After making these changes, restart the SSH service to apply them:

    sudo service ssh restart

By implementing these configurations, you significantly enhance the security of your SSH service, making it resilient against common attack vectors like brute force attacks and unauthorized root access.

6.3 AutoSSH with Systemd for Persistent SSH Tunnels

Introduction

AutoSSH is a program designed to start and monitor an SSH session, restarting the session if it goes down. By combining AutoSSH with systemd, we can ensure that our SSH tunnel is always up and running, even after the system reboots. This is particularly useful if you want to use a local server to host apps publicly through your EC2 server - saving tons of money on computing.

Installing AutoSSH

First, you’ll need to install autossh:

sudo apt update
sudo apt install autossh

Testing AutoSSH

Before we proceed with systemd, test your autossh connection:

autossh -M 0 -f -N -L 8080:localhost:80 -i ~/.ssh/id_rsa -o "ServerAliveInterval=30" -o "ServerAliveCountMax=3" user@remote_host

Here:

  • -M 0 disables the monitoring feature of autossh (since the SSH itself has a built-in feature to keep the connection alive).
  • -f runs autossh in the background.
  • -N tells SSH that we don’t want to run any commands on the remote host.
  • -L 8080:localhost:80 creates a tunnel from the local machine’s port 8080 to the remote machine’s port 80.

Setting Up Systemd Service

Create a systemd service file for our autossh tunnel:

sudo vim /etc/systemd/system/autossh-tunnel.service

Add the following content, adjusting the parameters as necessary:

[Unit]
After=network.target

[Service]
User=ec2-user
ExecStart=/usr/local/bin/autossh -M 20000 -vvv -N -o ServerAliveInterval=30 -o rverAliveCountMax=3 -i /home/ec2-user/.ssh/id_rsa -R 0.0.0.0:2222:localhost:22 ubuntu@ndexr.io
Environment="AUTOSSH_GATETIME=0"
Restart=always
RestartSec=3

[Install] WantedBy=multi-user.target

Replace username with your local username.

Restart the systemd daemon

sudo systemctl daemon-reload

Start the Service and manage

Now, you can start the autossh service:

sudo systemctl enable autossh-tunnel.service
sudo systemctl stop autossh-tunnel.service
sudo systemctl start autossh-tunnel.service
sudo systemctl status autossh-tunnel.service