-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
abstraction for transport level streams #34
Comments
The way I do it in js-libp2p is that I break it down in 3 subsets
I keep 'warmed' conns in a different pool than the pool of connections that were 'stream muxed', and when libp2p.dial is called, it checks if there is a stream muxer to the peer, if not, checks if there is a warmed conn (a conn that was established but never dialed a protocol on it, useful for Discovery protocols to attempt to dial, and not consume the stream), and if not, then do the transport dance. |
Hi guys, I just started integrating quic-go into IPFS. I already had a brief discussion today with @whyrusleeping, and we agreed that it might be helpful to have a Fundamentally, the main difference is that the I'm not really sure what the cleanest solution is here, since I'm pretty new to the libp2p code. Would it make sense to define two separate |
@marten-seemann Hrm... the quic conn will be closest to the go-libp2p-net interface here: https://github.com/libp2p/go-libp2p-net/blob/master/interface.go#L50 The question we need to ask first though is whether or not we want to run secio over quic. I think the answer is no, but i'm not sure. |
Looking into this more, I think adding capabilities to I think on making transport.Conn a much slimmer interface, we have two options:
Having written those down, i'm thinking that the second one might end up being the cleanest solution. |
@whyrusleeping The handshake question is something I've thought about a lot already (and also discussed with Juan), and we decided to use QUIC's TLS for doing the handshake. It would be nice if we define the interface such that we have the option to do the secio handshake over a stream-multiplexed connection. I'd use that in QUIC at first, and switch it off as soon as QUIC implements TLS (this will save us a couple of RTTs during the handshake). |
@marten-seemann hrm... that won't work. secio isnt just a handshake, its actually the encryption layer that everything else needs to run on top of. Lets just go with whatever works for now (a.k.a. get it working). |
I'm with @whyrusleeping that we don't need to change the Conn interface to signal its properties, special since Conn should be the bare minimum interface to send/receive data over a symmetric stream. I'm also up for the 'let's get it to work', even if it means to do secio over QUIC TLS. Currently, we have the WebRTC Crypto handshake (which is pretty much the same as QUIC) and on top we have secio. @marten-seemann I've had the conversation with @jbenet on how to signal the capabilities of each transport too and we kept trying to come with a clean language in the limited time we had in the past to dedicate to it. We've made some progress, but nothing yet to be considered finished. In JS, libp2p-swarm handles all the dialing and listening on different transports + upgrading the connections to a crypto channel and stream muxer. Right now its language enables us to define several combinations, but we haven't included any reasoning over different transport capabilities, it just puts all of them in the same box. Nevertheless, it should be inside libp2p-swarm (or the name we end up picking for it as right now it might be misleading https://github.com/libp2p/js-libp2p-swarm/issues/40), that as we dial and listen for connections, we realize what we already 'bought into' that connection and what we need to add on top to fulfill all the requirements. This could be achieve today by just adding a |
I agree with all of the above, and another future transport capability in addition to stream muxing and crypto, will be reliability. Depending on the swarm's needs regarding an individual connection, capabilities will be transparently wrapped around the connection. In the midterm it would be really awesome if DTLS from quic-go could be reused as a standalone capability, e.g. for wrapping a PacketConn. That'd enable us to finally have the swarm expose datagram communications, not just streams. (The same about standalone capability goes for QUIC's reliability and congestion control parts.) |
Can QUIC in libp2p be tested today? Now would be a good time how a transport can expose the properties it offers and therefore reduce the amount of other steps that are normally done. |
Integrating QUIC is currently in progress (bad timing given that @whyrusleeping isn't here right now and I'm not sure how he'll feel if I start accepting sweeping interface changes...). |
@diasdavid: You can, but it will be a lot work. You'd have to check out all the PRs referenced in libp2p/go-libp2p-transport#20. I had to change a bunch of interfaces to make native stream-multiplexing work in libp2p. I hope we can get these changes merged as soon as Jeromy returns. Is there anything you want to test in particular? |
@marten-seemann I'm interested on exposing all the properties that QUIC has so that we can start having dials that skip SECIO in favour of the QUIC crypto handshake (although we still want to do the challenge for PeerId) You mention that is hard to plug this transport in, any hope of getting transports be modules that are plugged in into the instance in the same way that happens in |
Currently, we do SECIO over each QUIC stream because QUIC only allows us to authenticate connections in one direction (i.e., the client can verify the server's identity). We can run a simple handshake protocol over an "authentication" stream before declaring the connection secure to authenticate the connection in the other direction however:
Protocol if you're interested:
Note: To save bandwidth, we could send a hash of known information instead of sending it back and forth. That is, the signed message in step 2 could be |
Does the client get anywhere the PubliKey/Cert of the server in the API? I can't find it anywhere: https://godoc.org/github.com/lucas-clemente/quic-go#Session In my opinion, deploying QUIC with crafted crypto on top to verify the identity is very risky. I am not sure if it is a risk we want to take. secio on one QUIC stream is not enough as it might be MitMed, we would have to do it in every stream or as how @Stebalien shown, by binding server authenticity to the public key used by QUIC. |
At the moment, we're not using any security guarantees of the QUIC crypto at all. The only reason the QUIC server sends a certificate is because there's no way to run QUIC unencrypted (the protocol explicitly forbids this). For reasoning about security properties, you should treat the QUIC connection as unencrypted. This is due to the fact that the currently implemented version of QUIC doesn't support client certificates (Google didn't feel the need to design for and implement that). This will change as soon as I implement TLS 1.3 for QUIC, which I'm planning to do later this year, but this is far from a trivial change, and might take a couple of months. Connection establishment over QUICConsidering that we currently don't use the QUIC crypto, here is how QUIC connections are secured (all the code for that is in libp2p/go-libp2p-conn#9):
At this point, the peers can send encrypted data on the handshake stream. All other streams are not secure, and could be MITMed. To prevent this, we
The security properties of this handshake should be equivalent to secio + protector (please let me know if you disagree). I agree that from a conceptual standpoint, this feels a little bit hacky, and I'm really looking forward to get rid of this in favor of TLS 1.3 soonish. However, I'd be happy if this doesn't block the merge. |
The go-libp2p-pnet Protector does not authenticate data, it was designed for use on a layer below than Authenticated Encryption so it didn't need it. Which if we treat the QUIC encryption as MitMed then it means that data is not authenticated and can be for example arbitrary bit flipped at the start of the stream when it is predictable.
RFC7250 (proposed standard) added raw public key key handling to TLS but it needs full public key (possible to get from DHT) and QUIC would have to use the full private key as its server cert. |
@Kubuxu: You're right, I didn't think of that. RFC7250 sounds interesting, we might be able to use that with QUIC. That means we probably should wait with the QUIC rollout until TLS 1.3 works properly. |
Fixed. |
* Single goroutine managing autonat-relevent events. * Watching incoming connections and local interface changes as signals. * Emit a single 'rechabilitychanged' persistent event fix #40 fix #36 fix #35 fix #34 fix #11 obsolete #28 obsolete #9 Co-authored-by: Aarsh Shah <aarshkshah1992@gmail.com> Co-authored-by: Adin Schmahmann <adin.schmahmann@gmail.com>
make the error check for not receiving a public key more explicit
fix the relay reset test again
Raise minimum bits required for RSA key to 2048
Some transports we will add in the future (example: QUIC) will support opening new streams at the transport level instead of requiring we use a stream multiplexer. This won't work with our current level of abstractions, we will need some thought around how to make this work.
The text was updated successfully, but these errors were encountered: