prototype-cjdns-pi icon indicating copy to clipboard operation
prototype-cjdns-pi copied to clipboard

Replacement for bootstrap script in IPFS

Open darkdrgn2k opened this issue 7 years ago • 15 comments

mDNS is available on libp2p but does not seem to work

Investigate if its functioning, if so see if we can craft something that will work over CJDNS

darkdrgn2k avatar Aug 13 '18 15:08 darkdrgn2k

I am confused by title of this ticket, is this ipfs specific?

benhylau avatar Aug 13 '18 21:08 benhylau

@benhylau yes, it's for IPFS peering over CJDNS, using mDNS.

makew0rld avatar Aug 14 '18 01:08 makew0rld

@makeworld-the-better-one How can mDNS replace unicasting to cjdns peers? mDNS will only work in local networks, if you have multiple nodes in your home. We'd still need peering over cjdns interface address to link distant nodes.

I am imagining:

  1. Offline network, like Meshstream demo or Workshop use case
  2. Home node with IPFS peerings over Internet
  3. Home node with IPFS over cjdns even without Internet

Which case(s) is this trying to solve?

benhylau avatar Aug 14 '18 12:08 benhylau

How can mDNS replace unicasting to cjdns peers

You dont replace mDNS.

mDNS is a service that uses Multicasts/Broadcasts to LAN connected devices. So you are right it mDNS packets would never reach CJDNS targets because they would never be sent to them

However if mDNS does work on a LAN (the receiving device can understand and act upon a mDNS packet) we can use that to our advantage.

From the device that receives the packets, it does not really care how the packet got there (if it was multicast or broadcast or even unicast) it just knows it received a packet.

The idea is to craft a valid mDNS packet but instead of multicasting it to a lan (that would not work) unicast it to each peered cjdns addresses.

But this is all speculation, needs to be looked into and tested but if successful we can use a built-in mechanism in IPFS to convince it to peer with its cjdns neighbors.

First step is to see if mDNS works over a LAN in IPFS.

darkdrgn2k avatar Aug 15 '18 00:08 darkdrgn2k

Thanks for clarifying @darkdrgn2k. I feel like @jedahan may be interested in this discussion too. There were brief conversations about a generalized module with plugin-based architecture that peers peer-to-peer apps (e.g. ssb, ipfs) over a cjdns-like network via crafting of mDNS packets that are really IPv6 unicast to direct cjdns peers, as we have done in Meshstream.

benhylau avatar Aug 15 '18 22:08 benhylau

Proposing Unicast to bootstrap IPFS over cjdns peers as title?

benhylau avatar Aug 15 '18 22:08 benhylau

  1. For ipfs.service, we ask cjdns for a peerlist, and unicast the appropriate bencoded udp command for adding a peer.
  2. For ssb.service, we ask cjdns for a peerlist, and unicast the appropriate json udp advertisement for adding a peer.

The tricky parts are that its kinda hard to hook into the cjdns peerlist. Maybe it would be a nice feature to be able to ask cjdns to give a streaming response of new peers when its up.

The more generic, complicated, and probably less useful version:

  1. Have ipfs.service, ssb.service etc do mDNS broadcasts.
  2. Create an mDNS responder for broadcasts, that forward them over cjdns unicast.
  3. Have ipfs-mdns-listen.service, ssb-mdns-listen.service that translates mDNS records received over unicast to appropriate commands/advertisements locally.

jedahan avatar Aug 16 '18 03:08 jedahan

The tricky parts are that its kinda hard to hook into the cjdns peerlist.

Using existing tools

while read -r cjdns_peer; do
    cjdns_addr=$(sudo /opt/cjdns/publictoip6 $cjdns_peer)

done << `sudo nodejs /opt/cjdns/tools/peerStats 2>/dev/null | awk '{ if ($2 == "ESTABLISHED") print $1 }' | awk -F. '{ print $6".k" }' | xargs`

Hooking into API instead to get json

./cexec "InterfaceController_peerStats(0)"

