XEP-0065: SOCKS5 Bytestreams

Abstract:This document defines an XMPP protocol extension for establishing an out-of-band bytestream between any two XMPP users, mainly for the purpose of file transfer. The bytestream can be either direct (peer-to-peer) or mediated (though a special-purpose proxy server). The typical transport protocol used is TCP, although UDP can optionally be supported as well.
Authors:Dave Smith, Matthew Miller, Peter Saint-Andre, Justin Karneges
Copyright:© 1999 - 2010 XMPP Standards Foundation. SEE LEGAL NOTICES.
Status:Draft
Type:Standards Track
Version:1.8rc1
Last Updated:in progress, last updated 2010-03-15

NOTICE: The protocol defined herein is a Draft Standard of the XMPP Standards Foundation. Implementations are encouraged and the protocol is appropriate for deployment in production systems, but some changes to the protocol are possible before it becomes a Final Standard.


Table of Contents


1. Introduction
2. Terminology
3. Determining Support
4. Discovering Proxies
5. Direct Connections
    5.1. Process
    5.2. Flow
    5.3. Protocol
       5.3.1. Requester Initiates S5B Negotiation
       5.3.2. Target Establishes SOCKS5 Connection with StreamHost/Requester
       5.3.3. Target Acknowledges Bytestream
6. Mediated Connections
    6.1. Process
    6.2. Flow
    6.3. Protocol
       6.3.1. Requester Initiates S5B Negotiation
       6.3.2. Target Establishes SOCKS5 Connection with Proxy
       6.3.3. Target Acknowledges Bytestream
       6.3.4. Requester Establishes SOCKS5 Connection with StreamHost
       6.3.5. Activation of Bytestream
7. Formal Description
    7.1. <query/> Element
    7.2. <streamhost/> Element
    7.3. <streamhost-used/> Element
    7.4. <activate/> Element
8. Optional UDP Support
    8.1. Discovering UDP Support
    8.2. Requesting UDP Mode
    8.3. UDP Process
       8.3.1. Establishing the UDP Association
       8.3.2. Initializing the UDP Channel
    8.4. Exchanging UDP Packets
9. Implementation Notes
    9.1. StreamHost Requirements
    9.2. SOCKS5 Parameter Mapping
10. Security Considerations
11. IANA Considerations
12. XMPP Registrar Considerations
    12.1. Protocol Namespaces
    12.2. Service Discovery Features
    12.3. Service Discovery Category/Type
13. Schema
14. Acknowledgements

Appendices
    A: Document Information
    B: Author Information
    C: Legal Notices
    D: Relation to XMPP
    E: Discussion Venue
    F: Requirements Conformance
    G: Notes
    H: Revision History


1. Introduction

XMPP is designed for sending relatively small fragments of XML between network entities (see XMPP Core [1]) and is not designed for sending binary data. However, sometimes it is desirable to send binary data to another entity that one has discovered on the XMPP network (e.g., to send a file). Therefore it is valuable to have a generic protocol for streaming binary data between any two entities on an XMPP network. The main application for such a bytestreaming technology is file transfer as specified in SI File Transfer [2] and Jingle File Transfer [3]. However, other applications are possible, which is why it is important to develop a generic protocol rather than one that is specialized for a particular application such as file transfer.

This document defines a protocol that meets the following conditions:

Specifically, this document makes use of the SOCKS 5 protocol, which is an IETF-approved, IPv6-ready technology for bytestreams defined in RFC 1928 [6]. However, because this proposal uses a subset of the SOCKS5 protocol that is specially adapted for bytestreaming over XMPP, existing SOCKS5 proxies cannot be used to implement this proposal without modifications.

There are two scenarios addressed by this protocol:

  1. A direct connection in which the StreamHost is the Requester, as described under Direct Connections
  2. A mediated connection in which the StreamHost is a Proxy, as described under Mediated Connections

Early versions of this specification documented only the use of TCP connections. In version 1.6 (approved in November 2004), optional UDP associations were added, as described in the Optional UDP Support section of this document. However, the main body of this document describes the use of TCP, which is the primary method of SOCKS5 Bytestreams ("S5B").

2. Terminology

The following terms are used throughout this document.

Requester
The entity that starts a bytestream negotiation with a Target. [7]
Target
The entity with which the Requester is attempting to establish a bytestream.
Proxy
An entity that is willing to be a middleman for the bytestream between the Requester and the Target.
StreamHost
The system that the Target connects to and that is "hosting" the bytestream; the Streamhost can be either the Requester or a Proxy.
StreamID
A relatively unique Stream ID for this connection; this is generated by the Requester for tracking purposes and MUST be less than 128 characters in length.

Note: Because either party can attempt to establish a bytestream (this is formalized in Jingle SOCKS5 Bytestreams Transport Method [8]), the Requester and the Target roles apply to a particular S5B negotiation, and do not map to the Initiator and Responder roles from Jingle [9] in a fixed way. For example, during a Jingle negotiation the Initiator might first take on the role of an S5B Requester but if that first bytestreams negotiation fails then the Jingle Responder might take on the role of an S5B Requester.

In the protocol flow diagrams, the line types have the following meaning:

In the examples, "streamer.example.com" is a Proxy that services bytestreams on port 7625.

3. Determining Support

If an entity supports this protocol, it MUST advertise that fact in its responses to Service Discovery [10] information ("disco#info") requests by returning a feature of "http://jabber.org/protocol/bytestreams".

Example 1. Requester Sends Service Discovery Request to Target

<iq from='requester@example.com/foo'
    id='gr91cs53'
    to='target@example.org/bar'
    type='get'>
  <query xmlns='http://jabber.org/protocol/disco#info'/>
</iq>
  

Example 2. Target Replies to Service Discovery Request

