TensorDock
  • Who we are
    • Welcome to TensorDock
    • Our Ethos and Commitment
  • Virtual Machines
    • How to SSH into your instance
    • How to RDP into your instance
    • Installing NVIDIA Drivers on Windows 10
    • Linux & NVIDIA Drivers
    • Cloud-init
    • File transferring with SCP and Rclone
    • Running Jupyter Notebook
    • SSH server hardening on Ubuntu
    • Running Stable Diffusion in Docker
    • Installing and running Stable Diffusion UI
    • Running Disco Diffusion on a Linux instance
    • Running Disco Diffusion on a Windows instance
    • Running SimpleTuner/Flux on a Linux instance
    • Using Parsec, Moonlight and Sunshine
  • Hosting
    • Installation Guide
  • Whitelabel
    • Overview
    • Setting Up a Storefront
    • Customization Overview
    • Customize Whitelabel Storefront
  • Legal Information
    • Company Information
    • Terms of Service (TOS)
    • Privacy Policy
    • Acceptable Use Policy (AUP)
    • Taxes, VAT, GST
    • Downtime Compensation
    • Supplier Hosting Agreement
  • Quick Links
    • Discord Server
    • TensorDock.com
    • Dashboard
    • API Documentation
Powered by GitBook
On this page
  • Preface: Security
  • Introduction
  • Step 1: Setting up your TensorDock server
  • Step 2: General Hardening
  • Create a configuration file backup
  • Editing and testing settings
  • Basic SSH hardening (Recommended)
  • SSH Key Authentication (Optional)
  • Disable other authentication methods (Optional)
  • Saving and applying changes
  • Step 4: Implementing an IP Address Allowlist
  • Step 5: (Optional/Advanced) Restricting the Shell of a User
  • Conclusion

Was this helpful?

  1. Virtual Machines

SSH server hardening on Ubuntu

Learn how to make your servers more secure using SSH hardening

PreviousRunning Jupyter NotebookNextRunning Stable Diffusion in Docker

Last updated 9 months ago

Was this helpful?

Preface: Security

Generally, intrusions only occur on ports that are actively serving requests. This might be port 22 (if you are using a standard SSH port), as well as port 80/443 if you are serving a web application. All requests to other ports would automatically be dropped given there is no service listening on those ports.

To secure your server, you should focus on limiting access to the services that listen to ports. In this tutorial, we'll secure SSH access, but these principles also apply to all other services that you may run on your server.

Introduction

We include OpenSSH server on every TensorDock virtual machine. OpenSSH is the default SSH server software that is used within Ubuntu, Debian, CentOS, FreeBSD, and many other Linux-based systems.

It is important to properly secure your OpenSSH server, as it is the gateway for anyone to enter server. In this tutorial, you will learn about hardening your OpenSSH server by using different configuration options to ensure that remote access to your server is as secure as possible.

Step 1: Setting up your TensorDock server

You can deploy a GPU on our to your specific configurations based on cost, RAM, storage, and vCPUs. You can use either Ubuntu 20.04 or Ubuntu 22.04 as your installation.

Step 2: General Hardening

In order to start securing your SSH server, we will start with a general secure configuration that will suit the majority of servers. Some advanced users may prefer to configure their servers depending on their own threat model and risk threshold, which is beyond the scope of this tutorial.

Most hardening configurations for OpenSSH will be using the standard OpenSSH server configuration file, located at /etc/ssh/sshd_config.

Create a configuration file backup

Before you continue with this tutorial, it is best practice to take a backup of your existing configuration file, in case something goes wrong. Use the following command to do this:

$ sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak

This saves a backup of the file to /etc/ssh/sshd_config.bak.

Editing and testing settings

We can review the current options that are set using this command which runs the OpenSSH server in extended test mode, which will validate the full configuration file and print out the effective configuration values:

$ sudo sshd -T

You can now open the configuration file using your preferred text editor and begin implementing the initial hardening measures:

$ sudo nvim /etc/ssh/sshd_config

