DC++ protocol negotiation via ALPN

Updated: 2019-01-02

Rationale
Since the beginning, many developers noted flaws and mistakes made by the authors of NMDC protocol. However, ADC protocol that was introduced to fix NMDC issues failed to replace it. DC++ network is still dominated by NMDC hubs, while most clients support both NMDC and ADC protocols.

One of the possible reasons for hubs to continue using NMDC may be the fact that protocol handshakes are incompatible, and it was not possible for a hub to upgrade the protocol without breaking existing users.

Some hub software developed workarounds to support both protocols (see Flexhub). It is usually done by waiting a certain amount of time for the client to send ADC handshake, and if it was not received - server will initiate NMDC handshake. Still, this workaround was not widely deployed.

This lead to a situation when DC++ network protocol becomes effectively frozen and it’s nearly impossible to improve the base protocol.

To solve this issue, another mechanism based on ALPN is proposed.

ALPN
Since HTTP/2 was introduced, all major browsers required TLS (HTTPS) support to enable the new protocol. To minimize handshakes that are necessary to agree on using the new protocol on a specific connection, the protocol negotiation process was built into the TLS. This mechanism is called Application-Layer Protocol Negotiation (ALPN).

The negotiation begins when the client sends ClientHello TLS message with a list of supported protocols. The server picks a preffered protocol and sends it back with a ServerHello. If the TLS handshake is successful, application can start using the selected protocol over established TLS connection without further negotiation.

For the specification, see https://tools.ietf.org/html/rfc7301

Proposal
The proposed solution is to implement DC++ protocol negotiation at the TLS level by using ALPN. Note, that the negotiation applies only to TLS connections.

NMDC

Client-to-Hub
NMDC protocol defines no standard URI scheme for signalling a TLS support on the connection. Instead, TLS may be enable after successful feature negotiation.

The proposal is to reuse adcs:// URI scheme for establishing a secure NMDC connection to a hub. The client should set an nmdc name in ALPN’s list of supported protocols. If the server does not support ALPN, TLS+ADC protocol should be assumed. If the server supports ALPN, and TLS handshake is successful, NMDC protocol handshake begins over established TLS connection as usual.

The client and hub should not signal TLS support in $Supports after negotiating NMDC protocol using ALPN.

Client-to-Client
NMDC TLS extensions allows adding S suffix to a peer address to initiate a secure connection.

The client should add nmdc name in ALPN’s list of supported protocols. If peer does not support ALPN, TLS+NMDC protocol should be assumed. If TLS handshake is successful, NMDC protocol handshake begins over established TLS connection as usual.

Clients should not signal TLS support in $Supports after negotiating NMDC protocol using ALPN.

ADC
ADC protocol supports establishing TLS by specifying a adcs:// URL scheme.

When establishing connection with either adcs:// scheme in URI (client-to-hub) or ADCS/1.0 (client-to-client), the client should set a adc value in ALPN’s list of supported protocols. If the hub or peer does not support ALPN, TLS+ADC protocol should be assumed. If TLS handshake is successful, ADC protocol handhsake begins over established TLS connection as usual.

Implications

New DC++ protocols
Accepting ALPN as a standard way of negotiating DC++ protocol opens possibilities for the new experimenting protocols to be tested. For example, clients and hubs may change ADC or NMDC command encoding to improve network performance, or introduce a different protocol. Adding support for new protocols will be as easy as adding a new value to ALPN protocol list. This mechanism was already successfully used to coordinate HTTP/1.1->SPDY->HTTP/2 transition.

HTTPS pingers
Currently, pingers are required to implement NMDC/ADC protocols to get live hub information and/or a list of hub users. With ALPN it will be possible to reuse the same port for both DC++ and HTTP connections. The hub can then serve a single /users.json or /users.xml file over HTTP for pingers to download. This way a pinger won’t need to support the DC++ protocol, and will only need to send a single HTTPS GET request.

Secure DC++ network
This proposal may also make DC++ network more secure by forcing hub owners to enable TLS.

It also looks like this may allow client-client connections for hybrid (NMDC+ADC) hubs.

Hubs may translate CTM commands between NMDC and ADC, replacing the protocol to the one used by the client-hub connection. And when the client will tries to initialize P2P connection, ALPN will determine if the protocol should be ADC or NMDC.

For example, client A speaks NMDC protocol to the hub, and client B speaks ADC to the same hub. Let’s also assume that client A does not support ADC protocol.

1.1) Client B listens for TLS connections and sets ALPN protocols to

adc, nmdc

.

1.2) Client B sends

DCTM BBBB CCCC ADCS/1.0 7777 123456789

to client A.

  1. Hub translates this request to
$ConnectToMe userB 192.168.1.2:7777S|

and sends it to client A.

  1. Client A initiates a TLS connection to client B, setting ALPN protocols list to
nmdc

.

  1. Client B receives a new TLS connection and the only mutual protocol supported is NMDC, so it automatically switches to NMDC, instead of ADC as it was expecting due to the hub connection.

See and updated proposal on the Github.