Av 协议


#1

Avim 协议第一层之 AV地址协议 继续讨论:

什么是 av 协议

av协议就是 avim 所使用的底层通讯协议。 av 协议让 avim 得以安全的交换信息。 av协议定义了 av地址和 av地址的路由规则。 avim 就是建立在 av协议基础上的。

要使两个 aver 可以相互通信,他们首先得知道对方的地址。在 avim 里,这个地址就是由一个类似 email 地址的形式表示的,叫 av地址。每个 aver 都拥有唯一的av地址。所有的aver通过 av地址相互识别和通信,他们之间组成了一个虚拟的网络,叫 av网。av网是一个基于包分组交换的路由式网络。

av 地址 和 av私钥 以及 av证书

av 地址由 3 部分构成, 用户名@域名/接口名。 其中,接口名是动态生成的,每次连接都能生成一个, 而且对用户是透明的,用户无需知道。 用户名和域名则是固定的。用户从申请 av地址的那一刻起,这个用户名和域名就唯一的确定了。

av地址虽然由用户名和域名表征,实际上在av网上定位一个 aver 的并不是 av地址, av地址只是一个让人容易记忆的别名。 av网上,真正用于识别一个用户的,是用户的av私钥。每个 aver 在获得一个av地址的同时,也会生成一份 av私钥,并由颁发机构将其对应的av公钥签名,获得一个 av证书。 av私钥和av证书非常重要,这是 avim 之所以安全的前提保证。

av 证书 和 CA 机构

av证书就是对应的 av地址签发机构签发的证书。这个证书签发机构只能是 avplayer.org 以及获得其认证的二级签发机构。 avplayer.org 被称为 ROOT CA。其他的一些组织也将有机会认证成为 二级CA。意味着这些 CA 拥有 avplayer.org 的签名。

av 网组织形式

av网的组织形式非常类似于 ip网(internet), av网的节点通过其他形式的网络连接起来。通常这个其他形式就是通过 TCP 协议承载于 IP 网络上。当然不排除有其他形式的承载形式。

av网和 av网节点之间通过转发进行。一些节点专门负责数据转发,这些节点被称为“路由器”。而用户使用的节点通常不进行转发,而只是简单的连接到一个路由器下,让路由器代为进行数据转发到节点。

一个典型的 av网上数据的流动:

alice@a.org -> router@a.org …> router@b.org …> router@c.org -> bob@c.org

在这里 alice 向 bob 发送了一个消息,这个消息经过 alice 的路由器(也被称为网关服务器)转发到中间服务器,再通过中间服务器转发到 bob的网关服务器上,然后再转发到 bob的电脑上。

网关服务器通常具有av地址 router@xxx 的形似,但是也并不是绝对的。这取决于管理员的偏好。

路由器和路由器之间如果使用 ip 网络连接的话,可能会形成一种拓扑结构,也可能会变得两两相连(任意两个路由器之间直接连接)。这些具体情况取决于管理员的配置,和 路由发现协议的运作(为了简化设计,路由协议暂时不在第一版 av协议里提供)。

av数据包和加密

两个 aver 通过 av网传输的信息,以 av数据包的形式进行。 av数据包包含了发送方的地址和目的地址,以及要发送到数据。这些数据使用目的 av地址的公钥进行了加密,使得只有接收方才能解开里面的数据。同时发送数据(加密后的数据)也使用了av地址发送方的私钥进行签名,因此任何aver都能对数据的真实性进行检验,以确保这个数据来自数据包所声称的地址。

av协议实现

avim 的实现进度可以查看 https://github.com/avplayer/avim

avif 接口

与 ip 网承载于以太网和光纤等各类链路层网络上一样,av网也需要一个承载网络。av网的承载网被称为 avif 。目前计划实行的接口仅有一个: avtcpif . 即以点对点的 tcp 链接来承载 av网络。 上文提到,av地址由 用户名@域名/接口 构成,这个接口即用于寻找av路由器上对应的接口以便顺利的发送数据。同时,接口这个部分也是可选的,如果没有,表示发送到所有的同 该av地址连接的接口上。 因为一个 aver 可以多台电脑多次登录到同一个网关上,通过 接口地址可以选择性的发送数据到其中一台电脑上。不过这个特性应该不会有太广泛的实用性,因此大部分av数据包将不包含接口地址。

另外一个设置接口地址的原因是,一个 avif 接口必须有本地地址。对于一个 路由器来说,可能会连接大量的用户,他为每个tcp连接都生成一个 avif, 这样他就需要分配大量的地址给 avif。使用接口地址,就可以保证路由器只需要一个 av地址。