<iq from='target@example.org/bar'
    id='gr91cs53'
    to='requester@example.com/foo'
    type='result'>
  <query xmlns='http://jabber.org/protocol/disco#info'>
    <identity category='client' type='pc'/>
    <feature var='http://jabber.org/protocol/bytestreams'/>
  </query>
</iq>
  

4. Discovering Proxies

Before attempting to initiate a bytestream, the Requester might need to find a proxy (e.g., if it has not been configured to know about a proxy). It can do so using Service Discovery by communicating with its server.

Example 3. Requester Sends Service Discovery Request to Server

<iq from='requester@example.com/foo'
    id='pi2b15fv'
    to='example.com'
    type='get'>
  <query xmlns='http://jabber.org/protocol/disco#items'/>
</iq>
  

The server will return all of the items it knows about.

Example 4. Server Replies to Service Discovery Request

<iq from='example.com'
    id='pi2b15fv'
    to='requester@example.com/foo'
    type='result'>
  <query xmlns='http://jabber.org/protocol/disco#items'>
    <item jid='chatrooms.example.com' name='Chatroom Service'/>
    <item jid='news.example.com' name='News Feeds'/>
    <item jid='streamer.example.com' name='File Transfer Relay'/>
  </query>
</iq>
  

In this case, the bytestreams proxy is hosted at "streamer.example.com".

For each item in the disco#items result, the Requester needs to query to determine if it is a bytestreams proxy.

Example 5. Requester Sends Service Discovery Request to Proxy

<iq from='requester@example.com/foo'
    id='yx92b153'
    to='streamer.example.com'
    type='get'>
  <query xmlns='http://jabber.org/protocol/disco#info'/>
</iq>
  

The proxy returns its information and the Requester inspects it to determine if it contains an identity of category "proxy" and type "bytestreams".

Example 6. Server Replies to Service Discovery Request

<iq from='streamer.example.com'
    id='yx92b153'
    to='requester@example.com/foo'
    type='result'>
  <query xmlns='http://jabber.org/protocol/disco#info'>
    <identity category='proxy'
              type='bytestreams'
              name='File Transfer Relay'/>
    <feature var='http://jabber.org/protocol/bytestreams'/>
  </query>
</iq>
  

Next the Requester needs to request the full network address to be used for bytestreaming through the Proxy. This is done by sending an IQ-get to the proxy containing a <query/> element qualified by the bytestreams namespace. [11]

Example 7. Requester Requests Network Address from Proxy

<iq from='requester@example.com/foo'
    id='uj2c15z9'
    to='streamer.example.com'
    type='get'>
  <query xmlns='http://jabber.org/protocol/bytestreams'/>
</iq>
  

The Proxy replies by returning an IQ-result that contains its network address, structured using the <streamhost/> child of the <query/> element; the <streamhost/> element MUST possess the following attributes:

Example 8. Proxy Informs Requester of Network Address

<iq from='streamer.example.com'
    id='uj2c15z9'
    to='requester@example.com/foo'
    type='result'>
  <query xmlns='http://jabber.org/protocol/bytestreams'>
    <streamhost
        host='24.24.24.1'
        jid='streamer.example.com'
        port='7625'/>
  </query>
</iq>
  

If the Requester does not have permissions to initiate bytestreams on the Proxy for whatever reason (e.g., a proxy implementation might enable administrators to ban JIDs or domains from using the Proxy), the Proxy MUST return a <forbidden/> error to the Requester.

Example 9. Requester is Forbidden to use Proxy

<iq from='requester@example.com/foo'
    id='uj2c15z9'
    to='streamer.example.com'
    type='error'>
  <query xmlns='http://jabber.org/protocol/bytestreams'>
  <error type='auth'>
    <forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
  

If the Proxy is unable to act as a StreamHost, the Proxy MUST return an error to the Requester, which SHOULD be <not-allowed/>.

Example 10. Proxy is Unable to Act as a StreamHost

<iq from='requester@example.com/foo'
    id='uj2c15z9'
    to='streamer.example.com'
    type='error'>
  <query xmlns='http://jabber.org/protocol/bytestreams'
         sid='vxf9n471bn46'/>
  <error type='cancel'>
    <not-allowed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
  

5. Direct Connections

In this situation, the StreamHost is the Requester, which means that the Requester knows the network address of the StreamHost and knows when to activate the bytestream.

5.1 Process

For direct connections, the process for establishing a bytestream is as follows:

  1. Requester initiates S5B negotiation with Target by sending an IQ-set that includes the full JID <localpart@domain.tld/resource> and network address of StreamHost/Requester as well as the StreamID (SID) of the proposed bytestream.

  2. Target opens a TCP socket to the specified network address at the StreamHost/Requester.

  3. Target requests SOCKS5 connection at StreamHost/Requester.

  4. StreamHost/Requester sends acknowledgement of successful connection to Target via SOCKS5.

  5. Target accepts the S5B stream by returning an IQ-result to the Requester, preserving the 'id' of the initial IQ-set.

  6. Requester and Target exchange data over the bytestream.

5.2 Flow

The data flow is shown in the following diagram.

Requester                           Target
   |                                  |
   | Send S5B initiation request      |
   | -------------------------------> |
   |                                  |
   | Open TCP socket                  |
   | <_______________________________ |
   |                                  |
   | Request SOCKS 5 connection       |
   | <\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ |
   |                                  |
   | Acknowledge SOCKS 5 connection   |
   | ///////////////////////////////> |
   |                                  |
   | Send S5B acceptance              |
   | <------------------------------- |
   |                                  |
   | Exchange data over S5B           |
   | <==============================> |
   |                                  |
    

5.3 Protocol

5.3.1 Requester Initiates S5B Negotiation

