Linux 网络:从协议栈到虚拟化

冰岩作坊 November 9, 2024

本次分享有不少概念和名词。如果你看完还不太懂,没关系,可以先学点前置知识;如果你没看就懂完了,没问题,下次分享就你了

神秘的网络

提到计算机网络,我们可能马上会想到什么 OSI 七层模型,三次握手四次挥手,在浏览器输入 URL 之后发生了什么之类的知识。考虑到我们既不需要像搞通信设备的那帮人天天研究网卡和交换机,也不需要像搞基础架构的那帮人天天研究协议和路由算法,我们的网络知识似乎已经够用了……吗?以下是我在实践中遇到过的与网络相关的问题:

了解一些 Linux 网络相关的知识,虽然不能完全帮助我们解决上面的问题,但也能提供点思考和分析的方向,还是很值得学习的。

网络协议栈

首先我们还是从基础的网络通信开开始,了解数据是如何从程序发出,经过网络设备,传输,最后被另一个程序接收。好消息是,这个过程和我们所熟知的分层模型基本上是对应的,数据流动的路径大致如下:

经过上面的过程,我们得到了一个完整的数据包:

接收方的处理大概就是上面的过程反过来,这就不细说了

由于这个过程中有比较明显的逐层调用,逐层封装,再后进先出处理的特点,与我们熟知的栈这种数据结构很类似,因此它也被称为 Linux 网络协议栈。

管理网络数据包

在前面的网络协议栈中,我们会发现除了应用层,剩下的都在系统内核空间里了。这样的设计在数据安全与隔离上确实很好,大黑客没法直接窃听或者伪造网络通信了,但我们自己想要管理和控制,似乎也不简单。还好,Linux 内核还给我们提供了一套通用、可编程的网络数据包管理框架:Netfilter

这套框架在数据包处理的过程中埋下了五个钩子(Hooks),应用程序先在这注册回调函数,每当有数据经过时就会触发调用,最终实现干预网络通信的功能。这五个钩子是:

有了这套框架,网络的玩法就变多了。比如被称为 Linux 自带防火墙的 iptables,比 iptables 更新更快的 nftables,kubernetes 中实现 Service 访问的 kube-proxy 等等,很强很灵活。

其他方法比如 proxychains 通过拦截库函数调用,在进入内核前修改,wireguard 通过虚拟网络设备捕获 IP 数据包并完成加密传输,还有最新最热的 ebpf 在内核中拦截,这里就不细说了

虚拟网络

前面提到的网络能力已经非常丰富了,但物理的网络毕竟还是有基础设施的限制,随着对灵活性、安全隔离、运维管理和云计算的需要,网络的虚拟化也变得重要起来。在物理网络的世界里,我们有网卡、交换机、路由器,而在虚拟网络中,我们也同样拥有:

我们可以用 TAP/TUN 设备实现一个简单的 VPN:

我们也可以用 VETH 简单的连接两个容器:

虽然他叫 Bridge 直译过来是网桥,但从功能上我们完全可以把它当交换机来用,另外 Linux 内核其实也带有路由功能,看做个自带的虚拟交换机好像也没啥问题

利用 Bridge,现在我们可以把多个网络连接到一起了(docker 的默认网络模式就是这样做的):

但是,虚拟网络的大网还少了点东西… 是的,他目前只能在本机完成。为了使我们的虚拟网络跨越不同的物理主机,简单来说,我们可以:

至此,我们的虚拟网络算是用比较现代的技术搭建起来了。当然,近些年云原生分布式大火,虚拟网络也成为热门研究领域,实现方式除了 vxlan 还有很多,感兴趣的话可以看看那些热门的 k8s 网络插件。

附:你可能不知道的校园网小知识

#Linux#网络