How can I have a port knocking sequence (or a command that does the port knocking) executed prior to trying to establish an SSH connection?

Preferably using the pre-installed ssh command, but also willing to switch if there's no "standard alternative".

  • Use bash functions or alias.
    – Jakuje
    Commented Jan 3, 2017 at 8:44
  • Attention Close voters: Port knocking as to open a number of ports and close them again before a daemon will "answer" on the regular port...
    – Fabby
    Commented Jan 4, 2017 at 4:36

3 Answers 3


You can also try to use the option ProxyCommand.

It gives you the ability to control the command used to connect to the server; sounds troublesome, but I haven't found any problem with it yet.

From the ssh_config docs:


Specifies the command to use to connect to the server. The command string extends to the end of the line, and is executed using the user's shell ‘exec’ directive to avoid a lingering shell process.

In the command string, any occurrence of %h will be substituted by the host name to connect, %p by the port, and %r by the remote user name. The command can be basically anything, and should read from its standard input and write to its standard output. It should eventually connect an sshd(8) server running on some machine, or execute sshd -i somewhere. Host key management will be done using the HostName of the host being connected (defaulting to the name typed by the user). Setting the command to none disables this option entirely. Note that CheckHostIP is not available for connects with a proxy command.

This directive is useful in conjunction with nc(1) and its proxy support. For example, the following directive would connect via an HTTP proxy at

ProxyCommand /usr/bin/nc -X connect -x %h %p


Lets say you have a command or script that does the knocking IN YOUR PATH: knock.sh <host> <port1 port2 ... portX>

And you want to connect to some host: myhost.net

You can add the following to your ~/.ssh/config

Host thehost
    HostName myhost.net              
    ProxyCommand bash -c 'knock.sh %h <port1 port2 ... portX>; nc %h %p'        
  • %h => the hostname (myhost.net)
  • %p => the port (22)

And you can connect to your host with: ssh user@thehost

You should also be able to use the option directly from the command line with: ssh -o ProxyCommand="bash -c 'knock.sh %h <port1 port2 ... portX>; nc %h %p'" [email protected]


If the program writes data to stdout by default it gets hidden, if you need to see it, add -v after ssh.

Also note that ssh has to execute the knocking before performing the connection, so the total time it will take to complete the connection will be greater.

I have a current configuration working with port forwarding enabled and no problem with it yet.


An alternative to feeding all traffic through nc as a ProxyCommand, as in the accepted answer, is to add a Match host/exec line to ~/.ssh/config that effectively only executes your knock command before connecting:

Match host thehost exec "knock -d 500 %h 1234 5678"
Match host thehost.domain.com exec "knock -d 500 %h 1234 5678"

This line doesn't actually do anything else than executing knock, since there's nothing following the directive.


To make the knock conditional (and prevent the delay and a ton of redundant firewall rules), probe using netcat before knocking:

Match host thehost exec "nc -zw 3 %h 22 || knock -d 500 %h 1234 5678"
Match host thehost.domain.com exec "nc -zw 3 %h 22 || knock -d 500 %h 1234 5678"

The -w 3 flag is to specify a timeout of 3 seconds for the probe.

updated to take comments of Adrien into account

  • 1
    This seems like a workaround of the Match exec feature. But it is really helpful. To be more precise, the Match exec will tell ssh that the configured section can be used if and only if the command return a 0 exit code. Commented Aug 20, 2020 at 7:01
  • 1
    Beware: The Match exec directive will replace the Host section for matching. So you need the following: Match originalhost thehost exec "nc -zw 3 %h 22 || knock -d 500 %h 1234 5678" Commented Aug 20, 2020 at 8:01
  • Good catch. My indenting is clearly off; the Match directive here is not part of the preceding Host directive.
    – mvds
    Commented Aug 20, 2020 at 8:43
  • This seems to work great, but I can't execute an interactive command with exec , and ideas/help? I've posted here: serverfault.com/questions/1117873/…
    – Rino Bino
    Commented Dec 13, 2022 at 17:36

According to an Ubuntu help page on port knocking, you can do the following:

  1. Install the knock program by running sudo apt-get install knockd
  2. Make a script in ~/bin to establish the SSH connection for the particular server:

    knock hostname port1 port2 port3...
    ssh hostname
  3. Make the script executable with chmod +x ~/bin/whatever

  4. Close the terminal, reopen it, and run whatever
  • meh, I kind of dislike the idea of having to resort to an alias or writing a script to accomplish this, but if there's no other way of doing it, alright. Thanks!
    – linkD
    Commented Jan 4, 2017 at 5:01

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .