由另一篇博中的分析可知,OpenVPN 中有两个加解密通道。一条是标准的 SSL 协议通道,被 OpenVPN 用于协商自己所用的密钥。这个通道的加密算法当然也是通过 SSL 协议来进行协商的,可以通过 --tls-cipher
选项来进行配置。另一条是 OpenVPN 自己的加解密通道,用于交换实际的数据,也就是虚拟网卡抓到的 IP 报文。这个通道的加密算法则是通过 --cipher
和 --auth
两个选项,分别在通调两端指定的。
对于第二条通道的加密算法,必须要同时在两端分别指定一致的选项,有时候不是很方便(当然,我研究的还是 2.1.1 版本的 OpenVPN ,不知道最新的版本还是不是这样)。比如说,我想通过在服务端修改配置,指定加密算法,然后让连接我的客户端自动用同一个算法。最简单的修改思路,就是借用第一条通道中的算法协商机制,从 SSL 对象中取得协商出来的算法。
具体做法就是:
首先,在函数 do_init_crypto_tls_c1()
中,去掉对函数 init_key_type()
的调用。这个调用就是根据 --cipher
和 --auth
选项进行算法配置的地方,我们要动态协商,自然是不需要这个了。
但同时,这会引起接下来一个步骤的错误。在函数 crypto_adjust_frame_parameters()
中,会根据之前配置的算法进行报文中密钥空间的分配。现在还不知道算法,怎么知道要分配多少空间呢?就只能改成最大值了。分别改为 MAX_CIPHER_KEY_LENGTH
和 MAX_HMAC_KEY_LENGTH
就行了。当然,这样改不仅浪费空间,而且也不够严谨,因为 key length 和 IV length 不是一回事,却只能都用 MAX_CIPHER_KEY_LENGTH
来初始化。
最后就是在 SSL 协商好之后,从里面取加密算法了。具体位置在 key_method_2_write()
和 key_method_2_read()
两个函数中,对 generate_key_expansion()
函数的调用之处了。在调用之前,初始化一下 key_type
就行了:
|
|
这样就行了。