Passive Mode C-C Connections and NAT Traversal
February 13, 2010 Leave a comment
Disclaimer: DC++ 0.76 does not support NAT traversal. DC++ 0.76+1 will support it only for ADC.
Currently, at least one user in a connecting C-C pair must have enabled active mode. NAT traversal ameliorates the problem of neither party having correctly configured active mode. Because about half of DC clients tend to use passive mode, approximately a quarter of possible pairs of DC users, DC++ currently has no means by which to directly transfer files. Commonly, these dual passive modes result from both such users having either a firewall or NAT device blocking inbound connections; in such cases NAT traversal can help.
This post summarizes how DC++ forms client-client connections, including active mode, passive mode, and using NAT traversal. Technical details on NAT traversal will appear in future posts; this post intentionally elides detail.
Several cases exist pertaining to client-client connection establishment. The easiest involves the requesting client sending a $ConnectToMe/CTM across the hub to the other client with its IP address and port. The contacted client then establishes a TCP connection to the specified address. The next easiest situation, also handled by DC++, involves a passive client A sending $RevConnectToMe/RCM to active client B, which then responds with $ConnectToMe/CTM and proceeds as in the first case. DC++ has handled both of these cases since its inception, with the following diagram showing schematically how RCM->CTM->connection works, where S represents the DC hub and client A represents that passive user sending first $RevConnectToMe/RCM:
The remaining case involves two passive users attempting to connect. Currently, a successful response to a $ConnectToMe/CTM represents a necessary and sufficient condition for the existence of a client-client connection, as ordinarily the TCP connections underlying client-client connections result from a pair of connecting and listening sockets. Without either client A or client B being able to perform the latter role, no connection can result.
In particular, NAT (Network Address Translation) involves the NAT device at 188.8.131.52 watching for outgoing packets from client A at 10.0.0.1 and rewriting them such that external hosts see them as having originated from 184.108.40.206 whilst simultaneously checking incoming packets for belonging to an already established (in the case of TCP) connections initiated by a host on that NAT device’s internal network, rewriting the packet destination address as 10.0.0.1, and forwarding it back along to client A. These actions effect a mostly-intact, backwards-compatible illusion that client A is directly connected to the internet while allowing the NAT device at 220.127.116.11 to multiplex packets from and to many private IP addresses through its one public IP.
However, because to an external host, packets originating from client A (10.0.0.1) appear to originate from 18.104.22.168, any responses will be sent to the NAT device (22.214.171.124) rather than A directly (10.0.0.1, which could easily be a wholly separate host for client B regardless). The NAT device must thus keep track of which extant packet streams it should redirect to which internal hosts (client A and other hosts within that network), usually by tracking which ports are held by connections from which internal hosts, watching for packets to those ports, and shunting them along to the waiting internal host.
One can use this session-tracking mechanism to punch holes in NATs, so long as one knows the port in question, by sending packets into the hole punched by that existing TCP connection: if the NAT device at 126.96.36.199 sees an incoming packet to port 4321 and already knows that port 4321 is held by client A at 10.0.0.1 for an existing outbound connection (to server S), it can route that packet to client A – even if the packet forms a new connection. This forms the basis of NAT traversal, by which one can form client-client connections through NAT devices.
DC++ will often thus be able to use the NAT mappings created by existing A-S and B-S connections to bootstrap a new direct A-B client-client connection, even if both A and B are in passive mode, allowing many formerly mutually inaccessible pairs of passive-mode users to directly transfer files.