Categories

Using Knockd to increase Linux security

Problem:

A number of Linux servers require remote ssh access but not all need allow anyone to access or attempt to access them. One of my larger pet peeves is dealing with the shear amount of bandwidth that is lost by unauthorized access attempts to the Linux servers I admin. Simply setting a server to face the Internet and keeping it running is work enough. Within hours, and sometimes minutes, the host is port scanned, nmapped, and subjected to dictionary attacks. Most of the attacks are foreign sources while the server itself is most often serving only a much smaller subset of countries.

Making sure that all of the security layers are in place is critical to success. After all of the patches are in place, I usually install and configure snort, bastille, tripwire, and make sure the iptables based firewall is dug in firmly. The firewall is usually configured to deny access by country IP codes, and always includes iptable rules to limit the number of ssh connections from any IP source in a very closely defined range of seconds. Any connection that violates the rules is dropped and logged.

All is well and good, except that port 22 is still open for authorized access. Consequently the host is hammered daily, and some attacks limit the bandwidth for legitimate traffic.

Solution:

Use knockd to hide the server and require a specific sequence of tcp or udp “port knocks” before opening the port for access. The process is basically a key in the possession of a legitimate user that further identifies legitimate use of the server.

Knockd listens at the link layer of the OSI model and will see packets to the host NIC even if the firewall is set to block the port. When the correct sequence of port knocks is received, knockd issues a new iptable rule to the firewall set of rules to open the designated port. What I really like is that it can be configured for any port. Even port 80 can be controlled to allow web page views only for those persons with the correct key.

Install knockd on the Linux sever:

# sudo apt-get install knockd

The following steps will assume physical console access to the host. If you are adding this feature remotely, it is best to configure knockd first before making any changes to the iptables configuration. It would not be good to do the installation, and then lock yourself out of the machine. Explain that one to the boss.

The first step is to make sure, if the host is behind a router, that the ports that will be used by knockd are forwarded to the server. Secondly, forward the ssh port 22 to the server. Obviously, this could be any port number if your host’s default ssh port is not 22. For our purposes here, we will assume port 22.

The next step is to insert an iptable rule to deny all connections to port 22. As root enter the command:

# /sbin/iptables -I INPUT 1 -p tcp –dport ssh -j REJECT

The same must be done for each of the ports that will be used in the key. Some examples that I have seen will define a range of ports to block. This method’s usefulness will become apparent if you decide to use one time usage port combinations.

# /sbin/iptables -I INPUT 1 -p tcp –sport 10000:20000 -j REJECT

For our purposes here we shall assume that the same key will be used for each login. Thus, my preference is to hard code the ports that will be used using the above line of code but substituting a single port (e.g. –sport 6911 -j REJECT) for each port to used in the sequence. Typically, I configure the firewall to reject everything and then specify what ports will be open based on the services provided by the server. (Always verify your configuration using nmap, and test each service).

Now the /etc/knockd.config file must be edited. The following is a basic configuration file. Knockd does have more advanced options, but this one will illustrate its usefulness easily. Notice the sections named “openSSH” and “closeSSH” and the sequence line. Here I have added port1. . . port6. In actual use, these port will be the actual numbers that you will be using. For example, we could use the numbers 10012, 7230, and 8119 for the open sequence, and a different set of port numbers to close the port.

[options]

UseSyslog

[openSSH]

sequence = port1, port2, port3

seq_timeout = 5

command = /sbin/iptables -A INPUT -s %IP% -p tcp –dport 22 -j ACCEPT

tcpflags = syn

[closeSSH]

sequence = port4, port5, port6

seq_timeout = 5

command = /sbin/iptables -D INPUT -s %IP% -p tcp –dport 22 -j ACCEPT

tcpflags = syn

Edit the sequence line as desired. More ports will offer greater security, but lets not go overboard.

The command line in each section shows the iptables command that knockd will issue if the correct sequence of knocks is received within the 5 second limit defined by the line “seq_timeout”. You may be thinking it is a bit cumbersome to type in the commands each time access is needed, but have no fear, Linux rule number one applies here.

If you are going to have to do something more than twice, write a script. We are not lazy, contrary to the opinions of some, simply efficient.

When the correct sequence is issued, the iptables rules set is modified to allow port 22 connections from the IP address of the host that issued the knocks. The user can now log in normally to the server, but the port remains closed for any other host with a different IP address.

The closeSSH section is important. Although the original user IP address is specifically used to modify the firewall, disconnecting from the session effectively leaves the port open, but only connections using the same IP address will be allowed to log in. The closeSSH section further defines the port sequence that will again cause knockd to modify and close the port at the firewall. It essentially deletes the previously created rule, which is why the initial iptables rule set was put in place prior to using this application. First we block all access, then modify the rules to temporarily allow access by a specific IP address to port 22. Then the user is finished we remove the iptables rule that modified the original set, thereby closing the port.

Again, knockd has other configuration options that can be utilized. One option will automatically close the port after a predetermined time period. It is useful to accommodate a users forgetfulness, a script writers failure to add the close sequence, or a simple loss of connection that cannot be restored.

To open the port we need a script to “automate” the process. I use variations of one shown below. In some cases a default script is simply called from other scripts to open and close the port. Other uses have added the sequence as a function to a particular script or bash program to accomplish the same result.

In essence, the script must contain a knock command the IP address, or domain name, of the server you are attempting to access. Each port number must be called in the order that was defined in /etc/knockd.config and in our case, three such ports were defined.

## Start knockd daemon

sudo /etc/init.d/knockd start

## Initiate knock sequence

echo “Knocking…”

knock <Domain or IP> <port number>

knock <Domain or IP> <port number>

knock <Domain or IP> <port number>

After this script is run, the port is opened and the user simply logs in using standard user name and password combinations. Alternatively, commands to use rsysnc could be added to the script and a series of command sent to the server. Personally, I have used this method to do a number or repetitious tasks, including, but not limited to, remote backups.

To close the port, the /etc/knockd.config contains a port number sequence that it must see before it will modify the firewall configuration. In some cases I have simply used the identical script and sequence, but in other’s the sequence will be the reverse, or completely different from the opening sequence. Obviously, using the more advance configuration of setting a time period to automatically close the port would probably be a better choice. I like to have more control and prefer to issue the command to close the port.

Knockd has proven valuable in many ways. The server load is reduced, and it does not respond to port scans. I have greater control over who is able to access the server. Because it is more difficult to determine if a host is on the other end of the IP address, and because the usual returns are not noted by the attacker, my life as an admin on a Linux network is made easier.

You must be logged in to post a comment.