Secure Remote Access in Linux with SSH

CompTIABeginner
Practice Now

Introduction

In this lab, you will learn the fundamentals of securing remote access to a Linux system using the Secure Shell (SSH) protocol. You will gain hands-on experience with essential SSH functionalities, including setting up key-based authentication for enhanced security, securely transferring files between systems, and creating SSH tunnels for port forwarding.

You will begin by setting up a Docker container to simulate a remote server environment, making the lab more realistic. You will then install the OpenSSH client on your host machine and generate a new RSA key pair using the ssh-keygen utility. Next, you will configure the Docker server to accept this key for authentication, establishing a secure, passwordless connection between your host and the containerized server. Finally, you will practice using the scp command for secure file transfers and the ssh -L command to forward a local port to a remote service, effectively creating a secure tunnel.

Set Up Docker SSH Server and Generate a Key Pair

In this step, you will set up a Docker container to simulate a remote SSH server and generate a secure key pair on your host machine. This approach provides a more realistic environment by separating the client (your host) from the server (Docker container).

Since Docker and the OpenSSH client are already installed in this environment, you can proceed directly to configuring the server.

First, ensure the Docker service is running:

sudo systemctl start docker
sudo systemctl enable docker

Now, let's create a Docker container that will act as our SSH server. We'll use Ubuntu as the base image and configure it with SSH server capabilities. Create a Dockerfile:

cat > Dockerfile << 'EOF'
FROM ubuntu:22.04

## Install OpenSSH server and other utilities
RUN apt-get update && \
    apt-get install -y openssh-server nginx sudo && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

## Create a user for SSH access
RUN useradd -m -s /bin/bash sshuser && \
    echo 'sshuser:password123' | chpasswd && \
    usermod -aG sudo sshuser

## Configure SSH
RUN mkdir /var/run/sshd && \
    sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin no/' /etc/ssh/sshd_config && \
    sed -i 's/#PasswordAuthentication yes/PasswordAuthentication yes/' /etc/ssh/sshd_config && \
    sed -i 's/#PubkeyAuthentication yes/PubkeyAuthentication yes/' /etc/ssh/sshd_config

## Create SSH directory for the user
RUN mkdir -p /home/sshuser/.ssh && \
    chown sshuser:sshuser /home/sshuser/.ssh && \
    chmod 700 /home/sshuser/.ssh

## Expose SSH port
EXPOSE 22 80

## Start SSH service
CMD ["/usr/sbin/sshd", "-D"]
EOF

Build the Docker image:

sudo docker build -t ssh-server .

Run the Docker container, mapping port 2222 on your host to port 22 in the container:

sudo docker run -d --name ssh-lab-server -p 2222:22 -p 8080:80 ssh-server

Verify that the container is running:

sudo docker ps

You should see output showing the running container:

CONTAINER ID   IMAGE        COMMAND               CREATED         STATUS         PORTS                                        NAMES
...            ssh-server   "/usr/sbin/sshd -D"   ...             Up ...         0.0.0.0:2222->22/tcp, 0.0.0.0:8080->80/tcp   ssh-lab-server

Next, you will generate an SSH key pair. SSH keys provide a more secure way of logging into a server with SSH than using a password alone. A key pair consists of a private key, which must be kept secret, and a public key, which can be shared.

We will use the ssh-keygen command to create a new key pair. We'll specify the key type as rsa and the key size as 2048 bits for strong security. The -f flag allows us to specify a filename for our keys, which helps in organizing them. We will name our key ~/.ssh/id_rsa_lab_ssh.

Run the following command. When prompted for a passphrase, simply press Enter twice to proceed without one. For this lab, we will omit the passphrase for simplicity, but in a real-world scenario, you should always use a strong passphrase to protect your private key.

ssh-keygen -t rsa -b 2048 -f ~/.ssh/id_rsa_lab_ssh

The command will generate the key pair and show you where the files are saved.

Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/labex/.ssh/id_rsa_lab_ssh
Your public key has been saved in /home/labex/.ssh/id_rsa_lab_ssh.pub
The key fingerprint is:
SHA256:... labex@...
The key's randomart image is:
+---[RSA 2048]----+
|        .o*+..   |
|       . =.o. .  |
|      . o o. .   |
|       o .  .    |
|      . S        |
|     . . .       |
|      o .        |
|     o .         |
|    E .          |
+----[SHA256]-----+

To confirm that the key files have been created, you can list the contents of the ~/.ssh directory. You should see your new private key (id_rsa_lab_ssh) and public key (id_rsa_lab_ssh.pub).

ls -l ~/.ssh/id_rsa_lab_ssh*

The output will look similar to this, showing the two new files:

-rw------- 1 labex labex 1876 ... /home/labex/.ssh/id_rsa_lab_ssh
-rw-r--r-- 1 labex labex  401 ... /home/labex/.ssh/id_rsa_lab_ssh.pub

You have now successfully installed the SSH server and created a key pair, which you will use in the next steps to configure and test secure authentication.

Configure and Test SSH Key-Based Authentication

In this step, you will configure the Docker SSH server to recognize your public key, enabling you to log in without a password. This process involves copying your public key to the Docker container and then testing the connection.

For the SSH server to authenticate you using your key, your public key must be placed in the ~/.ssh/authorized_keys file on the server. Since our server is running in a Docker container, we need to copy the public key from your host machine to the container.

First, copy your public key to the Docker container using the docker cp command:

sudo docker cp ~/.ssh/id_rsa_lab_ssh.pub ssh-lab-server:/home/sshuser/.ssh/authorized_keys

Next, we need to set the correct file permissions inside the container. SSH is very particular about security and will refuse to use keys if the permissions are too open. Execute the following command to set proper permissions:

