Subject: [Tsvwg] SCTP/UDP encapsulation fallback

From: Mark Butler <[email-masked]>
Date: Sun, 12 Mar 2006 00:16:46 -0700

Hello Michael,

I have a comment on the SCTP UDP encapsulation draft.  Supporting SCTP 
implementations should treat each UDP encapsulated address as a separate 
peer address in the INIT cycle, so that a connection is first attempted 
unencapsulated, and then encapsulated (subject to system configuration).

Most systems should default to encapsulation fallback enabled (on the 
standard encapsulation port) so that they automatically switch to 
encapsulated mode behind SCTP incapable / blocking middle boxes.

There should also be an SCTP socket option to specify a non-standard 
encapsulation port, turn encapsulation on and off, and set the 
encapsulation priority - something like SCTP_ENCAP with a parameter 
structure like:

struct sctp_encap {
    uint16_t  sen_proto;    /* IPPROTO_UDP */
    uint16_t  sen_flags;    /* SCTP_ENCAP_ENABLED */
    int16_t   sen_priority; /* -1 high, 0 default, +1 low */
    uint16_t  sen_port;   
};

Does that sound like a reasonable interface?  Any problems with the 
fallback convention?

 - Mark

_______________________________________________
tsvwg mailing list
[email-masked]
https://www1.ietf.org/mailman/listinfo/tsvwg

---

From: Michael Tuexen <[email-masked]>
Date: Mon, 13 Mar 2006 09:20:34 +0100

Hi Mark,

I have not thought about putting that into the kernel. I was more  
thinking about
running the encaps/decaps process in userland. I prototyped this on  
BSD using
divert sockets...

If one might put it into the kernel, your API looks OK... I have to  
think a bit
more about the consequences of putting it into the kernel....

Best regards
Michael

On Mar 12, 2006, at 8:16 AM, Mark Butler wrote:

> Hello Michael,
>
> I have a comment on the SCTP UDP encapsulation draft.  Supporting  
> SCTP implementations should treat each UDP encapsulated address as  
> a separate peer address in the INIT cycle, so that a connection is  
> first attempted unencapsulated, and then encapsulated (subject to  
> system configuration).
>
> Most systems should default to encapsulation fallback enabled (on  
> the standard encapsulation port) so that they automatically switch  
> to encapsulated mode behind SCTP incapable / blocking middle boxes.
>
> There should also be an SCTP socket option to specify a non- 
> standard encapsulation port, turn encapsulation on and off, and set  
> the encapsulation priority - something like SCTP_ENCAP with a  
> parameter structure like:
>
> struct sctp_encap {
>    uint16_t  sen_port;   };

---

From: Mark Butler <[email-masked]>
Date: Mon, 13 Mar 2006 12:27:09 -0700

Hello Michael,

I think both user space and kernel space SCTP/UDP implementations would 
work fine with the appropriate conventions.   Using UDP port 9899 for 
this is a bit of a security problem, because any user level process can 
bind to it and generate traffic for privileged SCTP ports (1..1023).  
That weakens some forms of IP address/port based security.   I suggest 
the following policy:

(1) When an SCTP/UDP endpoint receives an INIT, if the encapsulating UDP 
source port is an unprivileged port (port number 1024 or greater), and 
the encapsulated SCTP source port is a privileged port (port number less 
than 1024), the endpoint should respond with an ABORT.   Originating 
SCTP/UDP endpoints should select the source port accordingly.

(2) SCTP/UDP endpoints should accept INIT requests from any 
encapsulating UDP port, provided the SCTP/UDP port privilege check and 
other SCTP protocol requirements are satisfield.  The encapsulating UDP 
port should be saved n the state cookie and verified when a COOKIE ECHO 
is received.  If the encapsulating port does not match, the target 
endpoint should respond with an ABORT.

(3) A SCTP/UDP association must remain encapsulated on the same pair of 
source / destination UDP ports throughout the lifetime of the 
association.  A SCTP/UDP packet that arrives on a different UDP port but 
otherwise matches an existing SCTP/UDP association should be treated as 
an out-of-the-blue (OOTB) packet.

Second issue:  Endpoint identification - without appropriate handling, 
user level SCTP/UDP endpoints running in different applications may 
result in endpoint identification conflicts. Proposed solution:

