Besides changing the default port for SSH, and using a key pair for authentication, port knocking can be used to further secure (or more accurately, obscure) your SSH server. It works by refusing connections to your SSH network port. This essentially hides the fact that you're running an SSH server until a sequence of connection attempts are made to predefined ports. Very secure and simple to implement, port knocking is one of the best ways to protect your server from malicious SSH connection attempts.
A Vultr server running Ubuntu 18.04.
Before following the steps below, if you're not logged in as the root user, please obtain a temporary root shell by running
sudo -i and entering your password. Alternatively, you may prepend
sudo to the commands shown in this article.
Knockd is the package that is used in combination with iptables to implement port knocking on your server. The '
iptables-persistent' package is also required.
apt update apt install -y knockd iptables-persistent
Run the following commands in order:
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT iptables -A INPUT -p tcp --destination-port 22 -j DROP iptables-save > /etc/iptables/rules.v4
These commands will do the following, respectively:
Instruct iptables to keep existing connections alive.
Instruct iptables to drop any connection to port tcp/22 (if your SSH daemon is listening on a port other than 22, you should modify the above command accordingly.)
Save these two rules so they will persist after a reboot.
Using a text editor of your choice, open the file
You will see the following:
[openSSH] sequence = 7000,8000,9000 seq_timeout = 5 command = /sbin/iptables -A INPUT -s %IP% -p tcp --dport 22 -j ACCEPT tcpflags = syn
You should change the sequence of ports (choose port numbers above
1024 and unused by other services), and store it safely. This combination should be treated like a password. If forgotten, you will lose access to SSH. We will be referring to this new sequence as
seq-timeout line is the number of seconds Knockd will wait for the client to complete the port-knocking sequence. It would be a good idea to change this to something larger, especially if the port-knocking will be done manually. However, a smaller timeout value is safer. Changing it to
15 is recommended since we'll be knocking manually in this tutorial.
Change the opening sequence to you chosen ports:
[openSSH] sequence = x,y,z
Change the command value to the following:
command = /sbin/iptables -I INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
Now change the closing sequence accordingly:
[closeSSH] sequence = z,y,x
Save your changes and exit, and open the file
Add the following line to the end of the file:
KNOCKD_OPTS="-i ens3" (replace
ens3 with the name of your public network interface if it differs.)
Save and exit.
Now start Knockd:
systemctl start knockd
If you now disconnect from your server, you'll have to knock on ports
z to connect again.
You now will not be able to connect to your SSH server.
You can test port knocking with a telnet client.
Windows users can launch telnet from the command prompt. If telnet isn't installed, access the "Programs" section of Control Panel, then locate "Turn Windows features on or off". On the features panel, locate "Telnet Client" and enable it.
In your terminal/command prompt type the following:
telnet youripaddress x telnet youripaddress y telnet youripaddress z
Do this all in fifteen seconds, as that's the limit imposed in the configuration. Now, attempt to connect to your server via SSH. It will be accessible.
To close access the SSH server, run the commands in reverse order.
telnet youripaddress z telnet youripaddress y telnet youripaddress z
The best part about using port knocking is that if it is configured alongside of private key authentication, there's virtually no chance that someone else could get in unless someone knew your port-knocking sequence and had your private key.