To initiate an S5B negotiation with the Target, the Requester sends the Target network address information about one or more StreamHosts. In the case of a direct connection, the Requester might include information only about itself (as shown in the following example) or about itself and a Proxy. The <query/> element MUST possess a 'sid' attribute the specifies the Stream ID for this bytestream and MAY possess a 'mode' attribute whose value is "tcp" (the default) or "udp"; the <query/> element also MUST contain one or more <streamhost/> elements, each of which MUST possess the 'host', 'jid', and 'port' attributes.

Example 11. Requester Initiates Negotiation

<iq from='requester@example.com/foo'
    id='hu3vax16'
    to='target@example.org/bar'
    type='set'>
  <query xmlns='http://jabber.org/protocol/bytestreams'
         sid='vxf9n471bn46'>
    <streamhost
        jid='requester@example.com/foo'
        host='192.168.4.1'
        port='5086'/>
  </query>
</iq>
      

If the Target is unwilling to accept the bytestream, it MUST return a <not-acceptable/> error to the Requester.

Example 12. Target Refuses Bytestream

<iq from='target@example.org/bar'
    id='hu3vax16'
    to='requester@example.com/foo'
    type='error'>
  <error type='auth'>
    <not-acceptable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
      

If the Target is willing to negotiate a bytestream, it proceeds as shown in the following sections.

5.3.2 Target Establishes SOCKS5 Connection with StreamHost/Requester

Next the Target attempts to open a standard TCP socket on the network address of the StreamHost/Requester.

Note: If the Requester provides more than one StreamHost, the Target SHOULD try to connect to them in the order of the <streamhost/> children within the <query/> element. Jingle SOCKS5 Bytestreams Transport Method [12] modifies this rule by providing explicit priorities for each streamhost candidate.

If the Target is able to open a TCP socket on a StreamHost/Requester, it MUST use the SOCKS5 protocol to establish a SOCKS5 connection. In accordance with RFC 1928, the Target might need to authenticate in order to use the proxy. However, any authentication required is beyond the scope of this document.

Once the Target has successfully authenticated with the StreamHost/Requester, it sends a CONNECT request to the appropriate host in order to continue the negotiation. The following rules apply:

  1. The hostname MUST be SHA1(SID + Requester JID + Target JID) where the definition of the SHA1 hashing algorithm is as specified by RFC 3174 [13] and the output is hexadecimal-encoded (not binary).
  2. The port MUST be 0 (zero).
  3. The JIDs provided MUST be the JIDs used for the IQ exchange, which MAY be full JIDs (<localpart@domain.tld/resource> or <domain.tld/resource>) or bare JIDs (<localpart@domain.tld> or <domain.tld>).
  4. The appropriate stringprep profiles (as specified in XMPP Core [14]) MUST be applied to the JIDs before application of the SHA1 hashing algorithm.

Example 13. Target Establishes SOCKS5 Connection with StreamHost

CMD = X'01'
ATYP = X'03'
DST.ADDR = SHA1 Hash of: (SID + Requester JID + Target JID)
DST.PORT = 0
      

Example 14. StreamHost Acknowledges Connection

STATUS = X'00'
      

When replying to the Target in accordance with Section 6 of RFC 1928, the StreamHost MUST set the BND.ADDR and BND.PORT to the values provided by the client in the connection request.

If the Target tries but is unable to connect to any of the StreamHosts and it does not wish to attempt a connection from its side, it MUST return an <item-not-found/> error to the Requester.

Example 15. Target Is Unable to Connect to Any StreamHost and Wishes to End Negotiation

<iq from='target@example.org/bar'
    id='hu3vax16'
    to='requester@example.com/foo'
    type='error'>
  <error type='cancel'>
    <item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
      

5.3.3 Target Acknowledges Bytestream

After the Target has authenticated with the StreamHost/Requester, it replies to the initiate request with an IQ-result whose <query/> element contains a <streamhost-used/> child that specifies which StreamHost was used (in this case, the StreamHost/Requester).

Example 16. Target Notifies Requester of Bytestream

<iq from='target@example.org/bar'
    id='hu3vax16'
    to='requester@example.com/foo'
    type='result'>
  <query xmlns='http://jabber.org/protocol/bytestreams'
         sid='vxf9n471bn46'>
    <streamhost-used jid='requester@example.com/foo'/>
  </query>
</iq>
      

At this point, the Requester knows which StreamHost was used by the Target and the parties are able to use the StreamHost/Requester to exchange data over the bytestream.

6. Mediated Connections

In this situation, the StreamHost is not the Requester but a Proxy, which means that the Requester needs to discover the network address of the StreamHost before sending the initiation request to the Target, needs to negotiate a connection with the StreamHost in the same way that the Target does, and needs to ask the StreamHost to activate the bytestream before it can be used.

6.1 Process

For mediated connections, the process for establishing a bytestream is as follows:

  1. As a precondition, the Requester optionally discovers the network address of StreamHost over XMPP as discussed in the Service Discovery section of this document.

  2. Requester initiates S5B negotation with Target by sending IQ-set that includes the JabberID and network address of StreamHost as well as the StreamID (SID) of the proposed bytestream.

  3. Target opens a TCP socket to the selected StreamHost.

  4. Target requests SOCKS5 connection at StreamHost/Proxy.

  5. StreamHost sends acknowledgement of successful connection to Target via SOCKS5.

  6. Target sends IQ-result to Requester, preserving the 'id' of the initial IQ-set.

  7. Requester opens a TCP socket at the StreamHost.

  8. Requester establishes connection via SOCKS5, with the DST.ADDR and DST.PORT parameters set to the values defined below.

  9. StreamHost sends acknowledgement of successful connection to Requester via SOCKS5.

  10. Requester sends IQ-set to StreamHost requesting that StreamHost activate the bytestream associated with the StreamID.

  11. StreamHost activates the bytestream. (Data is now relayed between the two SOCKS5 connections by the proxy.)

  12. StreamHost sends IQ-result to Requester acknowledging that the bytestream has been activated (or specifying an error).

  13. Requester and Target can begin using the bytestream.

