完全在用户态实现IPSec VPN

来源:互联网 发布:接吻会传染什么病知乎 编辑:程序博客网 时间:2024/05/01 18:04

IPSec的复杂性之一在于它和内核协议栈实现高度相关,造成升级和管理的不便,如果能在用户态实现IPSec,那么所有的客户端就可以使用这种用户态的IPSec了。
     需要特别注意的是,如果你拥有一台IPSec硬件网关,那么不考虑NAT穿越的情况下其实IPSec也是很不错的,IPSec的困难在于客户端,特别是PC上或者中等服务器上的客户端,如果使用用户态的IPSec,那么IPSec起码能和OpenVPN一样好,比OpenVPN好的就是能和IPsec对端进行无缝衔接。其次你要知道,IPSec分为两大部分,第一部分是密钥协商和安全认证相关的,这部分都是在用户态实现的,比如racoon。第二部分是封装协议,这部分一般都在内核实现,比如使用Netfilter,或者xfrm。
     完全可以通过两个虚拟网卡来实现用户态的IPsec,这样IPSec的部署将简化很多,和内核协议栈彻底脱离干系。并且由于在用户态实现,IPSec使用的协议也会灵活很多,如果需要和远端的IPSec网关无缝衔接,那么必要的是实现IKE和ESP/AH等协议,IKE的开源实现已经很多了,那么需要做的仅仅是封装ESP/AH了。如果不需要兼容ESP/AH,那么完全可以实现自己的封装,甚至只用GRE或者IPIP封装都可以,当然,你可以自定义任何自己的协议,很方便,很灵活。然而如果使用自定义的协议,修改一边就不妥了,对端也要支持这个自定义的封装协议才行,有两个方式可用,第一就是在对端加载内核模块,使用内核的方式进行支持,在linux上无非就是注册一个协议而已,当然你也可以用netfilter实现;另外一种方案就是和客户端一样,也使用用户态的实现。
     那么,到底如何实现呢?由于时间关系,我的代码只调通了一半,但是思路很清晰,那就是使用af_packet套接字直接写IP封装后的以太帧,IP上层用ESP封装。当然也可以使用raw套接字。不管怎么说,下面这个图应该可以表达一些信息:

用户态实现IPSec的要点有两点,其一是TUN虚拟网卡的活用,其二是af_packet/raw套接字的使用。