Ha, the red balloon in the commit message gave my brain a quick "wait what's wrong, why does this repo have a bunch of red circles?". Just trained to see that and immediately think "something is broken".
Anyway, interesting approach using a secret like this. Is this approach used elsewhere?
Based on this it looks like the service will change what port it's listening on every N seconds. What happens if a port on the server is already open/ reserved though?
Also, not that it really matters from a security perspective, but md5 seems like a bit of an odd choice. There are faster options available. Might be nice to allow it to be configured.
Cool cool, thanks. Yeah so I was thinking that blake3 would be a good fit as it's faster (not that it really matters) and safer (again, not that it matters), and it also supports variable key sizes so it'd be easy enough to drop it in.
Given that there's really no major performance/security benefit it's totally fine to use md5 imo, I shouldn't have even mentioned it in retrospect lol I just see "md5" and immediately my brain is like "hmmm".
Collision chance is still pretty low, my guess is that in practice unless you're doing something automated that performs hundreds of SSH's a day you won't run into it (30 seconds of "collision time" every 2-4 hours, based on my math).
Yes, or at least in a similar fashion. An alternative variant of port knocking is SPA (Single Packet Authorization). Often SPA protocols use UDP and contain within the body field an encrypted payload containing all the required data to authenticate and authorize a particular request.
There are multiple different implementations of SPA: OpenSPA [1] (full disclosure: I am the author of OpenSPA), fwknop [2] just to name a few.
SDP (Software Defined Perimeter) often builds upon SPA technologies in order to achieve a form of zero trust access.
Correct me if I'm wrong, but I don't think iptables allows you to authenticate the knocks? Also, anyone listening to your network would be able to replay the sequence and open the port.
This project reminds me a bit of moxie's knockknock[1], where the idea of port knocking is kept intact, but with some added security. Plus, it seems really easy to setup, compared to writing dozens of iptables rules.
- A single SYN request is sent on an opened || closed port
- It carries an OTP for authentication so you can be the only one to open a port
- Once authentified, a random (HMAC based) port is opened for a TCP connection
- Then, the port is closed as soon as a connection has been established
Very clever. The fake SYN carries data, an OTP. Very nice!
Clever, yes. But this will break in presence of middle-boxen that rewrite IP-ID [1] and/or TCP-SEQ/ACK [2] numbers (SSL inspection firewalls, WAN optimizers, older satellite modems, even some particularly bad carrier-grade NAT devices).
If you have a Mikrotik kicking around, you can build firewall rules for this (IIRC, it's just a wrapper over top of linux iptables).
Basically a "knock" on a port adds an IP to a list for N seconds. A knock on port 2 from an IP in that list adds the port to another list for N seconds. A final knock on a third port adds an IP in the third list to the allowlist for a period of time (generally as long as there is activity).
For extra fun, add some guard ports around the knock ports that cause an immediate IP ban.
Port knocking is just a channel to send a password. Usually a static plaintext password.
It's overengineering to the nth degree.
If you want to send a password without any TCP baggage then just send a UDP packet. It's not as "cool", perhaps, but it'll be orders of magnitude easier to make secure.
Or use TCP MD5, and even a sniffer can't RST your TCP session.
It's a mechanism to deny attackers access to consuming your stateful resources. Attackers without the secret can't consume any more resources than sending you a packet that you perform a maccheck on.
UDP could be used instead but it's not uncommon for it to get blocked by firewalls. This approach will have its own, but different, issues with firewalls.
This kind of tool is used to do things like allow remote SSH access without getting inadvertently connection and log flooded by overzealous password crackers or exposing the service to enumeration.
It can also be used to protect weaker protocols that don't have adequate security internally (e.g. where you don't trust that they're not exploitable) but that you only need limited access to for emergency purposes.
23 comments
[ 3.2 ms ] story [ 35.1 ms ] threadAnyway, interesting approach using a secret like this. Is this approach used elsewhere?
Based on this it looks like the service will change what port it's listening on every N seconds. What happens if a port on the server is already open/ reserved though?
Also, not that it really matters from a security perspective, but md5 seems like a bit of an odd choice. There are faster options available. Might be nice to allow it to be configured.
Cool stuff.
The only tool I can think of right now is moxie0's tool https://github.com/moxie0/knockknock back in 2011.
About the TCP port, if it's already open, you'll just have to wait for the next HMAC because of the very limited communication.
Finally, the choice of md5 was made because of the 16 Bytes output (knockles uses 10 of them), but don't hesitate to make a pull request!
Given that there's really no major performance/security benefit it's totally fine to use md5 imo, I shouldn't have even mentioned it in retrospect lol I just see "md5" and immediately my brain is like "hmmm".
Collision chance is still pretty low, my guess is that in practice unless you're doing something automated that performs hundreds of SSH's a day you won't run into it (30 seconds of "collision time" every 2-4 hours, based on my math).
Anyway, yeah, super into this.
yes, fwknop https://github.com/mrash/fwknop
Yes, or at least in a similar fashion. An alternative variant of port knocking is SPA (Single Packet Authorization). Often SPA protocols use UDP and contain within the body field an encrypted payload containing all the required data to authenticate and authorize a particular request.
There are multiple different implementations of SPA: OpenSPA [1] (full disclosure: I am the author of OpenSPA), fwknop [2] just to name a few.
SDP (Software Defined Perimeter) often builds upon SPA technologies in order to achieve a form of zero trust access.
[1] - https://github.com/greenstatic/openspa
[2] - https://github.com/mrash/fwknop
I am currently re-writting the OpenSPA protocol (version 2) and I plan on playing around with eBPF as well, so thanks eeriedusk for paving the way :)
Example: https://www.digitalocean.com/community/tutorials/how-to-conf...
This project reminds me a bit of moxie's knockknock[1], where the idea of port knocking is kept intact, but with some added security. Plus, it seems really easy to setup, compared to writing dozens of iptables rules.
[1]: https://github.com/moxie0/knockknock
[1] https://en.wikipedia.org/wiki/IPv4#Identification
[2] https://en.wikipedia.org/wiki/Transmission_Control_Protocol#...
Maybe a TCP option could be used.
https://news.ycombinator.com/item?id=27249555#27250363
Basically a "knock" on a port adds an IP to a list for N seconds. A knock on port 2 from an IP in that list adds the port to another list for N seconds. A final knock on a third port adds an IP in the third list to the allowlist for a period of time (generally as long as there is activity).
For extra fun, add some guard ports around the knock ports that cause an immediate IP ban.
It's overengineering to the nth degree.
If you want to send a password without any TCP baggage then just send a UDP packet. It's not as "cool", perhaps, but it'll be orders of magnitude easier to make secure.
Or use TCP MD5, and even a sniffer can't RST your TCP session.
UDP could be used instead but it's not uncommon for it to get blocked by firewalls. This approach will have its own, but different, issues with firewalls.
This kind of tool is used to do things like allow remote SSH access without getting inadvertently connection and log flooded by overzealous password crackers or exposing the service to enumeration.
It can also be used to protect weaker protocols that don't have adequate security internally (e.g. where you don't trust that they're not exploitable) but that you only need limited access to for emergency purposes.