SCTP协议最新版本是RFC 4960。
以下简单介绍SCTP标准中的一些基本概念,希望对大家阅读SCTP相关标准时有所帮助,详细资料可以参考RFC。水平所限,有错漏之处请见谅。。
1. SCTP包的格式
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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Common Header |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Chunk #1 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| … |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Chunk #n |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
图1 SCTP包基本格式
SCTP包由一个SCTP头部以及一个或多个Chunk组成。
1.1 SCTP头部
SCTP头部主要指定了源和目的SCTP端口号(这与TCP/UDP端口号类似,),以及一个唯一标识一条SCTP连接的Verification Tag(与TCP/UDP不同,TCP/UDP只能用四元组(源IP、源端口、目的IP、目的端口)来唯一确定一条连接)。
Verification Tag由连接的两端各自分配,在连接建立过程中相互通知各自分配的Tag。后续的SCTP包的发送,需要在SCTP头部填充对端分配的Verification Tag,接收方可以通过Verification Tag来查找SCTP包对应的SCTP连接。
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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Port Number | Destination Port Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Verification Tag |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
图2 SCTP头部格式
1.2 SCTP CHUNK
CHUNK是SCTP包中的一种基本结构。有两大类CHUNK类型,一种是用于传输SCTP控制信息的CHUNK(比如SCTP的建立、关闭过程,heartbeat探测等),另一种是用于传输用户数据的CHUNK。CHUNK的基本格式如下:
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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Chunk Type | Chunk Flags | Chunk Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
\ \
/ Chunk Value /
\ \
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
图3 SCTP CHUNK格式
目前定义了以下CHUNK类型:
ID Value Chunk Type —– ———
0 – Payload Data (DATA)
1 – Initiation (INIT)
2 – Initiation Acknowledgement (INIT ACK)
3 – Selective Acknowledgement (SACK)
4 – Heartbeat Request (HEARTBEAT)
5 – Heartbeat Acknowledgement (HEARTBEAT ACK)
6 – Abort (ABORT)
7 – Shutdown (SHUTDOWN)
8 – Shutdown Acknowledgement (SHUTDOWN ACK)
9 – Operation Error (ERROR)
10 – State Cookie (COOKIE ECHO)
11 – Cookie Acknowledgement (COOKIE ACK)
以下通过SCTP连接的建立过程、关闭过程以及数据传输过程,看看上述各种CHUNK的作用。
2. SCTP连接建立过程
SCTP连接的建立需要在client端和server端之间四步握手,也就是要交换四条SCTP控制消息(由四个SCTP控制CHUNK传输)。

图4 SCTP连接建立过程
在图4中,SCTP的server端绑定了两个IP地址以及一个端口P2(在RFC中,这两个IP地址和一个端口组成了一个SCTP ENDPOINT。当然也可以只绑定一个IP地址,或者绑定更多的IP地址),并侦听;client端也绑定了两个IP地址以及一个端口P1,连接到server端。
2.1 INIT
在client端的应用程序调用sctp_connet()之后,协议栈会发送SCTP INIT消息给server端。
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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type = 1 | Chunk Flags | Chunk Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Initiate Tag |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Advertised Receiver Window Credit (a_rwnd) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Number of Outbound Streams | Number of Inbound Streams |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Initial TSN |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
\ \
/ Optional/Variable-Length Parameters /
\ \
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
图5 INIT CHUNK格式
与TCP/UDP类似,在建立连接的时候,需要在SCTP头部指定本端和对端的端口号(图4中的P1/P2)。
与TCP/UDP不同的是,client端指定了自己的IP列表(IP1和IP3),这种信息是在INIT CHUNK的Optional/Variable-Length Parameter中携带的(详情请参考RFC 4960,section 3.3.2.1)。那这种信息是从哪里来的呢?是应用程序在调用sctp_connect()之前,通过bind()/bindx()来绑定的。需要注意的是,bind()可以绑定多个IP地址,但是只能有一个SCTP端口。这些IP地址+SCTP端口,组成一个RFC中所说的SCTP ENDPOINT。即,client端的(IP1, IP3, P1)组成了一个SCTP ENDPOINT。后续client可以用IP1作为源IP地址发包给server端,也可以用IP3作为源IP地址发包给server端。
在INIT中,还指定自己分配的本端的Verification Tag(图4中的TAG1,图5中的Initiate Tag),server端在后续发送给client端的SCTP包的头部中的Verification Tag需要指定TAG1。
由于此时并不知道server端分配的Verification Tag,因此在client发送给server端的INIT中,SCTP头部的Verification Tag字段填0(图4中INIT中的PEER_TAG)。
其他几个参数:
a_rwnd表示client端的初始接收窗口;
Number of Outbound Streams指定了发送方向的Stream的数量(注意:SCTP的有序传递,只是针对某一条Stream来说的,后面描述数据传输的DATA CHUNK的时候会详细说明);
Number of Inbound Streams指定了接收方向的Stream的数量;
Initial TSN指定了第一个DATA CHUNK的TSN(传输序列号,SCTP双方确认的是TSN,TSN标识了一个DATA CHUNK;而TCP中,双方确认的是接收字节数)。
2.2 INIT_ACK
INIT ACK和INIT类似,不同之处是,由于server端收到INIT之后已经知道对端的Verification Tag(TAG1),因此,在INIT ACK的SCTP头部的Verification Tag字段会把TAG1填进去。
INIT ACK中,还有一个比较重要的信息,即cookie(由一种COOKIE parameter携带,详细格式请参考RFC 4960的section 3.3.3.1)。Cookie中主要包括INIT携带的内容、时间、生存周期等信息,以及通过这些信息和一个只有本地知道的KEY生成的MAC(Message Authentication Code),用于防止后续的COOKIE_ECHO被篡改。
值得注意的是,server端在发送INIT_ACK之后,一直到收到client端发回的COOKIE_ECHO之前,并不会为该连接分配内存,这样可以避免类似TCP的半连接攻击。
2.3 COOKIE_ECHO
client端需要在COOKIE_ECHO中原样返回INIT_ACK中的cookie。
server端在收到client端的COOKIE_ECHO之后,从cookie中取出有效信息(比如之前所述的INIT中指定的IP地址列表、时间、生存周期等信息),加上本地的KEY,重新计算MAC,并和cookie中的MAC比较,相同则表示有效信息没有被篡改,继续连接建立过程。比如为该连接分配内存,发送COOKIE_ACK给client端,并通知本端应用程序(即侦听该SCTP ENDPINT的应用程序)去accept一条新的SCTP连接。如果重新计算出来的MAC和cookie之中的MAC不同,则该连接建立请求会被拒绝。
2.4 COOKIE_ACK
client端收到COOKIE_ACK之后,表示该SCTP连接已经建立完成,通知本端应用程序(即调用sctp_connect()的应用程序)该连接建立成功。
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/231376.html原文链接:https://javaforall.net
