Linux网络虚拟化

本文详细介绍了Linux的network namespace技术,包括创建、管理和删除namespace,并展示了如何使用veth pair进行网络设备间的连接。接着,探讨了Linux Bridge在多个namespace间的作用,以及其配置和应用。此外,还讨论了iptables的用法,展示了如何设置防火墙规则。最后,提到了VXLAN和macvlan等虚拟化网络技术在容器和虚拟机环境中的应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、network namespace

Linux的namespace作用是隔离内核资源,而network namespace作用是隔离Linux系统的设备,包括IP地址、端口、路由表、防火墙等资源,docker作为轻量级虚拟化容器,它的隔离能力来自Linux内核的namespa技术。从网络的角度看每个容器都有自己的虚拟设备,容器里的进程不必担心端口冲突,可使一个主机上同时运行多个服务监听相同端口。
### 有图1

network namespace可以通过系统调用来创建,目前已集成到ip工具的netns子命令中

1. 创建名为netns1的network namespace
# ip netns add netns1

执行完该命令后,系统会在/var/run/netns路径下生成一个挂载点,挂载点的作用一方面是对namespace进行管理,另一方面使namespace即使没有进程也可以继续存在

ll /var/run/netns/
total 0
-r--r--r-- 1 root root 0 Apr  7 17:58 netns1

这个目录可以看到当前主机所创建的所有network namespace

2. 进入namespace
# ip netns exec netns1
3. 查询网络配置
# ip netns exec netns1 ip link list
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

目前没有进行任何配置,只有本地默认环回口设备lo

4. 查看系统中所有namespa
# ip netns list
5. 删除namesp
# ip netns delete netns1

这个命令实际并没删除netns1这个network namesp,只是把对应的挂载点删除,只要里面还有进程运行,netwo namespace就一直存在。

6. 配置network namespace设备状态

我们发现默认情况下自带的l0状态是down,当尝试访问本地环回口时是不通的

# ip netns exec netns1 ping 127.0.0.1
connect: Network is unreachable

我们通过命令

# ip netns exec netns1 ip link set dev lo up

此时再测试ping 127.0.0.1

ip netns exec netns1 ping 127.0.0.1
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.032 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.015 ms

但仅有一个环回口是没发与外部通信,比如主机上的网卡,这时需要在namespace里创建一对虚拟以太网卡,即veth pair,类似于双向管道,从一段进去从另一端收到。

7. 创建veth pair
# ip link add veth0 type veth peer name veth1
# ip link set veth1 netns netns1

我们创建了veth0和veth1一对以太网卡,默认情况下他们都属于根network namespace,然后第二步将veth1移到netns1这个network namespace,此时veth0和veth1还不能通信,因为两块网卡刚创建出来还是down状态,需要手动设置成up,与设置lo类似不过多了绑定ip地址过程

8. veth pair 手动up
# ifconfig veth0 10.1.1.1/24 up
# ip netns exec netns1 ifconfig veth1 10.1.1.2/24 up

在主机上给veth0口配置ip 10.1.1.1 并手动up
在netns1给veth1口配置ip 10.1.1.2 并手动up
此时主机与netns1可以双向通信

在主机里测试

ping 10.1.1.2
PING 10.1.1.2 (10.1.1.2) 56(84) bytes of data.
64 bytes from 10.1.1.2: icmp_seq=1 ttl=64 time=0.056 ms
64 bytes from 10.1.1.2: icmp_seq=2 ttl=64 time=0.015 ms

在netns1里测试

# ip netns exec netns1 ping 10.1.1.1
PING 10.1.1.1 (10.1.1.1) 56(84) bytes of data.
64 bytes from 10.1.1.1: icmp_seq=1 ttl=64 time=0.041 ms
64 bytes from 10.1.1.1: icmp_seq=2 ttl=64 time=0.023 ms
9. network namespace路由表和防火墙

不同network namespace之间的路由表和防火墙都是隔离的

查看路由表:

# ip netns exec netns1 route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
10.1.1.0        0.0.0.0         255.255.255.0   U     0      0        0 veth1

