How to Obscure Network Ports with a Port Knocking Sequence on Debian 10

Port knocking is a method of dynamically opening network ports by "knocking" (i.e. connecting) on a predefined sequence of ports. This is especially useful for obscuring an open network port from port scanning since the port in question will be closed unless the port knocking sequence is executed. A long enough port knocking sequence is practically impossible to brute force: for example, to successfully guess (by brute force) a combination of 3 TCP ports, an attacker would have to try knocking on each of the 281 trillion possible combinations, and scan for open ports after each port knocking sequence. As you can probably imagine, this would take a very, very long time.

This guide will help you through the installation of knockd, a flexible port knocking daemon, on Debian 10. For demonstration purposes, we will configure it to obscure the SSH port, though any other port/service can be protected with this approach.

Requirements

  • A server running Debian 10.
  • Root access to your server.
  • The $EDITOR environment variable should be set.
  • A second system for testing.

NOTE: If you intend on using port knocking to obscure the SSH port, make sure you have an alternative access method (via console for example), which will come in handy if you accidentally lock yourself out.

Before installing knockd, check the name of your system's public network interface with the following command:

ip link show | grep -v lo
2: ens18: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000

Take note of the interface name (ens18 in this case). It will be needed later.

Step 1: Installing Knockd

knockd is a port-knocking daemon that listens for connections and opens ports accordingly. We will be using knockd with iptables rules to implement port knocking. Install the required packages as follows:

apt update
apt install knockd iptables-persistent

Step 2: Knockd Configuration

Knockd employs a single configuration file, /etc/knockd.conf, to define knocking sequences and other parameters. There are two practical operating modes. The first requires a single knocking sequence to open and close the predefined port, while the other uses separate opening and closing sequences. We will be using the former as it requires less user interaction.

First, backup the existing configuration file:

mv /etc/knockd.conf /etc/knockd.conf.bak

Second, open the configuration file in your text editor:

$EDITOR /etc/knockd.conf

And enter the configuration shown below:

(replace ens18 with your the name of your network interface.)

[options]
        UseSyslog
	Interface = ens18
[SSH]
        sequence = 1000,2000,3000
        seq_timeout = 15
        tcpflags = syn
        start_command = /sbin/iptables -I INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
        stop_command = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
        cmd_timeout = 20

This will instruct knockd to enable traffic to port 22 after receiving the correct knock sequence (1000,2000,3000 in this case), then to re-disable traffic after a 20-second delay. SSH connections will thus only be accepted during this 20-second window.

Next, enable knockd by editing the file /etc/default/knockd:

$EDITOR /etc/default/knockd

And set START_KNOCKD to 1:

START_KNOCKD=1

Save the file and exit. We will also modify the systemd unit for knockd. To do so, create a new unit file to override the default:

$EDITOR /etc/systemd/system/knockd.service

And paste the following:

[Unit]
Description=Port-Knock Daemon
After=network.target
Requires=network.target
Documentation=man:knockd(1)
[Service]
EnvironmentFile=-/etc/default/knockd
ExecStartPre=/usr/bin/sleep 1
ExecStart=/usr/sbin/knockd $KNOCKD_OPTS
ExecReload=/bin/kill -HUP $MAINPID
KillMode=mixed
Restart=always
SuccessExitStatus=0 2 15
ProtectSystem=full
CapabilityBoundingSet=CAP_NET_RAW CAP_NET_ADMIN
[Install]
WantedBy=multi-user.target

Then use the following command to load and enable the new unit:

systemctl daemon-reload
systemctl enable --now knockd.service

Step 3: Firewall Rules

At this point, Knockd is ready, but all traffic is enabled through the firewall by default. We will create firewall rules to deny access to port 22/tcp.

The following commands ensure that existing connections are not interrupted.

iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
ip6tables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

The following are rules to drop connections to port 22/tcp:

iptables -A INPUT -p tcp --destination-port 22 -j DROP
ip6tables -A INPUT -p tcp --destination-port 22 -j DROP

Then, save the current rule chains for persistence across reboots:

iptables-save > /etc/iptables/rules.v4
ip6tables-save > /etc/iptables/rules.v6

Step 4: Testing

From a different system, try to start a new SSH session to your server. You should not be able to connect. To perform the knocking sequence, different tools can be used, though we will be demonstrating with knock, the knocking client included with Knockd. Install the knockd package as shown in Step 1 to a different system, then execute the commands:

knock server_ip_address 1000 2000 3000
ssh [email protected]_ip_address

The SSH connection should now succeed.

Alternative Configuration

Knockd can alternatively be configured to require two distinct sequences for opening and closing network ports. This is useful if you want to keep ports open for extended periods of time. To configure Knockd in the manner, open its configuration file:

$EDITOR /etc/knockd.conf

And replace the existing configuration with the following:

[options]
        UseSyslog
        Interface = your_interface
[openSSH]
        sequence = 1000,2000,3000
        seq_timeout = 15
        tcpflags = syn
        start_command = /sbin/iptables -I INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
[closeSSH]
        sequence = 3000,2000,1000
        seq_timeout = 15
        tcpflags = syn
        start_command = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 22 -j ACCEPT

 Then restart the service to load the new configuration:

systemctl restart knockd.service

Conclusion

Knockd can be an effective solution to brute force attacks, which are very common on SSH and other services. Even though systemd will restart Knockd if it fails, you should always have a backup method of accessing your server if you use port-knocking to hide the SSH port.

Share this page:

Suggested articles

2 Comment(s)

Add comment

Comments

By: Felipe at: 2019-10-30 15:12:10

In file /etc/systemd/system/knockd.service the correct path to sleep is /bin/sleep. Please, check it.

By: nxnjz at: 2019-11-02 18:21:28

Debian 10 images usually have the sleep binary in both locations, "/usr/bin/sleep" and "/bin/sleep".