OpenVPN的新钩子设计

openvpn是一个虚拟网卡和SSL相结合的vpn框架,使用虚拟网卡得到协议栈封装数据,然后通过ssl协议发送出去,此中重点在于:1.得到数据;2.得到的数据是协议栈封装好的数据;3.通过openssl的接口进行发送。如果一个客户终端没有虚拟网卡的支持,或者没有openssl库,那么openvpn将运行不起来,然而没有openssl的问题好解决,装一个就是了,没有虚拟网卡支持的问题就不好解决了,毕竟支持虚拟网卡需要操作系统内核的驱动程序,安装这个驱动程序要看操作系统同意与否,比如在linux上需要root权限,在windows2008之类的系统上需要微软签名等等,实为不便,于是考虑到stunnel的方式,在第七层设置一个代理,可以实现本地代理的方式而完全不使用openvpn,比如使用stunnel监听一个端口1234,然后将vpn的数据重新定向到这个1234端口,可以通过设置代理的方式,也可以通过iptables的REDIRECT的方式,可是又有问题了,这种方式虽然可以拿到需要代理的数据,然而由于vpn的server端需要识别客户端的“虚拟IP地址”,而stunnel却不支持这个虚拟ip地址,它完全就是一个应用层的代理程序,比如在服务端架设一台openvpn服务器,启动后其虚拟ip地址是172.16.1.1,它所接收到的数据是客户端传来的ip数据报或者以太帧,其携带的源ip必然要是172.16.1.0/24网段的才行,stunnel做不到这一点,因此必然需要一种办法,不使用虚拟网卡,又必然要支持虚拟网络。
其实这个问题也好办,我们可以自己封装ip数据报或者以太帧,比如使用基于python的scapy就可以很方便的封装任意的ip数据报或者以太帧,我们需要做的仅仅是将从scapy和openvpn结合起来,并且修改openvpn从虚拟网卡的字符设备读取数据为从scapy读取数据,然后再写一个一切和虚拟网卡接口的实现,比如ifconfig之类,实现此ifconfig的时候,我们不必配置真的虚拟网卡,而是保存ip地址,掩码信息以及mac信息在一个数据结构中,然后scapy封装数据报或者数据帧的时候从该数据结构取出即可,另外要做的就是在本地起一个代理服务,这是为了抓取需要通过vpn的裸数据。因此过程称为:
1.修改后的openvpn+scapy侦听1234端口;
2.修改浏览器的代理为本地的1234端口;
3.发送http请求,然后被openvpn+scapy得到;
4.openvpn+scapy通过openvpn服务器push过来的虚拟网络配置信息封装数据报(tun)或者数据帧(tap);
5.scapy封装好的数据通过修改后的openvpn的tun.c中tun_read函数进入openvpn;
6.至此,openvpn丝毫不能确定数据来自虚拟网卡还是别的;
7.一切按照正常的流程通过ssl发送;
8.如果有数据报回复,依然通过将修改后的tun_write将数据报(tun)或者数据帧(tap)发送给scapy,然后截掉协议头信息;
9.将裸数据发送给浏览器,浏览器显示之。
要点:
1.如果觉得python性能不够,完全可以重新以本地语言c实现scapy;
2.本地代理服务要完全与stunnel的前期行为相似,一定保存好session之信息,只是stunnel代理客户连接了真实的服务器,而openvpn+scapy却将数据直接交给了scapy。
总结起来就是,虚拟网卡仅仅是获取数据的一种方式,通过本地代理或者远程代理获取数据然后在用户空间封装成ip数据报或者以太数据帧终成的数据是获取数据的另外一种方式,可见必有第三种方式和第四种,因此将tun.c的接口抽取出来和实现相分离是一个很好的方向,后期可以将openssl也作为发送接口的一种方式,而其它的ssl实现可以作为另一种方式,至此,openvpn就完全变成了两部分的固定接口:1.获取封装好的数据;2.通过ssl发送数据,然后1和2的实现作为钩子提供给实现者,保留一个默认的实现,那就是以虚拟网卡技术实现1,并且以openssl实现2。

标签: 无
返回文章列表 文章二维码
本页链接的二维码
打赏二维码