查看防火墙:

# ip netns exec netns1 iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

这意味着network namespace连接到外网是不可能的
我们可以随意将虚拟网络设备分配到自定义的network namespace,但是真实的物理设备只存在于根network namespace,每个网络设备只能属于一个network namespace(即多个自定义network namespace里的ip不能重复)

10. network namespace 进程

非root进程被分配到network namespace只能访问和配置存在于该namespace下的设备

root进程被分配到network namespace可以新建设备还可以把本network namespace里的设备移到其他network namespace

ip netns exec netns1 ip link set veth1 netns 1
ip netns exec netns1 ip link set veth1 netns netns2

上述两种方式均可,一个是将veth1移到进程1所在的network namespace;一个是将veth1移到netns2这个network namespace

查看进程目录:

ll /proc/22505/ns
total 0
lrwxrwxrwx 1 root root 0 Apr  7 19:49 ipc -> ipc:[4026531839]
lrwxrwxrwx 1 root root 0 Apr  7 19:49 mnt -> mnt:[4026531840]
lrwxrwxrwx 1 root root 0 Apr  7 19:49 net -> net:[4026531956]  #network namespace
lrwxrwxrwx 1 root root 0 Apr  7 19:49 pid -> pid:[4026531836]
lrwxrwxrwx 1 root root 0 Apr  7 19:49 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 Apr  7 19:49 uts -> uts:[4026531838]

22505是进称号,若两个进程目录/proc/22505/ns和/proc/12505/ns下[]内的数字相同代表这两个进程属于同一个namespace

如果一个namespace里的所有进程都终止了,该namespace还能存在吗?
可以,只有将/proc/22505/ns/net文件挂载到其他文件下

# touch my/net
# mount --bind /proc/22505/ns/net my/net
二、veth pair

在主机上配置2块虚拟网卡

# ip link add veth0 type veth peer name veth1
# ip link list
40: veth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default qlen 1000
    link/ether ee:0f:6f:cf:e6:13 brd ff:ff:ff:ff:ff:ff
41: veth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default qlen 1000
    link/ether ee:0f:6f:cf:e6:13 brd ff:ff:ff:ff:ff:ff

创建完默认是DOWN状态,MTU是1500
## 有图2

主机上的veth口和容器内的eth0口是成对的关系,如何找到对应关系?

# ip link show
403: veth0@if402: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
    link/ether ee:0f:6f:cf:e6:13 brd ff:ff:ff:ff:ff:ff link-netns netns1

可以看到主机上veth403对应容器内eth402

三、Linux Bridge

两个network namespace直接可通过veth pair连接,多个network namespace之间需要通过Linux Bridge连接。

网桥是二层网络设备,不共享一条背板总线,隔离冲突域,与Linux上其他网络设备的区别是,普通网络设备只有2端,从一端进来的数据会从另一端出去,比如,物理网卡从外面收到的流量会发给内核协议栈,而从内核协议栈发过来的流量也会转发到外面的物理网络,Linux Bridge则有多个端口,数据从任意一个端口进来,根据mac地址匹配从哪个口出去。

1. 创建网桥
# brctl addbr br0

网桥刚创建是一个独立的网络设备,只有一个端口连接着协议栈,没有任何实际功能

2. 将veth100添加到br100
# ip link add veth0 type veth peer name veth1
# ip addr add 1.2.3.101/24 dev veth0
# ip addr add 1.2.3.102/24 dev veth1
# ip link set veth0 up
# ip link set veth1 up
# brctl addif br0 veth0

查看当前存在的网桥和网络接口

# brctl show
bridge name	    bridge id    STP enabled interfaces
br0		   8000.da65bbdcf99b	 no		  veth0

## 有图3

br0和veth0相连后两设备直接是双向的通道,可是veth0和协议栈直接变成单向通道,从veth0收到的数据包不会发给协议栈,而协议栈仍可将数据发给veth0

此时br0的mac地址变成了veth0的mac地址

测试:veth0 ping veth1不通