Maybe it would be a nice feature to be able to ask cjdns to give a streaming response of new peers when its up.

Yes but it may be low on his priority list. But im thinking maybe a "spam" like ssb does would work

darkdrgn2k avatar Aug 16 '18 03:08 darkdrgn2k

First things we need to do is see if mDNS even WORKS with IPFS.

darkdrgn2k avatar Aug 16 '18 03:08 darkdrgn2k

I am proposing we write our own advertisements so we don't have to add support to cjdns

jedahan avatar Aug 16 '18 13:08 jedahan

Yes i was thinking about that as well. Writing our own UDP6 Unicast advertisement mechanism is trivial even in bash.

Server:

socat - udp6-listen:1234,reuseaddr,fork | while read LINE
do 
    echo "Do something with  ${LINE}"; 
done 

Broadcast

while read -r cjdns_peer; do
    cjdns_addr=$(sudo /opt/cjdns/publictoip6 $cjdns_peer)
    echo "hello i am $cjdns_peer do something with me" |  socat - UDP6-datagram:[$cjdns_addr]:1234
done <<< `sudo nodejs /opt/cjdns/tools/peerStats 2>/dev/null | awk '{ if ($2 == "ESTABLISHED") print $1 }' | awk -F. '{ print $6".k" }' | xargs`

Although this is my "last resort" way (better than what we currently do)

I'd rather have the "receiver" use some sort of native implementation, so that its not depended on our own services being installed.

That way if you run an plain vanilla IPFS without any of our "special sauce", I can still get it to peer.

Otherwise it would only work if our services are running on both.

This is why i want to investigate if

  • mDNS receiver actually work in IFPS
  • can we exploit mDNS packets to trigger ipfs to peer with us

Once you are able to complete your work on UDP6 Multicast SSB Component, we can use the same unicast code as above to push the unicast udp6 over cjdns to peer SSB that way.

darkdrgn2k avatar Aug 16 '18 15:08 darkdrgn2k

If we have the ipfs daemon running with admin port open, we wouldn't even need an mdns responder:

while read -r cjdns_peer; do
    cjdns_addr=$(sudo /opt/cjdns/publictoip6 $cjdns_peer)
    curl "http://${cjdns_peer}:5001/api/v0/bootstrap/add?arg=/ip6/${cjdns_addr}/tcp/1234"
done <<< `sudo nodejs /opt/cjdns/tools/peerStats 2>/dev/null | awk '{ if ($2 == "ESTABLISHED") print $1 }' | awk -F. '{ print $6".k" }' | xargs

which would maybe want me to just distribute in ipfs/contrib:

function pargs() {
  while read -r cjdns_peer; do
    cjdns_addr=$(sudo /opt/cjdns/publictoip6 $cjdns_peer)
    $*
  done <<< `sudo nodejs /opt/cjdns/tools/peerStats 2>/dev/null | awk '{ if ($2 == "ESTABLISHED") print $1 }' | awk -F. '{ print $6".k" }' | xargs
}

which could be called:

pargs curl "http://\${cjdns_peer}:5001/api/v0/bootstrap/add?arg=/ip6/\${cjdns_addr}/tcp/1234"

and for ssb:

secret_handshake=$(cd ~/mvd && node bin config | jq '.shs') # psuedocode
pargs  echo "net:\${cjdns_addr}:8008~shs:${secret_handshake} |  socat - UDP6-datagram:[$cjdns_peer]:8008

jedahan avatar Aug 16 '18 22:08 jedahan

If we have the ipfs daemon running with admin port open

ipfs says not to leave the api open to the world. I would agree!

darkdrgn2k avatar Aug 16 '18 22:08 darkdrgn2k

This Cabal use case is probably related to current discussion https://github.com/tomeshnet/prototype-cjdns-pi/issues/213#issuecomment-429432706

benhylau avatar Oct 12 '18 19:10 benhylau

Idea on multi hop advertising #385

darkdrgn2k avatar Jul 19 '19 22:07 darkdrgn2k