Linux平台VPN技术概论

Linux大全评论1.8K views阅读模式

声明:

1.对于IPSec,不谈其Tunnel以及Transport模式
2.对于OpenVPN,不剖析代码
3.不涉及Linux内核源码剖析
4.不深入谈PPTP以及L2TP
5.本文不是HOWTO也不是技术文档
6.本文的性质是科普

第一部分.VPN要解决的问题以及方案

 

一.问题及方案

基于主机的第三层vpn的要旨就是“透明/安全的接入”,其中透明的含义就是配置要简单,尽量让用户感觉不到vpn的存在,因此这种vpn的实现其实只要解决两个问题即可:
1.如何拿到第N层数据,然后放回第M层;
2.加密/解密第三层ip数据报;

针对第一个问题,实际上我们依赖的是这样一个事实,即OSI的分层网络模型,这样才可以使第M层将第N层的PDU当成有效载荷,解析时只需要根据下层的协议号就可以定位上一层的协议类型。以封装第三层数据的VPN为例,上述第一个问题在linux上有三种方案:

1.使用netfilter

使用netfilter无疑是最直接的方式,对于接收的包,需要在prerouting上挂载一个钩子,对于本地发出的包,则需要在output上挂载一个钩子,这样就可以在钩子函数中进行加密/解密处理了,处理完毕之后再根据策略封装成一个新的ip数据报,重新路由并且发送出去或者接收。

2.使用虚拟网卡

这是一种不直接但是很自然的方式,因为,我们知道从网卡出来的包一个包含一个IP数据报(暂不考虑其它三层协议,比如ipx)。实现一个虚拟网卡,在其xmit发送函数中处理加密,然后重新封装,重新路由。这里暂时先不考虑在哪里解密,因为网卡发送和接收的逻辑是不一样的,我们可以实现一个虚拟网卡,然而却不能修改ip协议栈,除非使用netfilter。

3.将IP数据报导出到用户态,比如使用packet套结字以及替换send/recv

这是最灵活的方案,然而如果使用packet的话却不行。因为packet无法截获数据报。因此需要在socket层次替换send/recv函数,实现加密/封装以及解密/解封装。这里暂时不考虑send处理,因为对于一般的应用数据,是很难替换send的(Linux没有windows的LSP机制),这种方式,控制接收较方便,而控制发送则很难,和使用虚拟网卡的情形正好相反。
Linux平台VPN技术概论
我们发现,2和3是互补的,虚拟网卡很容易拿到发出的未封装的原始IP数据报-通过路由即可,但是拿不到接收的封装过的IP数据报,而替换socket的send/recv则很容易拿到接收的封装过的IP数据报但是拿不到发送的未封装的IP数据报。因此将2和3结合一下,就出现了第四种方式。接下来我们来讨论vpn整体的设计。在架设vpn的时候,首先要明白三件事:
1.确定不安全通路的两个端点。我们就在这两个端点之间建立vpn通路;
2.要考虑到对forward数据包的支持,否则就没有必要使用三层vpn了,使用应用层vpn即可。
3.隧道的概念。隧道其实就是vpn链路两个端点之间的加密通路,其中封装着加密后的原始IP数据报。

确定了vpn链路的端点以后,就可以根据上述的3种方式进行加密/封装,解密/解封装的操作了,也就是说,修建一条隧道。具体的方案如下:

方案1:采用netfilter的方式

这种方案部署起来比较简单,因为端点的两台设备是对称的,netfilter钩子会处理IPSec协议逻辑。成型的项目有Freeswan等,具体细节参见《FreeSWAN 结构框架》。

方案2:虚拟网卡+udp

企鹅博客
  • 本文由 发表于 2020年8月20日 06:43:46
  • 转载请务必保留本文链接:https://www.qieseo.com/208302.html

发表评论