6.2 Flow

The data flow is shown in the following diagram.

Requester                           Proxy                              Target
   |                                  |                                  |
   | Send S5B initiation request                                         |
   | ------------------------------------------------------------------> |
   |                                  |                                  |
   |                                  | Open TCP socket                  |
   |                                  | <_______________________________ |
   |                                  |
   |                                  | Request SOCKS 5 connection       |
   |                                  | <\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ |
   |                                  |
   |                                  | Acknowledge SOCKS 5 connection   |
   |                                  | ///////////////////////////////> |
   |                                  |                                  |
   | Send S5B acceptance                                                 |
   | <------------------------------------------------------------------ |
   |                                  |                                  |
   | Open TCP socket                  |                                  |
   | _______________________________> |                                  |
   |                                  |                                  |
   | Request SOCKS 5 connection       |                                  |
   | ///////////////////////////////> |                                  |
   |                                  |                                  |
   | Acknowledge SOCKS 5 connection   |                                  |
   | <\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ |                                  |
   |                                  |                                  |
   | Request activation               |                                  |
   | -------------------------------> |                                  |
   |                                  |                                  |
   | Acknowledge activation           |                                  |
   | <------------------------------- |                                  |
   |                                  |                                  |
   | Exchange data over S5B                                              |
   | <=================================================================> |
   |                                  |                                  |
    

6.3 Protocol

6.3.1 Requester Initiates S5B Negotiation

To initiate an S5B negotiation with the Target, the Requester sends the Target network address information about one or more StreamHosts. In the case of a mediated connection, the Requester might include information only about the Proxy (as shown in the following example) or about the Proxy and itself. The <query/> element MUST possess a 'sid' attribute the specifies the Stream ID for this bytestream and MAY possess a 'mode' attribute whose value is "tcp" (the default) or "udp"; the <query/> element also MUST contain one or more <streamhost/> elements, each of which MUST possess the 'host', 'jid', and 'port' attributes.

Example 17. Requester Initiates Negotiation

<iq from='requester@example.com/foo'
    id='npq71g53'
    to='target@example.org/bar'
    type='set'>
  <query xmlns='http://jabber.org/protocol/bytestreams'
         sid='vxf9n471bn46'>
    <streamhost
        host='24.24.24.1'
        jid='streamer.example.com'
        port='7625'/>
  </query>
</iq>
      

If the Target is willing to negotiate a bytestream, it proceeds as shown in the following sections.

6.3.2 Target Establishes SOCKS5 Connection with Proxy

Next the Target attempts to open a standard TCP socket on the network address of the Proxy.

If the Target is able to open a TCP socket on the Proxy, it uses the SOCKS5 protocol to establish a SOCKS5 connection. In accordance with RFC 1928, the Target might need to authenticate in order to use the proxy. However, any authentication required is beyond the scope of this document.

Once the Target has successfully authenticated with the Proxy, it sends a CONNECT request to the appropriate host in order to continue the negotiation. The following rules apply:

  1. The hostname MUST be SHA1(SID + Requester JID + Target JID) where the definition of the SHA1 hashing algorithm is as specified by RFC 3174 [15] and the output is hexadecimal-encoded (not binary).
  2. The port MUST be 0 (zero).
  3. The JIDs provided MUST be the JIDs used for the IQ exchange, which MAY be full JIDs (<localpart@domain.tld/resource> or <domain.tld/resource>) or bare JIDs (<localpart@domain.tld> or <domain.tld>).
  4. The appropriate stringprep profiles (as specified in XMPP Core [16]) MUST be applied to the JIDs before application of the SHA1 hashing algorithm.

Example 18. Target Establishes SOCKS5 Connection with StreamHost

CMD = X'01'
ATYP = X'03'
DST.ADDR = SHA1 Hash of: (SID + Requester JID + Target JID)
DST.PORT = 0
      

Example 19. StreamHost Acknowledges Connection

STATUS = X'00'
      

When replying to the Target in accordance with Section 6 of RFC 1928, the Proxy MUST set the BND.ADDR and BND.PORT to the values provided by the client in the connection request.

6.3.3 Target Acknowledges Bytestream

After the Target has established a SOCKS5 connection with the Proxy, it replies to the initiate request with an IQ-result whose <query/> element contains a <streamhost-used/> child that specifies which StreamHost was used (in this case, the Proxy).

Example 20. Target Notifies Requester of Bytestream

<iq from='target@example.org/bar'
    id='npq71g53'
    to='requester@example.com/foo'
    type='result'>
  <query xmlns='http://jabber.org/protocol/bytestreams'
         sid='vxf9n471bn46'>
    <streamhost-used jid='streamer.example.com'/>
  </query>
</iq>
      

At this point, the Requester knows which StreamHost was used by the Target.

6.3.4 Requester Establishes SOCKS5 Connection with StreamHost

Here, unlike the direct connection case described above, the Requester also needs to establish a SOCKS5 connection to the Proxy before the parties are able to use the Proxy to exchange data over the bytestream. Therefore the Requester will establish a connection to the SOCKS5 proxy in the same way the Target did (passing the same value for the CONNECT request), as shown in the following examples.

Example 21. Requester Connects to StreamHost

CMD = X'01'
ATYP = X'03'
DST.ADDR = SHA1 Hash of: (SID + Requester JID + Target JID)
DST.PORT = 0
      

Example 22. StreamHost Acknowledges Connection to Requester

STATUS = X'00'
      

6.3.5 Activation of Bytestream

Next the Requester needs to activate the bytestream with the Proxy. This is done by sending an IQ-set to the Proxy, including an <activate/> element whose XML character data specifies the full JID of the Target.

Example 23. Requester Requests Activation of Bytestream

<iq from='requester@example.com/foo'
    id='oqx6t1c9'
    to='streamer.example.com'
    type='set'>
  <query xmlns='http://jabber.org/protocol/bytestreams'
         sid='vxf9n471bn46'>
    <activate>target@example.org/bar</activate>
  </query>
</iq>
      

Using this information, with the SID and from address on the packet, the Proxy is able to activate the stream by hashing the SID + Requester JID + Target JID. This provides a reasonable level of trust that the activation request came from the Requester.

If the Proxy can fulfill the request, it MUST respond to the Requester with an IQ-result.

Example 24. Proxy Informs Requester of Activation

<iq from='streamer.example.com'
    id='oqx6t1c9'
    to='requester@example.com/foo'
    type='result'/>
      

At this point the parties can begin exchanging data over the bytestream.

If the Proxy cannot fulfill the request, it MUST return an IQ-error to the Requester; the following conditions are defined:

7. Formal Description

7.1 <query/> Element

The <query/> element is the container for all in-band communications. This element MUST be qualified by the "http://jabber.org/protocol/bytestreams" namespace. Depending on the use case, this element contains multiple <streamhost/> elements, a single <streamhost-used/> element, or a single <activate/> element.

The "sid" specifies the bytestream session identifier. The value of this attribute is any character data.

The "mode" specifies the mode to use, either 'tcp' or 'udp'. If this attribute is missing, the default value of "tcp" MUST be assumed.

The <streamhost/> element conveys the network connection information. At least one instance MUST be present in the initial IQ-set from the Requester to the Target. If multiple instances of this element are present, each one MUST be a separate host/port combination.

The <streamhost-used/> element transports the out-of-band token. It MUST be present in the IQ-set from the Target to the Requester, and there MUST be only one instance.

The <activate/> element is used to request activation of a unidirectional or bidirectional bytestream. It MUST be present in the IQ-set sent from the Requester to the StreamHost after the Requester receives an IQ-result from the Target, and there MUST be only one instance.

7.2 <streamhost/> Element

The <streamhost/> element contains the bytestream connection information. This element has attributes for the StreamHost's JID, network host/address, and network port. This element MUST NOT contain any content nodes.

The "jid" attribute specifies the StreamHost's JID. This attribute MUST be present, and MUST be a valid JID for use with an <iq/>.

The "host" attribute specifies the host to connect to. This attribute MUST be present. The value MUST be either a resolvable domain name or the "dotted decimal" IP address (e.g. "1.2.3.4").

The "port" attribute specifies the port to connect to. This attribute MAY be present. The value MUST be a valid port number in decimal form.

When communicating the available hosts, the Requester MUST the host and port.

7.3 <streamhost-used/> Element

The <streamhost-used/> element indicates the StreamHost connected to. This element has a single attribute for the JID of the StreamHost to which the Target connected. This element MUST NOT contain any content node.

The "jid" attribute specifies the JID of the StreamHost. This attribute MUST be present, and MUST be a valid JID for use with an <iq/>.

7.4 <activate/> Element

The <activate/> element is a flag to trigger a Proxy to complete a connection.

8. Optional UDP Support

Support for UDP associations is strictly OPTIONAL. However, implementations that support UDP associations MUST adhere to the profile described in this section.

8.1 Discovering UDP Support

If an implementation supports UDP associations, it MUST advertise that separately by returning a feature of 'http://jabber.org/protocol/bytestreams#udp' in response to Service Discovery information requests.

Example 25. Requester Sends Service Discovery Request to Target

<iq type='get'
    from='requester@example.com/foo'
    to='target@example.org/bar'
    id='hello2'>
  <query xmlns='http://jabber.org/protocol/disco#info'/>
</iq>
    

If the Target supports UDP associations, it MUST answer to that effect in the service discovery result.

Example 26. Target Replies to Service Discovery Request

<iq type='result'
    from='target@example.org/bar'
    to='requester@example.com/foo'
    id='hello2'>
  <query xmlns='http://jabber.org/protocol/disco#info'>
    <identity
        category='proxy'
        type='bytestreams'
        name='File Transfer Relay'/>
    <feature var='http://jabber.org/protocol/bytestreams'/>
    <feature var='http://jabber.org/protocol/bytestreams#udp'/>
  </query>
</iq>
    

8.2 Requesting UDP Mode

UDP associations are requested by setting the 'mode' attribute to a value of "udp" rather than "tcp".

Example 27. Initiation of Interaction (UDP)

<iq type='set'
    from='requester@example.com/foo'
    to='target@example.org/bar'
    id='initiate'>
  <query xmlns='http://jabber.org/protocol/bytestreams'
	 mode='udp'
         sid='mySID'>
    <streamhost
        host='192.168.4.1'
        jid='requester@example.com/foo'
        port='5086'/>
  </query>
</iq>
    

8.3 UDP Process

There is one main difference between UDP mode and TCP mode: rather than simply establishing a TCP connection, the Target and/or Requester MUST (1) establish a UDP association and then (2) initialize the UDP channel. In particular:

The processes for establishing the UDP association and for initializing the UDP channel are described below.

8.3.1 Establishing the UDP Association

Once the Target has successfully authenticated with the Proxy (as described under Target Establishes SOCKS5 Connection with StreamHost), it MUST send a UDP ASSOCIATE (rather than CONNECT) request to the host identified by the algorithm defined above.

Example 28. Target Requests UDP Association with StreamHost

CMD = X'03'
ATYP = X'03'
DST.ADDR = SHA1 Hash of: (SID + Requester JID + Target JID)
DST.PORT = 0
      

The StreamHost then acknowledges this request:

