理论上已经合理的 ip over ssl 还需要一些额外的技术支撑才能使用,必须想办法将一个 ip 数据报原封不动的让它被 ssl 重新封装一次,这个动作不可能在原始的标准协议栈中执行,标准协议栈不支持数据双向流动,那么解决方案之一就是修改协议栈,在 ip 层之下实现一个轻量的 ssl 协议层,但是如此一来就又回到了 IPSec 的老路上,因此此法不可取,正确的方法是不修改协议栈,让一切留在它应该在的地方,于是 ssl 必然得在应用层或者说是表示层实现,现在的问题是如何将下层的 ip 数据报重新引入上面的应用层,而且还不能修改标准协议栈,于是必然地要让 ip 数据报继续往下走,然后最终从一个网卡流出,于是就出了协议栈,接下来就可以自由发挥了,让数据流出网卡的原因是不能修改协议栈,但是还不能真的让它流出机器,如果它走了就不能指望用 ssl 封装它了,那么流到哪里呢?回环设备是一个不错的选择,从回环设备流出的数据实际上又流进了回环设备,用户空间只需要打开回环设备然后读取就可以了,注意不能通过一般套接字读取,毕竟那些数据不是发给我们的,要使用类似抓包的方式进行数据抓取,并且用防火墙禁止被抓取的数据继续被 forward,这实际上是一种巧妙的拦截方式,被抓取得数据然后经过 ssl 封装后再发向一个真的 ip 地址,我们需要配置的就是将所有的 vpn 数据全部发往回环设备,其实就是添加一条路由,虚拟网络已经建立,事情到此为止看似要结束了。
但是且慢,问题来了,以后所有 vpn 数据都会经标准协议栈流出再流进 loopback,然后作为裸数据进入应用层,接着整个原始 vpn 数据连同它的原始 ip 头封装作为应用数据接受 ssl 协议的封装,然后发往 vpn 的另一端,在另一端数据从真实网卡进入,然后由于这是隧道的终点,数据直接进入应用层,在应用层,vpn 服务器等候在那里,得到原始的 vpn 裸数据还有它在发送端的 ip 头,服务端得到这个东西有什么用呢,接下来它要怎么做呢,它只是隧道的终点,并不是真的要接收数据的机器,因此它必须将数据重新发到真正需要它的机器,很显然它要作为一个应用层代理存在,剥去原始的 ip 头,得到原始的数据,然后将数据发给真实的目的地,且不说此法是否可能,有两点不合理之处足以否定它,由于 vpn 服务器实现了代理,那么数据必然要在该处集中并剥去 ip 头,并且在相反的方向要做同样的处理,那么它就要记住所有的 ip 头,否则数据就会有去无回,如此一来,vpn 服务器的负载可堪忍受?性能呢?第二点,代理的方式消除了隧道的透明性,目的地受到数据后会不知道数据从何而来,统一认为是 vpn 服务器发来的,这样就无法根据数据源点进行策略化服务。
综上原因,loopback 设备可用但不可行,因为它是本机闭合的,也就是说只有 loopback 出去的数据才能进入 loopback,它又且仅有两个出口,一读一写都在应用层,你无法将数据作为物理层的流写入 loopback,而只能作为应用层的数据通过协议栈逐级封装到达 loopback,然后再逐级解封回来,vpn 发送端面临同样的问题,因为仅仅是路由将数据出口指向了 loopback, 如果不用抓包的方式(pcap)的话是得不到数据的,而这种方式又十分影响性能,加之还要配置复杂的防火墙规则禁止进入 loopback 的数据被转发,性能又受影响,隧道两端由于是全双工通信,因此一端面临的问题在数据反向时在对端同样存在,抛开这些不谈,仅就 loopback 无法自由配置 ip 地址这一条,它就不能被选中来实现隧道,vpn 网络需要被管理,有时管理本身就很复杂,虚拟网络不仅仅就一张,我们需要为每张虚拟网络准备一个子网,也就是每个虚拟网络要有不同的 ip,所以必然需要灵活的 ip 配置,故而 loopback 不能实现优雅透明的隧道,既然如此我们回到原点,无非就是做到两点,第一,数据必须按照协议栈的标准逐级封装和解封装,不能修改协议栈,第二就是数据到了最下面物理层的时候不能真的走掉,而是回到用户空间,于是乎虚拟网卡就成了很好的选择。