路由表

那么 av网上的路由器是如何路由一个av数据包的呢? 答案是通过路由表。 假设 bob@a.org 连接到了 router@a.org, 那么 bob 的计算机上会有个 avif 为 avtcp0 , 本地地址为 bob@a.org/xxx 目的地址为 router@a.org/xxxx , 而 router@a.org 上则会有个 avif ,接口名为 avtcp10 (这个接口名称数字每次创建新的都会增加1, 类似 linux 下的 ppp0 ppp1 这样的接口名) 本地地址为 router@a.org/xxxx 目的地址为 bob@a.org/xxx 。 这时 router@a.org 收到了一个目的地址标记为 bob@a.org 的 av数据包 (见上文,通常目的av地址不含接口名) route@a.org 通过查询路由表就知道这个数据包要通过 avtcp10 接口转发到目的地。于是他就将这个数据包交给 avtcp10 这个 avif , 这个 avif 就可以通过其到 bob 的 TCP 链接将数据传递出去。 同样在 bob 的电脑上,通常只有一个路由表条目: 就是 对 * 地址(也就是对所有的地址)都发送到 avtcp0 。所以 route@.a.org 又称为 bob 的默认网关。

注意不要把 av地址里的接口名和 avip 的名字接口名 混淆,他们并不一样。 avip的名字只是方便到路由表上寻找接口使用的。而 av 地址里的 接口名,可以把同一个用户的不同设备到同一网关路由器的链接区分开来(虽然大部分情况下没有区分的意义)。也方便网关路由器为 avip 配置不同的av地址。


十一月5日提交的 avim 进度报告和运行办法
#2

加密和认证

每个 av 数据包都需要附带签名,并使用接收方的公钥进行加密。 这样可以保证 2点

  • 只有接收方才能解密数据,可以保证数据传输过程中没有监听
  • 传输过程中的任何一方都可以对数据的发送方进行校验

这2点很重要,特别是第二点,直接决定了 router 是否打算替你转发数据包。。。

为了方便验证,所有的av数据包都会带上 发送方的公钥。而为了节约网络通信, 需要使用的是仅仅 512bit 长度的密钥。 为了防止过短的密钥被污染,这个密钥仅仅使用有限的一段时间。因此,每个 aver 都会使用一个 4-096bit 长的密钥,然后每个月生成一个 512bit 的新密钥,并利用自己的证书对这个密钥进行签名。

但是因为 av数据包并没有附带证书,所以需要一个额外的协议来传递证书,这个协议就是 agmp 协议

每当你收到了一个 aver 发来的消息,但是你没有对方的证书,无法验证对方的身份,就通过agmp协议向对方发起一个证书请求。 一般会一次性发2个,一个是当前使用的临时密钥的证书,一个是 av地址上真正的证书。 真正的证书呢,是必须由 avplayer.org 这个 CA 签发。 临时证书又必须使用aver的证书签发。

这样 agmp 协议就可以完成证书的获取了。 获取了证书就可以对 av数据包的有效性进行检验了。 agmp 协议除了证书交换的作用外,还有 网络可达性测试。 通过发送一个 echo 的 agmp 包到对方来探测对方是否在线,网络是否可达。

加密算法

在 av数据包的头部,有一个字段标识加密算法。目前只定义了 RSA 加密算法。 在以后可以添加更多的非对称加密算法。


#3

目前实现上遇到了一个比较难的难点,就是在对方公钥的获取上。

按照协议,发送信息的流程是这样的:

本地查找对方公钥 if ( 没找到) { 发送 pkask 消息请求 等待对方回应 }

这里,等待对方回应在软件实现上会比较棘手,因为对方的回应是异步到达的,不可能直接等在 async_read 读取数据包上,何况 asio 也不支持这种多重 async_read 调用。因为在另一个地方已经在不停的调用 async_read 接收数据包了。

那么,要怎么样简便的实现所要的异步等一个特定数据包到达的功能呢?


#4

异步等待一个特定数据包到达的机制

这里需要实现一个通用的框架,用于等待一个特定的数据包到达。并且为了避免死锁,要设定一个超时机制。

在用法上, api 是这样的

template<class _Pred>
async_wait_packet(  boost::ptime  deadline, _Pred  pred, asio::yield_context );

deadline 这里设置了一个戒指日期的期限, 而 pred 则是一个回调函数,如果这个数据包就是你要等的数据包,就返回 true。否则返回 false。 好让接收代码继续询问其他有兴趣的。

如果 pred 返回了 true , 那么数据就等到了,然后 async_wait_packet 这个函数本身就返回了 (协程嘛)。