« Previous 1 2 3 Next »
TCP Stealth hides open ports
TCP Camouflage
Data Integrity
As I mentioned previously, the typical port knocking setup does not provide any protection against man-in-the-middle attacks. The typical argument here is that the application itself is responsible for this kind of protection. However, a very short time slot still provides an attack vector. This is the period of time between successfully knocking and the connection being established at the protocol level.
In the present case, this is equivalent to the phase between successfully authenticating via the PSK through completion of the three-way handshake. TCP Stealth can provide protection here by checking the integrity of a small volume of data. The idea is that the client injects additional information into the first data packet. The server checks the correctness of the data and either allows the connection or rejects it.
The implementation follows principles that are similar to authentication using the pre-shared key. The integrity check is performed before establishing the connection by configuring the network sockets appropriately with setsockopt()
. To allow this to happen, the kernel patch mentioned previously introduces the TCP_STEALTH_INTEGRITY
and TCP_STEALTH_INTEGRITY_LEN
options. The former is only relevant for the client side; the additional data is defined separately.
In contrast to this socket option, TCP_STEALTH_INTEGRITY_LEN
is only used on the server side; it states the volume of data that is relevant for the integrity check. At the current point in time, this check is not possible without authenticating.
Figure 3 shows the three-way handshake with TCP Stealth enabled and an integrity check. In the first step of establishing the TCP connection, the client sends information relating to the PSK in the ISN. Where the client normally completes the handshake, it initiates the integrity check. TCP Stealth again relies on the MD5 checksumming method. The input data is the PSK and the integrity-check data mentioned previously – simply concatenated.
The 128-bit checksum is broken down into eight chunks of equal length by TCP Stealth and then XOR'd. The result ends up in the second part of the 32-bit ISN. In the first 16 bits, TCP Stealth hides the PSK (see above). Once the additional data has been transferred in the third step of the TCP connection establishment, the server can perform the integrity check. You can read all about the precise details online [8] [12].
Closed Doors?
For an application to be allowed to use TCP Stealth, it must set the appropriate socket options. In other words, this makes both modifications to the source code and creating new binary code inevitable. That said, if you are a regular user of open source, you will not have any trouble doing this. However, for many applications, users only have access to the binary and have no access at all to the source code. Again, TCP Stealth has a trick up its sleeve to solve this, as well.
The magic word here is libknockify
[11] [12]. This is a library that the developer loads using the LD_PRELOAD
mechanism before executing the application itself. At program run time, libknockify
overwrites system calls such as getsockopt()
, listen()
, or connect()
with the TCP Stealth counterparts (see also Listing 3). You can configure the PSK or the required details for the integrity check either via the shell environmental variables KNOCK_SECRET
and KNOCK_INT_LEN
or you can store them in $HOME/.knockrc
.
Listing 3
Server Process with libknockify.so
01 $ cat $HOME/.knockrc 02 KNOCK_INTLEN=0 03 KNOCK_SECRET="Nuer fuer LM-Leser :-)" 04 KNOCK_LOGLVL=2 05 $ 06 $ LD_PRELOAD=/usr/local/lib64/libknockify.so ncat 127.0.0.1 -l 4242 07 setting loglvl to 2 08 Initializing hooks ... 09 Resolving symbol socket ... 10 Resolving symbol connect ... 11 Resolving symbol listen ... 12 Resolving symbol write ... 13 Resolving symbol send ... 14 Resolving symbol sendto ... 15 Resolving symbol sendmsg ... 16 Resolving symbol getsockopt ... 17 Resolving symbol close ... 18 Resolving symbol epoll_wait ... 19 Resolving symbol select ... 20 All dynamic symbols could be resolved. 21 socket(2, 1, 6) = 3 22 Socket 3 will be Knockified. 23 Knockified. 24 listen(3, 10) = 0
Listing 3 sets a log-level parameter. A
value tells libknockify
not to make so much noise, whereas a value of 3
offers developers maximum verbosity. This is very useful for troubleshooting. A matching shell variable goes by the name of KNOCK_LOGLVL
. In our lab, we continually experienced connection failures. When we asked Julian Kirsch about this, he confirmed that the library is only a workaround and that the focus is quite clearly on appropriate modifications in the source code of the application.
What Else?
The "TCP Stealth in Daily Linux Use" box describes modifying the Linux kernel and OpenSSH to use this technology. You will find patches for systemd
online [11]. If you feel inclined to do so, you can use the code snippet you find there to modify other network services.
One more network aspect also must be considered. It is not unusual for individual packets to be lost. TCP then ensures that they are resent. If, however, the packet happens to be the first packet in the three-way handshake, à la TCP Stealth, this is fatal. As I described previously, the timestamp plays an important role in computing the ISN. In case of a resent packet, it no longer fits the bill.
The procedure for resending packets is part of the TCP stack. For Linux, this would mean that more changes are required to the kernel. The patch I described already takes the necessary precautions. For sockets that run in TCP Stealth mode, the kernel uses the original timestamp and does not generate a new one.
« Previous 1 2 3 Next »
Buy this article as PDF
(incl. VAT)