by Federico Kereki | Published August 31, 2010
If you require remote access to your computer and you enable Secure Shell (SSH) connections, you must accept that you will automatically attract hackers who will try to break your defenses and take command of your machine. Although there’s no guarantee that your machine won’t be “0wn3d” by a “h4x0r,” a few simple solutions can help reinforce your SSH door and make life a bit more difficult for anybody trying to break in. This article considers three such techniques:
To apply these techniques, you need to access the root account. Also, you’ll probably have to install some packages, and you’ll need to configure your firewall and your router—if you have one—to open and close specific ports and forward them to your machine.
The concept “security through obscurity” is well known—and well derided—because doing things in an obscure way, hoping that no one will get wise to your method, is just asking for problems. However, in some contexts, a bit of obscurity can help. Although simple measures cannot stop determined hackers, at least you can be better defended against “script kiddies”, whose scripts usually aren’t that thorough.
Everybody knows that the standard port for SSH connections is 22. So, the first step you should take to make your machine more secure is simply to change the port to another unused and nonstandard port number—say, 22960. Numbers above 1024 are usually safe, but check the references to avoid possible problems. This change simply means that you have to use this command line to connect to your computer:
ssh ‑p 22960 your.machine.url
To effect this bit of subterfuge, make a simple change in the /etc/ssh/sshd_config file. Edit it (you must work as root for this), look for the line that reads Port 22, and change the number to whatever you have chosen (If the line is commented out because it starts with a pound sign [#], remember to uncomment it). Save the file, and restart SSH with the command /etc/init.d/sshd restart. You should also open the chosen port in your firewall and close port 22.
But you can do even more. Fiddle with the configuration file so that it includes the lines shown in Listing 1. Note that some of these lines may already exist, but they could be commented out.
The LoginGraceTime allows 30 seconds for a login; if the user takes longer than this, he or she won’t be allowed access and will have to relog. MaxAuthTries limits the user to three wrong attempts before the login attempt is denied. The Protocol 2 line avoids using a somewhat weaker protocol. Finally, the last line doesn’t allow anybody to log in as root, making life a bit more difficult for hackers. You could also use the DenyUsers, AllowUsers, DenyGroups, and AllowGroups options for extra restrictions. These changes don’t substantially add to the security of your machine, but a common script that just tries brute force attacks at the standard port 22 will fail harmlessly. In any case, consider this a first step in the right direction. Further along in the article, you’ll use even safer methods to not only change the port number but to completely hide it.
For most people, PAM is a cooking oil that comes from a can. But in terms of Linux® security, PAM stands for Pluggable Authentication Modules. These modules provide extra authentication rules to harden access to your machine.
Let’s start with a basic question: Why use PAM at all? If every program had to define its own authentication logic, it would be a mess. How could anybody be certain that all applications implemented the same tests and checks? What would you do if extra controls were needed—reprogram everything? In computer science, it’s sometimes said that everything can be solved with an extra layer, and at least for security, that stands true. If a program needs to authenticate a user, it can call the PAM API. The API will take care of running all the checks that you might have specified in the PAM configuration files. This method even allows you to modify the authentication rules on the fly, because all PAM-aware programs start applying the new rules without the need for any changes in their code. If you want to use some biometric checks (such as iris scanners or fingerprint readers) and the manufacturer provides you with a PAM, you’re set. When you include the module call in the configuration files, your device will be available to all your applications.
PAM provides four distinct security areas, though it isn’t likely that your applications will require all of them. For example, the passwd command only requires the third group in the list below:
You will have to create a configuration file in the /etc/pam.d directory for each application that will use PAM, and the name of the file will be the same as the application’s name. For example, the configuration file for the login command would be /etc/pam.d/login.
You have to define which modules will be applied, creating a “stack” of actions. PAM runs through all the modules in the appropriate stack and, depending on their results, grants or denies the user’s request. You must also define whether or not checks are mandatory. Finally, an other file provides default rules for any application without specific rules.
The structure of the configuration files is simple. You can include comments, which start with a hash character (#); continue long lines by ending them with a backslash (\). Lines have three fields: the area (account, auth, password, or session), the control flag (optional, required, requisite, or sufficient), the path to the module that will be run, and any possible parameters. Note that the second field can be more complicated; see Resources on the right for more information. Also, you can use include rules, as in auth include common-account, to include rules from other files.
auth include common-account
The special /etc/pam.d/other file is a “default” configuration file (see Listing 2) whose rules are automatically applied to applications without specific configuration files of their own. To be safe, give the /etc/pam.d file a quick review and just rename all configuration files that you don’t use (so that the other configuration will be used). If you decide you actually need the application, just rename the configuration file to its original name. The default configuration usually denies all requirements (by using the pam_deny.so module) and warns the administrator (via the pam_warn.so module) so that he or she can fix the situation.
The standard “other” configuration file provides a secure default (which denies everything) for all applications without a configuration file of their own.
account required pam_deny.so
auth required pam_deny.so
auth required pam_warn.so
password required pam_deny.so
password required pam_warn.so
session required pam_deny.so
If you replace pam_deny.so with pam_unix.so, the standard authentication method (enter a user name and password) will be applied. Likewise, if you do not care about security, use pam_permit.so instead, which happily allows any request!
Although there is no standard list of modules, all distributions include most of the following options. Check the /lib/security or /usr/lib/security directories, where modules reside. For 64-bit operating systems, substitute lib64 for lib. If you need more information, you can try man the.name.of.the.module, but do not attempt to execute it directly; PAMs are not executable binaries.
auth sufficient pam_rootok.so
auth required pam_wheel.so
Check the resources on the right section for information on more modules and even on writing your own modules. Now, turn to using PAM so that you can decide who can log in to your machine.
Now, let’s use PAM to restrict who is going to be allowed to connect to your server. You must edit the /etc/pam.d/sshd file so that it reads like Listing 3.
account include common‑account
account required pam_access.so
auth include common‑auth
auth required pam_nologin.so
password include common‑password
session include common‑session
Adding pam_access.so to the sshd PAM file lets you easily define who can use SSH to connect to your machine. The pam_access.so module implements security controls based on the /etc/security/access.conf file, as shown in Listing 4.
+ : ALL : 192.168.1.
+ : jack : ALL
+ : jill : ALL
‑ : ALL : ALL
The first line enables everybody (ALL) to log in from within the internal network. The next two lines allow users jack and jill to access the server from any location. The last line is a “catch-all” and denies everybody else access from every other address. Another way of enabling several users access is to use pam_listfile.so, creating a list of approved users (for example, /etc/ssh_users). Add the following line to the /etc/pam.d/sshd file:
auth required pam_listfile.so item=user sense=allow
You’re not done yet. You have to modify the /etc/ssh/sshd_config file more so that it uses PAM. Add a UsePAM yes line to the file, restart the sshd daemon, and that’s all!
Even if you have applied the methods in both previous sections, you must assume that hackers will try to get through any open doors in your system, no matter your precautions. Changing the SSH port number is just a small bother to a knowledgeable would-be intruder, and the limitations placed on users also help (provided no user falls prey to a hacking or social engineering attack that reveals his or her password). However, the mere fact that there’s a door to your system is enough to tempt hackers.
The last scheme for adding security to your machine is the boldest one. You will close the open port making your machine virtually impregnable to any attack. Open it only to a user who can provide a “secret knock”, that opens the required port so that he or she can enter his password and gain access to the machine.
This technique, called port knocking, is appropriate for users who require access to servers that aren’t available to the public. The server can keep all of its ports closed until the user has provided a secret knock sequence (a sequence is easy to implement and requires modest resources).
When the secret ports are open, the usual security mechanisms (such as passwords or certificates) will apply. All services that require the secret ports will function correctly with an extra security layer provided at the firewall level.
The point of this method is to close all ports and monitor external attempts to make connection. Whenever a predefined and specific sequence of attempts is recognized (called a knock sequence), you can execute actions like opening a port so the outsider can get in. The knock sequence can be as complex as you wish—from a simple list (such as trying TCP port 7000; UDP port 7100; TCP port 7200) to a collection of use-once-only sequences. (In cryptography terms, this concept is similar to “one-time pads”, the most secure encryption method known.) The outsider must know the port number and the password to use SSH, as well as the knock sequence required to open that port and enable the password. Without the sequence, connection attempts just mutely fail.
Why is this a good safety scheme? There are 65,535 possible ports (see resources on the right side for more information). Even if you consider the ports already assigned, you’re still left with over 60,000 available ports. If you settle on a sequence just four “knocks” long, a hacker trying to guess it by brute force would have to test about 13 million million million possible sequences (that’s 13 followed by 18 zeros). It should be obvious that such an attack isn’t likely to work! Of course, never assume that brute force or blind luck are the only possible ways to guess the correct sequence. That’s the reason you’re not using a single security method; instead, you have a series of security layers making life more complex for hackers.
You have to install the knockd knocking daemon; it monitors the knock sequences and acts on detecting a valid one. If you wish, you can build it from source, but as this package is available in most (if not all) distributions. You’ll do better using your package-management tool. For example, in OpenSUSE, you could install it with Yast2 or by executing sudo zypper install knockd. In Ubuntu, you could similarly use sudo apt-get install knockd and in Debian use sudo aptitude install knockd. Just search for knockd with your distribution’s software-installation tool, and you’ll be set.
sudo zypper install knockd
sudo apt-get install knockd
sudo aptitude install knockd
After installing the package, you must edit the /etc/knockd.conf file to specify your port-knocking rules, and then you’ll have to start your daemon running. You must know how your firewall works to do the required setup. For example, in OpenSUSE, you could use something like the setup shown in Listing 5.
start_command= /usr/sbin/iptables ‑s %IP% ‑I input_ext 1 ‑p tcp ‑‑dport 22960 ‑j ACCEPT
stop_command= /usr/sbin/iptables ‑s %IP% ‑D input_ext ‑p tcp ‑‑dport 22960 ‑j ACCEPT
The above sample enables SSH access after successive knocks on ports 7000, 8000, and 9000, respectively.
Before starting knockd, close port 22960 and try to log in remotely. The attempt should fail, as shown below in Listing 6.
> ssh the.url.for.your.site ‑p 22960 ‑o ConnectTimeout=15
ssh: connect to host the.url.for.your.site port 22960: Connection timed out
Now try that again after starting the port-knocking daemon by using sudo /etc/init.d/knockd start or sudo knockd -d; the commands are equivalent. The port-opening sequence requires knocking at ports 7000, 8000, and 9000. You have 15 seconds to accomplish this sequence. The port opens after recognition, and you have 30 seconds to log in. Otherwise, the port will close again.
sudo /etc/init.d/knockd start
sudo knockd -d
To verify this process, go back to your remote machine and log in. This time provide the required knocks, as shown in Listing 7. Note that the knock command is usually installed when you get knockd. Otherwise, just use your distribution’s package-management tool and look for it.
> knock the.url.for.your.site 7000
> knock the.url.for.your.site 8000
> knock the.url.for.your.site 9000
> ssh the.url.for.your.site ‑p 22960 ‑o ConnectTimeout=10
If you provided a wrong sequence of knocks (or no knocks at all), you would receive a “Connection timed out” message, and the SSH port would remain completely closed with no sign of its existence.
If your server is connected to the Internet through a router, you’ll have to change its configuration a bit. Details vary among different routers and firewalls, but in general terms, you should:
Although the router will have some ports open, all access to them will lead to your machine’s firewall. Access will be blocked unless, obviously, a correct port knock sequence is detected.
The /etc/knockd.conf file has a general options section, options, and a section for each knock sequence you want to use. You can write options in uppercase, lowercase, or mixed case.
You can have knockd listen for several sequences and react in different ways to each one. In the earlier example, you had knockd open the SSH port; you could just as easily have enabled the HTTP port so a web server is accessible or run a specific process. You will have a section in the configuration file for each sequence.
Use any text editor to create the file; it should have a sequence (in the format shown above) in each line. You should have a copy of this file on your remote machine to remember how to log in.
/usr/sbin/iptables ‑s %IP% ‑I input_ext 1 ‑p tcp ‑‑dport 22960 ‑j ACCEPT
In this case, because you just wanted to open or close port 22960, a single command sufficed. If your needs are more complicated, you can invoke a script and do whatever you want—even if it doesn’t involve opening ports at all. You could trigger any action, such as running a process or performing a backup. Of course, learning what command to use can be tricky. For example, because I was running OpenSUSE and it provides its own firewall front end, I had to examine the output of iptables -l to learn what command I should provide to open or close port 22960.
As to knockd itself, there are few options to consider:
Finally, to produce the knock sequence itself, you could use many methods, but programming knock is the simplest way to go about it.
knock the.url.for.your.site 7000
for knocking TCP port 7000 and either:
knock the.url.for.your.site ‑u 8000
knock the.url.for.your.site 8000:udp
for knocking UDP port 8000. The -h parameter provides some help for this command.
You’ve seen three ways of hardening SSH access to your machine: modification of sshd configuration parameters, selecting which users can log in by means of PAM, and use of port-knocking sequences to hide the existence of SSH access. Although I mentioned that there is no way to secure fully any machine, adding these three layers will make your server more than just a little safer.
May 2, 2019
Powered by LinuxONE, IBM Cloud Hyper Protect Services provide a proven, hardware-driven cryptography back end to quickly and efficiently encrypt…
Back to top