Example 29. StreamHost Acknowledges Request

STATUS = X'00'
      

8.3.2 Initializing the UDP Channel

After connecting to the StreamHost, the Target (direct connection) or both Target and Requester (mediated connection) MUST initialize the UDP channel. In order to do so, each sending entity MUST send a SOCKS5 UDP packet to the StreamHost on the same port used for the initial TCP connection (in the foregeoing example, a host of 192.168.4.1 and port of 5086), with DST.PORT set to '1' and DATA containing the sending entity's JID (i.e, the JID of either the Target or Requester).

Example 30. Target or Requester Sends UDP Initialization Packet to StreamHost

ATYP = X'03'
DST.ADDR = SHA1 Hash of: (SID + Requester JID + Target JID)
DST.PORT = 1
DATA = Target or Requester JID
      

Upon successful receipt by the StreamHost, the StreamHost MUST reply with a message notification indicating success:

Example 31. StreamHost Notifies Target or Requester of UDP Success

<message
    from='streamer.example.com'
    to='target@example.org/bar'
    id='initiate'>
  <udpsuccess xmlns='http://jabber.org/protocol/bytestreams' 
              dstaddr='Value of Hash'/>
</message>
      

The <udpsuccess/> element indicates that the StreamHost has received a UDP initialization packet. This element has a single attribute containing the DST.ADDR that was used in the UDP packet.

If Target is unable to initialize the UDP channel, it MUST return a <remote-server-not-found/> error to RequesteRequester.

Note: Since UDP is not reliable, the Target SHOULD resend the UDP packet if the reply notification is not received within a short time (a 5-second retry is RECOMMENDED). The StreamHost SHOULD ignore duplicate UDP initialization packets once it has replied with a notification.

8.4 Exchanging UDP Packets

Once the UDP association is established, UDP packets can be exchanged with the StreamHost. When a UDP packet is sent by either party, it MUST contain a 4-byte header (in addition to other possible headers, such as that of SOCKS5), which consists of the source virtual port and then the destination virtual port of the packet, both 16-bit values in network byte order. This allows the peers to multiplex many packets for different purposes over one session. The actual application data shall follow this header, and thus the payload size will always be "Application Data Size + 4".

For all packets sent to the StreamHost, DST.PORT is set to 0, and DATA contains the payload.

Example 32. Sending UDP to StreamHost

ATYP = X'03'
DST.ADDR = SHA1 Hash of: (SID + Requester JID + Target JID)
DST.PORT = 0
DATA = (payload)
    

UDP packets sent from the StreamHost do not have any SOCKS5 headers, and so the payload shall be delivered as-is.

The programming interface for a SOCKS5 Bytestreams-aware UDP MUST report an available buffer space for UDP datagrams that is smaller than the actual space provided by the operating system and SOCKS5 layer if applicable. In other words, 4 more octets smaller.

9. Implementation Notes

9.1 StreamHost Requirements

A StreamHost MUST support TCP connections.

A StreamHost SHOULD:

  1. Allow bi-directional bytestreaming between the Requester and Target.
  2. Allow only one Target to connect to a bytestream (i.e., disallow multicasting).
  3. Track sessions based on a combination of the StreamID and the Requester's full JID, thus allowing an Requester to create more than one simultaneous session.
  4. Ignore but not drop any bytes sent before the bytestream is activated.

A StreamHost MAY:

  1. Support UDP associations in addition TCP connections.
  2. Ignore the DST.ADDR and DST.PORT parameters if desired.

9.2 SOCKS5 Parameter Mapping

To facilitate the usage of SOCKS5, command parameters MUST be mapped to the appropriate values. Parameters not specified in the table below SHOULD be used as defined in RFC 1928.

Table 1: Request/Parameter Mapping for CONNECT

ParameterValue
CMD1 (CONNECT)
ATYPHardcoded to 3 (DOMAINNAME) in this usage
DST.ADDRSHA1 Hash of: (SID + Requester JID + Target JID)
DST.PORT0

Table 2: Request/Parameter Mapping for UDP ASSOCIATE

ParameterValue
CMD3 (UDP ASSOCIATE)
ATYPHardcoded to 3 (DOMAINNAME) in this usage
DST.ADDRSHA1 Hash of: (SID + Requester JID + Target JID)
DST.PORT0

Table 3: Request/Parameter Mapping for UDP Packets

ParameterValue
ATYPHardcoded to 3 (DOMAINNAME) in this usage
DST.ADDRSHA1 Hash of: (SID + Requester JID + Target JID)
DST.PORT0 or 1, for payload or initialization packets, respectively.

10. Security Considerations

This proposal does not include a method for securing or encrypting SOCKS5 bytetreams. If such security is desired, it MUST be negotiated over the bytestream (once established) using standard protocols such as SSL or TLS. Negotiation of such security methods is outside the scope of this document.

11. IANA Considerations

This document requires no interaction with the Internet Assigned Numbers Authority (IANA) [17].

However, it is possible that a future version of this document will request assignment of a TCP/UDP port for SOCKS5 Bytestreams.

12. XMPP Registrar Considerations

12.1 Protocol Namespaces

The XMPP Registrar [18] includes 'http://jabber.org/protocol/bytestreams' in its registry of protocol namespaces.

12.2 Service Discovery Features

The XMPP Registrar includes 'http://jabber.org/protocol/bytestreams#udp' in its registry of service discovery features.

12.3 Service Discovery Category/Type

The XMPP Registrar includes the "proxy" category and associated "bytestreams" type in the Service Discovery registry. The registry submission is as follows:

  <category>
    <name>proxy</name>
    <desc>Proxy servers or services</desc>
    <type>
      <name>bytestreams</name>
      <desc>A proxy for SOCKS5 bytestreams</desc>
      <doc>XEP-0065</doc>
    </type>
  </category>
    

