-
Notifications
You must be signed in to change notification settings - Fork 4
Conversation
129da5e
to
cc3366d
Compare
cc3366d
to
4a79284
Compare
[`libp2p-websocket-star`](libp2p/js-libp2p-websocket-star#57) has a security vulnerability and was not converted in the refactor. This PR removes the `libp2p-websocket-star` information until libp2p/js-libp2p-stardust#14 lands and we can recommend using it instead. refs #2600
[`libp2p-websocket-star`](libp2p/js-libp2p-websocket-star#57) has a security vulnerability and was not converted in the refactor. This PR removes the `libp2p-websocket-star` information until libp2p/js-libp2p-stardust#14 lands and we can recommend using it instead. refs #2600
[`libp2p-websocket-star`](libp2p/js-libp2p-websocket-star#57) has a security vulnerability and was not converted in the refactor. This PR removes the `libp2p-websocket-star` information until libp2p/js-libp2p-stardust#14 lands and we can recommend using it instead. refs #2600
e0dd797
to
7706136
Compare
I currently have the register and discovery flows working with the new Since starting to tackle this, I was thinking on suggesting that we change the naming of the messages in a more meaningful way. However, I wanted to discuss this with both of you after getting an initial version working. Taking into account the current state for the dial flow, I got to a point when I really want to change the protobuf definition.
I will start working on changing the first part while I wait for your feedback, as it will ease a lot the implementation of the dial flow. Anyway, I would like feedback from you on both this points before getting this ready to review. |
FYI, I did not do the protobuf changes above, and I think that I will pass them into an issue to be discussed, instead of being included in this PR. |
My reasoning for not wanting to use a single message is that it doesn't matter if you put in a valid but wrongly typed message, it's still invalid. Except there's more stuff to check for the fields existing. And more code to be executed per parsed message since it needs to parse all the other non-existing messages aswell. Edit: Also the type is explicitly specified by the order, so no checking required. |
54f91de
to
f1d8b52
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sold on using an extra SECIO layer, due to e2e-secio and wss being assumed
src/server/index.js
Outdated
* @param {Array<multiaddr>} options.addresses | ||
* @param {Array<Transport>} options.transports | ||
* @param {Array<Multiplexer>} options.muxers | ||
* @param {Array<Encryption>} options.encryption |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The idea was to use stardust over wss:// protocol, making it encrypted already, and dropping the extra secio layer.
Connections between peers are always encrypted end-to-end encrypted and authed by secio, so even plaintext stardust isn't posing a security risk (aside from allowing praying eyes to view metadata)
Since it was planned to be used over wss:// the SECIO layer will only slow things down.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mkg20001 yeah, I know that not using the extra encryption layer was one the ideas here. I focused on getting this to work with the new libp2p api first. Now that things are getting shaped, I will understand if we will be able to not use the SECIO layer
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok
Possibly it could just use a switch with plaintext, otherwise making a new micro-switch would also be possible should the libp2p switch be either too complicated to run without a swarm or cause significant performance impacts
We should also look out to prevent the user from having to enter an id, even if it's just a placeholder for plaintext-crypto. If not possible to remove from the switch a fake id could always be appended by the listener in that case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should make the libp2p dialer working for all types of use cases, so I think that we should not go on creating a new "switch" to get this and understand what can be done without compromising security. In this way, we cannot use the Plaintext crypto protocol as peers would have to add it to use Stardust
🙅♂
We can potentially have an upgrader here, that would basically allow us to upgrade the connection manually instead of using the provided upgrader (this would an improvement over the micro-switch
idea).
I was discussing this with @jacobheun earlier today and he pointed out an important aspect. Our websocket
transport is relying on the underlying ws module to verify if the data is encrypted and it is not considering wss
/ ws
. This creates a risk for this.
We should probably think a bit about the alternatives that we have and understand what will be the best decision.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can potentially have an upgrader here,
Sounds good
ws module to verify if the data is encrypted and it is not considering wss / ws. This creates a risk for this.
As I already mentioned earlier the actual p2p connections are encrypted and authed by SECIO
What is possible with using a non-encrypted stardust connection is just DOSing the client with false discovery with a MITM information (this would only work if a MITM would happen and additionally would create at most a minor inconvenience) and the leakage of some metadata (who talks to whom) which would be leaked with regular TCP anyways as the SECIO-handshake is unencrypted.
Stardust is also mainly intended for websites that can't directly dial to peers so the website is most likely using HTTPS which means that we're not able to use unencrypted ws
So unless I'm missing something it appears to be a wrong assumption that this creates a problem.
Though checking if the underlying connection is ws or wss isn't hard as the transport is the one that's dialing so it should be enough to match it the multiaddr in question uses ws or wss
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So if we insist on encryption we could do:
- if ws: custom upgrader with SECIO (or user-specified) as only crypto
- if wss: custom upgrader with plaintext as only crypto
The server would use both plaintext and SECIO then
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One thing we need to keep in mind is that stardust allows for any reliable
address, which includes tcp, webrtc, http, etc. We are also not even checking that, just that the stardust multiaddr codec exists in the address. If we remove the potential additional encryption layer, we should be more strict about the addresses we allow. As @mkg20001 mentioned, the general use case is websockets in browser, which will mandate wss. However, I don't see anything in the dialer/listener preventing me from connecting to an insecure tcp stardust server if I discover the address, but as already mentioned it's a low threat attack vector.
We could enforce wss and use plaintext, but the fact that stardust potentially supports any reliable multiaddr is pretty nice. If we want to support broader use cases like tcp > stardust > websockets
broadly using secio to reduce the complexity might be worth the throughput hit. If we just care about wss > stardust > websockets
, I think we can enforce that and reasonably use a plaintext upgrader.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest .that we take this out of the scope of the refactor PR and discuss this on an issue. I think we should be able to provide options to the transport/server that would allow the users to operate with both of those cases. What do you think? Can you create an issue @mkg20001 ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be reasonable to take the double encryption hit for now and do a followup release for performance tuning for transports with built in encryption. It's not ideal but mitigates any risk/complexity of multiple reliable multiaddrs and gets the transport usable for folks.
aa7a793
to
c612a5c
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just two minor things. I think once we merged this it would be good to do an RC and test it out in js-ipfs before doing a final release.
src/listener.js
Outdated
|
||
// close stream and connection with the server | ||
const wrappedStream = this.wrappedStream.unwrap() | ||
wrappedStream.sink([]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be unnecessary. The call below to this.serverConnection.close()
is terminating the entire connection, so this.wrappedStream
, which is a stream of that connection should automatically terminate.
Also, just a note, wrappedStream.sink([])
ONLY closes the write side of the stream, the read would still be open. source
and sink
must both be closed. We should document this better in the libp2p and connection interface docs, with examples of how to properly close streams to help people avoid halfopen streams.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should document this better in the libp2p and connection interface docs, with examples of how to properly close streams to help people avoid halfopen streams.
Yeah, it makes sense
test/discovery.spec.js
Outdated
}, conn => pipe(conn, conn))) | ||
await Promise.all(listeners.map(listener => listener.listen(SERVER_URL))) | ||
|
||
await pWaitFor(() => discovered.length >= 3) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should validate the discovered peer list after the wait for. Also, it might be good to make discovered
a key:peerId
Map to avoid discovered being larger than 3. We should not find more than 3 peers, the excess is likely due to "rediscovering" peers we already know.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpicks mostly, otherwise good to go
0c3d407
to
d7abfde
Compare
@mkg20001 and @jacobheun made a few changes to this. Listen should take into account Also tested this with browser examples of |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Last batch of nitpicks to apply, after that LGTM
Co-Authored-By: Maciej Krüger <mkg20001@gmail.com>
As @jacobheun suggested, we should probably release this as a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM 🚀
Since I'm lead I should merge this now? (Haven't done a merge in eons) |
Yeah, go for it 🚢 For releasing, you can have a look at ipfs/aegir/#releasing. There is an example for the pre release! 🙂 |
You should just need to run: npm run release -- --type prerelease --preid rc --dist-tag next |
This PR refactors
libp2p-stardust
and its server to have an async await API, which is compliant with the new interface-transport, interface-connection and interface-peer-discovery.In addition, the stardust server was also completely refactor to work with the new transport.
There is some stuff that I would like to be different in this module, such as what I described in the next comment. However, I think that we should move that into a new issue to be considered later if relevant.
Needs:
Follow up tasks (create issues):
interface-transports
tests should be refactored to be used in this module (as well as for circuit relay)