让OpenVPN实现IKE似的两阶段密钥协商

OpenVPN实在不给力,最近发疯似得要搞定它,先一步一步来吧,首先说明问题之所在,每当OpenVPN重协商(--reneg-xxx)时,通道都要重新初始化一下,这看起来很不爽,并且用起来也比较不妥,然而如果将重协商的间隔设置太大,对称密钥又容易被暴破,因此两全不齐美!还好工作正好是这方面的,除了公司的安排,我自己也在做一些改造。首先就瞄上了它的密钥协商!“小顾de杂记”是一个很好的学习OpenVPN的博客,他曾经有一篇文章《OpenVPN & reneg-sec & 一小时断线一次 & Solution》引起了我的思考,最终我有了解决方案。因此我觉得我的博客也是学习OpenVPN的一个不错的去处,呵呵~~
我的想法很简单,那就是向IPSec靠拢即可!IPSec的密钥协商在两个阶段中的第二个阶段,两个阶段是分离的,而OpenVPN的密钥协商运行于SSL加密通道之上,SSL握手可以视为完成认证以及第二阶段加密通道构建的第一阶段。有了想法就要做了,第一步就是实现它,而不是先搞一大堆所谓的计划。我还是觉得程序员的快感来自于编码而不是计划。因此我十分讨厌《人月神话》之类的经验总结书。
在OpenVPN中,当SSL握手建立起一个安全的加密通道的时候,所谓的第一阶段完成,密钥协商这个第二阶段任务开始执行,它正是在第一阶段建立好的加密通道之上来完成的。反正说了这么多,很多人可能有点晕,因此可以参考我的《OpenVPN协议解析》系列文章,这里就不再谈论协议细节了。
在OpenVPN中,两个阶段的协商过程都用状态机来维持,第一阶段和第二阶段统一于一个状态机当中,因此只需要将第二阶段的状态机完美复制一份,然而和原始的第二阶段状态机稍作区分,就大功告成了。要完成这个修改,需要你对OpenVPN代码以及协议完全熟悉。
在OpenVPN的源码中,有以下的宏:

#define S_START           3    /* ready to exchange keys */
#define S_SENT_KEY        4    /* client does S_SENT_KEY -> S_GOT_KEY */
#define S_GOT_KEY        5    /* server does S_GOT_KEY -> S_SENT_KEY */

这也是我们需要复制模拟的宏,我们需要模拟出这三个宏即可,然后在ssl.c的tls_process函数中做以下修改:
0.起码增加三个新的状态;(在ssl.h中搞定)
1.第二阶段,在客户端写入key的时候,更新客户端的状态为新的添加的状态;
2.第二阶段,在服务端读取key的时候,更新服务端的状态为新的添加的状态;
3.第二阶段,在客户端得到key的时候,向对端确认;
4.第二阶段,在服务器端发送了key的时候,等待客户端的确认;
5.第一阶段后,服务器端可以根据配置引发第二阶段协商;
6.第一阶段后,客户端接收到服务端的消息,被动开始第二阶段协商,写入key。
如果完成了以上修改,你的OpenVPN虽然已面目全非,但是更像IPSec了。我的修改中,我使用了push消息在控制信道通知客户端第二阶段协商开启,经测试也是很不错的。最终,我们又多了一个配置,那就是第二阶段密钥协商的间隔,比如1小时,然后加上第一阶段密钥协商的时间间隔,比如5小时,OpenVPN就可以完美了。

标签: 无
返回文章列表 文章二维码
本页链接的二维码
打赏二维码
评论列表
  1. [...]2. 让OpenVPN实现IKE似的两阶段密钥协商[...]

添加新评论