S_lion's Studio

自己动手实现network namespace

字数统计: 2.2k阅读时长: 12 min
2021/07/13 Share
之前的文章提到了6种Linux的namespace隔离技术,其中network namespace为命名空间内的所有进程提供了全新隔离的网络协议栈。这包括网络接口,路由表和iptables规则。通过使用网络命名空间就可以实现网络虚拟环境,实现彼此之间的网络隔离,其实通过ip命令就可以模拟出网络命名空间。

安装软件

首先需要安装iprouter软件:

1
2
[root@slions_pc1 ~]# rpm -q iproute
iproute-4.11.0-14.el7.x86_64

我本地已经安装了,查看IP命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@slions_pc1 ~]# ip help
Usage: ip [ OPTIONS ] OBJECT { COMMAND | help }
ip [ -force ] -batch filename
where OBJECT := { link | address | addrlabel | route | rule | neigh | ntable |
tunnel | tuntap | maddress | mroute | mrule | monitor | xfrm |
netns | l2tp | fou | macsec | tcp_metrics | token | netconf | ila |
vrf }
OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] | -r[esolve] |
-h[uman-readable] | -iec |
-f[amily] { inet | inet6 | ipx | dnet | mpls | bridge | link } |
-4 | -6 | -I | -D | -B | -0 |
-l[oops] { maximum-addr-flush-attempts } | -br[ief] |
-o[neline] | -t[imestamp] | -ts[hort] | -b[atch] [filename] |
-rc[vbuf] [size] | -n[etns] name | -a[ll] | -c[olor]}

创建netns

查看本地是否存在netns

1
2
[root@slions_pc1 ~]# ip netns list
[root@slions_pc1 ~]#

创建两个netns,分别叫slions_ns1,slions_ns2

1
2
3
4
5
[root@slions_pc1 ~]# ip netns add slions_ns1
[root@slions_pc1 ~]# ip netns add slions_ns2
[root@slions_pc1 ~]# ip netns list
slions_ns1
slions_ns2

查看下这个命名空间下的网卡信息,可以看到都只有lo环回网卡

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@slions_pc1 ~]# ip netns exec slions_ns1 ifconfig -a
lo: flags=8<LOOPBACK> mtu 65536
loop txqueuelen 1000 (Local Loopback)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
[root@slions_pc1 ~]# ip netns exec slions_ns2 ifconfig -a
lo: flags=8<LOOPBACK> mtu 65536
loop txqueuelen 1000 (Local Loopback)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

创建veth网卡设备对

需要创建一对儿veth虚拟网卡

1
2
3
4
5
6
7
8
9
10
11
12
[root@slions_pc1 ~]# ip link add veth0 type veth peer name veth1
[root@slions_pc1 ~]# ip link show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
link/ether 00:0c:29:97:8c:d0 brd ff:ff:ff:ff:ff:ff
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default
link/ether 02:42:8a:8f:d7:d5 brd ff:ff:ff:ff:ff:ff
8: veth1@veth0: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether ae:f9:75:fa:93:4d brd ff:ff:ff:ff:ff:ff
9: veth0@veth1: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether d2:24:de:9b:b5:d9 brd ff:ff:ff:ff:ff:ff

可以看到,此时本地多了8和9两块没有被激活的网卡,并且从网卡名上可以看出对应关系

移动veth网卡到netns

把其中一个网卡移动到命名空间slions_ns1中

1
[root@slions_pc1 ~]# ip link set veth1 netns slions_ns1

在slions_ns1中验证网卡信息

1
2
3
4
5
[root@slions_pc1 ~]# ip netns exec slions_ns1 ip a
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
8: veth1@if9: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
link/ether ae:f9:75:fa:93:4d brd ff:ff:ff:ff:ff:ff link-netnsid 0

再来看下宿主机的网卡信息,发现之前的8号没了,仔细观察会发现slions_ns中新的网卡正是之前的8号网卡,从序号也可以看出来,并且网卡名中的@ifx就是veth设备对端的网卡序号

1
2
3
4
5
6
7
8
9
10
[root@slions_pc1 ~]# ip link show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
link/ether 00:0c:29:97:8c:d0 brd ff:ff:ff:ff:ff:ff
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default
link/ether 02:42:8a:8f:d7:d5 brd ff:ff:ff:ff:ff:ff
9: veth0@if8: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether d2:24:de:9b:b5:d9 brd ff:ff:ff:ff:ff:ff link-netnsid 0

我们还可以给slions_ns1中的veth1改名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@slions_pc1 ~]# ip netns exec slions_ns1 ip link set dev veth1 name eth0
[root@slions_pc1 ~]# ip netns exec slions_ns1 ifconfig -a
eth0: flags=4098<BROADCAST,MULTICAST> mtu 1500
ether ae:f9:75:fa:93:4d txqueuelen 1000 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

