SSH Port Knocking: Knock Knock. Who's There? Not the Bots.

I was casually checking one of my server logs one evening(around 9:30 PM😁) and saw something annoying. Hundreds of failed SSH login attempts. From Nepal, China, Russia, Brazil, everywhere. Bots were hammering my SSH door (port 22), as it owed them money.
$ tail -f /var/log/auth.log
Jan 18 10:23:45 server sshd: Failed password for invalid user admin from 185.234.x.x
Jan 18 10:23:47 server sshd: Failed password for root from 103.45.x.x
Jan 18 10:23:48 server sshd: Failed password for invalid user test from 45.227.x.x
Now, I use key-based authentication, so these bots weren't getting in. But still, watching strangers knock on your door all day is not fun. So I went down a rabbit hole and found this old-school technique called port knocking.
Honestly, it felt like something from a spy movie. And it really works.
So What is Port Knocking?
Imagine your server is like a hidden bar during prohibition. The door looks just like a regular wall with no signs or handles. But if you knock in a secret pattern - three knocks, pause, two knocks - the door suddenly appears and lets you in.
That's port knocking.
Your SSH port stays closed. Completely invisible to anyone scanning. But when you knock on a secret sequence of ports in the right order, the firewall opens SSH just for your IP.
1. You knock on port 7777
2. You knock on port 8888
3. You knock on port 9999
4. Server goes "ah, it's you!" and opens SSH
5. You connect normally
6. When done, knock the reverse sequence to close it again
A little daemon called knockd listens for these patterns. When it sees the right sequence from your IP, it runs an iptables command to let you through. Everyone else just sees a closed port.
Let's Set It Up
I'm on Ubuntu, but this works on most Linux distributions with iptables. You'll need sudo access and ideally a cup of tea/coffee/lemon-tea (not any other beverage😁) because we're doing this step by step.
Prerequisites
Before we dive in, make sure you have:
A Linux server (Ubuntu/Debian preferred, but any distro with iptables works)
Sudo or root access
SSH access to your server (obviously)
A second terminal is ready (trust me on this one)
Console access from your cloud provider as backup ( AWS, DigitalOcean, GCP, Vultr - they all have it)
That last point is important. If something goes wrong and you lock yourself out, console access is your "break glass in case of emergency" option. Don't skip setting this up.
Alright, let's do this.
Step 1: Move SSH to a Different Port
First things first. Let's get SSH off port 22. Every bot and their grandfather scans port 22. And here we're gonna be moving to a non-standard port.
sudo vim /etc/ssh/sshd_config
Find the Port line and change it:
# Change this
#Port 22
# To this
Port 13022
Why 13022? The 13th is my birthday date, unlucky for attackers, and 022 reminds me it's SSH. Pick whatever you like, just avoid obvious ones like 2222, 22222, etc.
Restart SSH:
sudo systemctl restart sshd
Now here's the important part. Don't close your current session. Open a new terminal and test:
ssh -p 13022 user@your-server-ip
If you can connect, great. If not, you still have your old session to fix things. Don't skip this step, or you might lock yourself out. Ask me how I know😞.
Step 2: Install knockd
sudo apt update
sudo apt install knockd -y
Step 3: Configure the Knock Sequence
Open the config:
sudo vim /etc/knockd.conf
Replace everything with:
[options]
UseSyslog
LogFile = /var/log/knockd.log
[openSSH]
sequence = 7777,8888,9999
seq_timeout = 10
command = /sbin/iptables -I INPUT -s %IP% -p tcp --dport 13022 -j ACCEPT
tcpflags = syn
[closeSSH]
sequence = 9999,8888,7777
seq_timeout = 10
command = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 13022 -j ACCEPT
tcpflags = syn
Quick breakdown:
sequence- your secret knock patternseq_timeout- you have 10 seconds to complete the knockcommand- the iptables magic that runs when you knock correctly%IP%- automatically replaced with your IPtcpflags = syn- only listens for connection attempts
I'm using 7777, 8888, 9999 for this tutorial. For your actual server, pick something less obvious. Maybe your lucky numbers or a birthday. Just don't use 1234, 5678 - you get the idea.
Step 4: Tell knockd to Actually Start
By default, knockd is installed but disabled. Let's fix that:
sudo vim /etc/default/knockd
Change these:
START_KNOCKD=1
KNOCKD_OPTS="-i eth0"
For the interface name, check yours:
ip addr show
Look for the one with your public IP. Usually eth0 or ens3 or something similar.
Fire it up:
sudo systemctl start knockd
sudo systemctl enable knockd
Step 5: Lock the Door
Now the fun part. We block SSH by default, so only the knock can open it.
If you're using UFW, disable it first:
sudo ufw disable
We're using raw iptables here. You can also use the UFW command as explained here - Link.
# This keeps your current session alive - very important!
sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# Allow localhost
sudo iptables -A INPUT -i lo -j ACCEPT
# Block SSH by default
sudo iptables -A INPUT -p tcp --dport 13022 -j REJECT
# Save the rules so they survive reboot
sudo apt install iptables-persistent -y
sudo netfilter-persistent save
That first rule is crucial. It tells iptables "don't kill existing connections." Without it, running the block rule would kick you out immediately. Not fun, SED LIFE!.
Do not close your current SSH session yet. Keep it open as a safety net while you test.
Testing Time
On your local machine, install the knock client:
# Ubuntu/Debian
sudo apt install knockd
# macOS
brew install knock
First, let's confirm the port is actually blocked:
ssh -p 13022 user@your-server-ip
You should get "Connection refused." Good. The door is locked.
Now perform the secret knock:
knock -v your-server-ip 7777 8888 9999
You'll see:
hitting tcp your-server-ip:7777
hitting tcp your-server-ip:8888
hitting tcp your-server-ip:9999
Quickly connect:
ssh -p 13022 user@your-server-ip
And you're in.
When you're done, close the door behind you:
knock -v your-server-ip 9999 8888 7777
Notice the reverse order. 9999, 8888, 7777. That's your "close" sequence.
No knock client? Telnet works too
telnet your-server-ip 7777
# Ctrl+C
telnet your-server-ip 8888
# Ctrl+C
telnet your-server-ip 9999
# Ctrl+C
You'll see "Connection refused" each time, but that's fine. The knock packets still get sent.
Making Life Easier with a Script
Typing the knock command every time gets old fast. Here's a simple script:
#!/bin/bash
# knock-ssh.sh
SERVER="your-server-ip"
SSH_PORT="13022"
USER="your-username"
echo "Performing secret knock..."
knock $SERVER 7777 8888 9999
sleep 1
echo "Opening the door..."
ssh -p $SSH_PORT $USER@$SERVER
echo "Closing the door..."
knock $SERVER 9999 8888 7777
Save it, make it executable:
chmod +x knock-ssh.sh
./knock-ssh.sh
One command to rule them all.
Watching the Magic Happen
Want to see Knockd in action? Check the logs:
sudo tail -f /var/log/knockd.log
When you knock correctly:
[2025-01-18 10:45:23] 203.0.113.50: openSSH: Stage 1
[2025-01-18 10:45:23] 203.0.113.50: openSSH: Stage 2
[2025-01-18 10:45:24] 203.0.113.50: openSSH: Stage 3
[2025-01-18 10:45:24] 203.0.113.50: openSSH: OPEN SESAME
[2025-01-18 10:45:24] openSSH: running command: /sbin/iptables -I INPUT -s 203.0.113.50 -p tcp --dport 13022 -j ACCEPT
"OPEN SESAME" - I didn't make that up, knockd actually says that. Whoever wrote this daemon had a sense of humor like mine!
A Few Things to Keep in Mind
Port knocking is clever, but it's not magic. Some limitations:
If someone is watching your network traffic, they can see the knock sequence.
Doesn't play well with CI/CD or automated deployments
If
Knockdcrashes, you might lock yourself out😔
This is perfect for personal servers, homelabs, and dev boxes. For production with a team, you probably want a VPN or something like Teleport.
Some tips from experience:
Always have console access as backup. Cloud providers have web-based consoles. Use them if you lock yourself out.
Don't use sequential ports like 1000, 2000, 3000. Too easy to guess.
Keep your knock sequence to yourself.
Still use key-based SSH authentication. Port knocking is an extra layer, not a replacement.
Quick Reference
# Install
sudo apt install knockd
# Config file
/etc/knockd.conf
# Enable on boot
sudo vim /etc/default/knockd # Set START_KNOCKD=1
# Start the service
sudo systemctl enable --now knockd
# Knock from client
knock -v server-ip port1 port2 port3
# Check logs
sudo tail -f /var/log/knockd.log
That's it. Your SSH server is now basically invisible. Port scanners see nothing. Bots find nothing to attack. Only you with the secret knock can get in.
My auth.log has been so much quieter since I set this up. No more watching random IPs fail to guess "admin" as a username fifty times a minute.
Hope this saves you some headaches, too.
#devops #security #linux #ssh #networking
Thanks! JADAU!
But Wait... There's More! (Bonus)
Port knocking works at the firewall level. You can use it for any port:
PostgreSQL (5432)
MySQL (3306)
Redis (6379)
Admin panels
Internal APIs
Literally anything
You just add more blocks in /etc/knockd.conf:
[openPostgres]
sequence = 5555,6666,7777
seq_timeout = 10
command = /sbin/iptables -I INPUT -s %IP% -p tcp --dport 5432 -j ACCEPT
tcpflags = syn
[closePostgres]
sequence = 7777,6666,5555
seq_timeout = 10
command = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 5432 -j ACCEPT
tcpflags = syn
Different knock sequences for each service.