13. Schema

<?xml version='1.0' encoding='UTF-8'?>

<xs:schema
    xmlns:xs='http://www.w3.org/2001/XMLSchema'
    targetNamespace='http://jabber.org/protocol/bytestreams'
    xmlns='http://jabber.org/protocol/bytestreams'
    elementFormDefault='qualified'>

  <xs:annotation>
    <xs:documentation>
      The protocol documented by this schema is defined in
      XEP-0065: http://www.xmpp.org/extensions/xep-0065.html
    </xs:documentation>
  </xs:annotation>

  <xs:element name='query'>
    <xs:complexType>
      <xs:choice>
        <xs:element ref='streamhost' minOccurs='0' maxOccurs='unbounded'/>
        <xs:element ref='streamhost-used' minOccurs='0'/>
        <xs:element name='activate' type='empty' minOccurs='0'/>
      </xs:choice>
      <xs:attribute name='mode' use='optional' default='tcp'>
        <xs:simpleType>
          <xs:restriction base='xs:NCName'>
            <xs:enumeration value='tcp'/>
            <xs:enumeration value='udp'/>
          </xs:restriction>
        </xs:simpleType>
      </xs:attribute>
      <xs:attribute name='sid' type='xs:string' use='required'/>
    </xs:complexType>
  </xs:element>

  <xs:element name='streamhost'>
    <xs:complexType>
      <xs:simpleContent>
        <xs:extension base='empty'>
          <xs:attribute name='jid' type='xs:string' use='required'/>
          <xs:attribute name='host' type='xs:string' use='required'/>
          <xs:attribute name='port' type='xs:string' use='optional'/>
        </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>

  <xs:element name='streamhost-used'>
    <xs:complexType>
      <xs:simpleContent>
        <xs:extension base='empty'>
          <xs:attribute name='jid' type='xs:string' use='required'/>
        </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>

  <xs:element name='udpsuccess'>
    <xs:complexType>
      <xs:simpleContent>
        <xs:extension base='empty'>
          <xs:attribute name='dstaddr' type='xs:string' use='required'/>
        </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>

  <xs:simpleType name='empty'>
    <xs:restriction base='xs:string'>
      <xs:enumeration value=''/>
    </xs:restriction>
  </xs:simpleType>

</xs:schema>
  

14. Acknowledgements

Thanks to Marcus Lundblad for his feedback.


Appendices


Appendix A: Document Information

Series: XEP
Number: 0065
Publisher: XMPP Standards Foundation
Status: Draft
Type: Standards Track
Version: 1.8rc1
Last Updated: in progress, last updated 2010-03-15
Approving Body: XMPP Council
Dependencies: XMPP Core, RFC 1928, RFC 3174, XEP-0030
Supersedes: None
Superseded By: None
Short Name: bytestreams
Schema: <http://www.xmpp.org/schemas/bytestreams.xsd>
Source Control: HTML  RSS
This document in other formats: XML  PDF


Appendix B: Author Information

Dave Smith

Email: dizzyd@jabber.org
JabberID: dizzyd@jabber.org

Matthew Miller

Email: linuxwolf@outer-planes.net
JabberID: linuxwolf@outer-planes.net

Peter Saint-Andre

Email: stpeter@jabber.org
JabberID: stpeter@jabber.org
URI: https://stpeter.im/

Justin Karneges

Email: justin@affinix.com
JabberID: justin@andbit.net


Appendix C: Legal Notices

Copyright

This XMPP Extension Protocol is copyright © 1999 - 2010 by the XMPP Standards Foundation (XSF).

Permissions

Permission is hereby granted, free of charge, to any person obtaining a copy of this specification (the "Specification"), to make use of the Specification without restriction, including without limitation the rights to implement the Specification in a software program, deploy the Specification in a network service, and copy, modify, merge, publish, translate, distribute, sublicense, or sell copies of the Specification, and to permit persons to whom the Specification is furnished to do so, subject to the condition that the foregoing copyright notice and this permission notice shall be included in all copies or substantial portions of the Specification. Unless separate permission is granted, modified works that are redistributed shall not contain misleading information regarding the authors, title, number, or publisher of the Specification, and shall not claim endorsement of the modified works by the authors, any organization or project to which the authors belong, or the XMPP Standards Foundation.

Disclaimer of Warranty

## NOTE WELL: This Specification is provided on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. ##

Limitation of Liability

