Skip to content

meh/nokku

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

25 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

nokku

Port knocking, without knocking ports, I guess.

Setup

First install it, cargo install --git https://github.com/meh/nokku works, or find it with your package manager.

Then on both sides create a Curve25519 keypair:

nokku gen-key | tee nokku.priv | nokku pub-key > nokku.pub

Examples

On the server (as root) after saving the public key of the client:

# In this example the client's public key is a file named `client.pub` and the
# interface to observe on is `eth0` and the firewall being used is nftables.
nokku observe -p nokku.priv -P client.pub -i eth0 \
  --open 'nft -a -e add inet FIREWALL INCOMING tcp dport $PORT ct state new accept | sed -e "s/^.*# handle //"' \
  --close 'nft delete rule inet FIREWALL INCOMING handle $HANDLE'

Once the server is listening, on the client (again, as root), after saving the public key of the server, you can open a port for 10 minutes by doing:

# In this example the server's public key is a file named `server.pub` and the
# interface to send the packets through is `eth0` and the IP of the server is
# `172.16.0.2`.
nokku knock 172.16.0.2 -p nokku.priv -P server.pub -i eth0 \
  open --port 9001 --minutes 10

In case there are multiple clients who want to be served by the same observer just add their public keys:

# In this example there are 4 clients with different public keys, and it
# observes on all interfaces.
nokku observe -p nokku.priv \
  -P client1.pub -P client2.pub -P client3.pub -P client4.pub 

Modes of operation

nokku provides different modes of operation which offer a tradeoff between security/stealthiness and speed.

Padding

Since the number of packets nokku sends is always the same this can raise some eyebrows, by adding a randomly generated number of padding packets (that will be ignored) it can hide this behavior away, although more packets mean more eyebrows.

The following example will open the port and then send a random number of padding packets between 0 and 50% of the original payload.

nokku knock 172.16.0.2 --padding \
  -p nokku.priv -P server.pub -i eth0 \
  open --port 9001 --minutes 10

If that's not enough and you feel frisky you can add more padding cycles:

nokku knock 172.16.0.2 --padding --padding --padding --padding \
  -p nokku.priv -P server.pub -i eth0 \
  open --port 9001 --minutes 10

Interval

The default interval follows the ping default, which is one packet per second, this means 16 bps of bandwidth, which isn't very good.

Reducing the interval time increases the bandwidth, but it also risks getting filtered by firewalls, so use at your own peril.

The interval is provided in milliseconds:

nokku knock 172.16.0.2 --interval 250 \
  -p nokku.priv -P server.pub -i eth0 \
  open --port 9001 --minutes 10

The minimum interval is 200ms, packets sent within a shorter time frame are dropped to prevent flooding the observer.

Paranoid

If you're very paranoid and do not mind waiting longer, you can enable this mode, which uses ephemeral-static ECDH to generate a (much bigger) nonce, to then proceed with the normal flow.

Paranoid mode always enable at least one round of padding.

nokku knock 172.16.0.2 --paranoid \
  -p nokku.priv -P server.pub -i eth0 \
  open --port 9001 --minutes 10

Design

The design takes some inspiration from WireGuard when it comes to key management and primitives used, because they just do it right.

Confident

This mode tries to be quick while being reasonably secure, in most cases this is enough.

X25119 is used for static-static ECDH, every message is prefixed with a 32 bits nonce that must be unique for each private key. The nonce is used as salt for the HKDF (to add randomness to an otherwise constant key (the shared secret)).

With HKDF 3 keys and a nonce are derived, one key is for the packet cookie, one for the packet length and the last key and nonce are for ChaCha20Poly1305.

In the packet, after the nonce, there's an unsigned 16 bits integer that represents the cookie, this is XOR'd with the cookie key (2 bytes) taken from the HKDF, once XOR'd back this cookie must be 0x1337 (obviously).

After the cookie 1 unsigned byte represents the length of the payload, this byte is XOR'd with the length key (1 byte).

After that there's length bytes with the encrypted payload followed by 16 bytes of Poly1305 MAC. The nonce, cookie and length are authenticated by ChaCha20Poly1305 as additional authenticated data.

The final packet is fragmented into 2 bytes chunks and sent to the endpoint through ICMP Echo Requests emulating what ping would send and the IPv4 header ID field is used as transport.

Paranoid

This mode tries to be as secure as possible which leads it to being a lot slower.

Every message is prefixed with an ephemeral public key (32 bytes) generated by the client, then X25519 is used with the static key of the endpoint and the shared secret is used as the nonce as in the confident flow, everything else is the same.

About

Knock knock knock, hitori bocchi.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages