Port knocking keeps a port, usually SSH, closed in the firewall until a client “knocks” by sending connection attempts to a secret sequence of other ports. A daemon watching the traffic sees the correct sequence and briefly opens SSH for that client’s IP. To scanners, the server shows no SSH port at all.

It’s a neat trick that removes nearly all brute-force noise. It’s also obscurity, not real authentication, so it’s worth knowing the trade-offs before you rely on it.

How it works

  1. The firewall drops all traffic to port 22.
  2. knockd watches incoming packets (via libpcap), even dropped ones.
  3. The client sends packets to, say, TCP 7000, 8000, 9000, in that order and within a short time.
  4. knockd runs a command that allows port 22 from the client’s IP.
  5. You connect with SSH normally. Later, the rule is removed again.

Before you start: don’t lock yourself out

Have the provider’s VNC console ready and test carefully. If knockd isn’t running or the firewall rule is wrong, SSH is unreachable. See Linux rescue mode.

Install knockd

sudo apt install knockd

Find your interface name with ip -br link (for example eth0 or ens3).

Configure knockd

/etc/knockd.conf:

[options]
    UseSyslog
    Interface = eth0

[openSSH]
    sequence      = 7113:tcp,8522:tcp,9431:udp
    seq_timeout   = 10
    tcpflags      = syn
    start_command = /usr/sbin/ufw insert 1 allow from %IP% to any port 22 proto tcp
    cmd_timeout   = 30
    stop_command  = /usr/sbin/ufw delete allow from %IP% to any port 22 proto tcp
  • Pick random, high, non-sequential ports, and mix TCP and UDP.
  • start_command opens SSH only for the knocking IP (%IP%).
  • After cmd_timeout seconds, stop_command removes the rule. Your established SSH session stays connected, because UFW allows established traffic. Only new connections need a new knock.

With plain iptables instead of UFW:

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

Enable the daemon. On Debian/Ubuntu, set START_KNOCKD=1 and KNOCKD_OPTS="-i eth0" in /etc/default/knockd, then:

sudo systemctl enable --now knockd

Close SSH in the firewall

Only after knockd is running, and with a console session ready:

sudo ufw delete allow OpenSSH          # or: sudo ufw delete allow 22/tcp
sudo ufw status

Knock from the client

sudo apt install knockd       # provides the 'knock' client (also available for macOS via Homebrew)
knock -v 203.0.113.10 7113:tcp 8522:tcp 9431:udp && ssh [email protected]

Without the client, use nmap or nc to hit each port in order. Wrap it in your ~/.ssh/config:

Host web1
    HostName 203.0.113.10
    ProxyCommand sh -c 'knock %h 7113:tcp 8522:tcp 9431:udp; sleep 1; nc %h %p'

Check the server log for knock events: journalctl -u knockd or grep knockd /var/log/syslog.

Limitations

  • Replayable: anyone who can observe your traffic (shared Wi-Fi, an ISP, a compromised network) can see and replay the sequence. Variants with one-time sequences exist, but they’re more complex.
  • NAT: if you’re behind carrier-grade NAT, the opened rule applies to a shared public IP.
  • Packet loss or reordering can break the knock, especially with UDP.
  • Another component to fail: if knockd crashes, you’re locked out until you use the console.
  • Not authentication: SSH still needs strong authentication behind it.

Better modern alternatives

Approach Why
Key-only SSH + Fail2Ban Brute force becomes pointless, with bans for noise. See key-only SSH
Firewall SSH to your IPs Simple and strong if your IPs are stable
VPN or mesh VPN (WireGuard, Tailscale) SSH not exposed to the internet at all. See WireGuard
Single Packet Authorization (fwknop) Like port knocking, but with an encrypted, authenticated, non-replayable packet
Bastion host One hardened entry point. See ProxyJump

Port knocking can still be a fun extra layer on a personal server. For production, a VPN, IP allow-listing or SPA give similar invisibility with real cryptographic protection.

Quick reference

Task Command
Install apt install knockd
Config /etc/knockd.conf
Start systemctl enable --now knockd
Knock knock host p1:tcp p2:tcp p3:udp
Logs journalctl -u knockd

Related: UFW firewall and change SSH port.

  • SSH
  • Security
  • Firewall