虽然以现在的加密技术,主要选择的加密算法没问题,在很长一段时间都不太用担心监听通讯的人解密获得明文。但是针对特定的加密通讯协议,还是很可能找到方法找到某种模式。这个模式不能转换为明文,但可以猜测出你是否在使用特定协议。
另外,无论你怎么加密通讯,访问特定服务流量的时间特征也可能泄露你的秘密:用什么节奏通讯,每个 ip 包多大,这些都是可供匹配的特征。
我认为,大多数情况下,通讯的稳定性是大于带宽的需求的。那么,采用本文这种方法应该能去掉上面这些流量特征。
先说说流量的时间特征。
所谓时间特征,就是通讯流量中每个字节送达的时间间隔序列。这是大多数加密算法所忽略的信息。因为通常我们不会用这个间隔序列来传递信息,也就没有必要对这个序列进行处理。但它却容易暴露协议特征。
消除这个特征的方法也很简单,我们让数据流以绝对稳定的速率传输就好了。无论有没有有效流量,我都保持绝对相同的包大小,按固定频率发送数据。只有有真正的数据需要发送时,再把数据负载到信道上,替换掉冗余流量即可。
如果保持着 64KBps 的稳定通讯带宽,7 * 24 小时工作,一个月的流量总和大约在 160GB 左右,而 linode 最便宜的 5$ 档,一个月提供的流量也有 1TB ,成本是相当低的。
如果保持一个长连接,在建立好之后就不需要监听接纳新连接进来,可以有效防止嗅探。握手协议也只发生一次,所以比较安全。
我测试了一天,从办公室宽带同美国一个机房的机器建立连接,以稳定速率发送纯随机的字符串,一整天下来都没有任何干扰。从两段的 log 分析,中间没有发生过波动。
第二是加密。
既然是有大量的闲时流量,我们也就不必浪费,完全可以利用它实现一个更好的加密。
想想量子通讯加密的原理,用量子同步一个密钥序列过去,然后用传统信道传输明文 xor 密钥 。这种方式只要保证了密钥不可能被窃听,传输的密文就是完全没有保留明文原有特征的。
我们正可利用闲时流量传输随机串,做一些简单的加密(比如使用预设的密钥),那么在真正数据载荷上,只要 xor 过去发送的随机串就可以完美加密了。在极端情况下,预先发送的随机串被消耗光,我们也至少可以获得固定带宽的一半来传输有效数据。
只要产生随机序列的算法够好:例如 linux 的随机数发生设备就会收集来自系統、驱动程序或或其它來源的环境噪音,就会比依赖有限 key 产生加密序列的算法(例如 rc4 等)要强的多。随机数列越随机,就越不可能残留模式。这样就能阻止监听者的模式分析。
通讯协议的设计也很简单,例如可以用 1bit 的标识 + 7bit 长度 + 数据块的方式来编码。只会增加 1/255 的额外负载。
在实现上,开两个线程或两个进程来做这件事情,一个线程负责以固定频率发送数据流,另一个线程负责接收有效数据流,传递给发送线程即可。
通讯信道上,我建议把上行通道和下行通道分离。至少要建立两条 TCP 连接,一条只传输数据,另一条只接收数据。
如果有条件的话,可以把两条连接走不同的 ISP ;或是同两个不同的机房建立连接,在对端两个机房间再建立通道合并在一处处理。