Home > Specs > BitTorrent > Peer Connections
Hole Punching
Hole punching works in conjunction with
PEX. When connecting to the peer of a remote peer, a holepunch request is sent to the common connected peer, which is then forwarded to the prospective peer that a connection attempt is being made to. The prospective peer will then attempt an outgoing connection or just send a packet to the local peer, so that a pathway will be established in it's NAT router or firewall, allowing the local peer to send it's connection initiating packet in the opposite direction.
This only works with connections made over
UDP. TCP can not be holepunched.
All holepunch requests, relayed requests, and responses are sent via an extended message. It starts with the message type 20 (one byte), followed by the ut_holepunch sub-type (one byte) that was specified in the initial extended handshake. The next byte is an action code:
0
This is the initial request sent to the common peer. The action code is followed by a single byte that is either a 0 for IPv4 target or a 1 for IPv6 target. Then comes the IP address (4 or 16 bytes) and big-endian two-byte port for the target peer that we want to connect to.
1
The common peer, upon receiving the initial request, sends this message to the target peer AND back to the initiating peer. It is exactly like the initial request, except, only in the message going to the target peer, the address will instead be that of the initiator. Upon receiving this, the target peer may try connecting to the initiating peer specified in the message, or simply send a short hole-punching packet to open a path through the router or firewall. The initiating peer, upon receiving this message reflected back, can check if it already has a peer matching the specified address in the process of connecting (which it generally should) and simply discard the message.
2
If the initial request can't be fulfilled by the common peer, it will send this message back to the initiating peer. It is exactly the same as the initial request, except with a four byte big-endian integer error code appended. The error codes are:
1
The common peer is not connected to the target peer, or the address may be invalid.
2
The common peer is not connected to the target peer.
3
The target peer does not support the ut_holepunch extension.
4
The target peer is the same as the initiating peer.
21
Requests will not be processed because the initiating peer has an inconsistent source port.
25
The request was rate-limited.
Some clients will append a little-endian error code instead of big-endian. The best way to handle this is check if the received error code is greater than 65535 and do an endian-flip if needed. It seems that the original BitTorrent client and utorrent use little-endian, and libtorrent derivatives use big-endian. Tixati can accept either and will send either depending on the remote client.
Error code 1 and 2 are used interchangeably. Original BitTorrent, utorrent, and Tixati use code 1 for peers that are not connected, and libtorrent derivatives seem to use error code 2 in the same situation.
It should also be noted that hole punching does not work on every network. Many will alter the source port of outgoing packets in a way that differs depending on the destination IP address, making it impossible to know the source port a hole punched connection will come. Two clients on such networks are very unlikely to connect to each other, even with hole punching.