ping -I veth0 1.2.3.102
PING 1.2.3.102 (1.2.3.102) from 1.2.3.101 veth100: 56(84) bytes of data.
From 1.2.3.101 icmp_seq=1 Destination Host Unreachable
From 1.2.3.101 icmp_seq=2 Destination Host Unreachable

原因是veth0不知道1.2.3.102的mac地址会先发ARP,veth1收到ARP后回复,veth0收到veth1的mac地址后并未发给网络协议栈而是发给了br0,协议栈不知道veth1的mac地址无法通信(协议栈相当于交换机)

由此我们发现给veth配置ip没有意义,无法通信,所以我们将veth0的ip地址给br0,而veth0不配置ip的话,协议栈不会给veth0发数据包。

# ip addr del 1.2.3.101/24 dev veth0
# ip addr add 1.2.3.101/24 dev br0

此时测试可以通过:br0 ping veth1

# ping -I br0 1.2.3.102
PING 1.2.3.102 (1.2.3.102) 56(84) bytes of data.
64 bytes from 1.2.3.102: icmp_seq=1 ttl=64 time=0.025 ms
64 bytes from 1.2.3.102: icmp_seq=2 ttl=64 time=0.017 ms
3. 将物理网卡添加到Linux Bridge
# brctl addif br0 eth0

对网桥来说物理网卡和虚拟网卡都是一样的设备。
此时eth0和veth0一样仍无法将收到的ARP报文发给协议栈,所以要把eth0的ip删掉,此时br0上的veth0、veth1都可通过br0连接的eth0访问外网。

4. Linux Bridge在网络虚拟化中的应用
  • 虚拟机
    虚拟机通过tnu/tap或者类似的网络设备将虚拟机内的网卡同br0连接起来,虚拟机发出的数据包先到达br0再由br0交给eth0发送出去,不需要经过host机器的协议栈,提升效率


注意:因为虚拟机eth0分配的网段和host上eth0连接的物理网络在同一网段,所以不需要经过host机器的协议栈

  • 容器
    容器运行在自己单独的namespace里,有自己单独的协议栈,从容器发出去的数据包先到达br0然后交给host机器的协议栈,host机器开启ip forward功能会通过eth0发送出去。
    ## 有图6

注意:因为虚拟机eth0分配的网段和host上eth0连接的物理网络不在同一网段,所以需要经过host机器的协议栈,发出去前会进行NAT转换

  • 网络接口的混杂模式
    在非混杂模式下一个网卡会接收目的mac是它自己的单播帧,多播帧及广播帧,在非混杂模式下一个网卡会接收的所有经过它的网络流量

  • tun/tap工作原理
    一端连着网络协议栈,一端连着用户态程序,利用Linux设备文件实现用户态和内核态的数据交互,普通网卡通过网线收发数据包,tun则是用户态进程对该文件的写操作都会通过tun设备转换成数据包传送给内核网络协议栈,当接收协议栈的数据时用户态进程直接读取文件内容(谁写谁是发送方,谁读谁是接收方)

iptables

iptables是用户空间的一个程序,有5条内置链

  1. INPUT:处理输入本地的数据包
  2. OUTPUYT:处理本地输出的数据包
  3. FORWARD:处理转发到其他机器/network namespace的数据包
  4. PREROUTING:在此进行DNAT
  5. POSTROUTING:在此进程SNAT

5张表

  1. filter:控制到达某条链操作,drop或者accept
  2. nat:修改数据包的原、目地址
  3. mangle:修改数据包的ip头信息
  4. raw:iptables对数据包有连接追踪,raw用来去除这种追踪
  5. security:在数据包应用SE Linux
1.查看iptables规则
# iptables -L -n

-n 可以将域名解析成ip地址

2. 允许SSH连接
# iptables -A INPUT -s 10.23.2.0/24 -p tcp --dport 22 -j ACCEPT

-A代表以追加的方式添加规则,添加到INPUT链,-s匹配源网段,-p匹配协议,–dport匹配目的端口,-j执行的动作

3. 封锁端口

3.1 封锁本地1234端口对外访问

# iptables -A OUTPUT -p tcp --dport 1234 -j DROP

