How to secure an SSH connection on a Linux server. IP access restriction

OpenSSH allows you to perform remote connection to the server, manipulate files and manage the system. Today we want to talk about the best methods that will increase the security of an OpenSSH-based system.

Configuration files

  • /etc/ssh/sshd_config- OpenSSH server configuration file;
  • /etc/ssh/ssh_config- OpenSSH client configuration file;
  • ~/.ssh/- directory in which user SSH settings are stored;
  • ~/.ssh/authorized_keys or ~/.ssh/authorized_keys- a list of keys (RSA or DSA) that are used to connect to user accounts;
  • /etc/nologin- if this file exists in the system, then sshd will prohibit all users except root from connecting to the system;
  • /etc/hosts.allow and /etc/hosts.deny- interdiction system (part of security). Works similar to ACL;
  • Default SSH port - 22

Not needed - turn it off

If your server does not require remote SSH connections, be sure to disable it. On systems like CentOS/RHEL this is done like this:

Chkconfig sshd off yum erase openssh-server

Use SSH version 2

The first version of the SSH protocol has security problems that are addressed in the second version. Therefore, use the second version. Make sure that the Protocol 2 option is specified in the /etc/ssh/sshd_config file.

Limit SSH access

By default, all system users have the ability to connect to the system via SSH. We recommend limiting SSH access for security reasons. For example, to allow SSH for root, merion and networks users:

AllowUsers root merion networks

On the other hand, you can allow access to all users except those specified:

DenyUsers root merion networks

Inactivity time

It is important to indicate the time during which the inactive session will be terminated (completed). This can be done with the following options:

ClientAliveInterval 300 ClientAliveCountMax 0

In this setting, we specified the inactivity time to be 300 seconds (5 minutes).

About .rhosts files

The fact is that this file contains a list of hosts and users. If in this file contains a combination of host and user, then this user will be able to connect to the system via SSH without asking for a password. We recommend disabling this “wonderful” feature:

IgnoreRhosts yes

No host-based authentication!

So-called Host-Based Authentication Allows a user from a specific host to connect to the server. Disable:

HostbasedAuthentication no

Direct connection via root

PermitRootLogin no

Make a banner

For each connection, make a banner in which you can threaten attackers who are trying to commit unauthorized access. The Banner parameter is responsible for setting up the banner.

Port 22 only from the inside!

Make access to system port 22 only through a chain of firewall rules. It is best to leave access only from within the LAN. For example, in Iptables you can give access to 192.168.11.0/24:

A RH-Firewall-1-INPUT -s 192.168.11.0/24 -m state --state NEW -p tcp --dport 22 -j ACCEPT

Where to listen

By default, SSH listens for connections on all available interfaces. We recommend changing the default port and specifying the IP address on which to wait for connection. For example, we will specify port 962 and IP address 192.168.11.24

Port 962 ListenAddress 192.168.11.24

Cryptographically strong passwords

Use strong passwords. There are many tools on the Internet that will generate a crypto-strong password online, free of charge and without SMS :)

Prohibit empty passwords

There are users without passwords. Their access to SSH must also be denied using the option:

Port 962 PermitEmptyPasswords no

Analyze logs

Set event logging to INFO or DEBUG mode - this will allow you to have expanded control over the system:

LogLevel INFO

Was this article useful to you?

Please tell me why?

