A proposal for "silent" port knocking
Port knocking is a longstanding technique to evade port scans that is typically implemented in user space. A recent patch proposed for the kernel would change that by adding support for port knocking into the TCP/IP stack itself. Beyond just allowing administrators to hide open ports, the patch would also provide some ability to thwart man-in-the-middle attackers either from making their own connections to those hidden ports or from hijacking those established by friendly clients. But the patch is facing some pushback from the network developers who think that user space is a better place to handle features like port knocking.
The details of the "knock" vary, but the basic idea for port knocking is that a protected port on a server will not respond to the normal connection-establishment protocol; instead, some special steps will be required to make a connection to the port. Those steps might include making a connection attempt to a different port, or to a series of ports, that show the server that the client knows the secret knock to gain entry to the clubhouse. Since port scanning programs generally don't know the secret knock and it is expensive to try lots of possibilities, the services behind the knock are hidden from view.
There are a few different reasons to hide a service. One is that the server program may have vulnerabilities, either because it has not been kept up-to-date or because there are unknown flaws in the code. If only trusted people know about the knock, it reduces the threat of someone exploiting the hole. In addition, hiding services like SSH will avoid brute-force username/password guessing attacks.
But there is another reason to hide the existence of a service: it may be illegal in certain jurisdictions or running it may draw unwanted attention to the host and its owner. Folks running Tor bridges or other privacy-oriented services may see them blacklisted by government-controlled internet service providers—or prompt a visit from some secret service.
Existing port knocking solutions generally either monitor firewall logs or capture packets from user space, then modify the firewall to open the port when the proper knock is detected. The Knock project—a part of the GNUnet project—looks to turn that on its head. With a few-hundred-line patch, authors Maurice Leclair, Julian Kirsch, and Christian Grothoff would move the port-knocking logic into the Linux networking stack. That would allow clients and servers to communicate, while hiding behind a port knock, simply by using the new TCP_STEALTH option to setsockopt(). If the code were widely available in most Linux kernels, users could rely on the feature being available, without having to install and configure some other port knocking solution.
Knock is different than other solutions in a couple of other ways. To start with, it is meant to be undetectable to a man in the middle. It just looks like a normal connection establishment to a particular port—there is no extra sequences of connections to other ports or other special knocks. It uses a technique called "silent knocking" that requires sharing a secret between the client and server using some unspecified, out-of-band mechanism. That secret is used to calculate the sequence number of the initial SYN packet that is sent to initiate the three-way handshake that starts TCP connections. Any SYN with an improper sequence number gets an RST reply; exactly what it would get for a closed port.
In addition, using the TCP_STEALTH_INTEGRITY option allows the the first bytes of the payload data to be protected by a hash-based message authentication code (HMAC), which effectively stops active man-in-the-middle attackers from hijacking the connection once it has been established. Essentially, the top 16 bits of the sequence number in the SYN packet correspond to the HMAC, while the low 16 bits are the authentication code that comes from the MD5 of the shared secret.
The 32-bit authentication code for stealth-only mode is calculated with one round of MD5 using the shared secret along with the destination IP address and port. In stealth+integrity mode, the client and server must agree on the number of payload bytes to be covered by the HMAC, which also uses MD5. A short paper [PDF] about Knock noted that using MD5 may be something of a surprise, but that it is already used by the kernel for initial TCP sequence number calculation as well as for SYN cookies. But in the linux-kernel mailing list thread, Jacob Appelbaum (who assisted in the design of Knock) was not particularly happy with the choice of MD5:
The stealth-only mode is vulnerable to replay attacks as a man in the middle can observe the proper sequence number to unlock the port and replicate it in their own packets (without knowing the secret). Stealth-only is also vulnerable to brute force attacks (trying all possible sequence numbers), but that could be expensive in terms of time and it is not particularly stealthy, so the attack might well be noticed. The stealth+integrity mode is more resistant, as the HMAC-protected bytes could be used to transfer a public key that is used to encrypt the rest of the data.
There are some other downsides to the idea that were briefly explored in the thread. For one thing, network address translation (NAT) implementations that change the sequence number in the SYN packet will not work at all with this technique. As David Miller pointed out, sequence number alteration is done in netfilter for tracking the SIP and FTP protocols as well as for virtual server load balancing.
Others were more explicitly suggesting that handling this kind of port
knocking (or, seemingly, any kind of port knocking) would be best done
outside of the TCP core—in user space. Both Stephen Hemminger and Andi Kleen suggested that user space was a
better home for the code. But Grothoff, who signed off on the patch and
posted it, was surprised by that attitude:
"I mean, if this was a patch for GNU Hurd,
I'd at least understand the strong urge to do everything in
userspace
". Kleen, though, noted
that keeping port knocking in user space meant that "the risk of adding exploitable holes to the kernel is [significantly]
lower
".
Eric Dumazet was also critical of the idea. He suggested allowing user space to implement parts of the TCP protocol, which would also help other proposals (like TCP Minion):
Dumazet is also concerned that reusing
the initial sequence number (ISN) will make it difficult for servers to
distinguish duplicated packets. He didn't mention it, but duplicate ISNs
(i.e. the sequence number sent with the SYN) might also make the
port knocking more obvious to a man in the middle. Overall, though, Dumazet
felt that the paper was too short to explore the idea: "You really need more than 3 pages to fully investigate all the pros/cons
of this idea.
"
He also hinted at a possible direction for getting Knock upstream: looking at TCP fast open, which is somewhat similar and was merged into the mainline. If Knock could be more like fast open, or use it directly, it might have more of a chance to be added to the networking core. The concerns raised by Dumazet and others are reflections of the complexity of the networking stack, that there are a lot of moving parts all of which need to work well together. That's part of the reasoning behind relegating features like port knocking to user space.
On the other hand,
Grothoff is not convinced that the small
patch he posted "really warrants moving TCP into
user land
". But the reception from core network developers like
Miller, Hemminger, and Dumazet would seem to make it fairly unlikely the
patch will make it into the kernel. Working on ways to either move some
pieces of TCP handling into user space or to extend netfilter to allow for
both silent knocking and payload protection would likely be the best way
forward. It is an interesting idea, though not without flaws, but
getting it into the kernel itself is going to be an uphill battle.
Index entries for this article | |
---|---|
Kernel | Networking/Security |
Kernel | Security/Security technologies |
Security | Linux kernel |
Security | Networking/Obfuscation |
Posted Dec 19, 2013 5:16 UTC (Thu)
by wahern (subscriber, #37304)
[Link] (2 responses)
Ah well. It's free software. People can spend their time however they wish.
Posted Dec 19, 2013 8:57 UTC (Thu)
by lolando (guest, #7139)
[Link] (1 responses)
Maybe at some point I'll make it more polished and distributable. In the meantime, as you said, free software and so on. Also, yes, I know, it doesn't protect from MITM (although the attack window can be made arbitrarily short).
Posted Dec 19, 2013 13:21 UTC (Thu)
by jengelh (guest, #33263)
[Link]
Posted Dec 19, 2013 20:30 UTC (Thu)
by imitev (guest, #60045)
[Link]
"I don't want something that runs in the kernel."
Sadly there's no explanation but one would guess he's against the added complexity of having something in the kernel.
FWIW, I've tried quite a few port knock implementations over the years (but not Marlinspike's one, which is on my todo list for months); I've eventually settled on a custom solution: since I'm running a web server anyway, I've set up an https restricted area with a cgi-bin that writes my IP/username to a temporary file. The firewall wgets the file every minute and adds/removes stuff with iptables's xt_recent. Works perfectly.
Posted Dec 20, 2013 5:11 UTC (Fri)
by jzbiciak (guest, #5246)
[Link] (2 responses)
For ISN, if your connection rate is low, it seems like you could mix a low resolution version of the current time in the hash calculation. Allow a small range of ISNs in a defined "acceptance" interval. Downside is that you need moderately accurate time on both sides of the link. I can't claim this as a new idea. The two-factor authentication scheme I use at work basically uses this principle. The client generates a time-based token locally based on a shared secret and the current time. That token is good for 30 seconds. I use that token in addition to my username and password to log in. It seems like a similar idea would work to "randomize" the ISN in a useful way.
Posted Dec 20, 2013 22:18 UTC (Fri)
by nybble41 (subscriber, #55106)
[Link] (1 responses)
If the server responds to the knocks with an ICMP error, it might be possible to piggyback some challenge data in the response so that each sequence is unique after the first knock. The client would hash the challenge data with the shared secret to determine the next knock.
Posted Dec 20, 2013 22:34 UTC (Fri)
by jzbiciak (guest, #5246)
[Link]
Posted Dec 24, 2013 16:13 UTC (Tue)
by rwmj (subscriber, #5474)
[Link] (2 responses)
Posted Dec 24, 2013 16:15 UTC (Tue)
by rwmj (subscriber, #5474)
[Link]
Posted Dec 25, 2013 14:15 UTC (Wed)
by mathstuf (subscriber, #69389)
[Link]
A proposal for "silent" port knocking
A proposal for "silent" port knocking
A proposal for "silent" port knocking
A proposal for "silent" port knocking
A proposal for "silent" port knocking
A proposal for "silent" port knocking
A proposal for "silent" port knocking
TCP in userland
TCP in userland
TCP in userland