BEP:11
Title:Peer Exchange (PEX)
Version: 7ad40d1b62068015b7b846e7d248f3770d0e9b6a
Last-Modified:Tue Sep 26 11:16:44 2017 +0200
Author: The 8472 <the8472.bep@infinite-source.de>
Status: Accepted
Type:Standards Track
Created:29-Oct-2015
Depends:10
Post-History:22-Sep-2017 (the8472.bep@infinite-source.de), add section on handling swarm configurations that lead to underpopulated pex lists

Peer Exchange (PEX) provides an alternative peer discovery mechanism for swarms once peers have bootstrapped via other mechanisms such as DHT or Tracker announces.

It provides a more up-to-date view of the swarm than most other sources and also reduces the need to query other sources frequently.

When combined with BEP 40 [1] it provides a way to quickly randomize the connection graph of a swarm.

Protocol Extension

PEX introduces a new message ut_pex via the extension protocol [2].

added message negotiated in the handshake:

{
  m: {
    ut_pex: <implementation-dependent local message ID (positive integer)>,
    ...
  },
  ...
}

The extension message itself consists of the bittorrent/extension message header and the following bencoded payload:

{
  added: <one or more contacts in IPv4 compact format (string)>
  added.f: <optional, bit-flags, 1 byte per added IPv4 peer (string)>
  added6: <one or more contacts IPv6 compact format (string)>,
  added6.f: <optional, bit-flags, 1 byte per added IPv6 peer (string)>,
  dropped: <one or more contacts in IPv6 compact format (string)>,
  dropped6: <one or more contacts in IPv6 compact format (string)>
}

Flags are defined as follows:

Bit when set
0x01 prefers encryption, as indicated by e field in extension handshake
0x02 seed/upload_only
0x04 supports uTP
0x08 peer indicated ut_holepunch support in extension handshake
0x10 outgoing connection, peer is reachable

Other bits are reserved for future use. Implementors should submit a request to amend this BEP if they intend to introduce a new flag.

A peer must only be included in an added field once a connection is successfully established and included in the dropped field once it is disconnected. Once a peer has been added a client must ensure to send the corresponding dropped event when appropriate. Only signaling added peers without ever dropping them is non-compliant behavior.

Rationale: PEX is intended to reflect which peers a client is currently connected to, this ensures that PEX provides better liveness information than other peer discovery mechanisms.

Rationale 2: Only propagating verified peers reduces the opportunity for attackers to abuse bittorrent swarms for distributed denial-of-service attacks.

Clients must batch updates to send no more than 1 PEX message per minute.

It is not required to send a PEX message immediately after a handshake, e.g. during torrent startup a client may wait until it has established enough connections to make sending pex messages worthwhile.

Added or removed contacts must not contain duplicates.

Transient connect-disconnect or disconnect-reconnect events may be elided between update messages as long as it does not affect the correctness.

Implementation Note: A simple approach is to queue up not-yet-sent connect/disconnect events for each connected peer and performing elision when generating the message. An slightly more complex but more memory-efficient approach is to keep a per-torrent timeline of connect/disconnect events and simply store a pointer for the point in time up to which events have already been sent for each peer. When creating a PEX message they only need to advance the pointer, take care to eliminate duplicates and to elide transient connections.

An added contact must not be dropped in the same message.

Except for the initial PEX message the combined amount of added v4/v6 contacts should not exceed 50 entries. The same applies to dropped entries.

Messages must contain at least one of the following fields: added, added6, dropped, dropped6.

Clients may disconnect peers that egregiously violate these constraints.

Filling underpopulated lists

A combination of the

  • above liveness requirements
  • disconnecting seeds or partial seeds [3] while seeding
  • disconnecting duplicate peers based on peer IDs between ipv4 and ipv6

can lead to underpopulated added or added6 lists. This problem frequently arises in swarms dominated by seeds where the seeds have no live connections to propagate and the peers only have seeds they can propagate to other seeds, dramatically reducing PEX's effectiveness. Similarly this can make it difficult to obtain ipv6 peers in an ipv4 dominated swarm because ipv6 connections will be considered duplicates of already-established v4 ones, thus preventing their propagation via PEX.

To remedy these issues the liveness requirement is relaxed if a client is connected to less than 25 clients for a particular address family. In that situation it may keep a list of up to 25 most recently established and fully handshaken connections for that address family and record the disconnect reason for those connections. The following reasons for locally initiated disconnects qualify a remote contact for inclusion in the in the added or added6 lists:

  • the same peer ID was already connected under a different address family
  • permanent lack of mutual interest, e.g. inferred from (partial) seed status and piece availability
  • local resource limits such as a global connection counts were exceeded

When including such a recently disconnected contact in a pex message it must be drained from the recently seen list so it will not be sent again in the next message. When the list gets repopulated through transient connect-disconnect events those may be included in the next message if all necessary conditions are fulfilled. In other words in addition to populating the initial pex message from the recently seen list a client may effectively also skip some of the connect-disconnect elisions.

But since recently seen contacts do not represent live connections they must be dropped with the next PEX message.

The restriction that the same address must not be added and dropped within the same message must still be maintained.

The requirement of less than 25 live connections and limit of 25 recently seen ones is chosen so that at most two pex messages worth of droppable contacts can accumulate and that no stale information is sent when there are enough live contacts to populate pex messages.

Note that this exemption can be applied separately for IPv4 and IPv6. I.e. even if there are enough v4 live contacts a client may still include recently seen v6 contacts or vice versa if the respective lists would be underpopulated.

Security Considerations

Data exchanged via PEX messages should be considered untrusted and potentially malicious.

An attacker might try to sabotage a swarm by flooding it with bogus or other uncooperative peers.

PEX may also be used to cause a distributed denial of service attack by inducing bittorrent clients to perform connection attempts to victim IP ranges.

To mitigate these a client should avoid taking all its connection candidates from a single PEX source. Duplicate IP addresses (e.g. with different ports) should be ignored. Additionally Canonical Peer Priority [1] can help spreading connection attempts over many subnets, thus reducing the impact on any potential victim subnet.

References

[1](1, 2)

BEP 40, "Canonical Peer Priority"

http://bittorrent.org/beps/bep_0040.html

[2]

BEP 10, "Extension Protocol"

http://bittorrent.org/beps/bep_0010.html

[3]

BEP 21, "Extension for partial seeds"

http://bittorrent.org/beps/bep_0021.html