Skip to content
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

[RFC] peer discovery with mDNS #80

Merged
merged 14 commits into from
May 6, 2019
94 changes: 94 additions & 0 deletions discovery/mdns.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Multicast DNS
Author: Richard Schneider (makaretu@gmail.com)


## Overview

The goal is to allow peers to discover each other when on the same local network with zero configuration.
MDNS uses a multicast system of DNS records; this allows all peers on the local network to see all query responses.

Conceptually, it is very simple. When a peer starts (or detects a network change), it sends a query for all peers.
As responses come in, the peer adds the other peers information into is local database of peers.

## Definitions

`service-name` is the DNS-SD service name for all IPFS peers. It is defined as `_ipfs._udp.local`.
raulk marked this conversation as resolved.
Show resolved Hide resolved

`host-name` is the name of the peer. It is derived from the peer's ID and `ipfs.local`, for example
`Qmid.ipfs.local`.

`peer-id` is the ID of the peer. It normally is the base-58 enconding of the hash of the peer's public key.

`port` is a port that the peer listens on. Normally 4001.

## Peer Discovery

### Request

To find all peers, a DNS message is sent with the question `_ipfs._udp.local PTR`.
raulk marked this conversation as resolved.
Show resolved Hide resolved
Peers will then start responding with their details.

Note that a peer must respond to it's own query. Thus allows other peers to passively discover it.

### Response

On receipt of a `find all peers` query, a peer sends a DNS response message (QR = 1) that contains
the **answer**

<service-name> PTR <peer-id>.<service-name>

The **additional records** of the response contain the peer's discovery details

<peer-id>.<service-name> SRV ... <port> <host-name>
<peer-id>.<service-name> TXT ...
<host-name> A <ipv4 address>
<host-name> AAAA <ipv6 address>


Multiple A and AAAA records are expected. The `TXT` is not needed for IPFS peer discovery, but is required by DNS-SD.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, we'll need it for multiaddrs. We're able to get away with this for now but not once we enable QUIC by default. Ideally, we'd only use TXT records. However, we have to supply an A or AAAA record and also have to supply a port. Personally, I'm all for using our TCP port and real IP addresses when announcing but mostly ignoring them when accepting (unless we get no TXT records in which case we can try the IP/PORT from the other records).

Note: We'd probably want to use dnsaddr=/ip4/.../tcp/... as the format for TXT records.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TXT record dnsaddr=/full/address is a problem. Strings must be less than 128 bytes.

dnsaddr=/ip6/2406:e001:1467:1:ecec:9ca6:XXXX:XXXX/tcp/4009/ipfs/QmTp1fwYnJxc5rUEVM2xowcDiyR61J7yvmBRUQzT4g8MHs almost reaches this limit. If the peer-id hashing algorithm changes to sha2-512 then the byte limit is exceeded.

I strongly suggest that TXT dnsaddr is not used.

Copy link
Contributor Author

@richardschneider richardschneider Jul 24, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, we are just trying to discover peers on the local link. So to my thinking is that an IP address, port and peer ID is all that is needed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we send multiple records?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, we also have protocols like QUIC and may add other random protocols in the future. We also do need to put the peer ID somewhere.

It looks like the standard way to do this is to break it into multiple records. You can see how DKIM does it here: https://serverfault.com/questions/255580/how-do-i-enter-a-strong-long-dkim-key-into-dns

We could also use a base64 encoded binary multiaddr but I'd rather not.


#### Multiported Peers

If a peer is listening on multiple ports, it must respond with multiple `SRV` records for each
port it is listening on. If the ports do not listen on the same IP addresses, then each 'SRV' record
must have a different `host-name`.

#### Multiaddress

**TODO** from DNS records

**TODO** to DNS records

## DNS Service Discovery

DNS-SD support is not needed for IPFS peers to discover each other. However, it is
extremely usefull for network admistrators to discover what is running on the
network.

### Meta Query

This allows discovery of all services. The question is `_services._dns-sd._udp.local PTR`.

A peer responds with the answer

_services._dns-sd._udp.local PTR <service-name>
richardschneider marked this conversation as resolved.
Show resolved Hide resolved

### Gotchas

Many existing tools ignore the Additional Records and always send individual queries for the
peer's discovery details. To accomodate this, a peer should respond to the following queries:

- `<peer-id>.<service-name> SRV`
- `<peer-id>.<service-name> TXT`
- `<host-name> A`
- `<host-name> AAAA`

## References

- [RFC 1035 - Domain Names (DNS)](https://tools.ietf.org/html/rfc1035)
- [RFC 6762 - Multicast DNS](https://tools.ietf.org/html/rfc6762)
- [RFC 6763 - DNS-Based Service Discovery](https://tools.ietf.org/html/rfc6763)

## Worked Example

**TODO**