(4) User level SCTP/UDP implementations should either allocate ephemeral 
SCTP ports from a random starting position, or (preferably) coordinate 
at the system level such that assigned SCTP ports are unique on an ([IP 
address set], SCTP port) basis.

(5) Kernel level SCTP/UDP implementations should always use a privileged 
UDP port.

There needs to be a standard privileged port for SCTP/UDP encapsulation. 
Port 988 is available.  Perhaps it could be allocated for this purpose.  
For most clients, it shouldn't matter what UDP source port is used, 
although using a standard port may be useful for some applications. 
i.e., a library level SCTP implementation should be generally able to 
bind to any UDP port and use it for SCTP/UDP communications, subject to 
a few restrictions.

Also, generating and checking a UDP checksum is unnecessary when 
encapsulating SCTP traffic that is already checksum protected. Therefore:

(6) An SCTP/UDP endpoint may set the UDP checksum field to zero, 
indicating no UDP checksum, as specified by RFC768, and rely on checksum 
protection at the SCTP layer.

The policy described generally requires integration with the SCTP stack. 
It is certainly possible for a middlebox to perform encapsulation / 
de-encapsulation, but there are a variety of complicating issues - an 
encapulating/de-encapsulating point generally needs to be either on the 
same system as the SCTP endpoint (so that it has the same IP addresses), 
or be integrated with an SCTP NAT implementation or other stateful 
router.  One problem is there is no simple means for the originating 
native SCTP endpoint to indicate what the target UDP port should be.  An 
INIT parameter would have to be provided and state maintained on the 
middlebox through the life of the association to support multiple or 
non-default target UDP encapsulation ports.  In general, stack 
integration is much simpler.

The SCTP_ENCAP option needs to be different that what I described 
earlier.  What really needs to be specified is the destination UDP 
encapsulation port for outgoing connections.  Selection of the source 
UDP port should be up to the SCTP/UDP implementation.  Here is an 
improved version:

SCTP_ENCAP

struct sctp_encap {
   uint32_t  sen_assoc_id;
   uint16_t  sen_flags;  
   uint16_t  sen_proto;    /* IPPROTO_UDP, zero */
   int16_t   sen_priority; /* -1 high, 0 default, +1 low */
   uint16_t  sen_local_port;  
   uint16_t  sen_peer_port;  
};

Setting this option would be effective only for the establishment of new 
outbound associations. For setsockopt(2) calls, the association id 
should either be zero, or be a pre-allocated association id obtained 
using the yet to be documented GET_PEER_ADDR_PARAMS technique.  
getsockopt(2) would be used to get the current socket level 
encapsulation defaults if the association id is zero, or the current 
encapsulation state of the specified association if non zero.

The flags would be:
  SCTP_ENCAP_SET_PROTO
  SCTP_ENCAP_SET_PRIORITY
  SCTP_ENCAP_SET_LOCAL_PORT
  SCTP_ENCAP_SET_PEER_PORT

A protocol value of zero means no encapsulation. IPPROTO_UDP specifies 
UDP encapsulation. The network layer protocol should be specified with 
an address family appropriate sockaddr (sockaddr_in or sockaddr_in6), as 
usual, not by specifying IPPROTO_IP (even if zero), or IPPROTO_IPV6. 

SCTP_ENCAP_SET_LOCAL_PORT is present for completeness. Kernel level 
implementations will generally have a single system level local 
encapsulation port, and should return an error if another local port is 
specified.

SCTP_ENCAP_SET_PEER_PORT is used to specify an alternate peer 
(de-)encapsulation port.  The default should be the standard 
(privileged) SCTP/UDP encapsulation port.

[I think SCTP/UDP encapsulation has great potential for expanding the 
usage of SCTP, notably for HTTP traffic, where the majority of HTTP 
clients are behind NAT routers.  A simple user level SCTP/UDP 
implementation that applications like Firefox could link to, (even on 
Windows) would be very helpful.  It would generally only need to to 
provide a one-to-one style interface with minimal option support and a 
convenient way to use multiple streams.  HTTP servers should generally 
support both standard 'SCTP/IP' and SCTP/UDP using kernel space stacks 
that make the encapsulation transparent to them.]

 - Mark