sudo docker exec ssh-lab-server chown sshuser:sshuser /home/sshuser/.ssh/authorized_keys
sudo docker exec ssh-lab-server chmod 600 /home/sshuser/.ssh/authorized_keys

With the public key added and permissions set, you are ready to test the key-based authentication. You will attempt to SSH into the Docker container using port 2222 (which we mapped to the container's port 22) as the user sshuser, specifying the private key you created.

Use the ssh command with the -i flag to point to your private key file and -p to specify the port:

ssh -i ~/.ssh/id_rsa_lab_ssh -p 2222 sshuser@localhost

Since you are connecting to a new host for the first time, you may be asked to verify the host's authenticity. Type yes and press Enter.

The authenticity of host '[localhost]:2222 ([127.0.0.1]:2222)' can't be established.
ED25519 key fingerprint is SHA256:....
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '[localhost]:2222' (ED25519) to the list of known hosts.

If everything is configured correctly, you will be logged in immediately without being prompted for a password. You will see a welcome message, and your command prompt will change to show you're now inside the Docker container:

Welcome to Ubuntu 22.04.3 LTS (GNU/Linux 5.15.0-88-generic x86_64)
...
sshuser@containerid:~$

To exit the SSH session and return to your host terminal prompt, simply type exit and press Enter.

exit

Successfully logging in without a password confirms that your key-based authentication is working correctly between your host and the Docker container. This method is significantly more secure than traditional password authentication.

Securely Transfer Files Using scp

In this step, you will learn how to use the Secure Copy Protocol (scp) to transfer files securely between hosts. scp leverages the underlying SSH protocol, meaning it benefits from the same encryption and authentication mechanisms you've already configured, including key-based authentication.

First, let's create a sample file in your current working directory, ~/project, that we can use for the transfer. We'll name it source_file.txt.

echo "This is a test file for scp." > source_file.txt

You can verify that the file was created by listing it:

ls -l source_file.txt

The output should show your newly created file:

-rw-r--r-- 1 labex labex 29 ... source_file.txt

Now, you will use scp to copy source_file.txt to the /tmp directory on the Docker container, demonstrating secure file transfer to a remote server. The basic syntax for scp is scp -i [private_key] -P [port] [source_file] [user]@[host]:[destination_path].

You'll use the -i flag to specify your private key, -P to specify port 2222 (our Docker container's SSH port), and transfer the file to the sshuser account on the container:

scp -i ~/.ssh/id_rsa_lab_ssh -P 2222 source_file.txt sshuser@localhost:/tmp/destination_file.txt

You will see output indicating the progress of the file transfer, which should be instantaneous for a small file.

source_file.txt                                   100%   29     6.7KB/s   00:00

To confirm that the file was copied successfully, connect to the Docker container and list the destination file:

sudo docker exec ssh-lab-server ls -l /tmp/destination_file.txt

The output will confirm the existence and details of the copied file:

-rw-r--r-- 1 sshuser sshuser 29 ... /tmp/destination_file.txt

You can also verify the file content was transferred correctly:

sudo docker exec ssh-lab-server cat /tmp/destination_file.txt

This should display:

This is a test file for scp.

You have now successfully transferred a file using scp, demonstrating a secure and practical way to move data between systems over a network.

Create an SSH Tunnel for Port Forwarding with ssh -L

In this step, you will learn one of SSH's most powerful features: tunneling, also known as port forwarding. This allows you to securely forward network traffic from a port on your local machine to a port on a remote server, effectively wrapping an unencrypted protocol within a secure SSH connection. We will practice local port forwarding.

To demonstrate this, we need a service running on a port that we can connect to. Fortunately, our Docker container already has Nginx installed and configured. We need to start the Nginx service inside the container.

First, start the Nginx service inside the Docker container:

sudo docker exec ssh-lab-server service nginx start

You can verify that Nginx is running correctly inside the container:

sudo docker exec ssh-lab-server service nginx status

The output should show the service as running:

 * nginx is running

Now, let's create the SSH tunnel. We will use the ssh command with the -L flag, which stands for local port forwarding. The syntax is ssh -L [LOCAL_PORT]:[DESTINATION_HOST]:[DESTINATION_PORT] [USER]@[SERVER].

We will forward traffic from port 9090 on our local machine to port 80 inside the Docker container. The -N flag tells SSH not to execute a remote command, which is ideal for just forwarding ports. Note that we use port 2222 to connect to our Docker container's SSH service.

Execute this command. This command will occupy your current terminal and will not return a prompt. You will need to open a new terminal to test the tunnel.

ssh -i ~/.ssh/id_rsa_lab_ssh -N -L 9090:localhost:80 -p 2222 sshuser@localhost

Now, open a new terminal by clicking the + icon in the terminal tab bar. In this new terminal, you can test the tunnel using curl. By accessing localhost:9090, your request will be securely tunneled through SSH to port 80 inside the Docker container.

curl http://localhost:9090

You should see the HTML content of the default Nginx welcome page, which confirms the tunnel is working.

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

You have successfully created a secure tunnel that forwards traffic from your host machine to a service running inside the Docker container. To close the connection, return to the first terminal (the one running the ssh command) and press Ctrl+C. You can then close the second terminal.

Summary

In this lab, you learned the essential skills for securing remote access on a Linux system using the Secure Shell (SSH) protocol. The key objectives covered include setting up and testing key-based authentication, securely transferring files with scp, and creating an SSH tunnel for port forwarding.

You began by preparing the environment, which involved updating the system's package list and installing both the openssh-server and openssh-client packages. After verifying that the SSH service was active, you generated a secure 2048-bit RSA key pair using the ssh-keygen command. This foundational step created the public and private keys required to establish secure, passwordless connections in the subsequent steps.