holepunchto / hyperswarm

A distributed networking stack for connecting peers.
https://docs.holepunch.to
MIT License
1.04k stars 84 forks source link

Topic when client === false? #6

Closed bplaster closed 4 years ago

bplaster commented 5 years ago

Is there (or could there be) a way to extract the topic from either socket or details when details.client === false in on('connection')?

pfrazee commented 5 years ago

We've been discussing how to deal with this. When we've got a solution, we'll update you here.

bplaster commented 5 years ago

Thanks! One thought would be to have a socket per topic, which would also allow streams to be isolated per topic. Not sure if this breaks anything else though.

telamon commented 4 years ago

This just became a blocker for me and I'm prepared to invest some effort for a solution.

I'm using one hyperswarm instance to listen on multiple topics, and whenever i get a peer-connection I need to know where to route said connection.

If i understand the issue at hand correctly. When you're connecting to a remote peer, you have the discovery information at hand and use it to initiate the new connection, thus the topic is a available.

Whilst when you're accepting a remote connection, all you really get is the socket and there's no guarantee that the remote peer has announced his own presence in the DHT for cross-referencing. And even if the peer exists in the DHT, he might be registered under multiple topics which puts us back to square one.

We can't transmit the topic over the connected socket, because that would unintentionally leak our topic to whoever we accidentally connect to and potentially harm anonymity. ( Is this true? or would it be harmless to do a topic-exchange during connection bootstrap? )

From the listening end, the only metadata we have is the ip-address and a port-number for the socket.

Question: Is it viable to listen on separate ports for each topic, and keep a local lookup table between port-number and registered topic?

mafintosh commented 4 years ago

@telamon are you using it to bootstrap hypercores after or is this some custom data structure?

mafintosh commented 4 years ago

to answer your question the only cost of listening on multiple ports is using more file descriptors locally unless you are relying on hole punching.

in that case you need to spin up a new utp/dht stack for each bind, as that's how hole punching works unfortunately.

telamon commented 4 years ago

@mafintosh well it's neither. I want to forward the socket to an replic8 instance. Which from the socket's perspective is an instance of hypercore-protocol with one 'virtual' feed used to bootstrap the encryption.

So I suspect that I have same scenario as if I had an array of hypercores that needed to be replicated on individual topics. (Trying to avoid first key must be the same errors)

telamon commented 4 years ago

@mafintosh thanks, I did not take the hole-punched connection accepts into consideration. I guess extra resource allocation for each topic will be unavoidable..

I'm currently experimenting with the thought of solving this on application level:

  _onSwarmConnection (socket, details) {
    if (details.client) {
      const hash = createHash('sha256')
      hash.update(this.peer.topic)
      hash.update(this.peer.port.toString() || someOtherPresharedIdentifier)
      const obfuscatedTopic = hash.digest()
      socket.write(obfuscatedTopic)
    } else {
      const obfuscatedTopic = socket.read(32)
      socket.cork()
      const target = findTarget(obfuscatedTopic)
      if (target) {
        socket.pipe(target).pipe(socket)
        socket.uncork()
      } else {
        socket.destroy()
      }
    }
  }

This would require more CPU on each connection, as I'd have to systematically calculate a hash for each topic on the listening end. Do DHT announcements have an id or something else I could use as an obfuscation pad?

mafintosh commented 4 years ago

@telamon the updated hypercore capability system basically does this for you

telamon commented 4 years ago

@mafintosh could you link me to it please? Been wanting to take a look at the cap system for a while now :)

mafintosh commented 4 years ago

@telamon https://github.com/mafintosh/simple-hypercore-protocol

basically does an initial noise handshake (one rt) to setup a unique session and the produces capabilities using the tx, rx keys derived from that :)

mafintosh commented 4 years ago

Closing this for now as this is by design. If there is still interest in talking about solutions reopen