Learn through the super-clean Baeldung Pro experience:
>> Membership and Baeldung Pro.
No ads, dark-mode and 6 months free of IntelliJ Idea Ultimate to start with.
Last updated: September 6, 2024
SSH is one of the main services used for administration, as such, any threats to its security should not be taken lightly. In this tutorial, we’ll discuss how to restrict SSH to the local network on Linux. As a rule, we must protect any open interfaces to our hosts against unauthorized access attempts. Restricting SSH to the local network is one way to do that.
We need to take care of SSH security in our production environments especially. Leaving it open can expose the host to brute-force attacks, vulnerability exploitation, or unauthorized access.
Furthermore, it’s good to apply a principle of least privilege, and only allow known sources to reach our SSH port.
The most common way to protect a Linux host from receiving unwanted network connections is to create host firewall rules. So, we start by creating a rule to enforce strict access control rules to the SSH service TCP port.
We can do this using the iptables command:
sudo iptables -A INPUT -s 10.1.2.0/24 -p tcp -m conntrack --ctstate NEW,ESTABLISHED -m tcp --dport 22 -m comment --comment ssh -j ACCEPT
This will instruct Linux only to accept connections to the SSH service port (TCP/22) originating from the 10.1.2.0/24 subnetwork.
To make this iptables rule persistent, we can install the iptables-persistent package (on Debian-based systems, like Ubuntu) and save all existing rules to its configuration:
# Install the IPTables-persistent package
sudo apt install iptables-persistent
# Add current IPtables rules to its configuration
sudo iptables-save > /etc/iptables/rules.v4
This will apply the protection rule every time the system is restarted.
From the SSH daemon perspective, there are a few options, we can filter in or out specific IP addresses and we can restrict the listening interfaces.
To configure the SSH daemon to disallow connections from any improper sources, we can add the following directives to the SSH daemon config file, usually located at /etc/ssh/sshd_config or /etc/openssh/sshd_config:
# This will disallow everyone
AuthorizedKeysFile /dev/null
# Put the netmask you want to allow here
Match Address 10.1.2.0/24
# Connections from above IP can use normal authorized keys to authenticate
AuthorizedKeysFile %h/.ssh/authorized_keys
The first uncommented directive, pointing the AuthorizedKeysFile to /dev/null will deny any access to the SSH server. The Match Address directive creates an exception to the hosts located at the 10.1.2.0/24 subnetwork, that shall use the standard AuthorizedKeysFile configuration.
One issue with this configuration is that, even though unwanted connections will be terminated, the SSH daemon must listen to connections and act on them. So, it still has some potential for exploitation.
Also, suppose we have a host with multiple network addresses host. In that case, we can use the ListenAddress directive to instruct the SSH daemon to listen for connections only on a specific IP address (the default is to listen on any address):
# Restrict the listening address to one specific host address
ListenAddress 10.1.2.20
This will narrow the attack surface, especially if the listening address network is not isolated from non-secure networks.
Administrative access stands out when we wonder about the risks any server is susceptible to. An attacker can do severe damage if he can compromise any server administration service.
We have discussed some options to protect our SSH server restricting access to the local network. Also, all the options shown can be mixed so that others will take over if one protection fails.
Finally, we can adapt the iptables rule for other services by changing the port and protocol of the firewall rule accordingly.