两个netns之间的通信
① netns的概念:
netns是linux中一个独立的网络栈,每个ns都有自己的网卡、loopback设备、路由表、iptables。有了这些,一个进程就可以和外部进行通信
② netns之间通信需要用到的设备:
- vethpair设备:是一种必须成对出现设备,两张虚拟网卡,分别置于两端,一端发包,另一端会收包;
- 网桥:交换机的角色
③ 具体方式:
- 两个netns之间通信,可以在两个netns下分别放一个vethpair设备;
- 多个netns之间通信,借助网桥来做交换机,将成对的vethpair设备分别放在netns和网桥上,此时,在网桥上的vethpair会从一个网卡,降级成交换机的端口,所有的流量都会被交换机,网桥劫持,并进行相关的转发。
④ 举个栗子:
下面会操作两个netns,借助网桥的方式来通信。
//创建net ns
ip netns add net1
//创建网桥
ip link add br0 type bridge
//创建vethpair设备
ip link add type veth
or
ip link add veth0 type veth peer name veth1
//将vethpair的veth1添加在net1 ns中,并配置ip,启动设备,配置ip的时候会默认配置路由规则
ip link set dev veth1 netns net1
ip netns exec net1 ip link set dev veth1 name eth0
ip netns exec net1 ip addr add 10.0.1.1/24 dev eth0
ip netns exec net1 ip link set dev eth0 up
//将vethpair的veth0添加在网桥br0上,并启动
ip link set dev veth0 master br0
ip link set dev veth0 up
另一个ns和上面操作相同,至此,配置已经完毕:我们可以测试一下:
1.bridge命令可以查看bridge的信息
[root@localhost ~]# bridge link
20: veth0 state UP @(null): <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master br0 state disabled priority 32 cost 2
22: veth2 state UP @(null): <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master br0 state disabled priority 32 cost 2
[root@localhost ~]# brctl show
bridge name bridge id STP enabled interfaces
br0 8000.1af19dd61e02 no veth0
veth2
- 进入net2中ping net1:
[root@localhost ~]# ip netns exec net2 ping -c 1 10.0.1.1
PING 10.0.1.1 (10.0.1.1) 56(84) bytes of data.
64 bytes from 10.0.1.1: icmp_seq=1 ttl=64 time=0.069 ms
--- 10.0.1.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.069/0.069/0.069/0.000 ms
查看当前的网络情况:
此时,可以看到,并没有给br0配置ip,在这里br0只是充当交换机的角色。
[root@localhost ~]# ifconfig
br0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet6 fe80::18f1:9dff:fed6:1e02 prefixlen 64 scopeid 0x20<link>
ether 1a:f1:9d:d6:1e:02 txqueuelen 1000 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 6 bytes 508 (508.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.6.213 netmask 255.255.255.0 broadcast 192.168.6.255
inet6 fe80::3979:3ddc:8722:3685 prefixlen 64 scopeid 0x20<link>
ether b6:41:48:9f:44:31 txqueuelen 1000 (Ethernet)
RX packets 25520 bytes 4561658 (4.3 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 15907 bytes 2560284 (2.4 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 944 bytes 94296 (92.0 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 944 bytes 94296 (92.0 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
veth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet6 fe80::f0ab:b1ff:fe72:ddec prefixlen 64 scopeid 0x20<link>
ether f2:ab:b1:72:dd:ec txqueuelen 1000 (Ethernet)
RX packets 11 bytes 774 (774.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 14 bytes 1156 (1.1 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
veth2: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet6 fe80::18f1:9dff:fed6:1e02 prefixlen 64 scopeid 0x20<link>
ether 1a:f1:9d:d6:1e:02 txqueuelen 1000 (Ethernet)
RX packets 14 bytes 900 (900.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 14 bytes 1156 (1.1 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
遗留的问题:
1.此时我们在net2中,不能ping通自己的ip,为什么呢?
因为lo网卡还没有启动,默认情况下访问本机ip,会走lo网卡。
上面的网络拓扑图如下所示:
ns内部和宿主机的通信
1.进入netns1中ping 宿主机ip,发现不能通
[root@localhost ~]# ip netns exec net2 ping 192.168.6.213
connect: Network is unreachable
此时需要查看net2 ns的路由规则:
[root@localhost ~]# ip netns exec net2 route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
10.0.1.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
路由规则不满足,无法到达指定的网络,故添加默认路由:使所有的流量都从ns中的eth0网卡发出。
ip route add default dev eth0
查看路由规则:
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 0.0.0.0 0.0.0.0 U 0 0 0 eth0
10.0.1.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
问题:其实添加路由后,包应该是可以发到br0网络了。但是抓br0包,发现并没有收到。为什么呢?
答:抓eth0包,发现它发的arp请求,获取192.168.6.2的mac地址,不能成功,故包不能组装成功,所以不能从网卡eth0发出。
[root@localhost ~]# tcpdump -i eth0
22:15:41.125393 ARP, Request who-has 192.168.6.2 tell localhost.localdomain, length 28
22:15:42.126989 ARP, Request who-has 192.168.6.213 tell localhost.localdomain, length 28
其实此时,交换机只是连接了两个ns,其实是相当于他创建了一个封闭的局域网,此时的交换机就是纯粹的交换机,即二层交换机,只工作在链路层。想要将交换机和宿主机连通网络,就需要三层交换机,三层交换机就是即做路由转发,又做交换机。工作在三层,当有arp请求,三层交换机会看mac是不是自己,是自己,判断ip是不是自己,ip是自己就不转发了。不是自己就进行转发策略。向上转发。
- 给br0网桥添加ip,此命令会默认添加路由:
ip addr add 10.0.1.1/24 dev br0
此时就可以ping 通宿主机的ip,如下:
[root@localhost ~]# ip netns exec net2 ping 192.168.6.213
PING 192.168.6.213 (192.168.6.213) 56(84) bytes of data.
64 bytes from 192.168.6.213: icmp_seq=1 ttl=64 time=0.068 ms
这里有一个问题,之前看到的,一台物理机上有多个网卡。当网卡之间需要访问时,需要打开ip_foward,但是,此处却不用打开,因为交换机会根据主机的路由表走 “直连路由”。 故不用宿主机进行转发。
另我困惑的是,我们可以通过在netns中使用arp -a 看到宿主机ip的mac映射是br0的mac,而不是宿主机的真实网卡ens33的mac。进行抓包的时候,也只能在br0上抓到包,不能在ens33上抓到包。
ns内部和宿主机外的通信
1.完成了ping宿主机ip,我们尝试ping 8.8.8.8,却发现不能ping通,其实当前ns中的包可以正常的发到宿主机,且宿主机可以访问到8.8.8.8。为什么呢?
答:我想可能是因为没有打开宿主机的Ipforward,打开,如下:
echo 1 > /proc/sys/net/ipv4/ip_forward
cat /proc/sys/net/ipv4/ip_forward
- 但是还是不能ping通,为什么呢?
抓netns内的网卡eth0的包,发现还是不能获取到mac地址,所以包不能完成组装,故不能发送。那怎么办呢?
解决:
因为广播原因,所以往其他宿主机的网络发包,需要先到网关,之后怎么去,是由网关来决定的。
而之前配置的默认路由是从eth0发出,并没有指向发到那里,此时网桥br0上因为veth pair设备的存在会收到包,但并不会继续广播。故我们需要在net ns中配置发往网关的路由。
- 修改路由规则改为发往br0网关:
[root@localhost ~]\# ip netns exec net2 route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.0.1.1 0.0.0.0 UG 0 0 0 eth0
10.0.1.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
再次ping 8.8.8.8,发现可以ping通:
[root@localhost ~]\# ip netns exec net2 ping -c 1 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
From 10.0.1.1 icmp\_seq=1 Destination Host Prohibited
--- 8.8.8.8 ping statistics ---
1 packets transmitted, 0 received, +1 errors, 100% packet loss, time 0ms