Question

I am busy implementing ICE-TCP (RFC 6544 https://www.rfc-editor.org/rfc/rfc6544) using C# and .NET Framework 4.5. However, I am facing a very tough issue related to the protocol layering which is as follows.

ICE-TCP RFC says:

„ICE requires an agent to demultiplex STUN and application-layer traffic, since they appear on the same port. This demultiplexing is described in [RFC5245] and is done using the magic cookie and other fields of the message.
Stream-oriented transports introduce another wrinkle, since they require a way to frame the connection so that the application and STUN packets can be extracted in order to differentiate STUN packets from application-layer traffic.
For this reason, TCP media streams utilizing ICE use the basic framing provided in RFC 4571 (https://www.rfc-editor.org/rfc/rfc4571#section-2), even if the application layer protocol is not RTP.“

The framing method looks like this:

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 ---------------------------------------------------------------
|             LENGTH            |  RTP or RTCP packet ...       |
 ---------------------------------------------------------------

I also want to use TLS in my implementation and the ICE-TCP RFC says:

„When Transport Layer Security (TLS) or Datagram Transport Layer Security (DTLS) is used, they are also run over the RFC 4571 framing shim, while STUN runs outside of the (D)TLS connection. The resulting ICE TCP protocol stack is shown in Figure 1, with (D)TLS on the left side and without it on the right side.”

Finally the ICE TCP stack looks like this:

                   +----------+
                   |          |
                   |    App   |
        +----------+----------+     +----------+----------+
        |          |          |     |          |          |
        |   STUN   |  (D)TLS  |     |   STUN   |    App   |
        +----------+----------+     +----------+----------+
        |                     |     |                     |
        |      RFC 4571       |     |      RFC 4571       |
        +---------------------+     +---------------------+
        |                     |     |                     |
        |         TCP         |     |         TCP         |
        +---------------------+     +---------------------+
        |                     |     |                     |
        |         IP          |     |         IP          |
        +---------------------+     +---------------------+

So I’m interested in the left side of the figure. The figure implies that the framing header is outside of the TLS encryption and I have to write the header unencrypted to the stream.

Currently my application uses the SslStream Class wrapped around the NetworkStream which I get from my TCPClient. My first intention was to write the framing header into the NetworkStream and afterwards write the encrypted application data to the SslStream. After some research I found this:

“After AuthenticateAsClient/Server, your connection will be SSL secured. Don't call the Socket or NetworkStream methods then: this will break the SslStream.“ Source: C# Sockets and SslStreams

So I can’t write to NetworkStream once the SSL connection is established.

My question is: Is there a way to “put” the header between TCP (NetworkStream) and TLS (SslStream)?

Thanks in advance.

Best regards

Markus

Was it helpful?

Solution

The SslStream instance is layering itself on top of the NetworkStream instance. Any data that you write to the SSL stream is handled by the SSL stream, which then writes any data that it produces to the NetworkStream instance.

If you keep a reference to the NetworkStream you can read or write directly to the NetworkStream as needed, bypassing the SSL stream.

As long as you keep anything that you write directly to the NetworkStream from being read by the SslStream on either side of connection, the SslStream will continue to operate correctly.

Effectively, you will be multiplexing two byte streams down a single stream. One of those byte streams will be the SSL stream and the other will be whatever your other stream is. As long as both ends of the connection know when to switch between the two stream, you should be fine.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top