What is Port knocking and how to configure it in Linux
The basic minimum security that any body can implement on a publicly exposed server is source address based or sometimes called as host based security. It is nothing but to allow your specified hosts or addresses to gain access, and block the rest.
An attacker can even compromise a source address based firewall by spoofing the source ip address (which will make the request appear to the server as one among your allowed source list )
But this situation becomes too difficult to implement if you wish to gain access to your publicly available server from anywhere in the world. The reason is you cant simply go ahead and do a “allow all addresses” to your remote login SSH port.
Opening ports like SSH to all source addresses can make your server victim of a brute force attack. Although such a brute force attack attempt from an attacker can take quite some time to succeed, I have seen such attempts on servers that carry on for several weeks.
In one of the cases I have seen, a monitoring server in one of the architectures I work for, was throwing an SSH alert. The thing that was confusing at first look was that the alerts were not too consistent, in other words it kept on flapping. The main problem was that during the time period of the alert, the server stopped responding to basic ssh connection requests(i was unable to gain access to the server).
Related: How SSH works
Once the alert stopped, I was able to access the server and to my surprise I was able to see a lot of “login failed” attempts from too many random source addresses.
It was quite clear that these requests were created by some automated scripts run by some attacker. And the funny fact was that as soon as you block the source, they changed the source and again the same pattern of requests began. The problem was that the SSH daemon was getting hit by too many requests that it was unable to handle any further legitimate requests.
My only intention of telling the above example is to show the fact that these kind of log in attempts by brute force, is quite common these days. And you always need to go and double check the security measures you have on your architecture.
A secure server is a server without an internet connection. Or a machine locked up physically without a Network interface card. I doubt even that is really secure..
There must be some method, using which we can secure our server to such an extent that no body, or say no source address is allowed to gain access to the login port. You might be thinking, if you go ahead and block all source addresses 0.0.0.0/0, how will you yourself gain access?.
There is one method using which such a security level can be achieved. We will be discussing that in this tutorial. We will first discuss some basics of how this kind of a security will work, and then at the later part of this tutorial, we will see methods to get it configured on a Linux machine.
The security topic that we will discuss in this article is called as "Port Knocking": A method to dynamically open a port at your wish ( which is by default closed for all source addresses, by providing some sort of pattern based authentication )
The name should give an idea of what it really is. Its a method used to send a pattern of requests to a set of closed port, which intern will trigger an event on the server(The event triggered is your required command that will be executed ). That's the simplest definition of Port Knocking i can give you. So the idea behind this security mechanism is nothing but, to provide a pattern to the server which will be a random pattern.
Now as i told earlier, you will have all of your network ports closed on your server. Or to be more precise, you will be having a firewall configured on your server, that will be by default blocking all the requests to all the ports.
All modern day software firewalls are capable of blocking requests based on a lot of parameters. Some of them are network ports, source ports, Type of traffic requests, Source IP address etc. So even if you have your firewall configured to block all requests, the firewall still knows the kind of requests that its getting (That's the reason a firewall is able to block requests based on the parameters configured.)
The range of port numbers begin with 1 and ends with a large number 65535. That is a large number. The firewall knows that a request originated from a source address of 18.104.22.168 to the destination port of 22, and on receiving the request it looks at the rules defined by the user to take an action on the request. So the bottom line is that all requests made to the server is available to the firewall to monitor.
A better method to monitor requests is to analyze the entire network traffic with the help of a packet capturing tool. So the second bottom line is a packet capturing tool also is capable of knowing the request type and kind. So to put a final note to this..
Related: Packet Capturing in Linux
The operating system knows about all the network request's it gets on its interfaces, irrespective of whether a service is running or not, which will answer that request (even if you don't have an SSH daemon running on port 22, the operating system still will come to know if you send a request to port 22). The kernel is configured to trigger an interrupt on receiving each network request. An interrupt is a mechanism used by the kernel to get attention of the CPU to process a request it received.
So the idea behind this security is to send a series of pattern based requests to a number of closed ports (This is the reason it's called knocking..), and another daemon will be monitoring this pattern of requests send, which will trigger an action defined by the user, if the pattern of requests is correct.
To further simplify this, let's take an example of a system engineer who want's to gain remote access through SSH to a remote server. The administrator will have a script/daemon on the server that will monitor the requests the server is getting. Now the system engineer, has previously configured the server to trigger an event, based on a pattern of request. If suppose the pattern that he has configured is to knock the ports 3000,4000,5000.
So now if this system engineer from an arbitrary location sends connection requests to those series of ports in the exact pattern defined (3000,4000,5000), he can trigger the event which he earlier configured on the server. So he can ask the server to open the port 22 for his source address (from which he did the knocking on the ports.)
Isn't it that amazing. Its a good idea, considering the total no of available ports on a server (1-65535). An administrator can configure random port numbers to be used as pattern authentication. However some people might argue that even such a security can be compromised by brute force attempt. But if you imagine a brute force attempt against this kind of a security, an attacker has to first attempt a port combination, then immediately start a port scan to check what was the event that got triggered (or which port is now opened, to confirm a successful break of the pattern). He has to do this for each pattern (first try a pattern and then scan the ports ).
But if the administrator is using a 4 port pattern, the attacker has to go through 65535 to the power of 4 times attempt. Hence brute force also becomes quite a tough task to be carried on a port knocking enabled server. The matter will become more worse if more number of ports are used to make the pattern.
There are few concerns about port knocking, that critics of this security says can be used against. We will be looking into those, at later part of this article.
Don't forget the fact that administrator can close the port, once his task is completed. Closing port is also nothing but another event triggered by the server, when another pattern is sent in the form of port knocking.
Let's see how to configure this Port Knocking in Linux, and then we will discuss some more details and concerns that critics have raised. We will be seeing the configuration of Port Knocking in Ubuntu Linux system. The configuration is pretty much self explanatory and similar in most of the distributions out there.
How to configure Port Knocking in Linux?
A port knocking server package for linux is freely available in ubuntu repository. It can be easily installed with a simple apt-get command. However if you are having any other distribution that has a different package manager, then you need to download that specific version of the package. Other wise its always better to go ahead and install from source. The source package link is given below.
Also you can find a list of RPM based package from the below link.
So let's go ahead and install this Port knocking server on our ubuntu machine.
root@ubuntu-dev:~# apt-get install knockd
The above command will install port knocking package called as "knockd" on your machine. If you carefully see the final output of the apt-get command, you will see something like the below.
* knockd disabled: not starting. To enable it edit /etc/default/knockd
Now the above message indicates that knockd is by default disabled and we need to modify the configs in /etc/default/knockd to start it. We will do that once we have our configuration ready. What we will do is we will first configure a port pattern based authenticaiton.
Now as we have installed the knockd package, we can go ahead and disable all traffic to this server by adding a default firewall rule. This firewall rule will deny all traffic to all ports, including ICMP. In short the server will not respond to any request it gets.
root@ubuntu-dev:~# iptables -P INPUT DROP
As mentioned before, the above iptable rule will drop all incoming traffic, irrespective of the protocol.
Now let's go ahead and edit our knockd configuration file, and at last we will enable knockd service. Knockd configuration is quite simple and straight forward in Linux. It mentions a sequence of port which will be knocked by the client trying to gain access. If the pattern is correct, knockd service will run a command that you have mentioned in the configuration file.
Let's see a sample configuration of knockd, which will add an iptable rule on the firewall which will allow ssh connections to the server, from the source address which was used to knock.
Let's see what is inside this knockd configuration file by default. The file location is /etc/knockd.conf.
[options] UseSyslog [openSSH] sequence = 7000,8000,9000 seq_timeout = 5 command = /sbin/iptables -A INPUT -s %IP% -p tcp --dport 22 -j ACCEPT tcpflags = syn [closeSSH] sequence = 9000,8000,7000 seq_timeout = 5 command = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 22 -j ACCEPT tcpflags = syn
Let's first understand what each of the options and its arguments specify in the configuration file.
Options: This field contains the configuration options to the knockd service. A sample option is given in the default config file shown above. Its telling to use syslog for logging.
You can also specify you own log file if you want to redirect log messages for knockd to another location other than syslog.
This can be done by specifying something like the one shown below.
logfile = /var/log/knockd.log
OpenSSH: Its nothing but simply a name given to a configuration that you need, which will trigger some action based on the knock. This is simply used to seperate different actions based on different knocks made by the client.
Sequence: This is self explanatory in itself. It tells the port sequence in the order of your wish that can be used as a pattern by the client, to trigger the action.
Sequence Timeout: Its the total time alloted to the client to complete the required port knock sequence.
Command: This is nothing but the command that will be executed, if the sequence of ports knocked by the client is correct. This is the place where you add an allow rule, to allow a particular service or port of your interest in the firewall (which by default will block all traffic)
TCP Flags: This is the flag that must be set on the knocks issued by the client. If the knocks with a correct pattern is recieved on the server, but the flag was incorrect, then the action will not trigger.
Of course the administrator who has logged in the server must also be capable of closing the SSH port once he has completed his task. Hence there is another knockd configuration for closing the port. An administrator can log out of the server and send the knockd requests to the series of ports mentioned to close the SSH port which was opened by the previous method.
Hence the client must send the exact tcp flag that the server looks for.
Now let's go ahead and change the configuration with our required port number sequence, and then enable the service. The default configuration, that you find in the knockd configuration works pretty well to enable port knocking for SSH.
I would never recommend taking the port sequence as round figures like 3000, 4000, and 5000. Its always better to take random series of ports which are quite hard to guess. An attacker can easily try attempting the default series of port's like 7000, 8000, 9000. However we will use the ports 3000,4000,5000 only for the sake of simplicity in showing this illustration.
So our final configuration will look something like the below.
[options] UseSyslog [openSSH] sequence = 3000,4000,5000 seq_timeout = 5 command = /sbin/iptables -A INPUT -s %IP% -p tcp --dport 22 -j ACCEPT tcpflags = syn [closeSSH] sequence = 5000,4000,3000 seq_timeout = 5 command = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 22 -j ACCEPT tcpflags = syn
Now let's go ahead and enable the knockd service so that it will start. The /etc/default/knockd file will consist something like the below.
START_KNOCKD=1 # command line options KNOCKD_OPTS="-i eth0"
The above knockd_opts option enables knockd for that specified interface.
Now let's go ahead and start the knockd service as shown below.
root@ubuntu-dev:~# /etc/init.d/knockd start * Starting Port-knock daemon knockd [ OK ]
Now let's test this configuration of our knockd server by sending a pattern request with SYN flag set to port 3000,4000, 5000.
How to send a Port Knocking request to a server?
Port Knocking request can be sent to a remote server in linux, with the client side command line tool that you get while installing knockd. On the client side, you only need to first install knockd as we saw previously (but configuration of course is only required on the server side.)
Once you have successfully installed the knockd package on the client side. You can issue the below command to knock the server with our configured port sequence on the server.
root@localhost:~# knock -v 192.168.0.101 3000 4000 5000 hitting tcp 192.168.0.101:3000 hitting tcp 192.168.0.101:4000 hitting tcp 192.168.0.101:5000
What the above command does is to send three SYN request to the remote server on the ports 3000, then 4000 and then 5000. The order must be same as the order you configured on the server.
Ok now let's try doing a telnet to our server to check if the port 22 is open or not...
root@localhost:~# telnet 192.168.0.101 22 Trying 192.168.0.101... Connected to 192.168.0.101. Escape character is '^]'. SSH-2.0-OpenSSH_5.9p1 Debian-5ubuntu1.1
Wow.... Did you saw that, we are now able to connect to the server. Our server has executed the allow rule for ssh port 22 when we knocked the ports. Now that the port is opened, let's go and check what's inside the syslog file.
You will be able to see the port hits we made from the client, as well as the server executing the iptable rule.
Nov 4 10:31:47 ubuntu-dev knockd: 192.168.0.105: openSSH: Stage 1 Nov 4 10:31:47 ubuntu-dev knockd: 192.168.0.105: openSSH: Stage 2 Nov 4 10:31:47 ubuntu-dev knockd: 192.168.0.105: openSSH: Stage 3 Nov 4 10:31:47 ubuntu-dev knockd: 192.168.0.105: openSSH: OPEN SESAME Nov 4 10:31:47 ubuntu-dev knockd: openSSH: running command: /sbin/iptables -A INPUT -s 192.168.0.105 -p tcp --dport 22 -j ACCEPT
Now the syslog file mentions that the server has received three port hits from the host 192.168.0.105. And as its the correct sequence, it executes the iptables command to open the port only for that host 192.168.0.105
Isn't that wonderful?. Now if you are a system administrator, who wants a secure server that have no ports opened by default, and you need to login from your home, from office from any where in the world, this port knocking with the exact sequence can be used to open ssh port for your source IP.
The main advantage i see in implementing this kind of a security layer is Dynamic white listing of IP addresses.
You can share the sequence of port numbers to trigger a particular white listing/action to be done on the server to your required list of system administrator's. Although it seems like passing credentials for authentication to the required people, it is completely different from traditional form of authentication.
Because the gate is not open for all to enter. In fact the gate is closed for all. This layer of security is an added layer to open the gate to gain access to other methods of authentication provided by a particular application ( Password or Key based for SSH, and webUI password for webui etc.).
Many people consider this kind of a security layer as "security by the method of obscurity". Which means, you are not even letting people to know whether something is running there or not. Although in a way its correct that the kind of security provided by port knocking is obscure to a certain extent, you sometimes need to go ahead and take that extra step to secure your critical server.
A good argument that criticizes the security of port knocking is that, anybody can sniff the packets and find out that a port knocking is being done by detecting the following.
If a series of static SYN request is found in the packet's sniffed, and no reply is being sent to those SYN requests, followed by an SSH traffic, then the attacker can be sure that a port knocking is being carried out.
The attacker can be doubly sure about such a thing, if he finds the ssh port closed on a particular server that he monitories and finds it opened after a series of SYN requests to random ports.
Some main concern's about Port Knocking is mentioned below.
- How will the serve verify whether the person sending the knock packets to the server is in fact the one that is allowed to send. Or in other words there is no method to authenticate client.
- 80 percent of the times, we all are behind some form of a NAT server. We are either behind an ISP NAT or sometimes our offices NAT server firewall. The design is such that the sender should be able to white list his source IP on the server, once he sends the correct series of knocks. But when you are behind the NAT box, the source of the NAT box is white listed, which means other clients who is being NATed with the same box can also gain access.
There are other two relatively less used implementations of port knocking. Using these two methods can achieve a higher level of stealth compared to our previously seen method of port knocking. As discussed before our previously seen method of implementing Port knocking can be detected by an attacker, by doing packet sniffing.
However If you use connection less protocols like UDP, and ICMP to achieve this it will be difficult for an attacker to detect the port knocking action happening. The basic idea behind this is to integrate the knocking inside normal traffic. For example, sending a DNS request with knock details crafted inside. Or sending a ICMP request with username/password and source address details etc.
There are two such implementations available out there. However i did not find any such implementation of port knocking available in the form of a package that can be installed or configured. Kindly please let me know if any of you guys know about the availability of any such package, that can be easily implemented. However being that said, a good programmer can easily take the idea behind this and implement it in his own code.
Let's have an overview and the idea behind such implementations of sending knock requests within an ICMP, or a UDP DNS request. Let's first discuss the second method of crafting knock patterns inside DNS requests and how it works.
A client will send a DNS request with a random domain name on the request, which will contain the source IP , destination IP, and the of course the domain name. A program on the server will monitor the DNS requests received. The program will be configured to map a Domain name to a command. When it finds a domain name which has a command associated with it (which is defined by the user) it executes it (for example, open the port of ssh for the source IP from where the DNS request originated ).
An added advantage behind this idea, is the simplicity to implement. Because the clients executing the knock, does not require a knock program. It can send requests with the help of normal tools like nslookup.
In the second implementation, the server will have a daemon that will look and watch knock information inside ICMP packets it receives.
In this method of using ICMP for knocks, a client first makes a MD5 hash value with the user name, password, time, source address etc. The password sent will be a one time password.
Similar to the DNS method, the added advantage is that it can be achieved with a normal ping command. Also this method helps in achieving a reasonable level of stealth.
Hope this article was helpful in getting a general idea of how port knocking works, and the kind of security it provides...Please let me know your thoughts and comments on this..