Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(Maybe) replace quic-go #649

Open
shanemcd opened this issue Jul 21, 2022 · 2 comments
Open

(Maybe) replace quic-go #649

shanemcd opened this issue Jul 21, 2022 · 2 comments

Comments

@shanemcd
Copy link
Member

From @ghjm:

Receptor seeks to provide its users with capabilities similar to those of TCP/IP: unreliable datagrams, similar to UDP; reliable streams, similar to TCP; and reliable secure streams, similar to TCP with TLS. As an implementation detail, Receptor makes use of a library called quic-go for the packet sequencing, error checking and retransmission required to implement reliable stream sockets. Note that the QUIC protocol is no part of the Receptor specification. End users of Receptor do not use QUIC and do not need to be aware that QUIC is in use, and Receptor only makes use of a subset of the capabilities of the quic-go library.

One of the capabilities Receptor affords to end users is non-TLS stream sockets. There are many use cases for this: for example, a chain of proxies where TLS is run over the whole proxy chain; running a DNS server; running or proxying SSH; running a protocol like SMTP that uses STARTTLS; and so on. The quic-go library insists on TLS, because its authors are only interested in the use case of running streaming web services and are not focused on more esoteric uses like that of Receptor. As a result, when a Receptor end user makes a non-TLS stream socket connection, Receptor constructs an insecure TLS configuration and passes it to quic-go. Note that in this case, the Receptor user has explicitly asked for no encryption at all.

If people are unhappy with this usage, one option would be to remove the dependency on quic-go entirely and use something else that does not require TLS. The requirements are that the library must accept an arbitrary PacketConn and provide reliable streaming sockets on top of it, without assuming that the PacketConn is TCP/IP-based (ie, uses IP addresses). A few such libraries exist, notably https://github.com/xtaci/kcp-go. However, none of them have quic-go's track record of successful production use. Rewriting Receptor to use a different library would also require development, testing and deployment resources, and would not provide any direct benefits to end-users. So it seems like the best option is to stick with quic-go, even though it makes us use TLS sometimes when we don't want to.

@ghjm
Copy link
Contributor

ghjm commented Jul 21, 2022

It's also worth thinking about the threat model. What do Receptor-level TLS certificates protect against?

You have a Receptor mesh constructed from backend connections which are themselves usually TLS-encrypted with verified certificates. So we could reasonably ask, is above-the-mesh encryption actually needed at all? The answer is that it is needed if traffic between two Receptor nodes will flow through a third, untrusted Receptor node. This is an unlikely scenario considering that most, perhaps all, Receptor meshes are owned by a single entity and have no untrusted nodes.

Given an untrusted node on the Receptor mesh, TLS encryption even with InsecureSkipVerify protects against casual snooping. The attack we are now considering is that a malicious Receptor node misidentifies itself as one of the endpoints, thus tricking the other peer into transmitting sensitive data, which it can now intercept. This kind of attack is relatively easy to execute on a TCP/IP network, where DNS and IP addressing are distinct from each other: gain control of some node's DNS server, and cause it to talk to an unexpected IP address. However, in above-the-mesh Receptor, naming and addressing are one and the same: the Receptor node ID just is the network address.

So suppose nodes A and B are communicating and evil node E wishes to conduct a man-in-the-middle attack. Leaving aside the question of how E establishes a back-end connection and assuming it somehow gets connected, it must now find a way to redirect A's B-bound traffic to itself, and vice versa. In other words, E has to look like B to A and like A to B. I won't call this impossible because there are some very clever and creative people in the world, but it is certainly far from obvious how you would do this. If the backend topology is such that A and B only connect to E, then E could send specially crafted routing messages - but this would require the back-end configuration of A and B to be compromised. If E just somehow finds its way onto the mesh as a leaf node, then it cannot influence the exchange of routing messages between A and B, so I don't see how the man-in-the-middle could be accomplished.

So, again ... why even have Receptor-level certificates? Basically, they are an "abundance of caution" sort of thing, and a holdover from the days when there were some contemplated use cases for Receptor that would include nodes from different entities on the same mesh. As long as there aren't big public Receptor meshes that untrusted parties can join, there's minimal need for above-the-mesh certificates. But we have them anyway, just in case.

@shanemcd
Copy link
Member Author

shanemcd commented Jan 9, 2023

Was looking into whether or not disabling TLS with quic-go was possible now and stumbled upon this: quic-go/quic-go#2868. Just linking for future reference.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants