Project: TOTP Port Knocking
Repository: https://github.com/john-craig/totp-port-knockd-rs
Traditional Port Knocking
Traditional port knocking is a network security specialty that makes a computer into a speakeasy. A client seeking to enter must perform the correct pattern of knocks, and the door opens for them. “Shave and a haircut” might get you right inside, while “S.O.S.” just gets you the cold shoulder. In technical terms, this is accomplished by sending a series of packets to different ports on the machine. All ports are closed, and these packets appear to be dropped, but the machine can still register on which port they were recieved. When it sees the correct pattern of ports was knocked by the same host, it will open up a protected port for connections from that host for a limited period of time.
Advantages
Port knocking has a number of advantages. By keeping the port of a protected service (usually an SSH server) closed except when in use by an authorized user, it closes it off as an attack surface from a adversary. Such an adversary might attempt to exploit a vulnerability in the SSH server, or even brute force a connection. However, they cannot even begin to do this if they have no way to even begin this process when the port of the SSH server itself is completely closed to them until they complete the knocking sequence.
Weaknesses
Unfortunately, port knocking is easily foiled due to its reliance on security by obscurity. Once an adversary deduces the knocking sequence for themself, they can repeat as many times as they wish. Because traditional port knocking implementations have no built in measure for changing their knocking sequence, once it is compromised any security benefit they provide is completely elminated. Determining the knock sequence is not a difficult task, either: an adversary can simply “overhear” an authorized user’s sequence through packet-sniffing.
Strengthening Port Knocking with TOTP
But what if the port knocking sequence could change? And rather than changing only in response to the sequence being compromised, it was changed periodically and automatically, like keys being rotated? This would solve the issue of security by obscurity, but there would be requirements. The knocking sequences would have to be deterministic, so that both the server and the clients connecting to it are able to come up with the same sequence independently. At the same time, the knocking sequences would need to be generated in such a way that an adversary could not identify the method and come up with the same sequence by merely mimicking it.
Fortunately, a mechanism that meets these requirements already exists and is in common us: time-based one-time passcodes. Time-based one-time passcodes, or TOTP, are generated deterministically based upon the current time, but also based upon a shared secret. If both parties possess the shared secret and are synchronized on timing, they will come up with the same passcode; but an adversary who does not possess the shared secret will be unable to do the same.
Of course, the regular TOTP algorithm defined by RFC-6238 does not produce codes long enough to suit our purposes, usually being restricted to between six and eight digits. However, this limitation is designed to produce human-readable and -writeable codes, making it largely artificial. These short codes are simply truncations of a much longer underlying value, the output of an HMAC-SHA-1 operation. In port knocking, the knocks are sent and recieved by software, meaning that the entire underlying value can be used to derive the knocking sequence. This article proposes the use of an HMAC-SHA-512 operation instead, resulting in a 512-bit value which can be broken up into a sequence of thirty-two 16-bit port numbers.
The range of ports which are selected for the knocking sequence can also be tuned dependant upon the requirements of the system. This article recommends a secure default range beginning at 1024 and ending at 32768, giving a total of 32768 or 2^15 possible ports, and a sequence length of 32, in order to utilize a total of 480 of the 512 bits of security provided by the HMAC-SHA-512 operation. The default time interval of 30 seconds used by most TOTP implementations is also recommended.
Guarding against Replayability
Although TOTP port knocking solves the issue of security by obscurity present in traditional port knocking, it does not fully address the problem of replay attacks. In a replay attack an adversary observes the knocking sequence and directly repeats it afterwards. If the knocking sequence is not changed periodically, then an adversary need only observe the sequence once and be able to replay it ad infinitum. However even with periodic changes, an attacker can still perform replays within the period.
The natural solution to the problem of replay attacks is to introduce a counter to the system. Each time a successful connection is made within the current time interval, a counter is updated and a new knocking sequence is generated. This is most easily accomplished by iterating the HMAC-SHA-512 operation. However, the introduction of a counter creates its own problems. With the server can easily keep track of how many successful connections there have been, and each client can keep track of its own successful connections, multiple separate clients do not have a way to know how many connections their peers have made.
A simple approach to solving this problem is for each client to simply assume that if a connection is not successful with its current counter value, it is behind the server and must continue retrying and incrementing its counter until a successful connection is made. In practice, it is very unlikely for a client to ever be more than one or two iterations off, as the count of successful connections will be reset at the end of each interval, and it is unlikely for a single system to have more than one or two connections made within a thirty-second interval.
However, with this solution there is no way for a client to distinguish whether its connections are not succeeding because its counter is behind that of the server or because its other parameters, such as its secret or its time value, are incorrect. A client with a clock that is more than thirty seconds off from that of the server will continuously attempt to connect to no avail. Therefore, other solutions to the this issue are worth exploring, such as having the server preserve the rules for a knocking sequences from lower counter values in the same time interval, but modifying the final rule to reject the client’s connection rather than simply dropping, as a means of communicating to the client that it is “on the right track”, but simply behind in counts. Alternatively, a client that has continuing retrying connections until a full interval has elapsed, and is still unable to connect on a new interval, could assume that its underlying parameters are incorrect.
Conclusion
TOTP port knocking, when implemented with measures against replayability is a network security mechanism which fixes many of the issues with traditional port knocking while preserving its benefits. In a day and age where zero-day vulnerabilities are discovered frequently, and the threat of malicious actors inserting their own backdoors into common security software is existent, the the advantage of a speakeasy computer that does not even let untrustworthy customers through the front door becomes greater and greater.