Linux网络虚拟化 Router

本文假设已经具备基本的路由交换基础。个人学习记录,欢迎指正。

Linux其实原生就是一台路由器,只是默认他只转发自身包含的地址段的流量,要想实现转发非自身(非默认名称空间)的数据包,需要开启路由转发功能。

学过数通的同学肯定记得,路由器中有VRF来实现路由表的隔离实现虚拟路由,Linux中其实也有该项技术,但是这里我们主要是让Linux实现路由器功能,暂不涉及隔离相关问题。后续会单独整理Linux中VRF的实现。

操作路由

# 开启路由转发功能
echo 1 > /proc/sys/net/ipv4/ip_forward  						# 临时开启
echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.conf  # 永久开启
sysctl -p /etc/sysctl.conf

# 添加路由
ip route add default via x.x.x.x dev ethx 					# 添加默认路由
ip route add 1.1.1.1/32 via x.x.x.x dev ethx				# 添加明细路由
ip route add blackhole 1.1.1.2/32										# 添加黑洞路由

# 查看路由
ip route show

# 删除路由
ip route del blackhole 1.1.1.2/32

模拟路由转发实现

之前我们测试了Bridge这个虚拟设备,实现了二层的转发和vlan tag过滤等功能。因为默认我们创建的Bridge都是在默认网络名称空间创建的,他们的协议栈是同一空间,所以逻辑上所有交换机都是通过默认协议栈连接在一块的。当打开路由转发功能之后,Bridge更像是一台三层交换,流量会触发三层寻路,就会查找的路由表实现转发。

拓扑如图,我们给BR配置IP地址,也就是下层网络的出口网关。给默认名称空间打开路由转发功能之后,这时候逻辑上就相当于一个大路由器,BR可以简单理解成vlan interface(这里只是为了方便理解)。
请添加图片描述

# 打开路由转发
echo 1 > /proc/sys/net/ipv4/ip_forward

# 创建ns,模拟终端
ip netns add ns1
ip netns add ns2

# 创建BR设备,配置并启用
ip link add BR1 type bridge
ip link set BR1 up
ip addr add 10.0.1.1/24 dev BR1
ip link add BR2 type bridge
ip link set BR2 up
ip addr add 10.0.2.1/24 dev BR2

# 创建veth
ip link add veth1 type veth peer name veth11
ip link add veth2 type veth peer name veth22

# 如图分配veth到ns设备,配置并启用
ip link set dev veth11 netns ns1
ip netns exec ns1 ip addr add 10.0.1.2/24 dev veth11
ip netns exec ns1 ip link set veth11 up
ip link set dev veth22 netns ns2
ip netns exec ns2 ip addr add 10.0.2.2/24 dev veth22
ip netns exec ns2 ip link set veth22 up

# 终端配置默认路由
ip netns exec ns1 ip route add default via 10.0.1.1 dev veth11
ip netns exec ns2 ip route add default via 10.0.2.1 dev veth22

# 如图分配veth到BR设备,并启用
ip link set dev veth1 master BR1
ip link set veth1 up
ip link set dev veth2 master BR2
ip link set veth2 up

# 查看ns配置
[root@localhost ~]# ip netns exec 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
5: veth11@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether e2:b5:00:98:92:c8 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 10.0.1.2/24 scope global veth11
       valid_lft forever preferred_lft forever
    inet6 fe80::e0b5:ff:fe98:92c8/64 scope link
       valid_lft forever preferred_lft forever
[root@localhost ~]# ip netns exec ns1 ip route
default via 10.0.1.1 dev veth11
10.0.1.0/24 dev veth11 proto kernel scope link src 10.0.1.2
#
[root@localhost ~]# ip netns exec ns2 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
7: veth22@if8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 92:c9:8d:da:d9:68 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 10.0.2.2/24 scope global veth22
       valid_lft forever preferred_lft forever
    inet6 fe80::90c9:8dff:feda:d968/64 scope link
       valid_lft forever preferred_lft forever
[root@localhost ~]# ip netns exec ns2 ip route
default via 10.0.2.1 dev veth22
10.0.2.0/24 dev veth22 proto kernel scope link src 10.0.2.2

# ns1到ns2做ping测
[root@localhost ~]# ip netns exec ns1 ping 10.0.2.2 -c 2
PING 10.0.2.2 (10.0.2.2) 56(84) bytes of data.
64 bytes from 10.0.2.2: icmp_seq=1 ttl=63 time=0.027 ms
64 bytes from 10.0.2.2: icmp_seq=2 ttl=63 time=0.072 ms