We are sorry that the article was not useful for you: (Please, if it is not difficult, indicate why? We will be very grateful for a detailed answer. Thank you for helping us become better!

As soon as a service “lights up” on a public network, it instantly becomes a target for attack. One of the problems is an attempt to gain access using passwords (brute force). And SSH in this case is no exception.

Analysis of the authentication log file /var/log/auth.log or analogues shows that an attempt to guess a password is usually made from several IPs at once and is extended over time.

SSH Bruteforce Protection

You can protect yourself from this in different ways:

  • Using SSH daemon configuration options
  • Packet filter
  • Special Applications
  • Port knocking

The simplest and effective way- this is to change the default port 22, for example, to 2002, if this does not interfere with other tasks. We make an entry in /etc/ssh/sshd_config:

After this, attempts to guess passwords practically stop. There are times when you cannot change the port. Alternatively, you can restrict SSH access to certain users (in particular, root) or a group. In sshd_config a number of parameters are responsible for this: AllowUsers, AllowGroups, DenyUsers and DenyGroups. It’s convenient that you can specify an IP or subnet with your login. For example, let's allow access to the user admin and user, the latter from only one IP:

Another effective option for protection against brute force is the use of certificates for authentication. Moreover, using the special match parameter, you can create a conditional block in which to redefine the parameters of the global section. For example, we will prohibit login via SSH using a password for the root user, allowing everyone else:

# Allow everyone access using a password
PasswordAuthentication yes
# root will only use the certificate
match user root
PasswordAuthentication no
KbdInteractiveAuthentication no

Using TCP Wrapper, we can also restrict access to any service only from certain IPs; to do this, you just need to write the required rule in the /etc/hosts.allow or /etc/hosts.deny file. Let's allow access in /etc/hosts.allow only from the required subnet:

sshd:192.168.1.0/24:allow

Or in /etc/hosts.deny:

sshd: ALL: deny
sshd: ALL EXCEPT 192.168.1.0/24: allow

The packet filter allows you to very precisely set connection parameters, discarding unnecessary packets. With its help, it is easy to limit access to port 22 to only certain addresses. Simple example:

iptables -A INPUT -s !192.168.0.1 -p tcp -m tcp --dport 22 ↵
-j REJECT -reject-with icmp-port-unreachable

Filtering packets by ports and IP addresses is not very effective if the Administrator is not tied to a workplace. In this case they will help special utilities: Fail2ban, Sshguard. Fail2ban was originally developed for SSH security. Although today it is already a framework that can be easily customized for any application. The operating principle is very simple. The daemon periodically checks the logs for records of any suspicious activity. The suspicious IP address is then blocked using iptables or TCP Wrapper. After the time specified in the settings, the blocking is usually removed so as not to accidentally block a legitimate node. When a rule is triggered, an event is written to the log /var/log/fail2ban.log, and an email can be sent.

One process can control several services at once, and the package comes with ready-made settings for popular Linux applications. By default, only SSH is protected.

On Ubuntu and Debian it is installed with the command:

$ sudo apt-get install fail2ban

All settings are made in several files located in the /etc/fail2ban directory. fail2ban.conf stores the launch parameters of the daemon itself, jail.conf describes the controlled services (inside the SSH section).

Enabled = true
port = 22
filter = sshd
logpath = /var/log/auth.log
maxretry = 3

Filters and actions are written in files located in the filter.d and action.d subdirectories. By default, all files have the .conf extension; it is better not to touch them (including jail.conf). All changes should be made to a file with the .local extension (for example, jail.local), the parameters of which replace the settings from the first one, and will not be lost during the update. To check the operation of the filter, you can use the fail2ban-regex utility.

Several rules for protecting access to the ssh server.

1. Add to the ssh server configuration to listen to one more port, in addition to the standard one. (For ease of remembering, you can use 4 repeating numbers for all your servers).

$ sudo vi /etc/ssh/sshd_config Port 22 Port xxxx

2. We limit calls to port 22 only to trusted IP addresses *for example 8.8.8.8 (you can create several such rules, work/home)

$ sudo vi /etc/sysconfig/iptables -A INPUT -s 8.8.8.8 -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT

3. Don’t forget to check if we are using ipv6; if so, then close the unnecessary one

$ sudo vi /etc/sysconfig/ip6tables *filter:INPUT ACCEPT :FORWARD ACCEPT :OUTPUT ACCEPT -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT -A INPUT -p ipv6-icmp -j ACCEPT -A INPUT - i lo -j ACCEPT -A INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT -A INPUT -m state --state NEW -m tcp -p tcp --dport 443 -j ACCEPT -A INPUT -j REJECT --reject-with icmp6-adm-prohibited -A FORWARD -j REJECT --reject-with icmp6-adm-prohibited COMMIT

In order to use ssh only on a specific address, it is enough in the configuration file sshd_config specify the parameter ListenAddress(for example ListenAddress 74.125.200.100). In this case, ssh will only be available on this address and will not work via ipv6

4. Use the ssh configuration file on the client side.

Location: ~/.ssh/config

# fix Write failed: broken pipe ServerAliveInterval 120 TCPKeepAlive no # to use short names Host dev-vps # ip address or public Domain name host Hostname 127.0.0.3 # Under which user to log in User developer # Key file for authorization (if used) IdentityFile ~/.ssh/id_rsa.dev

And another example of using a configuration file:
{<1>}

Host ssh-server-1 Hostname 1.2.3.4 User dev Port 1234 Host ssh-server-2 User root # Hostname 192.168.10.20 # nc without -q0 if RHEL based & with -q0 debian based IdentityFile ~/.ssh/id_rsa.work -pc ProxyCommand ssh -q0 ssh-server-1 nc -q0 192.168.10.20 22

And now, when connecting to ssh-server-1, we will immediately jump to the host we need. (Convenient to use, for example, with different keys on servers)

And hipster proxy option:

{<2>}

Download the ngrok client to the server, which is located behind the firewall. We launch the binary and indicate which port we need to forward

SSH allows you to create a secure connection to a server, but the SSH service itself must have Internet access to work properly. This creates an attack vector for potential attackers, hence SSH needs additional protection.

In general, any service with network access is a potential target. In the logs of these services, you may notice repeated, systematic login attempts - these are brute force attacks carried out by users and bots.

The fail2ban service can mitigate attacks using rules that automatically change the iptables firewall configuration based on a predefined number of unsuccessful attempts login. This will allow the server to promptly respond to unauthorized access without administrator intervention.

This guide will help you install and configure fail2ban on an Ubuntu 14.04 server.

Installation of fail2ban

The Ubuntu repository provides the fail2ban package, so it can be installed using a standard package manager.

Update your package index and install fail2ban using these commands:

sudo apt-get update
sudo apt-get install fail2ban

Now you can start setting up the utility.

fail2ban configurations

The fail2ban configuration files are stored in the /etc/fail2ban directory. The default settings can be found in the jail.conf file.

Because this file can be changed during a package update, there is no need to edit it. It is better to copy its contents to another file and adjust the parameters there. To ensure that these two files work correctly, it is best to leave only those settings in the new file that you want to override in the jail.local file. All default settings will be read from the jail.conf file.

Copy jail.conf and use it as the basis for the jail.local file. To do this, enter:

awk "( printf "# "; print; )" /etc/fail2ban/jail.conf | sudo tee /etc/fail2ban/jail.local

After that, look at jail.conf:

sudo nano /etc/fail2ban/jail.conf

Some parameters can be updated in this file. The partition settings will apply to all services that fail2ban supports (unless these values ​​are overridden in configuration files these services).


. . .
ignoreip = 127.0.0.1/8
. . .

The ignoreip parameter configures the source addresses that fail2ban will ignore. By default, it allows any traffic coming from the local machine. You can add other addresses to ignore by placing them at the end of the ignoreip directive, separated by a space.


. . .
bantime = 600
. . .

The bantime parameter sets the time during which a client will be blocked if it fails authentication. Its value is measured in seconds. The default value is 600 seconds (10 minutes).


. . .
findtime = 600
maxretry = 3
. . .

The next two parameters to pay attention to are findtime and maxretry. Together they define the conditions under which illegal users will be blocked.

The maxretry variable specifies the number of login attempts, and findtime specifies the time interval within which the user must authenticate. If a client exceeds any of these indicators, he will be blocked. By default, the fail2ban service blocks clients that fail to provide credentials 3 times within 10 minutes.


. . .
destemail = root@localhost
sendername = Fail2Ban
mta = sendmail
. . .

The parameters destemail, sendername and mta allow you to configure email alerts. The destemail parameter specifies the address Email, which should receive messages about blocked users. The sendername parameter specifies the sender of the message. The mta parameter determines which Post service will be used to send mail. Add these parameters to the jail.local section and set the appropriate values.


. . .
action = $(action_)s
. . .

This setting configures what fail2ban will do in the event of a ban. The action_ value is defined in the file a little before this parameter. The default action will block the attacker's traffic until the ban expires by reconfiguring the firewall.

If you want to configure email alerts, add or uncomment an action element to the jail.local file and change its value from action_ to action_mw. If you want the email to include the corresponding lines from the logs, you can specify the action_mwl value. If you decide to use email alerts, make sure your email settings support them.

Individual parameters

Support for individual services is included in special sections of the same name. For example, the parameters of the ssh service can be specified in the section.

Each of these sections can be enabled by uncommenting the section header in jail.local and changing the enabled line to "true":


. . .
enabled = true
. . .

By default, only the SSH service is supported, and all other services are disabled.

These sections use the values ​​set in the section as a basis and adjust them as necessary. To override any values, add a section for the appropriate service to jail.local and change its values.

Some other parameters are also set here. The filter parameter helps determine whether a line in the log indicates a failed authentication attempt; The logpath parameter tells fail2ban where the logs for that particular service are located.

The value of the filter parameter is a link to a file with a .conf extension located in the /etc/fail2ban/filter.d directory. These files contain regular expressions, which determine whether the line in the log is a message about a failed authentication attempt. These files are beyond the scope of this tutorial because they are quite complex and the default settings are fine in most cases.

You can view filters in this directory:

ls /etc/fail2ban/filter.d

Find the file associated with the required service and open it with text editor. Most of the files are quite well commented, and you can familiarize yourself with the service protection script. Most of these filters have corresponding sections in the jail.conf file (they are disabled by default). They can be enabled in the jail.local file if necessary.

Let's say you have a website that is served using Nginx. The web server logs are constantly updated with failed login attempts. The fail2ban utility can use the nginx-http-auth.conf file to constantly check /var/log/nginx/error.log.

Almost all the parameters needed for this are already in the section in the /etc/fail2ban/jail.conf file. You just need to uncomment this section in the jail.local file and set the enabled parameter to true.

. . .
enabled = true
. . .

After this you need to restart fail2ban.

Setting up fail2ban

Now you know the basics of how fail2ban works. Try setting up an automatic blocking policy for the SSH and Nginx service. You also need the fail2ban tool to send an email if an IP address is blocked.

To get started, install the necessary software.

You will need nginx, since fail2ban will monitor its logs, and sendmail to send notifications. You also need the iptables-persistent package so that the server saves and automatically loads firewall rules when the server boots. All these packages can be downloaded from the standard Ubuntu repositories:

sudo apt-get update
sudo apt-get install nginx sendmail iptables-persistent

Stop the fail2ban service to set up a basic firewall.

Setting up a firewall

The basic firewall must support established connections, as well as traffic generated by the server itself and traffic destined for SSH and web server ports. All other traffic will be blocked. The rules look like this:

sudo iptables -A INPUT -i lo -j ACCEPT
sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
sudo iptables -A INPUT -p tcp -m multiport --dports 80,443 -j ACCEPT
sudo iptables -A INPUT -j DROP

These commands implement the above policy. To view your current firewall rules, type:

sudo iptables -S
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-A INPUT -i lo -j ACCEPT




-A INPUT -j DROP

Save your firewall rules so they won't be lost after a reboot.

sudo dpkg-reconfigure iptables-persistent

Restart fail2ban:

sudo service fail2ban start

Query firewall rules:

sudo iptables -S
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-N fail2ban-ssh

-A INPUT -i lo -j ACCEPT
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
-A INPUT -j DROP
-A fail2ban-ssh -j RETURN

Each chain now has its own default policy. There are also five basic rules in the firewall. The fail2ban structure is highlighted in red: this tool already enforces SSH ban rules. Sometimes this structure is not shown at first, since fail2ban may not add the structure until the first ban.

Setting up fail2ban

Now you need to add the fail2ban settings to the jail.local file:

sudo nano /etc/fail2ban/jail.local

Here you can set a more strict blocking time interval. Find and uncomment the title. In this section, change the bantime parameter so that the service blocks the client for half an hour:


. . .
bantime = 1800
. . .

You also need to set up notifications. First, find the destemail parameter, which should also be in the section. Enter the email address you want to use to collect these messages:


. . .
destemail = [email protected]
. . .

In sendername, specify any convenient value. It is recommended to use a descriptive value here that the email service can easily filter out.

Then you need to correct the value of action. You can set action_mw to block the client and then send a "whois" report. The action_mwl value does the same thing, but also sends the corresponding log lines in the message.


. . .
action = %(action_mwl)s
. . .

In the SSH section of the maxretry directive, you can change the number of failed authentication attempts. If you are using non-standard port(not 22), specify it in the port parameter. As stated earlier, this server is already enabled.

Then find the nginx-http-auth section. Uncomment the header and change the enabled parameter to “true”.

. . .

enabled = true
. . .

That's all you need to do in this section if the web server uses standard ports and its logs are stored in a standard directory.

Restart fail2ban

Save and close the file.

Then restart the fail2ban service. Sometimes it's even better to stop it and then start it again.

sudo service fail2ban stop
sudo service fail2ban start

It may take a few minutes for all the firewall rules to download. Sometimes rules are not added until the first client is blocked. After a while you will be able to check the new rules:

sudo iptables -S
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-N fail2ban-nginx-http-auth

-N fail2ban-ssh

-A INPUT -p tcp -m multiport --dports 80,443 -j fail2ban-nginx-http-auth


-A INPUT -p tcp -m multiport --dports 22 -j fail2ban-ssh

-A INPUT -i lo -j ACCEPT
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
-A INPUT -j DROP
-A fail2ban-nginx-http-auth -j RETURN

-A fail2ban-ssh -j RETURN

Lines created by the fail2ban policy are highlighted in red. Right now they simply route traffic to new, mostly empty chains, and then pass the flow of traffic back to the INPUT chain.

Blocking rules will be added to these chains.

Testing the blocking policy

Now you can test the rules by connecting from another server that does not have credentials on the fail2ban server.

Try creating an SSH connection to the server using non-existent credentials:

ssh blah@fail2ban_server_IP

Enter a random set of characters as your password. Repeat several times. At some point, fail2ban will deny access and display a “Permission denied” message.

Return to the first server and view the new iptables rules:

sudo iptables -S
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-N fail2ban-nginx-http-auth
-N fail2ban-ssh
-A INPUT -p tcp -m multiport --dports 80,443 -j fail2ban-nginx-http-auth
-A INPUT -p tcp -m multiport --dports 22 -j fail2ban-ssh
-A INPUT -i lo -j ACCEPT
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
-A INPUT -j DROP
-A fail2ban-nginx-http-auth -j RETURN
-A fail2ban-ssh -s 203.0.113.14/32 -j REJECT --reject-with icmp-port-unreachable
-A fail2ban-ssh -j RETURN

The new rule is highlighted in red. It blocks traffic from the second server's IP address to the SSH port. You will soon receive a notification that the client has been blocked.

Conclusion

Now you are familiar with the basics of fail2ban and can create a basic configuration for this tool.

In this article we will look at the basic method of protecting SSH from mass Bruteforce attacks. In this case, a massive bruteforce attack does not mean targeted password guessing specifically for your SSH, but an extensive capture of a range of servers for subsequent identification of login-password pairs that are not resistant to guessing.

The main features of a massive SSH bruteforce attack are extensive scanning of IP ranges on open port 22 and use as username and password, often used (for example, root:passwd123, admin:server123, etc.).

To view statistics from the log files of unsuccessful SSH authorization attempts on your server, enter the command:

Cat /var/log/secure* | grep "Failed password" | grep sshd | awk "(print $1,$2)" | sort -k 1,1M -k 2n | uniq -c

This screenshot provides statistics on the number of failed authorizations by day. If you steal similar data, you should take steps to protect your SSH from massive bruteforce.

1. If you don't use for authorization, frequently used usernames such as root, admin, administrator, user, etc. and use a complex password for authorization, then you can immediately proceed to the second point. To change the password to a more complex one, enter the command:

Passwd #your_login#

Where #your_login#— Your username.
When entering a new password, the password is not displayed, the cursor will remain in one place.

Let's log into the server via SSH, create a new user and give him a password, to do this we enter the commands:

Adduser #newuser# passwd #newuser#

Where #newuser#— Your new username, do not use frequently used ones as a username, a good option your_nameadmin(for example, foxadmin, useralex, rootidler).

2. After that, log in via SSH with a new username and password. And open the SSH daemon configuration (sshd_config) with the command:

Vi /etc/ssh/sshd_config

After which you should see something like this:

Lines starting with # are commented out.

To protect SSH from massive bruteforce, uncomment and change, or add following parameters file:
a) port- the port on which SSHD accepts and services connections. Uncomment (delete before the start of the line # ) and change the default value 22 , to any other from 1024 to 65536, except for reserved ones - a list of reserved ports, for example:

Port 2022

To delete # and change the value port 22, press first on your keyboard i, after editing required line press the key ESC

b) LoginGraceTime— waiting time for user registration in the system. If the user fails to log in within the time allotted by this directive, the session is terminated. Let's reduce this value:

LoginGraceTime 1m

c) PermitRootLogin- allow user root login via SSH protocol. Let's change to no.

PermitRootLogin no

d) AllowUsers— usernames allowed for logging in via SSH protocol, separated by a space. Here, instead of #your_login#, we indicate the new created username.

AllowUsers #your_login#

e) MaxAuthTries— number of login attempts per session. When the maximum allowed number of attempts is reached, the session is terminated.

MaxAuthTries 2

As a result we get:

Port 2022 LoginGraceTime 1m PermitRootLogin no AllowUsers #your_login# MaxAuthTries 2

In this article we will complete the setup SSH for protection against mass brute force. After editing , press on the keyboard : , a line appears below and then enter in it wq and press the key Enter. In this case, all changes made will be saved.

If you did something wrong (for example, accidentally deleted something), to exit without saving use instead of keyboard shortcut wq, keys q!

After completing the SSH setup, restart the daemon with the command:

Service sshd restart

Now when connecting via SSH, use the new port 2022 (or the one you specified in the settings) instead standard port 22.

In the next article on setting up SSH, I would like to tell you that we will prohibit password authentication and allow authorization only using a private SSH key, thereby protecting ourselves as much as possible from password guessing.

In contact with