3.2 封锁其他人访问本地1234端口

# iptables -A INPUT -p tcp --dport 1234 -j DROP
4. 端口转发

对外声称web在端口80上运行,若80被人占了实际服务在8080我们让外部用户不感知,可使用转发命令

# iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080

-j 操作是将浏览转发到8080端口
我们修改了目的端口需要在nat表操作,对DNAT相关链PREROUTING修改规则

5. 禁止icmp协议
# iptables -A INPUT -p icmp -j DROP
6. 删除规则
# iptables -D INPUT -s 10.1.0.0/24 -j DROP
7. DNAT
#iptables -t nat -A PREROUTING -d 1.2.3.4 -p tcp --dport 80 -j DNAT --to-destination 10.1.1.200:8080

匹配:目的ip为1.2.3.4端口80的数据包
执行操作:修改目的ip为10.1.1.200,目的端口为8080
链:PREROUTING

8. SNAT
# iptables -t nat -A POSTROUTING -s 192.168.1.100 -j SNAT --to-source 10.1.1.100

匹配:源ip为192.168.1.100的数据包
执行操作:修改源ip为10.1.1.100
链:POSTROUTING

9. 保存与恢复
#iptables-save
Linux隧道网络:VXLAN

VXLAN是一种虚拟化隧道技术,是一种在底层物理网络(underlay)之上的overlay技术,使逻辑网络和物理网络解耦,适配虚拟机环境和容器环境,不需要对原网络做任何改动,就可在原网络基础上架设一层新的网络

不同于其他网络隧道协议,vxlan是一对多的网络,一个vxlan设备可以学到其他对端的IP,也可以直接配置静态转发表。

VXLAN应用:
1、VLAN报文的header里有12bit最多支持4096个子网,无法满足大规模需求,VXLAN报文里有24bit,可以支持2的24次方个子网。
2、VXLAN创建在3层之上,只要三层可达(IP互通)即可部署VXLAN。
3、VXLAN网络的每个端点都有一个VTEP设备,负责封装和解封vxlan报文
4、每个vxlan隧道通过vni标识,使得不同vxlan相互隔离

  • VTEP
    vxlan的边缘设备,用来进行vxlan报文的封装和解封装,vtep可以是一台交换机也可以是一台物理机
  • VNI
    每个vxlan的标识,最大值2的24次方
  • VXLAN 报头
    ## 有图

vxlan报文比原始报文多了50字节(8字节的vxlan头+8字节UDP+20字节IP报头+14字节二层报头),注意封装时将内层的mac、ip、协议封装在vxlan header里,再套用标准的二、三层(外层)和UDP完成封装。
需要注意的是UDP的目的端口是4789
VXLAN一共需要知道三个信息:内部mac、vtep ip、vni就可以转发数据包。

1. 创建vxlan接口
# ip link add vxlan0 type vxlan id 42 group 239.1.1.1 dev eth0 dstport 4789

创建vtep口,vni=42,通过eth0的多播组239.1.1.1转发数据包

2. 删除vxlan接口
# ip link delete vxlan0
3. 查看vxlan接口信息
# ip -d link show vxlan0
4. 点对点vxlan

两台机器,每个机器上都有一个vtep口,vtep之间通过ip通信
## 有图

host1配置:

# ip link add vxlan0 type vxlan id 42 dstport 4789 remote 192.168.1.3 local 192.168.1.2 dev eth0

创建vxlan0接口,vni=42,对端端口4789,默认8472,对端ip=192.168.1.3,本地ip=192.168.1.2,vtep通信的网卡设备是eth0,敲完该命令后host1上创建vxlan0网卡

# ip link add 172.16.1.2/24 dev vxlan0
# ip link set vxlan0 up

原始报文经过vxlan0口后会在添加上外部的ip头192.168.1.2
此时在host1上ping 172.16.1.3是通的

5. 多播模式vxlan

前提是底层的网络结构支持多播
主机之间不是点对点连接而是通过多播组成一个虚拟整体
## 有图

host1配置:

# ip link add vxlan0 type vxlan id 42 dstport 4789 group 224.1.1.1 local 192.168.1.2 dev eth0

