From a224492937dc2c93c6a084c2ea1bb7b7aa49d941 Mon Sep 17 00:00:00 2001 From: Yusef Napora Date: Mon, 11 Mar 2019 12:05:25 -0400 Subject: [PATCH 1/9] make multiplexing less specific to mplex --- content/reference/glossary.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/content/reference/glossary.md b/content/reference/glossary.md index 6a593868..4cbd6ba2 100644 --- a/content/reference/glossary.md +++ b/content/reference/glossary.md @@ -86,8 +86,9 @@ Multiplexing (or "muxing"), refers to the process of combining multiple streams Multiplexing allows peers to offer many [protocols](#protocol) over a single connection, which reduces network overhead and makes [NAT traversal](#nat-traversal) more efficient and effective. -Applications built with libp2p get multiplexing "for free" via the [mplex specification](https://github.com/libp2p/specs/tree/master/mplex). +libp2p supports several implementations of stream multiplexing. The [mplex specification](https://github.com/libp2p/specs/tree/master/mplex) defines a simple protocol with implementations in several languages. Other supported multiplexing protocols include [yamux](https://github.com/hashicorp/yamux) and [spdy](https://www.chromium.org/spdy/spdy-whitepaper). +See [Stream Muxer Implementations](https://libp2p.io/implementations/#stream-muxers) for status of multiplexing across libp2p language implementations. ### multistream From 06da7466ed12d0b7c964685b3e6fb16ffcb080a0 Mon Sep 17 00:00:00 2001 From: Yusef Napora Date: Tue, 12 Mar 2019 15:53:50 -0400 Subject: [PATCH 2/9] concept doc for nat traversal & circuit relay --- content/concepts/circuit-relay.md | 58 ++++++++++++++++++++++++ content/concepts/nat.md | 73 ++++++++++++++++++++++++++++++- 2 files changed, 129 insertions(+), 2 deletions(-) create mode 100644 content/concepts/circuit-relay.md diff --git a/content/concepts/circuit-relay.md b/content/concepts/circuit-relay.md new file mode 100644 index 00000000..1e035764 --- /dev/null +++ b/content/concepts/circuit-relay.md @@ -0,0 +1,58 @@ +--- +title: Circuit Relay +weight: 3 +--- + + +In some cases, peers will be unable to [traverse their NAT](/concepts/nat/) in a way that makes them publicly accessible. Or they may not share common [transport protocols](/concepts/transport/) that would allow them to communicate directly. + +To enable peer-to-peer architectures in the face of connectivity barriers like NAT, libp2p [defines a protocol called p2p-circuit][spec_relay]. This "circuit relay" protocol uses an intermediary peer to shuffle traffic between two peers that are unable to communicate directly. + +Circuit relay is useful for any situation where peers are unable to connect directly to each other. For example, peers running in a web browser are unable to directly dial a peer over TCP. A relay supporting websockets and TCP could act as an intermediary. + +{{% notice "note" %}} +Relay connections are end-to-end encrypted, which means that the peer acting as the relay is unable to read or tamper with any traffic that flows through the connection. +{{% /notice %}} + +An important aspect of the relay protocol is that it is not "transparent". In other words, both the source and destination are aware that traffic is being relayed. This is useful, since the destination can see the relay address used to open the connection and can potentially use it to construct a path back to the source. + +#### Relay addresses + +A "relay circuit" is identified using a [multiaddress][definition_muiltiaddress] that includes the [peer id](/concepts/peer-id/) of the peer whose traffic is being relayed (the listening peer or "relay target"). + +Let's say that I have a peer with the peer id `QmAlice`. I want to give out my address to my friend `QmBob`, but I'm behind a NAT that won't let anyone dial me directly. + +The most basic `p2p-circuit` address I can give out looks like this: + +`/p2p-circuit/p2p/QmAlice` + +The address above is interesting, because it doesn't include any [transport](/concepts/transport/) addresses for either the peer we want to contact (`QmAlice`) or for the relay peer that will convey the traffic. + +An address like the above effectively says "if you can find a relay node, you can try reaching me using my peer id `QmAlice`". In many cases, this is enough, since peers are able to discover relay nodes using a process called [AutoRelay](#autorelay). + +Now let's say that I've established a connection to a specific relay with the peer id `QmRelay`. They told me via the identify protocol that they're listening for TCP connections on port `55555` at IPv4 address `7.7.7.7`. I can construct an address that describes a path to me through that specific relay over that transport: + +`/ip4/7.7.7.7/tcp/55555/p2p/QmRelay/p2p-circuit/p2p/QmAlice` + +Everything prior to the `/p2p-circuit/` above is the address of the relay peer, which includes the transport address and their peer id `QmRelay`. After `/p2p-circuit/` is the peer id for my peer at the other end of the line, `QmAlice`. + +By giving the full relay path to my friend `QmBob`, they're able to quickly establish a relayed connection without "ask around" for a relay that has a route to `QmAlice`. + +#### AutoRelay + +The circuit relay protocol is only effective if peers can discover willing relay peers that are accessible to both sides of the relayed connection. + +We saw above how it's possible to construct relay addresses that don't specify any particular relay peers. To make use of such addresses, we need a way to discover relay peers that might be able to route our request. + +While it's possible to simply "hard-code" a list of well-known relays into your application, this adds a point of centralization to your architecture that you may want to avoid. This kind of bootstrap list is also a potential point of failure if the bootstrap nodes become unavailable. + +AutoRelay is a feature (currently implemented in go-libp2p) that a peer can enable to attempt to discover relay peers using libp2p's [content routing](/concepts/content-routing/) interface. + +When AutoRelay is enabled, a peer will try to discover one or more public relays and open relayed connections. If successful, the peer will advertise the relay addresses using the libp2p's [peer routing](/concepts/peer-routing/) system. + +{{% notice "note" %}} +Because relayed connections add overhead and consume the resources of the relay peer, go-libp2p will only try to establish relay connections if it determines that it is unreachable publicly using the [AutoNAT service](/concepts/nat/#autonat) +{{% /notice %}} + +[spec_relay]: https://github.com/libp2p/specs/tree/master/relay +[definition_muiltiaddress]: /reference/glossary/#mulitaddress diff --git a/content/concepts/nat.md b/content/concepts/nat.md index 7d91786c..9b725e58 100644 --- a/content/concepts/nat.md +++ b/content/concepts/nat.md @@ -3,6 +3,75 @@ title: NAT Traversal weight: 2 --- -This article is coming soon! +The internet is composed of countless networks, bound together into shared address spaces by foundational [transport protocols](/concepts/transport/). -Please [refer to this issue](https://github.com/libp2p/docs/issues/14) to track the progress and make suggestions. +As traffic moves between network boundaries, it's very common for a process called Network Address Translation to occur. Network Address Translation (NAT) maps an address from one address space to another. + +NAT allows many machines to share a single public address, and it is essential for the continued functioning of the IPv4 protocol, which would otherwise be unable to serve the needs of the modern networked population with its 32-bit address space. + +For example, when I connect to my home wifi, my computer gets an IPv4 address of `10.0.1.15`. This is part of a range of IP addresses reserved for internal use by private networks. When I make an outgoing connection to a public IP address, my router sends my *public* IP address, which is shared across all the machines on my home network. When the other side sends data back to that address, the router remembers to send the data to my internal address. + +While NAT is usually transparent for outgoing connections, listening for incoming connections requires some configuration. The router listens on a single public IP address, but any number of machines on the internal network could handle the request. To serve requests, your router must be configured to send certain traffic to a specific machine, usually by mapping one or more TCP or UDP ports from the public IP to an internal one. + +While it's usually possible to manually configure routers, not everyone that wants to run a peer-to-peer application or other network service will have the ability to do so. + +We want libp2p applications to run everywhere, not just in data centers or on machines with stable public IP addresses. To enable this, here are the main approaches to NAT traversal available in libp2p today. + +### Automatic router configuration + +Many routers support automatic configuration protocols for port forwarding, most commonly [UPnP][wiki_upnp] or [nat-pmp.][wiki_nat-pmp] + +If you router supports one of those protocols, libp2p will attempt to automatically configure a port mapping that will allow it to listen for incoming traffic. This is usually the simplest option if supported by the network and libp2p implementation. + +{{% notice "info" %}} +Support for automatic NAT configuration varies by libp2p implementation. +Check the [current implementation status](https://libp2p.io/implementations/#nat-traversal) for details. +{{% /notice %}} + +### Hole-punching (STUN) + +When an internal machine "dials out" and makes a connection to a public address, the router will map a public port to the internal IP address to use for the connection. In some cases, the router will also accept *incoming* connections on that port and route them to the same internal IP. + +libp2p will try to take advantage of this behavior when using IP-backed transports by using the same port for both dialing and listening, using a socket option called [`SO_REUSEPORT`](https://lwn.net/Articles/542629/). + +If our peer is in a favorable network environment, they will be able to make an outgoing connection and get a publicly-reachable listening port "for free," but they might never know it. Unfortunately, there's no way for the dialing program to discover what port was assigned to the connection on its own. + +However, an external peer can can tell us what address they observed us on. We can then take that address and advertise it to other peers in our [peer routing network](/concepts/peer-routing/) to let them know where to find us. + +This basic premise of peers informing each other of their observed addresses is the foundation of [STUN][wiki_stun] (Session Traversal Utilities for NAT), which [describes][rfc_stun] a client / server protocol for discovering publicly reachable IP address and port combinations. + +One of libp2p's core protocols is the [identify protocol][spec_identify], which allows one peer to ask another for some identifying information. When sending over their [public key](/concepts/peer-id/) and some other useful information, the peer being identified includes the set of addresses that it has observed for the peer asking the question. + +This external discovery mechanism serves the same role as STUN, but without the need for a set of "STUN servers". + +The identify protocol allows some peers to communicate across NATs that would otherwise be impenetrable. + +### AutoNAT + +While the [identify protocol][spec_identify] described above lets peers inform each other about their observed network addresses, not all networks will allow incoming connections on the same port used for dialing out. + +Once again, other peers can help us observe our situation, this time by attempting to dial us at our observed addresses. If this succeeds, we can rely on other peers being able to dial us as well and we can start advertising our listen address. + +A libp2p protocol called AutoNAT lets peers request dial-backs from peers providing the AutoNAT service. + +{{% notice "info" %}} +AutoNAT is currently implemented in go-libp2p via [go-libp2p-autonat](https://github.com/libp2p/go-libp2p-autonat). +{{% /notice %}} + + +### Circuit Relay (TURN) + +In some cases, peers will be unable to traverse their NAT in a way that makes them publicly accessible. + +libp2p provides a [Circuit Relay protocol](/concepts/circuit-relay/) that allows peers to communicate indirectly via a helpful intermediary peer. + +This serves a similar function to the [TURN protocol](https://tools.ietf.org/html/rfc5766) in other systems. + +[wiki_upnp]: https://en.wikipedia.org/wiki/Universal_Plug_and_Play +[wiki_nat-pmp]: https://en.wikipedia.org/wiki/NAT_Port_Mapping_Protocol +[wiki_stun]: https://en.wikipedia.org/wiki/STUN +[rfc_stun]: https://tools.ietf.org/html/rfc3489 +[lwn_reuseport]: https://lwn.net/Articles/542629/ + + +[spec_identify]: https://github.com/libp2p/specs/pull/97 From 4d1909f4bea3f9542b19bcd6339024e0d27aeee0 Mon Sep 17 00:00:00 2001 From: Yusef Napora Date: Tue, 12 Mar 2019 15:54:05 -0400 Subject: [PATCH 3/9] stub doc for content routing --- content/concepts/content-routing.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 content/concepts/content-routing.md diff --git a/content/concepts/content-routing.md b/content/concepts/content-routing.md new file mode 100644 index 00000000..8d212cbc --- /dev/null +++ b/content/concepts/content-routing.md @@ -0,0 +1,8 @@ +--- +title: Content Routing +weight: 5 +--- + +This article is coming soon! + +Please [refer to this issue](https://github.com/libp2p/docs/issues/23) to track the progress and make suggestions. From 56c75736e958961eadfeb01e55540728de262b66 Mon Sep 17 00:00:00 2001 From: Yusef Napora Date: Tue, 12 Mar 2019 16:03:41 -0400 Subject: [PATCH 4/9] update deploy image in circle config --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 7fa44aa7..4213a773 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -14,7 +14,7 @@ jobs: deploy: docker: - - image: olizilla/ipfs-dns-deploy:1.1 + - image: olizilla/ipfs-dns-deploy:latest environment: DOMAIN: docs.libp2p.io BUILD_DIR: public From 82b010025689ab416443dac75f5b4884cd70ec25 Mon Sep 17 00:00:00 2001 From: Yusef Napora Date: Tue, 12 Mar 2019 16:05:06 -0400 Subject: [PATCH 5/9] Revert "update deploy image in circle config" 56c75736e958961eadfeb01e55540728de262b66 --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 4213a773..7fa44aa7 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -14,7 +14,7 @@ jobs: deploy: docker: - - image: olizilla/ipfs-dns-deploy:latest + - image: olizilla/ipfs-dns-deploy:1.1 environment: DOMAIN: docs.libp2p.io BUILD_DIR: public From 840afb8c28a7917dc77d5aa38654720abada5f65 Mon Sep 17 00:00:00 2001 From: Yusef Napora Date: Wed, 13 Mar 2019 10:36:25 -0400 Subject: [PATCH 6/9] small fixes --- content/concepts/circuit-relay.md | 4 ++-- content/reference/glossary.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/content/concepts/circuit-relay.md b/content/concepts/circuit-relay.md index 1e035764..652fd985 100644 --- a/content/concepts/circuit-relay.md +++ b/content/concepts/circuit-relay.md @@ -36,7 +36,7 @@ Now let's say that I've established a connection to a specific relay with the pe Everything prior to the `/p2p-circuit/` above is the address of the relay peer, which includes the transport address and their peer id `QmRelay`. After `/p2p-circuit/` is the peer id for my peer at the other end of the line, `QmAlice`. -By giving the full relay path to my friend `QmBob`, they're able to quickly establish a relayed connection without "ask around" for a relay that has a route to `QmAlice`. +By giving the full relay path to my friend `QmBob`, they're able to quickly establish a relayed connection without having to "ask around" for a relay that has a route to `QmAlice`. #### AutoRelay @@ -48,7 +48,7 @@ While it's possible to simply "hard-code" a list of well-known relays into your AutoRelay is a feature (currently implemented in go-libp2p) that a peer can enable to attempt to discover relay peers using libp2p's [content routing](/concepts/content-routing/) interface. -When AutoRelay is enabled, a peer will try to discover one or more public relays and open relayed connections. If successful, the peer will advertise the relay addresses using the libp2p's [peer routing](/concepts/peer-routing/) system. +When AutoRelay is enabled, a peer will try to discover one or more public relays and open relayed connections. If successful, the peer will advertise the relay addresses using libp2p's [peer routing](/concepts/peer-routing/) system. {{% notice "note" %}} Because relayed connections add overhead and consume the resources of the relay peer, go-libp2p will only try to establish relay connections if it determines that it is unreachable publicly using the [AutoNAT service](/concepts/nat/#autonat) diff --git a/content/reference/glossary.md b/content/reference/glossary.md index 4cbd6ba2..d8d736bc 100644 --- a/content/reference/glossary.md +++ b/content/reference/glossary.md @@ -176,7 +176,7 @@ Kademlia routing algorithm to efficiently locate peers. ### Peer-to-peer (p2p) -A peer-to-peer (p2p) network is one in which the participants (referred to as [peers][#peer] or [nodes](#node)) communicate with one another directly, on more or less "equal footing". This does not necessarily mean that all peers are identical; some may have different roles in the overall network. However, one of the defining characteristics of a peer-to-peer network is that they do not require a privileged set of "servers" which behave completely differently from their "clients", as is the case in the the predominant [client / server model](#client-server). +A peer-to-peer (p2p) network is one in which the participants (referred to as [peers](#peer) or [nodes](#node)) communicate with one another directly, on more or less "equal footing". This does not necessarily mean that all peers are identical; some may have different roles in the overall network. However, one of the defining characteristics of a peer-to-peer network is that they do not require a privileged set of "servers" which behave completely differently from their "clients", as is the case in the the predominant [client / server model](#client-server). ### Pubsub From 61840dec8849964a5631c6a28e8cdc14cdc4607b Mon Sep 17 00:00:00 2001 From: Yusef Napora Date: Wed, 13 Mar 2019 14:21:22 -0400 Subject: [PATCH 7/9] add @raulk's autorelay content from filecoin doc --- content/concepts/circuit-relay.md | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/content/concepts/circuit-relay.md b/content/concepts/circuit-relay.md index 652fd985..65384766 100644 --- a/content/concepts/circuit-relay.md +++ b/content/concepts/circuit-relay.md @@ -28,7 +28,7 @@ The most basic `p2p-circuit` address I can give out looks like this: The address above is interesting, because it doesn't include any [transport](/concepts/transport/) addresses for either the peer we want to contact (`QmAlice`) or for the relay peer that will convey the traffic. -An address like the above effectively says "if you can find a relay node, you can try reaching me using my peer id `QmAlice`". In many cases, this is enough, since peers are able to discover relay nodes using a process called [AutoRelay](#autorelay). +An address like the above effectively says "if you can find a relay node, you can try reaching me using my peer id `QmAlice`". In many cases, this is enough, since peers are able to discover relay nodes using a process called [Autorelay](#autorelay). Now let's say that I've established a connection to a specific relay with the peer id `QmRelay`. They told me via the identify protocol that they're listening for TCP connections on port `55555` at IPv4 address `7.7.7.7`. I can construct an address that describes a path to me through that specific relay over that transport: @@ -38,7 +38,7 @@ Everything prior to the `/p2p-circuit/` above is the address of the relay peer, By giving the full relay path to my friend `QmBob`, they're able to quickly establish a relayed connection without having to "ask around" for a relay that has a route to `QmAlice`. -#### AutoRelay +#### Autorelay The circuit relay protocol is only effective if peers can discover willing relay peers that are accessible to both sides of the relayed connection. @@ -46,13 +46,28 @@ We saw above how it's possible to construct relay addresses that don't specify a While it's possible to simply "hard-code" a list of well-known relays into your application, this adds a point of centralization to your architecture that you may want to avoid. This kind of bootstrap list is also a potential point of failure if the bootstrap nodes become unavailable. -AutoRelay is a feature (currently implemented in go-libp2p) that a peer can enable to attempt to discover relay peers using libp2p's [content routing](/concepts/content-routing/) interface. +Autorelay is a feature (currently implemented in go-libp2p) that a peer can enable to attempt to discover relay peers using libp2p's [content routing](/concepts/content-routing/) interface. -When AutoRelay is enabled, a peer will try to discover one or more public relays and open relayed connections. If successful, the peer will advertise the relay addresses using libp2p's [peer routing](/concepts/peer-routing/) system. +When Autorelay is enabled, a peer will try to discover one or more public relays and open relayed connections. If successful, the peer will advertise the relay addresses using libp2p's [peer routing](/concepts/peer-routing/) system. -{{% notice "note" %}} -Because relayed connections add overhead and consume the resources of the relay peer, go-libp2p will only try to establish relay connections if it determines that it is unreachable publicly using the [AutoNAT service](/concepts/nat/#autonat) -{{% /notice %}} +##### How Autorelay works + +The Autorelay service is responsible for: + +1. discovering relay nodes around the world, +2. establishing long-lived connections to them, and +3. advertising relay-enabled addresses for ourselves to our peers, thus making ourselves routable through delegated routing. + +When [AutoNAT service](/concepts/nat/#autonat) detects we're behind a NAT that blocks inbound connections, Autorelay jumps into action, and the following happens: + +1. We locate candidate relays by running a DHT provider search for the `/libp2p/relay` namespace. +2. We select three results at random, and establish a long-lived connection to them (`/libp2p/circuit/relay/0.1.0` protocol). Support for using latency as a selection heuristic will be added soon. +3. We enhance our local address list with our newly acquired relay-enabled multiaddrs, with format: `/ip4/1.2.3.4/tcp/4001/p2p/QmRelay/p2p-circuit`, where: + `1.2.3.4` is the relay's public IP address, `4001` is the libp2p port, and `QmRelay` is the peer ID of the relay. + Elements in the multiaddr can change based on the actual transports at use. +4. We announce our new relay-enabled addresses to the peers we're already connected to via the `IdentifyPush` protocol. + +The last step is crucial, as it enables peers to learn our updated addresses, and in turn return them when another peer looks us up. [spec_relay]: https://github.com/libp2p/specs/tree/master/relay [definition_muiltiaddress]: /reference/glossary/#mulitaddress From f5b672d7dc6820f10ee6d69d3859e8d8782a0fa4 Mon Sep 17 00:00:00 2001 From: Yusef Napora Date: Thu, 14 Mar 2019 11:56:22 -0400 Subject: [PATCH 8/9] clarify IP translation example --- content/concepts/nat.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/concepts/nat.md b/content/concepts/nat.md index 9b725e58..d996f4f0 100644 --- a/content/concepts/nat.md +++ b/content/concepts/nat.md @@ -9,7 +9,7 @@ As traffic moves between network boundaries, it's very common for a process call NAT allows many machines to share a single public address, and it is essential for the continued functioning of the IPv4 protocol, which would otherwise be unable to serve the needs of the modern networked population with its 32-bit address space. -For example, when I connect to my home wifi, my computer gets an IPv4 address of `10.0.1.15`. This is part of a range of IP addresses reserved for internal use by private networks. When I make an outgoing connection to a public IP address, my router sends my *public* IP address, which is shared across all the machines on my home network. When the other side sends data back to that address, the router remembers to send the data to my internal address. +For example, when I connect to my home wifi, my computer gets an IPv4 address of `10.0.1.15`. This is part of a range of IP addresses reserved for internal use by private networks. When I make an outgoing connection to a public IP address, the router replaces my internal IP with its own public IP address. When data comes back from the other side, the router will translate back to the internal address. While NAT is usually transparent for outgoing connections, listening for incoming connections requires some configuration. The router listens on a single public IP address, but any number of machines on the internal network could handle the request. To serve requests, your router must be configured to send certain traffic to a specific machine, usually by mapping one or more TCP or UDP ports from the public IP to an internal one. From 95e421f72dfada9a480a332e8227a76d14c9e7ef Mon Sep 17 00:00:00 2001 From: Yusef Napora Date: Thu, 14 Mar 2019 12:02:23 -0400 Subject: [PATCH 9/9] pull in PR feedback --- content/concepts/circuit-relay.md | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/content/concepts/circuit-relay.md b/content/concepts/circuit-relay.md index 65384766..8afce04d 100644 --- a/content/concepts/circuit-relay.md +++ b/content/concepts/circuit-relay.md @@ -3,34 +3,35 @@ title: Circuit Relay weight: 3 --- +Circuit relay is a [transport protocol](/concepts/transport/) that routes traffic between two peers over a third-party "relay" peer. -In some cases, peers will be unable to [traverse their NAT](/concepts/nat/) in a way that makes them publicly accessible. Or they may not share common [transport protocols](/concepts/transport/) that would allow them to communicate directly. +In many cases, peers will be unable to [traverse their NAT](/concepts/nat/) in a way that makes them publicly accessible. Or they may not share common [transport protocols](/concepts/transport/) that would allow them to communicate directly. -To enable peer-to-peer architectures in the face of connectivity barriers like NAT, libp2p [defines a protocol called p2p-circuit][spec_relay]. This "circuit relay" protocol uses an intermediary peer to shuffle traffic between two peers that are unable to communicate directly. +To enable peer-to-peer architectures in the face of connectivity barriers like NAT, libp2p [defines a protocol called p2p-circuit][spec_relay]. When a peer isn't able to listen on a public address, it can dial out to a relay peer, which will keep a long-lived connection open. Other peers will be able to dial through the relay peer using a `p2p-circuit` address, which will forward traffic to its destination. -Circuit relay is useful for any situation where peers are unable to connect directly to each other. For example, peers running in a web browser are unable to directly dial a peer over TCP. A relay supporting websockets and TCP could act as an intermediary. +The circuit relay protocol is inspired by [TURN](https://tools.ietf.org/html/rfc5766), which is part of the [Interactive Connectivity Establishment](https://tools.ietf.org/html/rfc8445) collection of NAT traversal techniques. {{% notice "note" %}} Relay connections are end-to-end encrypted, which means that the peer acting as the relay is unable to read or tamper with any traffic that flows through the connection. {{% /notice %}} -An important aspect of the relay protocol is that it is not "transparent". In other words, both the source and destination are aware that traffic is being relayed. This is useful, since the destination can see the relay address used to open the connection and can potentially use it to construct a path back to the source. +An important aspect of the relay protocol is that it is not "transparent". In other words, both the source and destination are aware that traffic is being relayed. This is useful, since the destination can see the relay address used to open the connection and can potentially use it to construct a path back to the source. It is also not anonymous - all participants are identified using their peer id, including the relay node. #### Relay addresses -A "relay circuit" is identified using a [multiaddress][definition_muiltiaddress] that includes the [peer id](/concepts/peer-id/) of the peer whose traffic is being relayed (the listening peer or "relay target"). +A relay circuit is identified using a [multiaddr][definition_muiltiaddress] that includes the [peer id](/concepts/peer-id/) of the peer whose traffic is being relayed (the listening peer or "relay target"). Let's say that I have a peer with the peer id `QmAlice`. I want to give out my address to my friend `QmBob`, but I'm behind a NAT that won't let anyone dial me directly. -The most basic `p2p-circuit` address I can give out looks like this: +The most basic `p2p-circuit` address I can construct looks like this: `/p2p-circuit/p2p/QmAlice` -The address above is interesting, because it doesn't include any [transport](/concepts/transport/) addresses for either the peer we want to contact (`QmAlice`) or for the relay peer that will convey the traffic. +The address above is interesting, because it doesn't include any [transport](/concepts/transport/) addresses for either the peer we want to contact (`QmAlice`) or for the relay peer that will convey the traffic. Without that information, the only chance a peer has of dialing me is to discover a relay and hope they have a connection to me. -An address like the above effectively says "if you can find a relay node, you can try reaching me using my peer id `QmAlice`". In many cases, this is enough, since peers are able to discover relay nodes using a process called [Autorelay](#autorelay). +A better address would be something like `/p2p/QmRelay/p2p-circuit/p2p/QmAlice`. This includes the identity of a specific relay peer, `QmRelay`. If a peer already knows how to open a connection to `QmRelay`, they'll be able to reach us. -Now let's say that I've established a connection to a specific relay with the peer id `QmRelay`. They told me via the identify protocol that they're listening for TCP connections on port `55555` at IPv4 address `7.7.7.7`. I can construct an address that describes a path to me through that specific relay over that transport: +Better still is to include the transport addresses for the relay peer in the address. Let's say that I've established a connection to a specific relay with the peer id `QmRelay`. They told me via the identify protocol that they're listening for TCP connections on port `55555` at IPv4 address `7.7.7.7`. I can construct an address that describes a path to me through that specific relay over that transport: `/ip4/7.7.7.7/tcp/55555/p2p/QmRelay/p2p-circuit/p2p/QmAlice` @@ -38,18 +39,24 @@ Everything prior to the `/p2p-circuit/` above is the address of the relay peer, By giving the full relay path to my friend `QmBob`, they're able to quickly establish a relayed connection without having to "ask around" for a relay that has a route to `QmAlice`. +{{% notice "tip" %}} +When [advertising your address](/concepts/peer-routing/), it's best to provide relay addresses that include the transport address of the relay peer. If the relay has many transport addresses, you can advertise a `p2p-circuit` through each of them. +{{% /notice %}} + #### Autorelay The circuit relay protocol is only effective if peers can discover willing relay peers that are accessible to both sides of the relayed connection. -We saw above how it's possible to construct relay addresses that don't specify any particular relay peers. To make use of such addresses, we need a way to discover relay peers that might be able to route our request. - While it's possible to simply "hard-code" a list of well-known relays into your application, this adds a point of centralization to your architecture that you may want to avoid. This kind of bootstrap list is also a potential point of failure if the bootstrap nodes become unavailable. Autorelay is a feature (currently implemented in go-libp2p) that a peer can enable to attempt to discover relay peers using libp2p's [content routing](/concepts/content-routing/) interface. When Autorelay is enabled, a peer will try to discover one or more public relays and open relayed connections. If successful, the peer will advertise the relay addresses using libp2p's [peer routing](/concepts/peer-routing/) system. +{{% notice "warning" %}} +Autorelay is under active development and should be considered experimental. There are currently no protections against malicious or malfunctioning relays which could advertise relay services and refuse to provide them. +{{% /notice %}} + ##### How Autorelay works The Autorelay service is responsible for: