Exposing port 22 to the internet invites bots and brute-force attacks. One approach is to change your SSH port, which is simple enough. This doesn’t improve your security per se in the sense that anyone scanning your specific box will still find your SSH port, but for hackers scanning entire net blocks for any IP that answers on port 22, you’ll be effectively invisible.
However, changing the port is not always desirable. You may have scripts or automation that expects port 22. Or you may just be philosophically opposed to “security by obscurity,” even in this one not-quite-that case.
One approach is to use Fail2Ban which will ban a client machine if it fails to login successfully to SSH after a certain number of attempts (which prevents brute force attacks).
Another approach is to implement port knocking, which adds a layer of security by blocking access to a port unless a specific action is taken. There are various ways to trigger this. For example:
- You have to send an email to the server, which is then processed by the system, and some script on the box opens the SSH port in the IP
- You have to change a certain web page which the box constantly scans
- You post a message in some kind of private chat (e.g., Telegram) which your server regularly checks for new messages
- You send a text to a certain number, and Twilio has some automation which alerts your server to open SSH for a certain port
etc. The possibilities are endless. The simplest solution is to implement firewall rules where you first have to “knock” on a secret port, and then your firewall unlocks SSH access for that IP.
Let’s show you how this is done.
Installing the Software
I’ll be using Debian 12 and we’ll pretend my client ID is 1.2.3.4. My knock port is 55025. There’s nothing special about that port number.
On Debian/Ubuntu:
apt update
apt install knockd iptables-persistent
If you want to use a RedHat-derived distro (Alma, Rocky, RHEL, etc.):
yum install epel-release
yum install knock knock-server iptables-services
Configure knockd
Edit the knockd config file:
vi /etc/knockd.conf
Paste this configuration:
[options]
UseSyslog
[openSSH]
sequence = 55025
seq_timeout = 5
command = /sbin/iptables -A INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
tcpflags = syn
[closeSSH]
sequence = 55025,55025
seq_timeout = 5
command = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
tcpflags = syn
What this does is to open port 22 with a single knock on port 55025, only for the IP that knocked. It will close port 22 after a double knock on port 55025. Under the covers the firewall is adding and removing a rule.
Lock down SSH by default
I’m assuming you don’t have any firewall rules. If you do, you’ll need to tweak to suit your needs.
Flush any existing rules:
iptables -F
Add a rule to block SSH (port 22) by default:
iptables -A INPUT -p tcp --dport 22 -j DROP
Allow everything else (tweak as needed):
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
iptables -A INPUT -i lo -j ACCEPT
Save your iptables rules. On Debian:
netfilter-persistent save
On RedHat-derived:
service iptables save # CentOS
Enable and start knockd
On Debian/Ubuntu (only):
Edit /etc/default/knockd
and make this change:
START_KNOCKD=1
Then regardless of distro:
systemctl enable --now knockd
Setup Your Client Machine
Install the knock client:
On Debian/Ubuntu:
apt install knock
On macOS, install Homebrew and then:
brew install knock
On Windows, install the precompiled binary from the knock project: https://github.com/grongor/knock
Start Knockin’
Send the knock:
knock your-vps-ip 55025 # or knock.exe on Windows
Then try:
ssh your-user@your-vps-ip
You should now be able to connect via SSH.
Close the SSH Port When You’re Done
You can close the SSH access again with:
knock your-vps-ip 55025 55025 # or knock.exe on Windows
This triggers the closeSSH
command in your knockd config.
Leave a Reply