jvinet / knock

A port-knocking daemon
http://www.zeroflux.org/projects/knock
GNU General Public License v2.0
552 stars 114 forks source link

[feature request] knock should return a returncode #41

Closed shibumi closed 8 years ago

shibumi commented 8 years ago

Hello, I am currently playing around with knock and I've created a service file for knock so if I boot up my system will automatically knock a specific IP.

This works fine so far. But I want to add that the service restarts if the IP was not reachable. For this I would need a returncode for the knock client.

knock could ping the host first or maybe check if the TCP handshake was complete (there would be no returntype for UDP I think.. because UDP has not really a handshake).

Is there an easy way to add this in knock.c?

airwoflgh commented 8 years ago

Hi,

Can you detail out the use case a bit more please? What user runs the service that initiates the knock? Ping (ICMP echo) requires root privileges.

Given knocking is suppose to be transparent to the receiving end (i.e. a service or response is not necessarily required), checking for a valid TCP handshake and setting a return code for an unreachable host, is not practical.

I would suggest writing a shell script that pings the host first if you absolutely require knowing whether the host is up or not first.

Cheers,

P.

shibumi commented 8 years ago

For sure. I am currently running the following setup.. I have 1 systemd timer unit and 1 systemd service unit for knock. Both unit files are running on my client. The goal is that evertime when I boot up my laptop it will automatically send some knocks to my server.

The service file is the knock command and the timer file is just for starting the knock command at boot and after some hours again for making sure that the server is always open for my laptop. (it's like a cronjob).

The problem is for example when i am not at home and I boot my laptop somewhere else I will not have internet at boot. So I want that the knock sequence will automatically try again if it fails. I could handle this really easy in systemd but I need a return-code for this. Yes I could just write a wrapper bash script that checks if the server is available and then knocks the server. But why I should do this? I mean knock is sending stuff to the server so it would be great if knock could also check if the server is up. (I must say I dont know how the knocking stuff is working.. is there a full TCP handshake between the daemon and the client?)

Thats my point of view but I see that writing a shell script is maybe the better way.

airwoflgh commented 8 years ago

Thanks for the clarification.

I can see the ping option being another command line switch that will enable a check before performing a knock. If the host does not respond, return an error code. However, if and when knockd supports ICMP knocking, this option would not work with a knock configuration looking for ICMP echoes (but that's not available yet).

That segues into something I am writing in my fork at that moment (version series 0.8.x) that allows for dynamic port knocking using one time port combinations that can even randomise the protocol and profocol flags (for supported protocols). N.B. knockd does not listen on any ports - it uses libpcap to sniff the interface passively flor knock requests.

This relates to your TCP handshake question because as I looked at the knock.c code, I realised a couple of things:

1) connect() is used from socket.h so a full handshake will occur. However, that doesn't support knock configurations where TCP flags could be required meaning a full connection won't occur. In addition, if you have your server configured with a software firewall like iptables to DROP packets, the handshake would never complete, rendering connect() unusable in those scenarios.

2) I need to update knock.c for the 0.8.x series to support dynamic port knocking on the client side and in addition will need to support raw socket connections with various flag combinations to not only provide the dynamic port functionality but cover existing possible knock configs.

This means the connect() (i.e. handshake) approach would be deprecated.

Returning an error code for anything other than a failure in the binary or a lack of a ping response (if explicitly requested) would not be practical.

jvinet commented 8 years ago

I'd agree with P. Portknocking is predicated on the notion of subterfuge, so we can't reasonably expect a host to respond to ICMP echoes as it may be trying to cloak itself entirely.

I'd recommend you wrap the knocking process in a shell script that does the additional ping-or-return-error-code behaviour.