OpenSSH port knocking with UFW 2023-10-21 Last edit: 2023-10-21 --------------------- There are quite a few known methods for securing an **OpenSSH** server that you should already be familiar with, such as disabling remote root access, disabling password login or changing the port (22 by default). Another highly effective method applicable to SSH ports is port knocking. Port knocking is a method of opening ports on a machine by making a series of connections to closed ports. The firewall will then react accordingly. This is very useful, as it allows you to keep your SSH port closed, so it won't show up on port scans (nmap or other). This can be done directly by configuring `iptables`, but I've opted to use `ufw` coupled with `knockd`. ## How does it work ? `knockd` is the port-knock server that will run on the target machine as a daemon. It is going to handle the connection on the specified ports in the configuration. `ufw`, our netfilter firewall program, will be called by `knockd` and in ou case edit `iptables` rules. ## Installation The whole installation have been done on a Debian system (Debian 12). So first, install the packages for both of them ```bash apt install ufw knockd ``` ## Configuration Now, let's see how to configure this tools. I assume that you are using Systemd. ### ufw The default `ufw` configuration is enough to perform port knocking, it should be as the following. `ufw` has to be enabled to show its default policies. ```bash ufw enable ufw status verbose | grep Default ``` Output ```bash Default: deny (incoming), allow (outgoing), deny (routed) ``` If it is not the case, you can change the default policies. ```bash ufw default allow incoming ufw default deny outgoing ``` Once it is done, you can reload the `ufw` configuration to make sure the modifications take effect immediatly. ```bash ufw reload ``` ### knockd First of all, make sure that you are using the network interface you want. In `/etc/default/knockd`, you can edit the `knockd` options that will be used with the executed command by the Systemd service. ```ini ... # command line options KNOCKD_OPTS="-i eth0" ``` Now we describe how will `knockd` act by editing `/etc/knockd.conf`. Here is an example of what could be done, in this example our SSH port is `47612`. ```ini [options] UseSyslog [openSSH] sequence = 7264,3981,5410 seq_timeout = 5 start_command = ufw allow from %IP% to any port 47612 [tmpOpenSSH] sequence = 8792,6137,2058 seq_timeout = 5 start_command = ufw allow from %IP% to any port 47612 tcpflags = syn cmd_timeout = 10 stop_command = ufw delete allow from %IP% to any port 47612 [closeSSH] sequence = 4496,1625,7349 seq_timeout = 5 start_command = ufw delete allow from %IP% to any port 47612 ``` In this configuration are described three `knockd` knocks. **`openSSH`** will add a new `ufw` rule to allow the client IP address on the port 47612 after the received TCP sequence `7264,3981,5410`. **`tmpOpenSSH`** will add a `ufw` rule that allowed the client IP address on the port 47612 after the received TCP sequence `8792,6137,2058`. This rule is going to timeout and then be removed after 10 seconds **`closeSSH`** will remove a `ufw` rule that allowed the client IP address on the port 47612 after the received TCP sequence `4496,1625,7349`. You can finally start the port-knock server. ```bash systemctl restart knockd ``` ## Usage Now everything is setup, you can use the port-knock client `knock` (from the package `knockd`) to perform TCP connections on your target machine. As example: ```bash knock -v localhost 7264 3981 5410 ```