因为疫情的原因,很多公司通信采用了视频会议的方式进行业务沟通。在视频会议解决方案中,很多的用户需要在进行视频通话的同时还要和其他用户共享某些客户端的资源,例如文件,PPT等数据。这是视频会议的一个基本需求。在基于SIP通信的网络中,SIP视频功能结合资源共享功能就可以实现这些视频会议的功能需求。在视频会议应用中,Binary Floor Control Protocol (BFCP,RFC4582)-双流控制协议是其核心的协议,和基于SDP拓展实现BFCP的Session Description Protocol (SDP) Format for Binary Floor Control Protocol(RFC4583)。笔者在本讨论中,首先会就RFC4582的概要和一些技术详解(part 1),然后介绍关于BFCP中SDP拓展和其他应用场景(part 2)。其次,笔者会介绍几个目前比较热门的BFCP的应用场景。
1
关于双流控制协议的背景介绍-RFC4582和RFC4583
在本文档的讨论中,我们仅涉及SIP和BFCP的功能讨论,不涉及其他协议对BFCP的功能支持。在我们讨论双流控制协议之前,我们首先需要介绍几个常用的定义。在一般的基于SIP的网络环境中,不外乎语音视频或者加一个图片传输的通信方式。但是,目前大部分的企业通信要求不仅仅支持视频,同时还要支持会议人员在进行视频会议的同时,可以分享或者对其他用户发送其他文本文件或者演讲的其他资料,例如PPT文件。视频会议同时完成以上这两种功能就需要所谓的双流数据来实现。
首先,我们介绍一下什么是Floor Control(流控制)。Floor control 简单来说就是一种处理机制,它支持应用程序或者用户安全获得相互对端独有资源,访问共享一些目标文件或者资源,例如对端文本文件,PPT等客户数据资源。这里需要读者注意的是,这种机制必须以安全的方式,相互访问一些特定的目标文件和资源。同时,Floor control 也可以实现会议和媒体的创建,会议策略管理,媒体控制等其他功能。当然,这些功能需要第三方协议来协助完成。
其次,我们需要关于Binary Floor Control Protocol(BFCP)的定义。BFCP是一种协议,它可以在视频会议中协调各种资源。比较典型的示例就是利用BFCP实现的视频会议服务:
本图片和以下所有图片均来自于互联网资源
在会议服务中涉及了几个核心的要素:
Floor Control Server(流控制服务器)
Floor(一个逻辑实体,流处理/获得访问权限访问文件)
Floor Chair(一个逻辑实体,流管理/会议主持人,权限管理,流管理,唤醒流处理)
Floor Participant(一个逻辑实体,流成员者/会议人员)。在会议开始以后,一般会议主持人会按照约定的流程,首先让每个人开始讲话,然后第二个人开始讲话或者分享其他的文件。
2
双流控制协议(BFCP)概要-RFC4582
RFC4582规范是Binary Floor Control Protocol (BFCP)的标准协议。在此协议中规定了BFCP中多个方面的内容。其主要内容包括:规范处理范围, 操作流程,数据包格式,传输,较底层的安全处理,协议事务, 签权和认证,流会议成员操作,流会议主持人操作,一般会议人员操作,流控制服务器操作,和安全问题。下面,我们按照RFC4582的规范说明来进一步介绍以上这几个方面的内容。
规范处理范围(Scope),首先说明,此规范重点讨论的是关于BFCP协议本身的内容,它所关心的是在会议状态下如何通过BFCP来实现对资源的控制,它所遵守的要求是根据RFC4376来实现。另外,关于会议处理的介绍架构是通过RFC4597定义。关于流会议人员和限定的内容,读者可以参考RFC4597做进一步学习研究。以下示例是BFCP所能够提供的功能。
根据以上示例,BFCP提供的通信方式包括:
对于流会议成员来说,发送请求到流控制服务器。
对于流控制服务器来说,它可以允许或者拒绝流会议人员的请求。
对于流会议主持人来说,它对流控制服务器发送一个针对流会议人员的请求的决定。
对于流控制服务器来说,它负责维护流会议人员和流会议主持人针对流会议的消息状态和流会议人员的请求。
在BFCP中,流会议处理流程大概经过四个步骤:
流创建,关联一个给定的流和相关的资源
获得客户端资源联系流控制服务器,客户端需要各种相关数据来创建和BFCP 流控制服务器的连接。客户端所需要的消息数据包括服务器端的传输地址,会议 ID和用户ID。
获得流资源的关联绑定,流绑定相关资源。流会议用户和流会议主持人需要获得相关的系统资源绑定信息,以及如何获得这些绑定消息的机制等。例如,BFCP可以通过SDP =m行使用offer/answer的交互模式获得的消息。当然,也可能通过其他的方式获得资源信息。
获得流资源的优先权限,流会议人员被允许访问某些特定的资源,决定何种流会议人员有权限访问资源。
介绍完关于BFCP的一个规范使用范围以后(Overview of Operation),我们再继续了解关于BFCP的整个操作核心流程。在BFCP整体操作流程中,其实它就存在两种流程的操作。一种是流会议成员和流控制服务器的接口操作,另外一种是流会议主持人和流控制服务器接口之间的操作。在BFCP的消息体的构造中,BFCP消息使用的是TLV (Type-Length-Value) binary编码方式,其消息由公共的头值和一系列的属性设置构成。公共头值包括一个32-bit的会议标识符(identifier),流会议成员方,媒体参与方,和一个会议主持人(一个16-bit 用户标识符)。BFCP同时支持内嵌属性(属性中包含其他的属性),这些内嵌属性可以构成一个组属性。在BFCP中支持两种事务处理(client-initiated transactions 和 server-initiated transactions.)。我们从它们各自的含义都可以了解到,客户端初始的事务包含一个从客户端到服务器端的消息,和从服务器端到客户端的响应消息。因为这两种消息都在普通头值的同一事务ID传递,因此,它们具有相关性。服务器端初始的事务由一个单个消息构成,事务ID是0,从流控制服务器发送到客户端。下面,我们分别讨论一下流成员到流控制服务器接口的流程和流主持人到控制服务器接口的流程。
现在,我们讨论一下流成员到流控制服务器接口流程。根据前面的图例,流成员如果需要请求一个流的话,它需要对流控制服务器发送一个FloorRequest消息到流控制服务器。这里需要注意,BFCP也支持第三方的流请求。这种情况下,发送流请求的成员不需要和媒体一起配置发送,流请求同意以后,媒体可以直接获得流。FloorRequest消息传输在公共头值的用户 ID传递请求者的身份标识,并且在BENEFICIARY-ID属性中流受益者身份标识(在第三方流请求中)。FloorRequest消息确认流或者在FLOOR-ID属性中传输的其他的流(通过16-bit 流身份标识符)。如果FloorRequest消息传输了一个以上的floor identifier 标识符,流控制服务器将把所有的流标识符看作一个atomic数据包。这也就是说,流控制服务器允许或者拒绝所有流成员的请求。流控制服务器接收到请求以后,它会返回一个FloorRequestStatus 消息,此消息中包含流请求的状态。另外,FLOOR-REQUEST-INFORMATION属性是一个非常重要的属性,它涉及了流请求的状态和流成员的一些绑定关系(包括Floor Request ID和事务ID等),读者可以通过RFC4582做更多了解。
接下来,我们讨论关于流主持人和流控制服务器接口的处理流程。此接口流程相对比较简单。但是这里需要说明的是,尽管流主持人可以对流控制服务器发送ChairAction消息获取流控制服务器权限资源,但是,流控制服务器没有必要允许流主持人的所有请求,流控制服务器根据ChairAction和流控制服务器的内部状态来进行处理。例如,如果此流请求涉及到了atomic流请求的话,即使流主持人对某个流请求了获得允许,流控制服务器仍然不会允许其他的流请求通过,直到流主持人获得所有流请求通过,流控制服务器才允许所有的流请求通过。因此,流控制服务器最终根据其相关的流主持人命令的流状态来决定其最终处理状态。
流主持人命令流控制服务器示意图
接下来,我们继续讨论关于BCFP的数据包格式(Packet Format)。BFCP的数据包格式一个12-octet的公共头(COMMON-HEADER)和其属性构成。公共头的格式如下:
BFCP公共头格式
我们经常需要注意的或者比较重要的是Primitive(消息目的和方向),Conference ID(会议ID),Transaction ID和User ID。
BFCP的数据包格式除了公共头的格式以外,还有一个属性的格式。
其中,Type 包括了各种类型定义,内容和格式。
BFCP属性
这里,读者需要注意经常见到的一下错误代码-ERROR-CODE,和其他的错误引申含义。因为篇幅关于,笔者不再介绍BFCP的其他格式内容,读者可以参考RFC4582来进一步研究。
BFCP会议错误码
BFCP实体之间的的传输方式(Transport)是通过TCP连接实现。大家都知道,TCP可以提供可靠按序传输方式,保证其资源访问的稳定性。在会议中,流会议客户端只能使用一个TCP连接来连接流控制服务器,不能使用多于一个以上的连接。但是,如果同样的物理终端支持了不同的流会议终端的话(例如,流会议成员和会议主持人),它们本身具有各自的用户ID的话,可以支持不同的TCP连接来连接流控制服务器,不同终端对流控制服务器的独立的连接方式是允许的。
如果BFCP实体(流客户端或流控制服务器端)从TCP收到数据,此数据不能被实体正确解析的话,此实体就会关闭TCP连接,需要重新创建一个新的连接。同样的,如果TCP连接不能传递BFCP消息或者出现超时的话,TCP连接也需要重新创建。重新创建TCP连接方式的规则取决于流客户端从流控制服务器获得的消息来决定,例如,使用SDP offer/answer交互模式实现。关于SDP 的offer/answer 交互模式,读者可以参考作者历史文档来进一步学习,这里不再做更多讨论。
WebRTC-ICE/RFC5245中文详解发布关于SDP answer/offer介绍。
一旦重新TCP连接创建以后,流客户端可以重新对流控制服务器端发送上次没有从流控制服务器端收到响应的消息。如果流控制服务器端检测到其中一个流客户端的TCP连接断开的话,流控制服务器将会使用本地策略,流控制服务器根据自己的策略对待处理请求进行进一步处理。RFC4582建议,无论在何种场景中,重新TCP建立连接时,流控制服务器都要保持流请求,不能被取消。如果流客户端希望断开对BFCP流控制服务器的连接时,它可以使用相对比较合理的方式断开流控制服务器TCP连接。如果流控制服务器希望断开流客户端BFCP连接,流控制服务器需要使用比较合理的处理方式断开BFCP流客户端连接。
BFCP使用了较低层(Lower-Layer Security)的安全机制来实现回放和完整的安全保护。BFCP 服务器端和客户端都必须支持TLS。任何BFCP实体可以支持其他的安全机制。BFCP必须至少支持TLSTLS_RSA_WITH_AES_128_CBC_SHA ciphersuite算法。当然,目前发布了很多比较新的安全算法,很多终端特别是SIP业务方面的的安全算法也有很多更新。关于安全机制的算法,读者可以查阅RFC3268, RFC4366和TLS拓展RFC6066。关于TLS设置一定要注意。在TLS设置支持时,TSL服务器端的设置取决于流客户端和流控制服务器的TCP连接方式处理流程。不一定是流控制服务器端就是TLS服务器端。如果TCP连接协商机制使用的是SDP offer/answer交互模式时,answerer方(无论是流客户端或流控制服务器端)总是TLS服务器端。
在BFCP协议中支持两种事务类型(Protocol Transactions)。一种是基于客户端初始化的事务,另外一种是服务器端初始的事务(notifications,流控制服务器对流会议终端发送的提示消息)。基于客户端发起的事务由客户端到服务器端的一个请求和一个由服务器端发送到客户端的响应消息构成。请求中会在公共头中传递一个Transaction ID,流控制服务器端会拷贝这个ID到响应消息中。流客户端会使用这个ID来匹配响应消息,流客户端检查是否和前一次发送的请求匹配。基于服务器发起的事务由一个单个从流控制服务器端发送到流客户端的消息构成。基于服务器发起的事务因为没有触发任何响应消息,因此,它的Transaction ID为0。下面,我们分别讨论关于客户端处理流程和服务器端处理流程。如果一个流客户端发起了客户端事务的话,这个客户端必须把消息的公共头中Conference ID设置为会议的ID,这个会议ID是客户端前面获得的ID。另外,客户端必须把公共头中的Transaction ID设置为一个数值,这个数值是从0开始的不同的数值,并且,这个数值一定不能在客户端消息中重新使用,直到流客户端从流控制服务器收到一个针对此事务的响应以后,此数值才能变化。流客户端使用Transaction ID来匹配从流控制服务器返回的响应消息。流控制服务器端的处理有两种情况。流控制服务器在基于客户端发起的事务中发送响应,流控制服务器端必须从请求中拷贝Conference ID,Transaction ID和User ID到响应中。如果是基于服务器端发起的事务,则必须包含一个Transaction ID,这个ID为0。
BFCP实体之间的资源访问需要认证和签权的处理机制(Authentication 和 Authorization)。BFCP客户端应该在对流控制服务器发送消息或者接收消息前,它首先对流控制服务器进行验证处理。同样的,流控制服务器端对流客户端发送或者接收消息前也要进行认证处理。在RFC4582中规定,BFCP的流客户端和控制服务器支持基于TLS的相互认证的机制。这是BFCP推荐的认证机制,当然,BFCP也应该支持TLS未来拓展的认证机制。更多关于BFCP TLS安全机制处理,读者可以参考RFC4582-9.1章节。除了认证以外,BFCP的流控制服务器也需要对消息进行签权处理。流控制服务器在收到认证消息以后,它需要对消息进行签权处理,它会检查流客户端发送的消息是否是通过签权处理。如果流客户端没有被允许进行某些操作的话,流控制服务器将会对流客户端生成一个错误响应,错误代码为5(Unauthorized Operation)。没有被流控制服务器允许的消息不会被进行进一步的处理。
以上介绍了关于BFCP中的一些基本操作和处理流程。接下来,我们具体介绍BFCP实体操作的流程细节。
首先,我们介绍流会议成员的操作流程(Floor Participant Operations)。流客户端首先需要对流控制服务器发送一个FloorRequest消息。它发送的消息中包括一个公共头和属性值,其中包括一些必要选项和一些可选选项。FloorRequest需要在公共头中设置Transaction ID和Conference ID,同时流成员需要把在公共头中的User ID设置为流成员标识符。此用户ID将被流控制服务器作为认证和签权的主要凭证。注意,如果FloorRequest发送方不是会议成员(它将获得流资源),例如第三方发送的流请求,请求发送方应该在消息中增加一个BENEFICIARY-ID属性,表示其是流资源的第三方收益方。
流会议成员必须在FloorRequest消息中插入一个FLOOR-ID属性值。如果流会议成员在其floor请求中插入一个以上的FLOOR-ID,流控制服务器会认为这个流请求是一个atomic package,流控制服务器就会允许或者拒绝FloorRequest消息中所有的流。当然,流会议成员也可以使用PARTICIPANT-PROVIDED-INFO属性来说明流或者其他流是流成员要求的请求,可以在PARTICIPANT-PROVIDED-INFO属性中增加文本说明来声明其原因。流控制服务器端收到FloorRequest消息以后,对其请求进行处理,然后流控制服务器生成一个或多个FloorRequestStatus消息。流会议成员从返回的FloorRequestStatus消息中获得必要的属性参数,例如FLOOR-REQUEST-INFORMATION,OVERALL-REQUEST-STATUS,STATUS-INFO,FLOOR-REQUEST-STATUS,BENEFICIARY-INFORMATION和PRIORITY属性。当然,返回的信息也可能是错误响应。具体以上这些属性的具体内容,读者可以查阅RFC4582-10.1.2,这里不再做过多解释。
如果流会议成员希望取消正在发送的请求的话,它可以对流控制服务器发送一个FloorRelease消息。另外注意,流会议成员也可以通过FloorRelease消息来实现流等待请求,然后释放流资源。FloorRelease发送和接收需要流会议成员和流控制服务器双方协商处理,通过公共头中的Conference ID和Transaction ID实现释放匹配处理。另外,流控制服务器需要处理错误响应等流程。
除了上面介绍的流成员方的操作以外,另外一个实体是流主持人(Chair Operations)。这里,我们再继续介绍关于流会议主持人的操作流程。流会议主持人的作用就是对流控制服务器发出指令,使用前面章节中的协议通过流控制服务器获得或者取消流资源。流会议主持人通过对流控制服务器发送ChairAction消息来实现对流控制服务器的指令。当然,按照正常的响应处理流程,流会议主持人通过发送ChairAction和接收ChairAction的响应消息实现对流控制服务器的指令操作。首先,流会议主持人对流控制服务器端发送ChairAction消息,在公共头中设置Conference ID,Transaction ID和user ID。User ID将被流控制服务器用来对流会议主持人进行认证和签权处理。在ChairAction请求消息中包含对流控制服务器的指令,在一个特定的流请求中,这些指令可以应用在一个流或多个流的场景中。流会议主持人可以使用FLOOR-REQUEST-STATUS提供一个新的流请求状态,这个状态可以关联到一个特定的流资源(其状态可以支持队列位置,允许或者拒绝权限访问)。流会议主持人也可以在ChairAction消息中添加一个OVERALL-REQUEST-STATUS,对其流请求提供一个整体状态的说明。流会议主持人也可以通过STATUS-INFO属性说明流被接受,解决或者取消的原因,此描述是文本格式。流会议主持人可以收到从流控制服务器返回的ChairActionAck消息,此消息确认流控制服务器收到了ChairAction请求消息。如果流会议主持人收到一个错误消息的话,它说明流控制服务器因为某些原因,它不能处理ChairAction消息,原因需要查看错误消息。
以上我们讨论了针对流会议成员和流会议主持人的操作流程。除了这两个实体的特定操作以外,BFCP仍然有一些不针对特定一方的非常基本的操作流程(General Client Operation)。这些操作流程不仅针对流会议成员或者流会议主持人,也可能同时支持两种角色的操作。这些操作包括:
关于流的信息,包括操作流程是发送FloorQuery消息和接收响应消息。
关于流请求的信息,包括的操作流程是FloorRequestQuery消息和接收其相应的响应消息。
关于对用户的请求消息操作,包括发送UserQuery消息,接收其响应消息。
关于获得流控制服务器的支持能力的操作,包括发送Hello 消息,接收其响应能力支持消息。
以上章节介绍流流会议成员操作,流会议主持人操作和它们的一些一般操作流程。接下来,我们将介绍最后的一个操作,那就是流控制服务器端的操作流程(Floor Control Server Operations)。流控制服务器端的流程涉及了八个不同的消息处理流程,这八个处理流程分别针对的是流会议成员,流会议主持人。
FloorRequest消息接收,流控制服务器收到FloorRequest消息以后,检查其认证和签权状态。(注意,以下其他消息也必须经过同样的认证和签权流程和消息解析)在处理其请求过程中,如果不理解消息内容,服务器端生成一个错误响应。如果流控制服务器成功解析其请求消息,则返回一个或多个FloorRequestStatus 消息,说明其是否接受或者拒绝流请求。当然,流请求也可能继续进行,流控制服务器也可以获得其它状态消息。
FloorRequestQuery消息接收,流控制服务器收到请求查询消息以后,流控制服务器需要处理几个必要的属性参数,例如,Conference ID, Transaction ID 和 User ID,添加FLOOR-REQUEST-STATUS,提供REQUESTED-BY-INFORMATION,增加PARTICIPANT-PROVIDED-INFO说明添加的理由,添加PRIORITY来表示流请求组控制的优先级。
UserQuery 消息接收,流控制服务器收到用户查询消息后,它会快速生成
一个UserStatus消息。它经过同样的处理流程,流控制服务器需要把
Conference ID, Transaction ID 和 User ID拷贝到UserStatus消息中。
流控制服务器在响应消息中添加BENEFICIARY-ID(受益人ID)。
FloorRelease 消息接收处理,流控制服务器收到释放请求消息以后,它会生成一个FloorRequestStatus。它会它经过同样的处理流程,流控制服务器需要把Conference ID, Transaction ID和用户ID拷贝到FloorRequestStatus消息中。流控制服务器必须在状态消息中添加FLOOR-REQUEST-INFORMATION组属性。流控制服务器必须从释放消息中拷贝FLOOR-REQUEST-ID到FLOOR-REQUEST-INFORMATION属性中的Floor Request ID。流控制服务器也必须确认其流请求的身份,通过添加FLOOR-REQUEST-ID来实现。最后,流控制服务器必须在FLOOR-REQUEST-INFORMATION组属性中增加一个OVERALL-REQUEST-STATUS属性。
FloorQuery消息接收处理,流控制服务器收到流查询消息以后,它会通过FloorStatus 消息不断通知流客户端。单个的FloorStatus传递单个的流状态消息。如果流客户端需要多个流状态消息的话,流控制服务器端需要分开独立发送其状态消息。取决于用户对不同状态的请求不同,FloorQuery也可以查询待处理请求的状态等消息。
ChairAction消息接收处理,流控制服务器收到主持人的请求以后,它会生成一个ChairActionAck响应消息。它会它经过同样的处理流程,流控制服务器需要把Conference ID, Transaction ID和用户ID拷贝到ChairActionAck消息中。当然,流控制服务器会根据本地策略,对流会议主持人返回拒绝或者接受请求等消息。
Hello消息接收处理,流控制服务器收到Hello消息以后,它会生成一个HelloAck消息。它会它经过同样的处理流程,流控制服务器需要把Conference ID, Transaction ID和用户ID拷贝到HelloAck消息中。最后,流控制服务器必须在HelloAck增加一个SUPPORTED-PRIMITIVES属性,表示流控制服务器支持的BFCP消息。流控制服务器在HelloAck中必须增加一个SUPPORTED-ATTRIBUTES,在属性列表中列出流控制服务器所支持的属性能力。
Error 消息生成处理,错误消息是一个响应消息,它是由客户端发出的,它是基于客户端事务的一个部分。它会它经过同样的处理流程,流控制服务器需要把Conference ID, Transaction ID和用户ID拷贝到错误消息中。在错误消息中必须增加一个ERROR-CODE,此属性错误码包含一个错误代码。另外,流控制服务器也可以增加一个ERROR-INFO属性来说明具体的错误原因。
以上讨论基本上涵盖了RFC4582关于BFCP的基本处理流程。最后一个需要讨论的是BFCP的安全问题。
BFCP本身默认支持了TLS的安全机制,只要支持的参数类似,BFCP同时它也可以增加其他的安全机制。
在BFCP安全讨论中,主要的几个攻击威胁是冒充流会议成员或者流会议主持人获得流资源权限。
另外,可以冒充一个流控制服务器端,让流会议成员和主持人访问来获得终端用户信息。
攻击者修改相关的交互信息来获得认证权限。攻击者也可能盗取相关的安全交互信息,然后访问其流资源服务器内容。
规范推荐会议用户使用TLS加密方式来进行流会议实体之间的交互,这样可以避免攻击者非法盗取相关的会议信息。
参考资料:
https://www.rfc-editor.org/rfc/rfc4582.html
https://www.hjp.at/doc/rfc/rfc5018.html
https://www.hjp.at/doc/rfc/rfc5567.html
https://sci-hub.st/https://ieeexplore.ieee.org/abstract/document/8599589/
融合通信/IPPBX/FreePBX商业解决方案:www.hiastar.com
最新Asterisk完整中文用户手册详解及免费slack支持:www.asterisk.org.cn
Freepbx/FreeSBC技术文档: www.freepbx.org.cn
如何使用FreeSBC,qq技术分享群:334023047
关注微信公众号:asterisk-cn,获得有价值的通信行业技术分享