Port knocking is like a secret handshake or magic word between client and server. It can be used in various ways, but most commonly as a security feature to deny all contact to a specific service - like SSH - and only allow connections if the client used the correct port knocking sequence. But it is not limited to it and can used to run different commands, too. In this article, I've decided to use
- It works like this:
knockdserver checks logs for specific sequence/ pattern (e.x. TCP Syn Packets of 3 specific ports)
knockdclient runs specific sequence against server (e.x. to open up SSH access over the FW)
knockdserver recognises sequence and runs a specified command (e.x. to open access via SSH for a specific IP)
- adds another security layer (e.x. gainst automated attacks and information gathering)
- could run commands in a secure way for third parties
- limited compatibility/ availability (clients and servers (like AS400 etc)) + on third party machines not possible
- knocking sequence could be captured (on client or network traffic)
- additional work on network firewalls and IPS solution requiered, since the knocking ports must be reachable + knocking could be interpreted as a (malicious) network/port scans
- additional software/configuration on client needed
- unreliable on certain networks as high latency and packet loss can interfere with the knocking process/sequence
- complexity might require additional user training
- make it more difficult to use automation services like Ansible
- if the knocking listener service dies or is misconfigured, access could impossible without further preperation (no long term experience)
- because of the reasons above, troubleshooting is a pain!
Linux Ubuntu 22.04 LTS as Client and Server, using
knockd as a port knocking service, iptables as firewall, and my goal is to secure my SSH access.
knockd Configuration - Server
Install the service with
sudo apt install knockd. The service is not running after installation, but let us check the configuration before we start it.
The first configuration file can be found here
[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 [openHTTPS] sequence = 12345,54321,24680,13579 seq_timeout = 5 command = /usr/local/sbin/knock_add -i -c INPUT -p tcp -d 443 -f %IP% tcpflags = syn
Make sure to change the sequences since they are known and, therefore, not secure. For this article, I am going to remove the
[openHTTPS] section as it is not needed for now.
The sequence is a number of ports - 3 TCP ports per default, but you can change the number of ports and the protocol to UDP. In this article, I'll just use the default.
This is the new configuration file:
[options] UseSyslog [openSSH] sequence = 22222,33333,44444 seq_timeout = 5 command = /sbin/iptables -A INPUT -s %IP% -p tcp --dport 22 -j ACCEPT tcpflags = syn [closeSSH] sequence = 44444,33333,22222 seq_timeout = 5 command = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 22 -j ACCEPT tcpflags = syn
- Let me explain the command in
/sbin/iptables -A INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
-A INPUT- append rules to the
INPUTchain (last position), replace with
-Ito >insert it to the chain into the first position
-s %IP%- specifies the source with the
knockdvariable of the IP of the 'knocker'. You can change it to a specific IP, network, or all source IPs
-p tcp- choose TCP as a protocol for SSH
--dport 22- specify the destination port (SSH)
-j ACCEPT- tells iptables what to do with this packet
The second command in
closeSSH deletes the previous rule with
-D and the rule specifications.
The second configuration file can be found here
/etc/default/knockd - in which we 'enable'
knockd and specify the interface that we are going to use.
Open it in your favorite text editor, change the value of
1 to enable knockd.
In the next option, you can specify the interface on which
knockd is listening. Uncomment
KNOCKD_OPTS and change
eth1 with the interface of your choice. You can use
ip -br a to find the name:
$ ip -br -c a lo UNKNOWN 127.0.0.1/8 ::1/128 eth0 UP 188.8.131.52/32 metric 100 ens10 UP 10.20.10.7/32
Starting knockd - Server
So, after the configuration, let us start
sudo systemctl start knockd and
sudo systemctl enable knockd to start the service and make sure that it autostarts after rebooting.
sudo systemctl status knockd to ensure the service is running.
The logs can be found in the
syslog of the server:
user@test-ubu-01:/var/log$ sudo tail -f syslog [sudo] password for user: [...] Nov 12 15:20:24 test-ubu-01 knockd: 184.108.40.206: openSSH: Stage 1 Nov 12 15:20:24 test-ubu-01 knockd: 220.127.116.11: openSSH: Stage 2 Nov 12 15:20:24 test-ubu-01 knockd: 18.104.22.168: openSSH: Stage 3 Nov 12 15:20:24 test-ubu-01 knockd: 22.214.171.124: openSSH: OPEN SESAME Nov 12 15:20:24 test-ubu-01 knockd: openSSH: running command: /sbin/iptables -A INPUT -s 126.96.36.199 -p tcp --dport 22 -j ACCEPT
You can check the firewall rules with
sudo iptables --list:
sudo iptables --list Chain INPUT (policy ACCEPT) target prot opt source destination ACCEPT tcp -- 188.8.131.52 anywhere tcp dpt:ssh
Important: Make sure that you remove all 'allow-all' accept rules for SSH and keep one session open so you don't get locked out.
knockd - Client
knockdon the client, and use the
knock -d 5 -v 184.108.40.206 22222 33333 44444
-d 5- add a delay of 5 milliseconds between the port hits. It can prevent you from getting hit by various security solutions that block network scans
-v- increase the verbosity
220.127.116.11- destination IP
22222 33333 44444- the sequence, TCP is the default, use
-uto change all ports to UDP, or add
:tcpdirectly behind the port to specify the protocol per port
- more information can be found via
As this is the sequence for
[openSSH], the logs and rule set should look like the examples in the previous section. To remove the rule, run the command with the sequence of the
As a side note: I bet you could do the knocking part without any client and use netcat, nmap or some other tool, but I have not tested it yet.
Just a small list of tips in case something is not working:
- make sure there is no other firewall ruleset active, UFW, for example
- make sure that the order of rules is correct
- check the logs on the server
- make sure the client can reach the necessary ports of the knocking itself (network firewall, IPS, etc)
- make sure
knockdis enabled, listening to the correct interface and is running
Port knocking is an interesting idea, but I don't plan to implement it anywhere. I've got some ideas for some niche cases, but that's it.
E-Mail hello @itta vern. com
- 22.11.2023 SSH Server Hardening Guide v2
- 08.11.2023 Getting started with rclone - Data transmission
- 01.11.2023 How to: Cisco ISE backup to SFTP repository with public key authentication
- 24.10.2023 Getting started with dig - DNS troubleshooting
- 04.08.2023 Getting started with Fail2Ban on Linux