You are here

Knock: Practical and Secure Stealthy Servers

Primary tabs

Knock is a kernel patch that implements a new NAT-compatible TCP option for stealthy port knocking with a few new twists for improved security which is referred to as TCP Stealth.

Background

Today, port scanners can scan all IPv4 addresses in less than one hour. Port knocking is a method for making TCP servers less visible on the Internet. The basic idea is to make a TCP server not respond (positively) to a TCP SYN request unless a particular "knock" packet has been sent first. This can be helpful for security, as an attacker that cannot establish a TCP connection also cannot really attack the TCP server. There are a bunch of existing user-space tools, such as Knock Knock and knockd. Most of these implementations send some other traffic (such as a UDP packet) to the target host to have it (briefly) open the server port. A particularly noteworthy recent idea in this domain is the SilentKnock, which adds the idea of integrating the knock secret in the initial TCP SYN packet in the SQN field, which is a technique borrowed from network steganography.

Features of Knock

Knocking is stealthy: as in SilentKnock, the secret to open the port is part of the TCP SYN packet's SQN, so there is not a single extra packet on the wire (one Knock instead of KnockKnock). Thus, using Knock is indistinguishable on the network from a standard TCP handshake. Furthermore, as there is only one packet, there is no window of opportunity for an attacker to use, as would be the case if a first packet enables the server.

Knocking is done in the Linux kernel. Applications can activate Knock with a single additional setsockopt call (in both client and server). Thus, once Linux has been patched, deployment will be much simpler compared to other implementations. Also, as Knock operates in the Kernel, timing attacks should be much harder to do.

Our Knock optionally does not merely enable opening the connection, but also can be used to protect the first N bytes of the TCP payload. Thus, given a sane protocol being run above TCP (one begins with a key exchange), an active attacker cannot simply take over the TCP connection after the handshake without also being locked into sending the same TCP payload. Thus, if the client begins by sending his public key and then continues to send data that must be authenticated with that key, even an active man-in-the-middle adversary cannot hijack the connection.

Knock is designed to work with clients behind NAT. Only NAT implementations that change the SQN or the optional TCP timestamp are not supported. Note that Linux can perform SQN rewrites in netfilter. Furthermore, as David Miller writes, Linux does this for load balancing (DNAT) and SIP/FTP tracking. However, for most protocols and configurations we still believe SQN rewrites should be rare according to our measurements. After all, the fact that a NAT implementation can do it does not necessarily mean that it is configured to do so. Still, we have no hard data on this, except that it worked fine with the NAT implementations we tested. Note that SilentKnock, a previous implementation of single-packet port knocking, does not work with any kind of NAT.

The main disadvantage is that the SQN only has 32 bits, so a brute-force attack can succeed against Knock. However, an attack involving (on average) billions of packets is at least more likely to be noticed. Not to mention that the adversary would still need to know about the existence of the stealthy TCP server in the first place.

Knock is free software and provided as a simple Kernel modification (which should be easy to audit)

Further reading

Julian Kirsch's Master Thesis with the full details on TCP Stealth can be found here. The the Kernel patch (against Linux 3.16 and 3.18), libknockify and toy example programs are attached to this page.

Support by userspace applications

We provide patches for several applications to make use of the functionality introduced by the kernel patch.

General notice concerning all user space applications

In order to activate Knock's user space functionality in our programs, you have to make sure that the following four preprocessor constants are defined:

There are several possibilities: Either your libc implementation exports the constants in <netinet/tcp.h> (none do at the time of writing). Alternatively, you can use the headers_install target of your patched linux kernel source to install the kernel headers which export the constants to user space. In this case, <linux/tcp.h> is the file that needs to be included in the source. As a third way, grep for the names of the four constants in the respective patch you applied to your kernel and define them manually. (Be warned that the values of the constants differ not only across operating systems, but also as linux kernel versions grow.)

OpenSSH

In the download section, a patch can be found which enables OpenSSH 6.7p1 (and very likely other versions) to use the authentication mechanism of Knock. Several steps need to be taken to customize OpenSSH (assuming the running kernel already was patched with the Knock patches):

Download the OpenSSH source from the project website and get the OpenSSH patch from the download list below.

Make sure that the four TCP Stealth constants are defined (see above) and configure the source of OpenSSH.

openssh-6.7p1 $ ./configure

That's it! Compile OpenSSH by simply typing make into your prompt.

To specify a secret on both sides use the newly introduced SSH configuration option

TCPStealthSecret

or (not recommended) the -z command line argument. The patch also extends the man pages of ssh, ssh_config, sshd and sshd_config which give more information. Notice: Due to the limitations of the SSH protocol TCP Stealth can not offer integrity protection of for example the exchanged key material used by OpenSSH. As only authentication is used it is especially critical that TCP timestamps are activated to provide effective protection against port scanners.

Systemd

A patch for systemd can be found in the download section which enables Knock's authentication and integrity protection for applications using systemd for their socket I/O. Several steps need to be taken to customize systemd (assuming the running kernel already was patched with the Knock patches):

When configuring systemd, make sure you pass in the --enable-tcp-stealth flag by supplying it as a command line argument to the ./configure command.

Make sure that the four TCP Stealth constants are defined in your system (see above) and type make to build systemd.

In order to enable the functionality at runtime, the new configuration options TCPStealthSecret and TCPStealthIntegrityLen are available for use in .socket unit files. TCPStealthSecret specifies the TCP Stealth secret whereas TCPStealthIntegrityLen is an unsigned integer indicating the number of bytes that should be integrity protected (0 means disabled).

Future plans

In the future, we plan to integrate Knock with GNUnet to enable running peers in "stealth" mode, which would be useful for users that do not want to make it obvious that they are operating a GNUnet peer at a particular IP address. We hope to convince the kernel community to adopt this patch. Once this happens, we hope that projects that care about privacy and security (for example, Tor and OpenSSH) will add support for this option.

Acknowledgements

Knock was designed and implemented by Julian Kirsch, Maurice Leclaire and Christian Grothoff. We thank Jacob Appelbaum for constructive discussions on an earlier version of the design.