In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall the XMPP Standards Foundation or any author of this Specification be liable for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising from, out of, or in connection with the Specification or the implementation, deployment, or other use of the Specification (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if the XMPP Standards Foundation or such author has been advised of the possibility of such damages.

IPR Conformance

This XMPP Extension Protocol has been contributed in full conformance with the XSF's Intellectual Property Rights Policy (a copy of which can be found at <http://xmpp.org/extensions/ipr-policy.shtml> or obtained by writing to XMPP Standards Foundation, 1899 Wynkoop Street, Suite 600, Denver, CO 80202 USA).

Appendix D: Relation to XMPP

The Extensible Messaging and Presence Protocol (XMPP) is defined in the XMPP Core (RFC 3920) and XMPP IM (RFC 3921) specifications contributed by the XMPP Standards Foundation to the Internet Standards Process, which is managed by the Internet Engineering Task Force in accordance with RFC 2026. Any protocol defined in this document has been developed outside the Internet Standards Process and is to be understood as an extension to XMPP rather than as an evolution, development, or modification of XMPP itself.


Appendix E: Discussion Venue

The primary venue for discussion of XMPP Extension Protocols is the <standards@xmpp.org> discussion list.

Discussion on other xmpp.org discussion lists might also be appropriate; see <http://xmpp.org/about/discuss.shtml> for a complete list.

Given that this XMPP Extension Protocol normatively references IETF technologies, discussion on the <xsf-ietf@xmpp.org> list might also be appropriate.

Errata can be sent to <editor@xmpp.org>.


Appendix F: Requirements Conformance

The following requirements keywords as used in this document are to be interpreted as described in RFC 2119: "MUST", "SHALL", "REQUIRED"; "MUST NOT", "SHALL NOT"; "SHOULD", "RECOMMENDED"; "SHOULD NOT", "NOT RECOMMENDED"; "MAY", "OPTIONAL".


Appendix G: Notes

1. RFC 3920: Extensible Messaging and Presence Protocol (XMPP): Core <http://tools.ietf.org/html/rfc3920>.

2. XEP-0096: SI File Transfer <http://xmpp.org/extensions/xep-0096.html>.

3. XEP-0234: Jingle File Transfer <http://xmpp.org/extensions/xep-0234.html>.

4. RFC 793: Transmission Control Protocol <http://tools.ietf.org/html/rfc0793>.

5. RFC 768: User Datagram Protocol <http://tools.ietf.org/html/rfc0768>.

6. RFC 1928: SOCKS Protocol Version 5 <http://tools.ietf.org/html/rfc1928>.

7. Before version 1.8 of this document a Requester was known as an Initiator.

8. XEP-0260: Jingle SOCKS5 Bytestreams Transport Method <http://xmpp.org/extensions/xep-0260.html>.

9. XEP-0166: Jingle <http://xmpp.org/extensions/xep-0166.html>.

10. XEP-0030: Service Discovery <http://xmpp.org/extensions/xep-0030.html>.

11. Before version 1.8 of this specification, the <query/> element in this use case possessed a 'sid' attribute; however, it is unnecessary for the Requester to specify the StreamID here and it would be harmful for the Proxy to reserve the StreamID at this point because the StreamID might never be used and because the Requester might use the Proxy's services for multiple different streams.

12. XEP-0260: Jingle SOCKS5 Bytestreams Transport Method <http://xmpp.org/extensions/xep-0260.html>.

13. RFC 3174: US Secure Hash Algorithm 1 (SHA1) <http://tools.ietf.org/html/rfc3174>.

14. RFC 3920: Extensible Messaging and Presence Protocol (XMPP): Core <http://tools.ietf.org/html/rfc3920>.

15. RFC 3174: US Secure Hash Algorithm 1 (SHA1) <http://tools.ietf.org/html/rfc3174>.

16. RFC 3920: Extensible Messaging and Presence Protocol (XMPP): Core <http://tools.ietf.org/html/rfc3920>.

17. The Internet Assigned Numbers Authority (IANA) is the central coordinator for the assignment of unique parameter values for Internet protocols, such as port numbers and URI schemes. For further information, see <http://www.iana.org/>.

18. The XMPP Registrar maintains a list of reserved protocol namespaces as well as registries of parameters used in the context of XMPP extension protocols approved by the XMPP Standards Foundation. For further information, see <http://xmpp.org/registrar/>.


Appendix H: Revision History

Note: Older versions of this specification might be available at http://xmpp.org/extensions/attic/

Version 1.8rc1 (in progress, last updated 2010-03-15)

(psa)

Version 1.7 (2007-05-21)

Incorporated errata: specified format for SHA1 output; specified BND.ADDR and BND.PORT for SOCKS5 reply; removed extraneous SOCKS5 acknowledgement example from Section 4.9; clarified rules for creation of SOCKS5 connection request in Section 4.6; added examples to Section 4.8; specified that ATYP value is hardcoded to 3 in this usage.

(psa)

Version 1.6 (2004-11-12)

Added UDP support (OPTIONAL).

(ds/psa)

Version 1.5 (2004-06-29)

Added requirement to apply stringprep profiles before SHA1 hashing; added reference to RFC 3174.

(psa)

Version 1.4 (2004-06-28)

Cleaned up narratives to reflect current practices and removed unnecessary authentication references; fixed mismatch SOCKS5 parameter table values.

(ds)

Version 1.3 (2003-09-24)

Added disco#info <identity/> and corresponding XMPP Registrar submission; added XMPP error handling.

(psa)

Version 1.2 (2003-07-15)

Removed SIDs from the result queries, key off the IQ 'id' attribute instead. Added the disco exchange for finding available proxies.

(rwe)

Version 1.1 (2003-07-09)

Changed srvid to zeroconf; cleaned up use cases; updated the schema.

(ds)

Version 1.0 (2003-04-21)

Per a vote of the Jabber Council, advanced status to Draft.

(psa)

Version 0.7 (2003-03-04)

Clarified that this proposal uses an adaptation of the SOCKS5 protocol, not the full protocol; replaced DTD with schema; added security considerations.

(psa)

Version 0.6 (2003-01-27)

Added service discovery example; added 'srvid' attribute to streamhost element and required inclusion of either 'srvid' or 'port' attribute; improved the algorithms for generating SOCKS5 UNAME and PASSWD parameters; specified that the DST.ADDR and DST.PORT parameters can be ignored; removed references to connected/disconnected notification, bidirectional bytestreams, and multiple targets; updated implementation notes.

(psa/ds)

Version 0.5 (2002-12-20)

Specified option of "reversing the connection" (Target becomes Initiator); added more error cases; resurrected and cleaned up formal use case.

(psa)

Version 0.4 (2002-12-19)

Added section on connected/disconnected notifications sent from Proxy to Initiator; cleaned up several examples; specified more error conditions; clarified the formal descriptions; added implementation notes and future considerations.

(psa, mm)

Version 0.3 (2002-12-17)

Added lots of detail to the narrative and protocol.

(psa)

Version 0.2 (2002-12-16)

Added SOCKS info.

(ds)

Version 0.1 (2002-12-13)

Initial version.

(ds)

END