OK, here's a draft draft on the issue. I think this is in keeping with your mail, but provides background too, and I think changes how IANA allocates DCCP ports. Comments? Flames? Shall I turn this into a proper draft, or is there disagreement on this? Cheers, Mark
On the Use of DCCP Service Codes ================================ Mark Handley, UCL, 25th July 2007 Introduction ------------ The Datagram Congestion Control Protocol (DCCP) includes a 32-bit Service Code in the DCCP-Request packet used to initiate a DCCP connection. RFC 4340 includes the following text describing service codes: Each DCCP-Request contains a 32-bit Service Code, which identifies the application-level service to which the client application is trying to connect. Service Codes should correspond to application services and protocols. For example, there might be a Service Code for SIP control connections and one for RTP audio connections. Middleboxes, such as firewalls, can use the Service Code to identify the application running on a nonstandard port (assuming the DCCP header has not been encrypted). Endpoints MUST associate a Service Code with every DCCP socket, both actively and passively opened. The application will generally supply this Service Code. Each active socket MUST have exactly one Service Code. Passive sockets MAY, at the implementations discretion, be associated with more than one Service Code; this might let multiple applications, or multiple versions of the same application, listen on the same port, differentiated by Service Code. If the DCCP-Request's Service Code doesn't equal any of the server's Service Codes for the given port, the server MUST reject the request by sending a DCCP-Reset packet with Reset Code 8, "Bad Service Code". A middlebox MAY also send such a DCCP-Reset in response to packets whose Service Code is considered unsuitable. RFC 4340 omits to describe the motivation behind service codes, nor does it describe properly how well-known ports relate to service codes. The intent of this document is to clarify these issues. Background ---------- It is simplest to understand the motivation for service codes by describing the history of the DCCP protocol. In the earliest drafts of DCCP we wanted to address the issue of well-known ports in a future-proof manner. Ports in all common IETF protocols are 16-bit quantities, and the server port must be known to the client to allow a connection to be established. This can be achieved using out-of-band signalling, but more commonly a well-known port is allocated to a particular protocol or application; for example HTTP commonly uses port 80 and SMTP commonly uses port 25. The principle of well-known ports suffers from several problems: - The port space is not really large enough for them to be allocated in an unregulated manner. Thus many applications operate on unregistered ports, and perhaps collide with other such applications. - The use of port-based firewalls encourages application-writers to wish to disguise one application as another to attempt to bypass firewall filtering rules. This in-turn encourages firewall writes to use deep packet inspection to attempt to validate the application really is what it says it it, and an arms race follows. - ISPs often deploy transparent proxies, primarily to improve performance and reduce costs. For example, TCP requests destined to TCP port 80 are often redirected to a web proxy. These issues of course are coupled. When applications collide on the same "well-known" but unregistered port, there is no simple way for network security equipment to tell them apart, with the likelihood of bad feature interaction problems. There is little that a transport protocol designer can do about applications that attempt to masquerade as other applications, but for ones that are not attempting to hide, the problem is simply that they cannot trivially obtain a well-known port. Ideally, it should be sufficiently easy that every application-writer can request a well-known port and get one instantly with no questions asked. Such trivial allocation of well-known ports cannot happen with the traditional 16-bit port space, as it is simply not large enough. Thus, in DCCP we sought an alternative solution. The idea was simple: a 32-bit server port space should be large enough that very lax allocation policies could be used. However we did not want to put 32-bit ports in every packet, as DCCP needed to be useful for low-bitrate applications. The DCCP solution to this problem is to use a 32-bit Service Code which is included only in the DCCP-Request packet. This was intended to perform the primary role of a well-known server port, in that it would be trivially simply to obtain a unique one for each application. By only putting it in the request packet, there is no additional overhead for the actual data flow. This is however sufficient for both the end-system and any stateful firewalls along the path to understand what is actually going on. The original DCCP draft did not use traditional ports at all; instead the client allocated a 32-bit connection identifier that served to uniquely identify the connection, and the server listen on a socket bound only to a service code. This solution is unambiguous; the Service Code is the only identifier for a listening socket at the server side, and the DCCP client would have to include a service code in the request or there would be no way for the request to reach the listening application. However it suffered from the downside of being sufficiently different from existing protocols that we were concerned that it would hinder the use of DCCP through NATs. The final DCCP specification had abandoned the use of a 32-bit connection identifier in favour of two traditional 16-bit ports, one chosen by the server and one chosen by the client. Thus NATs can perform for DCCP exactly as they perform for TCP. This also has the advantage that two servers listening on the same service code can co-exist on the same server host. However it introduces a new problem; how does the server port relate to the service code? The intent was that the service code maintained its original role of being the globally-unique identifier for the application or protocol being used, and that the pair of ports would effectively be a 32-bit connection identifier, unique at both end-systems, even though the two parts were allocated by the two different ends of the connection. There remains a problem though. As the server port is chosen by the server, the client needs to know it to establish a connection. We did not wish to mandate out-of-band communication to discover the server port, and (short of using a port discovery protocol) the only solution is to allow well-known DCCP ports to be registered. This somewhat reduces the benefits of DCCP service codes, because although it may be trivial to obtain a service code, it is likely not trivial to obtain a well-known port from IANA. It also leads to confusion as to how well-known ports relate to well-known service codes. The goal of this document is to clarify these issues. Sockets, Ports and Service Codes -------------------------------- As RFC 4340 states, every DCCP connection (and hence every DCCP active socket) must be associated with a single DCCP service code. This is the DCCP service code that was sent in the DCCP-Request packet. The situation is a little more complex for passively listening sockets on DCCP servers. Consider the case of two servers listening on the same server host. There are four cases to consider: - The servers use different service codes and different server ports. There is no possible confusion in this case. - The servers use the same DCCP service code, but different server ports. Obviously for this to work, the client application must have some out-of-band way to discover the existence of the server port. However there is no ambiguity, and this MUST be permitted by a DCCP stack. - The servers use different DCCP service codes, but wish to listen on the same port. We will discuss this in detail below. - The servers use the same DCCP service code and the same port. This case is not possible, as there is no way for the DCCP stack to direct a new connection to the correct server application. This MUST be disallowed by a DCCP stack. Multiple Service Codes on the Same Server Port ---------------------------------------------- RFC 4340 states that an implementation MAY allow the same socket to be bound to more than one service code. There are two cases to consider. First, a single application may wish to accept connections for more than one service code. It should not be necessary to create more than one hole in a firewall for this to be the case; for example DTLS connections and unencrypted connections for the same application will normally use different service codes to distinguish them, but as it is the same application, it makes sense to use the same port. The requirement on the host stack would be that the service code of the incoming connection request can be made available to the application, so that the application can correctly process the data without requiring some application-specific method to distinguish the two types of data. For DCCP ports to be able to be re-used in this way, we revise RFC 4340 as follows: A DCCP implementation MUST allow one application using more than one DCCP service code to listen for all those service codes on the same server port. A DCCP implementation SHOULD provide a way for the application accepting the connection to discover the service code used in the DCCP-Request packet. Second, more than one application might need to bind to the same server port, using different DCCP service codes. The reason for this should be clear; service codes are allocated from a larger space than server ports. Thus in the long run it is unlikely that a unique well-known port can be allocated to every application that wishes to obtain one. However a unique service code can be allocated to every application that wishes one. Inevitably this leads to a collisions in the server port space. Two different applications can have the same well-known port, and need to run on the same host at the same time. There is no protocol issue with two (or more) applications listening on the same server port simultaneously, each bound to a different server port. Any incoming DCCP-Request will carry a service code, so can be routed to the correct application. After the connection has been accepted, as with any other port-based protocol, its protocol control block is associated with the pair of ports and the pair of IP addresses, so there is no ambiguity as to which socket a particular DCCP packet should be directed. There is a potential issue with APIs for DCCP. The problem is that for two applications to bind to the same port, they need to specify the DCCP service code at the point they bind. Current socket APIs generally require separate requests to bind the port and to set the service code on the socket. This is not a problem, so long as the implementation requires both to be specified before the socket is capable of accepting connections. For DCCP ports to be able to be re-used in this way, we revise RFC 4340 as follows: A DCCP implementation MUST allow multiple applications using different DCCP service codes to listen on the same server port. Finally, there is the question of how the IANA registry should allocate DCCP well-known ports. To encourage application writers to register there applications, and to avoid restricting DCCP service codes to a 16-bit space, we revise RFC 4340 as follows: IANA should allocate well-known DCCP ports on demand to anyone to applies, without requiring a specification or additional justification. Each well-known port request MUST be for a specific registered DCCP service code. IANA should use an allocation policy that attempts to minimize server port collisions, but it is expected that the same well-known port will sometimes be allocated to more than one service code. DCCP Service Code 0 ------------------- In contradiction of RFC 4340, service code 0 has sometimes been used as a wildcard service code. We clarify: DCCP service code 0 has no special meaning. If a listening DCCP socket bound to a particular port is not explicitly bound to service code 0, then an incoming DCCP request containing service code 0 MUST be rejected, as specified in RFC 4340 by sending a DCCP-Reset packet with Reset Code 8, "Bad Service Code". An application MAY choose to listen on DCCP service code 0. Implementations MUST NOT prohibit this, but this SHOULD NOT be used as a wildcard service code. Instead application writers SHOULD simply request a service code from IANA, or SHOULD choose a code from the private use space (first ASCII character equal to '?').