# 在veth2处抓包
[root@localhost ~]# tcpdump -i veth2 -ne
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on veth2, link-type EN10MB (Ethernet), capture size 262144 bytes
11:00:24.557496 22:88:b5:2d:3d:24 > Broadcast, ethertype ARP (0x0806), length 42: Request who-has 10.0.2.2 tell 10.0.2.1, length 28
11:00:24.557516 92:c9:8d:da:d9:68 > 22:88:b5:2d:3d:24, ethertype ARP (0x0806), length 42: Reply 10.0.2.2 is-at 92:c9:8d:da:d9:68, length 28
11:00:24.557520 22:88:b5:2d:3d:24 > 92:c9:8d:da:d9:68, ethertype IPv4 (0x0800), length 98: 10.0.1.2 > 10.0.2.2: ICMP echo request, id 1208, seq 1, length 64
11:00:24.557553 92:c9:8d:da:d9:68 > 22:88:b5:2d:3d:24, ethertype IPv4 (0x0800), length 98: 10.0.2.2 > 10.0.1.2: ICMP echo reply, id 1208, seq 1, length 64
11:00:25.588366 22:88:b5:2d:3d:24 > 92:c9:8d:da:d9:68, ethertype IPv4 (0x0800), length 98: 10.0.1.2 > 10.0.2.2: ICMP echo request, id 1208, seq 2, length 64
11:00:25.588433 92:c9:8d:da:d9:68 > 22:88:b5:2d:3d:24, ethertype IPv4 (0x0800), length 98: 10.0.2.2 > 10.0.1.2: ICMP echo reply, id 1208, seq 2, length 64

模拟将ns和外部网络打通

拓扑如图:两台虚拟机Node1和Node2,Node1配置netns模拟PC,创建Bridge并配置ip作为网关,Node2作为外部网络测试用。

请添加图片描述

# 虚拟机信息
[root@Node1 ~]# ifconfig ens32
ens32: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.65.5  netmask 255.255.255.0  broadcast 192.168.65.255
        ether 00:0c:29:36:2c:a5  txqueuelen 1000  (Ethernet)
        ...
[root@Node2 ~]# ifconfig ens32
ens32: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.65.6  netmask 255.255.255.0  broadcast 192.168.65.255
        ether 00:0c:29:dd:8f:0a  txqueuelen 1000  (Ethernet)
        ...
        
# 开启Node1的路由转发
echo 1 > /proc/sys/net/ipv4/ip_forward

# 创建Bridge BR1启用并配置IP
ip link add BR1 type bridge
ip addr add 10.0.1.254/24 dev BR1
ip link set BR1 up

# 创建两个ns PC1 PC2
ip netns add PC1
ip netns add PC2

# 创建veth pair
ip link add veth1 type veth peer name veth11
ip link add veth2 type veth peer name veth22

# 按图示,将veth移入ns启用并配置ip和默认路由
ip link set dev veth11 netns PC1
ip link set dev veth22 netns PC2
ip netns exec PC1 ip addr add 10.0.1.1/24 dev veth11
ip netns exec PC2 ip addr add 10.0.1.2/24 dev veth22
ip netns exec PC1 ip link set veth11 up
ip netns exec PC2 ip link set veth22 up
ip netns exec PC1 ip route add default via 10.0.1.254 dev veth11
ip netns exec PC2 ip route add default via 10.0.1.254 dev veth22

# 按图示,将veth插入Bridge并启用
ip link set dev veth1 master BR1
ip link set veth1 up
ip link set dev veth2 master BR1
ip link set veth2 up

# 配置Node2的回程路由
ip route add 10.0.1.0/24 via 192.168.65.5 dev ens32

# 使用Node2 ping PC1
[root@Node2 ~]# ping 10.0.1.1 -c 2
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=63 time=2.62 ms
64 bytes from 10.0.1.1: icmp_seq=2 ttl=63 time=0.691 ms

# 在veth11抓包
[root@Node1 ~]# ip netns exec PC1 tcpdump -i veth11 -ne
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on veth11, link-type EN10MB (Ethernet), capture size 262144 bytes
15:26:47.765325 2a:da:9f:c3:7a:33 > Broadcast, ethertype ARP (0x0806), length 42: Request who-has 10.0.1.1 tell 10.0.1.254, length 28
15:26:47.765352 3a:3a:31:a3:f2:c9 > 2a:da:9f:c3:7a:33, ethertype ARP (0x0806), length 42: Reply 10.0.1.1 is-at 3a:3a:31:a3:f2:c9, length 28
15:26:47.765358 2a:da:9f:c3:7a:33 > 3a:3a:31:a3:f2:c9, ethertype IPv4 (0x0800), length 98: 192.168.65.6 > 10.0.1.1: ICMP echo request, id 1153, seq 1, length 64
15:26:47.765370 3a:3a:31:a3:f2:c9 > 2a:da:9f:c3:7a:33, ethertype IPv4 (0x0800), length 98: 10.0.1.1 > 192.168.65.6: ICMP echo reply, id 1153, seq 1, length 64
15:26:48.767492 2a:da:9f:c3:7a:33 > 3a:3a:31:a3:f2:c9, ethertype IPv4 (0x0800), length 98: 192.168.65.6 > 10.0.1.1: ICMP echo request, id 1153, seq 2, length 64
15:26:48.767524 3a:3a:31:a3:f2:c9 > 2a:da:9f:c3:7a:33, ethertype IPv4 (0x0800), length 98: 10.0.1.1 > 192.168.65.6: ICMP echo reply, id 1153, seq 2, length 64
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值