What is Circuit Relay?
Circuit relay is a transport protocol that routes traffic between two peers over a third-party “relay” peer.
In many cases, peers will be unable to traverse their NAT and/or firewall in a way that makes them publicly accessible. Or they may not share common transport protocols 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. 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.
The circuit relay protocol is inspired by TURN, which is part of the Interactive Connectivity Establishment collection of NAT traversal techniques.
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.
Today there are two versions of the circuit relay protocol, v1 and v2. We recommend using the latter over the former. See the circuit relay v2 specification for a detailed comparison of the two. If not explicitly noted, this document describes the circuit relay v2 protocol.
A relay circuit is identified using a multiaddr that includes the 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 construct looks like this:
The address above is interesting, because it doesn’t include any 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.
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.
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
198.51.100.0. I can construct an address that describes a path to me through that specific relay over that transport:
Everything prior to the
/p2p-circuit/ above is the address of the relay peer, which includes the transport address and their Peer ID
/p2p-circuit/ is the Peer ID for my peer at the other end of the line,
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
p2p-circuitthrough each of them.
The below sequence diagram depicts a sample relay process:
Ais behind a NAT and/or firewall, e.g. detected via the AutoNAT service.
Atherefore requests a reservation with relay
R. I.e. node
Rto listen for incoming connections on its behalf.
Bwants to establish a connection to node
A. Given that node
Adoes not advertise any direct addresses but only a relay address, node
Bconnects to relay
R, asking relay
Rto relay a connection to
Rforwards the connection request to node
Aand eventually relays all data send by