lo: flags=8<LOOPBACK> mtu 65536
loop txqueuelen 1000 (Local Loopback)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

激活veth网卡

给宿主机veth网卡设置ip地址为10.0.0.1,激活网卡

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
[root@slions_pc1 ~]# ip addr add 10.0.0.1/24 dev veth0
[root@slions_pc1 ~]# ip link set veth0 up
[root@slions_pc1 ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:97:8c:d0 brd ff:ff:ff:ff:ff:ff
inet 192.168.100.10/24 brd 192.168.100.255 scope global noprefixroute ens33
valid_lft forever preferred_lft forever
inet6 fe80::8199:4454:db1e:911c/64 scope link tentative noprefixroute dadfailed
valid_lft forever preferred_lft forever
inet6 fe80::22c9:e9bb:e5a1:9403/64 scope link noprefixroute
valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:8a:8f:d7:d5 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:8aff:fe8f:d7d5/64 scope link
valid_lft forever preferred_lft forever
9: veth0@if8: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state LOWERLAYERDOWN group default qlen 1000
link/ether d2:24:de:9b:b5:d9 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 10.0.0.1/24 scope global veth0
valid_lft forever preferred_lft forever

给slions_ns1命名空间的veth网卡设置ip地址为10.0.0.2,激活网卡

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[root@slions_pc1 ~]# ip netns exec slions_ns1 ifconfig eth0 10.0.0.2/24 up
[root@slions_pc1 ~]# ip netns exec slions_ns1 ifconfig -a
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.0.0.2 netmask 255.255.255.0 broadcast 10.0.0.255
inet6 fe80::acf9:75ff:fefa:934d prefixlen 64 scopeid 0x20<link>
ether ae:f9:75:fa:93:4d txqueuelen 1000 (Ethernet)
RX packets 8 bytes 656 (656.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 8 bytes 656 (656.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

lo: flags=8<LOOPBACK> mtu 65536
loop txqueuelen 1000 (Local Loopback)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

在宿主机ping slions_ns1的网卡地址

1
2
3
4
5
6
7
8
9
[root@slions_pc1 ~]# ping 10.0.0.2 -c 3
PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.
64 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=0.013 ms
64 bytes from 10.0.0.2: icmp_seq=2 ttl=64 time=0.023 ms
64 bytes from 10.0.0.2: icmp_seq=3 ttl=64 time=0.024 ms

--- 10.0.0.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 1999ms
rtt min/avg/max/mdev = 0.013/0.020/0.024/0.005 ms

可以ping通,此时证明宿主机和slions_ns1网络命名空间已经通过veth网卡实现了网络联通

测试两个netns联通性

最开始还创建了一个slions_ns2的网络命名空间,我们把宿主机的那块veth0网卡加到其里面去进行测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@slions_pc1 ~]# ip link set dev veth0 netns slions_ns2
[root@slions_pc1 ~]# ip netns exec slions_ns2 ifconfig -a
lo: flags=8<LOOPBACK> mtu 65536
loop txqueuelen 1000 (Local Loopback)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

veth0: flags=4098<BROADCAST,MULTICAST> mtu 1500
ether d2:24:de:9b:b5:d9 txqueuelen 1000 (Ethernet)
RX packets 24 bytes 2000 (1.9 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 24 bytes 2000 (1.9 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

发现网卡没被激活,手动再设置下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[root@slions_pc1 ~]# ip netns exec slions_ns2 ifconfig veth0 10.0.0.3/24 up
[root@slions_pc1 ~]# ip netns exec slions_ns2 ifconfig -a
lo: flags=8<LOOPBACK> mtu 65536
loop txqueuelen 1000 (Local Loopback)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

veth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.0.0.3 netmask 255.255.255.0 broadcast 10.0.0.255
inet6 fe80::d024:deff:fe9b:b5d9 prefixlen 64 scopeid 0x20<link>
ether d2:24:de:9b:b5:d9 txqueuelen 1000 (Ethernet)
RX packets 24 bytes 2000 (1.9 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 30 bytes 2516 (2.4 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

这时从slions_ns2中测试能否ping通slions_ns1

1
2
3
4
5
6
7
8
9
10
[root@slions_pc1 ~]# ip netns exec slions_ns2 ping 10.0.0.2 -c 3
PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.
64 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=0.014 ms
64 bytes from 10.0.0.2: icmp_seq=2 ttl=64 time=0.023 ms
64 bytes from 10.0.0.2: icmp_seq=3 ttl=64 time=0.023 ms

--- 10.0.0.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 1999ms
rtt min/avg/max/mdev = 0.014/0.020/0.023/0.004 ms

和料想的一样可以ping通。

CATALOG
  1. 1. 安装软件
  2. 2. 创建netns
  3. 3. 创建veth网卡设备对
  4. 4. 移动veth网卡到netns
  5. 5. 激活veth网卡
  6. 6. 测试两个netns联通性