将vtep加入多播组,多播组地址是224.1.1.1

  • ICMP数据包转换过程
    1、host1的vxlan0 ping 172.16.1.3,内核发现源目ip是同一网段,不知道mac地址发送arp报文
    2、arp报文的源mac是vxlan0的mac,目的mac是255.255.255.255,vni=42
    3、多播模式下vtep会给224.1.1.1发送报文
    4、多播的所有主机都会收到这个报文,内核发现是vxlan报文根据vni转发给对应vtep
    5、host2的vtep收到vxlan报文去掉头部,发现arp报文,发现arp是发送给自己的记录下vtep的源mac和源ip到自己的转发表,若不是发给自己直接丢弃
    6、host2单播回复应答报文,目的mac是host1的vtep口地址(192.168.1.2)
    7、host1的vtep口收到host2的vtep口的报文后记录到自己的转发表
    8、host1的vxlan0口发送icmp包可单播到host2
Macvlan

最早版本的docker是不支持容器网断和宿主机网断互通的,macvlan的引入使得容器可以直接可以使用宿主机的网断资源。
macvlan出现之前可以给一个网卡添加多个IP地址但是不能添加多个mac地址,因为网卡的mac地址唯一;macvlan允许用户在一个网络接口上配置多个虚拟接口,每个macvlan接口都有区别于父接口的mac地址,因此macvlan技术带来的效果是一块物理网卡上绑定多个IP地址,每个IP地址都有自己的mac地址

Macvlan支持5种模式:bridge、VTEP、private、passthru、source

1. bridge模式

在bridge模式拥有相同父接口的macvlan虚拟网卡之间可以直接通信,它不需要学习mac地址,但如果父接口故障所有的macvlan子接口也会跟着故障,子接口之间无法通信

2. VTEP模式

VTEP模式是macvlan的默认模式,所有从macvlan子接口发出的流量无论目的地址是哪里一律发给父接口,父接口收到后会广播泛红给所有子接口;注意macvlan子接口之间通信的话也要经过父接口。

3. private模式

private模式类似VTEP模式,但又增强了隔离能力,即阻隔了同一父接口下macvlan子接口之间的通信

4. passthru模式

passthru模式下每个macvlan父接口只能和一个子接口绑定,且子接口继承父接口的mac地址,限制了子接口直接通信。

5. source模式

source模式下macvlan只接收指定源mac的数据,其他数据一律丢弃。

macvlan配置

创建macvlan子接口:

# ip link add eth0.1 link eth0 type macvlan mode bridge

查看macvlan子接口信息:自动分配mac,需要手动配置IP

# ip -d link show eth0.1

将macvlan接口状态修改为up

# ip link set eth0.1 up

## 有图

注意,主机192.168.1.3 ping 192.168.1.21可以通信,主机192.168.1.2 ping 192.168.1.21不通,因为父接口相当于交换机的一个端口只负责转发不负责处理数据包,所以收到了也不处理。

macvlan和overlay对比

1、overlay网络的作用范围是全局,macvlan网络的作用范围是本地。
2、宿主句创建的macvlan都是独立的,宿主机之间互不影响。

macvlan局限

macvlan需要大量的mac地址,许多物理网卡对虚拟mac地址的数量有限制,超过限制会影响性能。
无线网络环境下,一个客户端不许有多个mac地址,所以macvlan也无法在无线网络使用。
IPvlan可以解决这个问题。

IPvlan

IPvlan是从一个主机接口虚拟出多个虚拟网络接口,与macvlan的区别在于所有虚拟接口都用相同的mac地址,而IP地址不相同,这些IP共享同一个mac地址。
IPvlan有2种模式:L2、L3

L2模式

L2模式类似macvlan的bridge模式,父接口作为转发接口,多个子接口直接可以通信。

L3模式

L3模式类似开启路由功能,不通ipvlan子接口配置的ip地址可以分别属于不通网断,也可以与父接口属于不同网段。

IPvlan配置
# ip link add ipv1 link eth0 type ipvlan mode l3
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值