When editing your configuration file, some options will be commented out by default using a single hash character (#) at the start of the line, which can be seen above. In order to edit these options and/or have the commented option be recognized, you will have to uncomment them by removing the hash.

Basic SSH hardening (Recommended)

First, disable logging in via SSH as the root user by setting the following option:

PermitRootLogin no

We do this as it will prevent a potential attacker from logging in directly as root. Virtual machines do not include root users by default, but as a good measure, we'll prevent root user login in case you define a root user later on.

Next, limit the maximum number of authentication attempts for a particular login session by changing the following:

MaxAuthTries 3

Generally, a value of 3 is acceptable for most setups, but you can set this higher or lower if you'd like. However, setting a value too low may prove problematic; if you fail to enter your password correctly three times in a row, you'll be blocked from SSH'ing onto your server via fail2ban, which we include on all of our Linux operating system templates.

If required, you can also set a reduced login grace period, which is the amount of time a user has to complete authentication after initially connecting to your SSH server:

LoginGraceTime 20

This is automatically specified as seconds, unless otherwise specified.

SSH Key Authentication (Optional)

Then, you'll need to transfer your computer's public key to the TensorDock server. You can do this by running the following command from your own computer:

ssh-copy-id user@<TENSORDOCK IP>

If you have configured SSH keys for authentication, rather than using passwords, disable SSH password authentication to prevent leaked user passwords from allowing an attacker to log in:

PasswordAuthentication no

As a further hardening measure related to passwords, you may also wish to disable authentication with empty passwords. This will prevent logins if a user’s password is set to a blank or empty value:

PermitEmptyPasswords no

Disable other authentication methods (Optional)

In the majority of use cases, SSH will be configured with public key authentication as the only in-use authentication method. However, OpenSSH server also supports many other authentication methods, some of which are enabled by default. If these are not required, you can disable them to further reduce the attack surface of your SSH server:

ChallengeResponseAuthentication no
KerberosAuthentication no
GSSAPIAuthentication no

If you’d like to know more about some of the additional authentication methods available within SSH, you may wish to review these resources:

X11 forwarding allows for the display of remote graphical applications over an SSH connection, but this is rarely used in practice. It is recommended to disable it if it isn’t needed on your server:

X11Forwarding no

OpenSSH server allows connecting clients to pass custom environment variables, that is, to set a $PATH or to configure terminal settings. However, like X11 forwarding, these are not commonly used, so can be disabled in most cases:

PermitUserEnvironment no

If you decide to configure this option, you should also make sure to comment out any references to AcceptEnv by adding a hash (#) to the beginning of the line.

Next, you can disable several miscellaneous options related to tunneling and forwarding if you won’t be using these on your server:

AllowAgentForwarding no
AllowTcpForwarding no
PermitTunnel no

Finally, you can disable the verbose SSH banner that is enabled by default, as it shows various information about your system, such as the operating system version:

DebianBanner no

Note that this option most likely won’t already be present in the configuration file, so you may need to add it manually.

Saving and applying changes

Save and exit the file once you’re done. You can now validate the syntax of your new configuration by running sshd in test mode:

$ sudo sshd -t

If your configuration file has a valid syntax, there will be no output. In the event of a syntax error, there will be an output describing the issue.

Once you’re satisfied with your configuration file, you can reload sshd to apply the new settings:

$ sudo service sshd reload

In this step, you completed some general hardening of your OpenSSH server configuration file. Next, you’ll implement an IP address allowlist to further restrict who can log in to your server.

Step 4: Implementing an IP Address Allowlist

You can use IP address allowlists to limit the users who are authorized to log in to your server on a per-IP address basis. In this step, you will configure an IP allowlist for your OpenSSH server.

By implementing an IP address allowlist, you can ensure that people will only be able to log in from one of the pre-approved IP addresses, greatly reducing the risk of a breach in the event that your private keys and/or passwords are leaked.

Note: Please take care in identifying the correct IP addresses to add to your allowlist, and ensure that these are not reserved or dynamic addresses that may regularly change, for example as is often seen with consumer internet service providers.

You can identify the IP address that you’re currently connecting to your server with by using the w command:

$ w

This should output something similar to the following:

Output
 14:11:48 up 2 days, 12:25,  1 user,  load average: 0.00, 0.00, 0.00
         USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
your_username     pts/0    203.0.113.1     12:24    1.00s  0.20s  0.00s w

Locate your user account in the list and take a note of the connecting IP address. Here we use the example IP of 203.0.113.1

In order to begin implementing your IP address allowlist, open the OpenSSH server configuration file in your favorite text editor:

$ sudo nvim /etc/ssh/sshd_config

You can implement IP address allowlists using the AllowUsers configuration directive, which restricts user authentications based on username and/or IP address.

Your own system setup and requirements will determine which specific configuration is the most appropriate. The following examples will help you to identify the most suitable one:

When you have found your appropriate use case, add it to the bottom of your OpenSSH server configuration file.

  • Restrict all users to a specific IP address:

AllowUsers *@203.0.113.1
AllowUsers *@203.0.113.0/24
  • Restrict all users to a specific IP address range (using wildcards):

AllowUsers *@203.0.113.*
  • Restrict all users to multiple specific IP addresses and ranges:

AllowUsers *@203.0.113.1 *@203.0.113.2 *@192.0.2.0/24 *@172.16.*.1
  • Disallow all users except for named users from specific IP addresses:

AllowUsers sammy@203.0.113.1 alex@203.0.113.2
  • Restrict a specific user to a specific IP address, while continuing to allow all other users to log in without restrictions:

Match User ashley
  AllowUsers ashley@203.0.113.1

Warning: Within an OpenSSH configuration file, all configurations under a Match block will only apply to connections that match the criteria, regardless of indentation or line breaks. This means that you must be careful and ensure that configurations intended to apply globally are not accidentally put within a Match block. It is recommended to put all Match blocks at the bottom/end of your configuration file to help avoid this.

Once you have finalized your configuration, add it to the bottom of your OpenSSH server configuration file as seen above.

Save and close the file, and then proceed to test your configuration syntax:

$ sudo sshd -t

If no errors are reported, you can reload OpenSSH server to apply your configuration:

$ sudo service sshd reload

In this step, you implemented an IP address allowlist on your OpenSSH server. Next, you will restrict the shell of a user to limit the commands that they are allowed to use.

Step 5: (Optional/Advanced) Restricting the Shell of a User

In this step, you’ll look at the various options for restricting the shell of an SSH user.

In addition to providing remote shell access, SSH is also great for transferring files and other data, for example, via SFTP. However, you may not always want to grant full shell access to users when they only need to be able to carry out file transfers.

There are multiple configurations within OpenSSH server that you can use to restrict the shell environment of particular users. For instance, in this tutorial, we will use these to create SFTP-only users.

Firstly, you can use the /usr/sbin/nologin shell to disable interactive logins for certain user accounts, while still allowing non-interactive sessions to function, like file transfers, tunneling, and so on.

To create a new user with the nologin shell, use the following command:

$ sudo adduser --shell /usr/sbin/nologin alex

Alternatively, you can change the shell of an existing user to be nologin:

$ sudo usermod --shell /usr/sbin/nologin sammy

If you then attempt to interactively log in as one of these users, the request will be rejected:

$ sudo su alex

This will output something similar to the following message:

Output
This account is currently not available.

Despite the rejection message on interactive logins, other actions such as file transfers will still be allowed.

Next, you should combine your usage of the nologin shell with some additional configuration options to further restrict the relevant user accounts.

Begin by opening the OpenSSH server configuration file in your favorite text editor again:

$ sudo nano /etc/ssh/sshd_config

There are two configuration options that you can implement together to create a tightly restricted SFTP-only user account: ForceCommand internal-sftp and ChrootDirectory.

The ForceCommand option within OpenSSH server forces a user to execute a specific command upon login. This can be useful for certain machine-to-machine communications, or to forcefully launch a particular program.

However, in this case, the internal-sftp command is particularly useful. This is a special function of OpenSSH server that launches a basic in-place SFTP daemon that doesn’t require any supporting system files or configuration.

This should ideally be combined with the ChrootDirectory option, which will override/change the perceived root directory for a particular user, essentially restricting them to a specific directory on the system.

Add the following configuration section to your OpenSSH server configuration file for this:

Match User alex
  ForceCommand internal-sftp
  ChrootDirectory /home/alex/

Warning: As noted in Step 2, within an OpenSSH configuration file, all configurations under a Match block will only apply to connections that match the criteria, regardless of indentation or line breaks. This means that you must be careful and ensure that configurations intended to apply globally are not accidentally put within a Match block. It is recommended to put all Match blocks at the bottom/end of your configuration file to help avoid this.

Save and close your configuration file, and then test your configuration again:

$ sudo sshd -t

If there are no errors, you can then apply your configuration:

$ sudo service sshd reload

This has created a robust configuration for the alex user, where interactive logins are disabled, and all SFTP activity is restricted to the home directory of the user. From the perspective of the user, the root of the system, that is, /, is their home directory, and they will not be able to traverse up the file system to access other areas.

You’ve implemented the nologin shell for a user and then created a configuration to restrict SFTP access to a specific directory.

Conclusion

In this article, you reviewed your OpenSSH server configuration and implemented various hardening measures to help secure your server.

This will have reduced the overall attack surface of your server by disabling unused features and locking down the access of specific users.

Setting this to a lower value helps to prevent certain where multiple authentication sessions are kept open for a prolonged period of time.

SSH keys are another method to authenticate a remote connection into a server. Learn more .

First, if you haven't already, you'll need to define an SSH key pair. Read more on how to do so .

In many cases, you will only be logging on to your server from a small number of known, trusted IP addresses. For example, your home internet connection, a corporate VPN appliance, or a static or in a data center.

Restrict all users to a specific IP address range using :

You may wish to review the and its associated , to identify any potential further tweaks that you want to make.

denial-of-service attacks
here
here
Challenge Response Authentication
Kerberos Authentication
GSSAPI Authentication
jump box
bastion host
Classless Inter-Domain Routing (CIDR) notation
manual pages for OpenSSH server
configuration file
Marketplace
Page cover image