libp2p / universal-connectivity

Realtime decentralised chat with libp2p showing ubiquitous peer-to-peer connectivity between multiple programming languages (Go, Rust, TypeScript) and runtimes (Web, native binary) using QUIC, WebRTC and WebTransport

Home Page:https://universal-connectivity.vercel.app

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Setup a private bootstrap node

p-shahi opened this issue · comments

Setup a private bootstrap node

Just to be clear, there's nothing actually private about this bootstrap node besides it not being advertised, right?

In order for the network of universal connectivity nodes and the network of IPFS nodes not to merge, we should make sure to use different Kademlia protocol IDs.

https://github.com/libp2p/rust-libp2p/blob/7c85f92e31771b89f109f2e069eb8d0fea56bbdb/protocols/kad/src/behaviour.rs#L222-L234

One thing to consider here before we overcomplicate things with a separate Kademlia DHT is how the frontend will kick off the peer discovery process.

Once we set u a private bootstrap node, what address will we hardcode into the frontend?

  • We cannot hardcode either a WebRTC nor a WebTransport multiaddr because they are ephemeral
  • One option is to use DNS, the same way that the bootstrap nodes' multiaddrs are discovered (see below), and update the DNS records with new multiaddrs every time the certificate hash changes
  • Another is to rely on some delegated peer routing mechanism. Currently the only option supported by js-libp2p is https://github.com/libp2p/js-libp2p-delegated-peer-routing which uses the Kubo RPC API over HTTPS.
  • Another option is to enable WebSocket support with a TLS certificate — but this is hella ugly and goes against the self-certifying nature of this app.

I hope these insights help!

How DNS is used for multiaddr resolution

Basically, with _dnsaddr.bootstrap.libp2p.io all mutliaddrs of the bootstrap nodes can be found

➜  ipfs-docs git:(main) dig +short TXT _dnsaddr.bootstrap.libp2p.io
"dnsaddr=/dnsaddr/sv15.bootstrap.libp2p.io/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN"
"dnsaddr=/dnsaddr/am6.bootstrap.libp2p.io/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb"
"dnsaddr=/dnsaddr/ny5.bootstrap.libp2p.io/p2p/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa"
"dnsaddr=/dnsaddr/sg1.bootstrap.libp2p.io/p2p/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt"
➜  ipfs-docs git:(main) dig +short TXT _dnsaddr.ny5.bootstrap.libp2p.io
"dnsaddr=/ip6/2604:1380:45d2:8100::1/tcp/4001/p2p/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa"
"dnsaddr=/ip6/2604:1380:45d2:8100::1/udp/4001/quic/p2p/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa"
"dnsaddr=/dns4/ny5.bootstrap.libp2p.io/tcp/443/wss/p2p/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa"
"dnsaddr=/dns6/ny5.bootstrap.libp2p.io/tcp/443/wss/p2p/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa"
"dnsaddr=/ip4/145.40.65.77/tcp/4001/p2p/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa"
"dnsaddr=/ip4/145.40.65.77/udp/4001/quic/p2p/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa"

@2color we discussed this in the meeting today and we'll be using the DNS option

The bootstrap functionality will also be rolled into the rust peer

  • We cannot hardcode either a WebRTC

A thought that came to my mind is that for rust-libp2p we can use a static TLS certificate. Given that all nodes bootstrap off of the rust-libp2p, that would relieve us from the need to setup /dnsaddr DNS TXT records.

@mxinden What exactly is a static TLS certificate?

Would a Let's Encrypt certificate (which are valid for 90 days) work? and if so, would that mean that TLS is used for transport encryption instead of Noise?

we can use a static TLS certificate

Can we do this by

// do a one off and generate pem_str
let pem_str = webrtc::tokio::Certificate::generate(&mut thread_rng())?.serliaize_pem();

// update code and hardcode pem_str in rust-peer
let pem = "whatever the string value is";

// create transport using this hardcoded static certificate
    let transport = webrtc::tokio::Transport::new(
        local_key.clone(),
        webrtc::tokio::Certificate::from_pem(pem_str)?,
    );

This would make it static across restarts since it'll use the same pem_str
If this is indeed the right way to do it and I'm not confused, perhaps it'd be better for the from_pem function to take a Path so we don't have to hardcorde the pem_str in the code

Would this work @mxinden or would we need to get a "real" certificate i.e. Let's Encrypt