1. Introduction

The SSH protocol is one of the most common forms of remote access to Linux systems. As such, it provides many options for access control.

In this tutorial, we look at ways to configure sshd on multiple ports. First, we briefly refresh on concepts around the SSH server setup. Next, we delve into setting up multiport access. Finally, we test our changes and configure a new daemon to start automatically.

We tested the code in this tutorial on Debian 11 (Bullseye) with GNU Bash 5.1.4 and OpenSSH 8.4p1. It should work in most POSIX-compliant environments.

2. SSH Server Setup

By default, the configuration for sshd is located at /etc/ssh/sshd_config. Naturally, it includes options in many categories:

  • port and address
  • logging
  • keys and key policy
  • login settings
  • cryptography policy
  • user permissions
  • timeouts
  • daemon options

To apply changes, we restart the SSH service via systemctl or (not recommended) directly via /etc/init.d/sshd:

$ systemctl restart ssh.service
$ /etc/init.d/sshd restart

Importantly, we can use the sshd daemon to verify our settings before applying, which is especially important in remote sessions:

$ sshd -t

Here, no output means our /etc/ssh/sshd_config should not cause issues. Failing to check our modifications may result in the inability to log back into the system remotely.

Finally, sshd also offers the -f flag to supply an alternative options file:

$ /usr/sbin/sshd -f /etc/ssh/sshd_config_custom

Critically, we must use the absolute path when starting the daemon, and the default or supplied configuration file must exist for a successful launch.

3. Multiport Access

With its initial setup, SSH servers run on port 22 without root login permissions. Since this is the default, the settings are not specified explicitly but are only comments in /etc/ssh/sshd_config.

Indeed, there can be different reasons for setting up sshd with multiple ports. In fact, depending on our goal, we can achieve multiport access.

3.1. Same Daemon on Different Ports

Perhaps the simplest scenario is to allow access to the same SSH server configuration on multiple ports. To set that up, we can follow several steps:

  1. Open /etc/ssh/sshd_config
  2. Find any existing Port statements
  3. Add more ports on new lines via Port followed by the port number, e.g., Port 666
  4. Restart the SSH service

Since the second step is not mandatory, we can reduce the above to a one-liner:

$ echo -e 'Port 666\nPort 667' >> /etc/ssh/sshd_config && sshd -t && systemctl restart ssh.service

Since the default implicit Port 22 line is just a comment in the configuration, once we insert an actual Port statement, we override port 22. If we need to retain access via that port along with others, we must specify a separate line with it explicitly. At this point, we should be able to access our server on ports 666 and 667:

$ ssh user@baeldung -p 666
baeldung $

On the other hand, we may want to have separate ports leading to independent SSH daemons.

3.2. Two Daemons on Two Ports

Sometimes, running different SSH server setups is beneficial. In such cases, we can identify the configurations by port.

For example, root login is disabled by default, but we might want to allow it for internal IP addresses. Let’s begin by copying our current /etc/ssh/sshd_config file:

$ cp /etc/ssh/sshd_config /etc/ssh/sshd_config_internal

Next, we perform several changes to the new configuration:

  • configure the Port statement with a port other than 22, e.g., 666
  • add PermitRootLogin yes to allow root login
  • restrict the configuration or port to internal IP addresses

Basically, the first step boils down to one command:

$ echo 'Port 666' >> /etc/ssh/sshd_config_internal

While we can achieve IP filtering via iptables and ufw, sshd also offers a simple way to do the same:

$ cat <>/etc/ssh/sshd_config_internal
Match Address 192.168.66.*
  PermitRootLogin yes

Above, we use a here string to insert a Match block, which only permits root logins for addresses on the internal 192.168.66.* network. Importantly, Match blocks must be at the end of the file.

Now, we have /etc/ssh/sshd_config and /etc/ssh/sshd_config_internal with their respective settings. Let’s see how to start them.

3.3. Testing

We already saw how to manually launch an SSH daemon with a given configuration file. Let’s do that with our secondary configuration from above:

$ /usr/sbin/sshd -f /etc/ssh/sshd_config_internal

Now, from another host on the local network, we can try both ports with root and a regular user:

$ ssh user@baeldung -p 22
baeldung $ exit
$ ssh root@baeldung -p 22
root@baeldung's password:
Permission denied, please try again.
$ ssh user@baeldung -p 666
baeldung $ exit
$ ssh root@baeldung -p 666
root@baeldung's password:
baeldung $

While our original server configuration /etc/ssh/sshd_config with the default port 22 doesn’t allow root logins from local machines, the new /etc/ssh/sshd_config_internal with port 666 does.

Of course, external access leads to a disabled root login on either due to the local network filter:

$ ssh root@baeldung -p 666
root@baeldung's password:
Permission denied, please try again.

At this point, we have a working way to start our new SSH daemon, but we must do so manually.

3.4. Autostart

Further, to run our custom configuration daemon automatically on reboots, we can set it up as a new separate service:

$ cp /lib/systemd/system/ssh.service /lib/systemd/system/ssh_internal.service

We then configure the Exec* lines of /lib/systemd/system/ssh_internal.service to the appropriate values by adding the -f switch with the proper file path where necessary.

Finally, we can enable and start our new service:

$ systemctl enable ssh_internal
$ systemctl start ssh_internal

Indeed, with this configuration, we don’t need to bother starting our new service manually.

4. Conclusion

In this article, we discussed how to start an SSH server on multiple ports.

In conclusion, running a separate SSH daemon enables different configurations to run concurrently on the same system.

Comments are open for 30 days after publishing a post. For any issues past this date, use the Contact form on the site.