24

Linux SRv6实战 服务链功能详解(第二篇)

 5 years ago
source link: https://www.sdnlab.com/22900.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

作者简介:李嘉明 思科系统工程师、苏远超 思科首席工程师、钟庆 思科系统工程师

摘要:本文基于Linux SRv6功能,结合Vagrant,Snort等工具,对SRv6服务链功能进行详细解析和验证。实现SRv6服务链上同时支持SR-aware服务和Non SR-aware服务。

本文所有代码见: https://github.com/ljm625/srv6_Sandbox

一、SRv6服务链简介

Cisco-linux-668x400.jpg

如本文第一篇(《Linux SRv6实战:VPN、流量工程和服务链(第一篇)》)所述,SR实现服务链本质上是基于自身的流量工程能力,事实上服务节点(或代理)本质上只是Segment列表中的一个Segment,这不但适用于SR-aware服务,也适用于Non SR-aware服务。除非特别说明,SR服务链解决方案同时适用于SR MPLS和SRv6,本文只以SRv6为例进行说明。

在本文第一篇中,我们使用Mininet等工具,验证了Linux SRv6的VPN、流量工程和服务链(SR-aware服务)功能。在本篇中,我们将更进一步深入分析SRv6服务链功能,验证SRv6服务链对Non SR-aware服务的支持能力。

下面是SRv6服务链相关操作简介(更多SRv6操作介绍参见本文第一篇):

End.AD4:该操作要求SL不为0(不是最后一跳),是为了兼容Non SR-aware服务的服务链操作。核心思想是配置了此操作的节点作为SR代理(SR Proxy),即在把数据包转发给Non SR-aware服务处理之前,把外层的封装暂时去掉,再转发给服务进行处理,这样服务无需支持SRv6即可正常工作。End.AD4操作要求内层必须是一个IPv4数据包,此操作将更新外层报头的SL,去掉外层IPv6报头后发送给Non SR-aware服务;在服务处理完成后把数据包发回时,SR Proxy重新添加IPv6和SRH报头,继续转发。End.AD4操作需要为每条服务链维护一个动态的缓存,以封装服务发回的数据包。具体如下图所示:

SR1.png

图1:End.AD4操作

End.AD6:该操作和End.AD4基本一致,唯一区别是其要求内层是一个IPv6数据包。

End.AM:该操作要求SL不为0(不是最后一跳),也是为了兼容Non SR-aware服务的服务链操作。虽然同样是基于SR Proxy机制,但和End.AD操作不同,End.AM操作会将IPv6目的地址更新为SL=0时的Segment,即最终的IPv6目的地址,然后转发给服务;根据RFC8200规定,服务(中间节点)不会处理SRH而只是根据目的地址转发,这里假设服务可以处理跟在SRH之后的负载。服务把数据包发回后,End.AM节点把IPv6目的地址更新为SL指定的Segment,继续转发。End.AM操作不需要为每条服务链维护缓存,其规则适用于所有经由End.AM节点的服务链。End.AM这种实现机制只在SRv6上支持,SR MPLS不支持类似的机制。具体如下图所示

SR2.png

图2:End.AM操作

二、为什么使用Linux SRv6实现服务链?

在数据中心/云网络部署中,不少用户采用主机叠加网络(Host Overlay)的方式为租户提供服务。这种方式采用主机的虚拟交换机/FD.IO进行Host Overlay部署,实现不同主机上虚拟机或者容器之间的二三层互通,也常用于实现服务链。

RFC 7665提出了服务功能链(SFC)架构,RFC 8300提出网络服务头(NSH)作为实现SFC架构的封装。NSH携带了服务链路径和元信息(Metadata),这些信息可在不同的服务之间共享,利用NSH可实现动态的服务链配置,可在服务链形成后进行动态的路径和拓扑修改、插入新的服务,提供端到端可视化、OAM、性能管理能力。

但NSH目前实际应用很少,原因有三点:
1.NSH目前面临的最大问题是:网络设备、VNF、主机操作系统对NSH的支持非常有限。网络设备只有个别路由器例如思科ASR9000支持,大部分硬件交换机不支持;实现NSH所设计的功能依赖于服务链中的VNF对路径和元信息的操作能力,但很多VNF都不支持

2.NSH需要在每条服务链的所有服务设备上维持状态,这很大程度上限制了扩展性

3.NSH携带了服务链路径信息,但是流量在不同VNF之间的引导还需要通过其他隧道技术机制来实现(例如VxLAN、GRE等),没有实现Overlay和Underlay的融合。这造成解决方案的差异性不强,OVS+Openflow等替代方案可以实现类似的功能且较简单

如本文第一篇所述, Linux内核从4.10版本(2017年2月)就开始支持SRv6,支持丰富的SRv6操作,通过开源的Linux内核模块SREXT(https://github.com/netgroup/SRv6-net-prog/)支持更多的操作,其中包括对服务链功能的增强。通过把不同的SRv6 Segment组合起来,Linux SRv6能够完美地整合Overlay、Underlay和服务链,其性能通过应用DPDK或者FD.IO/VPP也可以得到极大的提升。

SRv6可以与现有不支持SRv6的IPv6网络无缝互操作,基于SRv6的服务链也可以同时支持SR-aware和Non SR-aware的服务,因此基于Linux SRv6的服务链具有很高的实用性,基本上可以部署在任何支持IPv6的网络上。

三、准备工作

验证环境基于Vagrant,可在Windows/Linux/Mac 下进行,需要提前自行安装好Virtualbox和Vagrant,这里不再赘述这两个软件的安装过程。容器内的软件如下

  • Linux,内核版本高于4.14
  • Snort,开源IDS软件,我们会使用两个版本的Snort:SR-aware版本以及Non SR-aware版本

3.1 拓扑说明

SR3.png

图3 SRv6服务链拓扑

拓扑如图3所示,有三台支持SRv6的路由器。其中R2连接配置了End.AD4操作的SR Proxy,SR Proxy下挂Non SR-aware版本的Snort(Service1);R3连接了SR-aware版本的Snort(Service2)。
主机a和主机b只通过IPv4连接到路由器R1以及R3,默认情况下它们无法通讯。路由器之间只有IPv6地址和路由。

主机a发送给主机b的数据包,经由R1、R2,然后发往Service1;接着经由R3,发往Service2;最后发给主机b。

3.2 部署脚本说明

在Vagrant File里面我们定义了拓扑结构,每个节点的镜像文件和配置信息,当我们执行“Vagrant up”命令的时候,会自动根据Vagrant的描述文件进行虚拟机的创建、启动及配置。

SR4.png

图4 Vagrant 配置示例

上图是Vagrant的配置文件中定义的一个节点。包括以下部分的内容:
1.镜像信息
其中“vm.box”定义了我们使用的镜像,“vm.box_version”定义了所使用镜像的版本,在vagrant启动虚拟机的时候,如果本地找不到这个镜像,会去vagrant的镜像仓库下载,这一点和docker的镜像下载机制基本相同。

2.虚拟网络
接着定义了该虚拟机的网络,这部分就是用来定义Vagrant的网络拓扑的相关配置,其中“virtualbox_intnet”定义了不同的私网,对于IP地址,这里可以设置v4或者v6地址,但如果是IPv6地址,建议手动设置子网掩码,会避免很多问题。

3.内存、网卡状态、抓包等信息
“memory”定义虚拟机的内存大小,由于是测试用途,256MB即可满足需求。

“nictrace”则是配置通过网卡实时抓包,并保存为pcap文件。我们设置了在所有的网卡上进行实时的抓包存储,这样方便测试和理解。

“cableconnected”定义了网卡的连接状态。读者可能有一个疑问是我们只定义了2个网络,为什么会有3张网卡?其实第一个网卡是系统默认定义的NAT网卡,用于连接互联网。此外,Virtualbox具有每台虚拟机最多支持4张网卡的限制,因此所定义的虚拟机,除了默认的NAT网络,如果有多于3个网络,那么多出的网卡将不会被正确添加。

4.Day0配置
“vm.provision” 定义了当虚拟机启动之后运行的Day0自动配置脚本,在脚本里我们配置了默认路由,启用SRv6以及安装一些测试用的软件,相关的配置会在后面章节中说明。

四、安装教程

由于本次使用的是Vagrant安装方案,所以宿主机可以是Windows/Mac/Linux,只需要按照官网的教程安装git、Vagrant以及Virtualbox即可。
在完成安装git、Vagrant以及Virtualbox之后,就可以启动测试环境了。

Java
git clone https://github.com/ljm625/srv6_Sandbox cd srv6_Sandbox vagrant up
1
2
3
git clonehttps://github.com/ljm625/srv6_Sandbox
cd srv6_Sandbox
vagrant up

接着Vagrant会自动下载镜像,启动拓扑里面的主机,以及完成Day0的配置。需要注意的是单台虚拟机的内存为256MB,因此电脑需要256*6=1.5GB的空闲内存空间。

这里用的镜像是定制过的Debian image,已经包含了4.14的Kernel以及最新版的iproute2,因此无需重新安装iproute2或者更新内核。

下面对每台设备的Day0启动脚本关键部分进行解析。
1.R1
对路由器R1的配置主要是把IPv4数据包封装入SRv6并转发;同时对回程数据包指定与End.DX4操作对应的Segment,解封装后发给主机a(10.0.0.1),具体可以参考本文第一篇。

Java
# 把去往10.0.1.0/24的数据包封装入SRv6,设置Segment列表,并转发 ip route add 10.0.1.0/24 encap seg6 mode encap segs fc00:2::a,fc00:3::a dev eth2 # 对R1收到的回程数据包执行End.DX4操作,把内层的IPv4数据包发给主机a ip -6 route add fc00:1::a/128 encap seg6local action End.DX4 nh4 10.0.0.1 dev eth1
1
2
3
4
#把去往10.0.1.0/24的数据包封装入SRv6,设置Segment列表,并转发
ip route add10.0.1.0/24encap seg6 mode encap segs fc00:2::a,fc00:3::adev eth2
#R1收到的回程数据包执行End.DX4操作,把内层的IPv4数据包发给主机a
ip-6route add fc00:1::a/128encap seg6local action End.DX4 nh410.0.0.1dev eth1

2.R2
对路由器R2的配置对指定与End操作对应的Segment,此操作更新SL并更新数据包的IPv6 目的地址。

Java
# 中间节点,只需配置End操作 ip -6 route add fc00:2::a/128 encap seg6local action End dev eth1
1
2
#中间节点,只需配置End操作
ip-6route add fc00:2::a/128encap seg6local action Enddev eth1

3.R3
对路由器R3的配置和R1的配置基本相同,对回程数据包指定与End.DX4操作对应的Segment,解封装并转发给主机b(10.0.1.1),实现主机a和主机b的通信;并对主机b的回程数据包封装,添加SRH报头。

Java
# 对R3收到的回程数据包执行End.DX4操作,把内层的IPv4数据包发给主机b ip -6 route add fc00:3::a/128 encap seg6local action End.DX4 nh4 10.0.1.1 dev eth1 # 把去往10.0.0.0/24的数据包封装入SRv6,设置Segment列表,并转发 ip route add 10.0.0.0/24 encap seg6 mode encap segs fc00:1::a dev eth2
1
2
3
4
#R3收到的回程数据包执行End.DX4操作,把内层的IPv4数据包发给主机b
ip-6route add fc00:3::a/128encap seg6local action End.DX4 nh410.0.1.1dev eth1
#把去往10.0.0.0/24的数据包封装入SRv6,设置Segment列表,并转发
ip route add10.0.0.0/24encap seg6 mode encap segs fc00:1::adev eth2

4.SR Proxy
SR Proxy的配置包含3部分:

  • 使用Linux Network Namespace(Linux自带的网络虚拟化)机制,创建一个名字为”snort”的 VNF,相当于SR Proxy下挂了一个新的主机,突破了Vagrant单机只能有最多4张网卡的限制。这部分使用了一键脚本进行配置,VNF的2张网卡IP分别为192.168.1.2和192.168.2.2,VNF会对传入的流量进行处理,然后从192.168.2.2发出。
  • 在SR Proxy的VNF内安装并配置Snort,实现IDS功能,即上图中的Service1。
  • 在SR Proxy下安装SREXT内核模块,这个内核模块扩展了Linux内核所支持的SRv6操作,使其能够支持End.AD4、End.AD6以及End.AM等操作,从而在服务链上支持Non SR-aware服务。
    安装完毕之后配置SR Proxy。
Java

# 配置SR Proxy的VNF,使用Linux Namespace进行隔离。 #这里使用了一键脚本 cd ~/ rm -rf srv6_Sandbox/ git clone https://github.com/ljm625/srv6_Sandbox cd srv6_Sandbox/config/ sh deploy-vnf-v4.sh add snort veth0 veth1 192.168.1.1/24 192.168.2.1/24 192.168.1.2/24 192.168.2.2/24

# 安装Snort,这里安装的是官方版本的Snort,不支持SRv6 cd ~/ wget https://snort.org/downloads/snort/daq-2.0.6.tar.gz wget https://snort.org/downloads/snort/snort-2.9.12.tar.gz

tar xvzf daq-2.0.6.tar.gz cd daq-2.0.6 ./configure && make && sudo make install

cd ~/ tar xvzf snort-2.9.12.tar.gz cd snort-2.9.12 ./configure --enable-sourcefire --disable-open-serverid && make && sudo make install sudo ldconfig # 配置Snort(IDS)的默认监测规则 sudo mkdir -p /etc/snort/ /etc/snort/rules/ /var/log/snort

touch /etc/snort/snort.conf /etc/snort/rules/local.rule echo 'var RULE_PATH rules' >> /etc/snort/snort.conf echo 'include $RULE_PATH/local.rule' >> /etc/snort/snort.conf echo 'alert icmp any any -> any any (msg:"ICMP detected"; sid:1000)' >> /etc/snort/rules/local.rule

# 安装SREXT模块,其扩展了Linux所支持的SRv6操作,例如End.AD4 cd ~/ git clone https://github.com/SRouting/SRv6-net-prog cd SRv6-net-prog/srext/ make && make install && depmod -a && modprobe srext

# 配置SR Proxy启用End.AD4操作,服务的地址设置为192.168.1.2 srconf localsid add fc00:a::a1 end.ad4 ip 192.168.1.2 veth0 veth1

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
28
29
30
31
32
33
34
35
36
37
38
39
40
#配置SR ProxyVNF,使用Linux Namespace进行隔离。
#这里使用了一键脚本
cd~/
rm-rf srv6_Sandbox/
git clonehttps://github.com/ljm625/srv6_Sandbox
cd srv6_Sandbox/config/
sh deploy-vnf-v4.sh add snort veth0 veth1192.168.1.1/24192.168.2.1/24192.168.1.2/24192.168.2.2/24
 
#安装Snort,这里安装的是官方版本的Snort,不支持SRv6
cd~/
wget https://snort.org/downloads/snort/daq-2.0.6.tar.gz
wget https://snort.org/downloads/snort/snort-2.9.12.tar.gz
 
tar xvzf daq-2.0.6.tar.gz
cd daq-2.0.6
./configure&&make&&sudo make install
 
cd~/
tar xvzf snort-2.9.12.tar.gz
cd snort-2.9.12
./configure--enable-sourcefire--disable-open-serverid&&make&&sudo make install
sudo ldconfig
#配置SnortIDS)的默认监测规则
sudo mkdir-p/etc/snort//etc/snort/rules//var/log/snort
 
touch/etc/snort/snort.conf/etc/snort/rules/local.rule
echo'var RULE_PATH rules'>>/etc/snort/snort.conf
echo'include $RULE_PATH/local.rule'>>/etc/snort/snort.conf
echo'alert icmp any any -> any any (msg:"ICMP detected"; sid:1000)'>>/etc/snort/rules/local.rule
 
 
#安装SREXT模块,其扩展了Linux所支持的SRv6操作,例如End.AD4
cd~/
git clonehttps://github.com/SRouting/SRv6-net-prog
cd SRv6-net-prog/srext/
make&&make install&&depmod-a&&modprobe srext
 
#配置SR Proxy启用End.AD4操作,服务的地址设置为192.168.1.2
srconf localsid add fc00:a::a1 end.ad4 ip192.168.1.2veth0 veth1

5.Service2
Service2的配置相比SR Proxy要简单很多,因为上面运行的是支持SRv6的服务。所以Service2只需要配置一个End操作即可,以更新SL和IPv6目的地址。

Java

# 配置Service2支持End操作 ip -6 route add fc00:b::a1/128 encap seg6local action End dev eth1

# 配置SR-aware版本Snort的监测规则 sudo mkdir -p /etc/snort/ /etc/snort/rules/ /var/log/snort touch /etc/snort/snort.conf /etc/snort/rules/local.rule echo 'var RULE_PATH rules' >> /etc/snort/snort.conf echo 'include $RULE_PATH/local.rule' >> /etc/snort/snort.conf echo 'alert icmp any any -> any any (msg:"ICMP detected"; sid:1000)' >> /etc/snort/rules/local.rule

1
2
3
4
5
6
7
8
9
#配置Service2支持End操作
ip-6route add fc00:b::a1/128encap seg6local action Enddev eth1
 
#配置SR-aware版本Snort的监测规则
sudo mkdir-p/etc/snort//etc/snort/rules//var/log/snort
touch/etc/snort/snort.conf/etc/snort/rules/local.rule
echo'var RULE_PATH rules'>>/etc/snort/snort.conf
echo'include $RULE_PATH/local.rule'>>/etc/snort/snort.conf
echo'alert icmp any any -> any any (msg:"ICMP detected"; sid:1000)'>>/etc/snort/rules/local.rule

五、验证Linux SRv6高级服务链功能

5.1 概述

SR5.png

图5 验证所用拓扑

本验证所用拓扑及验证场景如图5所示。在该拓扑中,默认情况IPv4主机a和主机b之间通过SRv6 End.DX4操作实现VPN互通,流量路径是R1->R2->R3。通过修改R1的SRv6策略,我们使流量在去往主机b之前,先被引导至SR Proxy下Non SR-aware版本的Snort(Service1),再被引导至Service2的SR-aware版本的Snort,最后到达主机b实现互通。

5.2 具体步骤

5.2.1 验证SR Proxy上的Non SR-aware服务(Service1)
在本次的验证中,我们已经默认实现了主机a与主机b之间的IPv4互访,这一步骤的细节参见本文第一篇。
当所有环境通过vagrant up启动之后,我们登陆到主机a。

Java
vagrant ssh hosta ping 10.0.1.1
1
2
vagrant ssh hosta
ping10.0.1.1

SR6.png

图6 主机a可以正常ping通主机b

如图6所示,主机a与主机b可以正常互通。

在默认情况下,我们在R1配置的SRv6 Policy是经由R1->R2->R3进行转发,并没有经过Service1/Service2。

我们可以通过Wireshark打开R1的eth2接口的抓包文件予以确认(默认为trace12.pcap文件)。

SR7.png

图7 R1上抓包结果-数据包被加上了SRH

如图7所示,从主机a(10.0.0.1)去往主机b(10.0.1.1)的数据包,加上SRH,Segment列表指定了数据包经由R2、R3进行转发。

现在登陆到R1上,查看当前的SRv6 Policy:

Java
vagrant ssh r1 sudo -i ip route list|grep seg6
1
2
3
vagrant ssh r1
sudo-i
ip route list|grep seg6

SR8.png

图8 R1上当前的SRv6 Policy

然后,我们修改SRv6 Policy,加入2个新的Segment,引导流量至Service1和Service2上的Snort进行监测。主要注意的是,Service1对应的Segment其实是SR Proxy配置的End.AD4,而不是实际提供服务的VNF的地址(192.168.1.2)。

Java
ip route del 10.0.1.0/24 ip route add 10.0.1.0/24 encap seg6 mode encap segs fc00:a::a1,fc00:b::a1,fc00:3::a dev eth2
1
2
ip route del10.0.1.0/24
ip route add10.0.1.0/24encap seg6 mode encap segs fc00:a::a1,fc00:b::a1,fc00:3::adev eth2

再次查看抓包文件trace12.pcap,可以看到数据包的下一跳被重定向到了Service1。

SR9.png

图9 R1上抓包结果-修改SR Policy后

接着,登陆到SR Proxy这台主机,名字叫“server1”。

Java
vagrant ssh server1 sudo -i srconf localsid show
1
2
3
vagrant ssh server1
sudo-i
srconf localsid show

SR10.png

图10 SR Proxy上配置的End.AD4操作

可以看到SR Proxy配置了End.AD4操作。由于使用了SREXT模块,因此需要使用srconf命令。
如前所述,在SR Proxy上配置End.AD4操作的命令为(包含在Day0脚本中):

Java
srconf localsid add fc00:a::a1 end.ad4 ip 192.168.1.2 veth0 veth1
1
srconf localsid add fc00:a::a1 end.ad4 ip192.168.1.2veth0 veth1

其中fc00: a::a1为End.AD4对应的Segment,192.168.1.2为Non SR-aware服务的地址。
在这里我们添加服务的方法是使用Linux Network Namespace虚拟出一个名字为”snort”的VNF,此VNF包含有2个接口veth0和veth1,接口地址设置见图3。在VNF内安装Non SR-aware版本的Snort。
首先通过tcpdump,在veth0抓包

Java
ip netns exec snort tcpdump -i veth0-snort
1
ip netns exec snort tcpdump-iveth0-snort

SR11.png

图11 VNF内tcpdump的抓包结果

如图11所示,在我们新建的VNF上收到的数据包已经没有了IPv6报头,而只有内层的IPv4报头。
接下来检查Snort上的规则。

Java
ip netns exec snort bash # 进入Snort这个VNF的bash cat /etc/snort/rules/local.rule
1
2
3
ip netns exec snort bash
#进入Snort这个VNFbash
cat/etc/snort/rules/local.rule

SR12.png

图12 VNF内的Snort配置的规则

本验证所使用的Snort规则如图12所示,该规则针对所有ICMP包都会发出一个告警,并显示详细信息。
接下来运行Snort,并查看Snort日志:

Java
snort -c /etc/snort/snort.conf -A console
1
snort-c/etc/snort/snort.conf-Aconsole

SR13.png

图13 VNF内的Snort监测日志

可以看到不支持SRv6的Snort能够正常地监测到ICMP包的源地址、目的地址以及协议,这是因为数据包原有的外层IPv6报头在执行End.AD4 操作时已经被SR Proxy去除了,此时Snort收到的是内层的IPv4数据包。

我们再看一下SR Proxy处理之后继续转发的数据包,使用wireshark打开traceserver1.pcap

SR14.png

图14 SR Proxy上抓包结果-经过SR Proxy处理之后的数据包

如图14所示,可以看到经过End.AD4处理之后的数据包,在发回SR Proxy的时候,SR Proxy会自动加回IPv6报头以及SRH,其中SL和IPv6目的地址都已经更新。

下表总结了数据包经过SR Proxy前后的变化情况。

biao1.jpg

表1 数据包经过SR Proxy前后的对比

5.2.2 验证SR Proxy上的Non SR-aware服务(iptables)
在这里我们继续做个测试,使用Linux iptables实现一个简单的防火墙功能。官方版本的Linux iptables目前是Non SRv6-aware的。

Java
# 切换到Snort的VNF vagrant ssh server1 sudo -i ip netns exec snort bash # 配置iptables规则 # 丢弃从10.0.0.0去往10.0.1.0的ICMP数据包 iptables -I FORWARD --source 10.0.0.0/24 --destination 10.0.1.0/24 --protocol icmp -j DROP # 查看iptables状态 iptables -L -nvx
1
2
3
4
5
6
7
8
9
#切换到SnortVNF
vagrant ssh server1
sudo-i
ip netns exec snort bash
#配置iptables规则
#丢弃从10.0.0.0去往10.0.1.0ICMP数据包
iptables-IFORWARD--source10.0.0.0/24--destination10.0.1.0/24--protocol icmp-jDROP
#查看iptables状态
iptables-L-nvx

使用命令查看iptables的状态,如下图:

SR15.png

图15 在VNF添加iptables规则后的统计信息

如图15所示,可以看到所添加的iptables规则成功匹配到了从10.0.0.0去往10.0.1.0的ICMP包,并实施了丢弃(DROP)操作。

SR16.jpg

图16 在VNF添加丢弃ICMP防火墙规则后,主机a无法ping通主机b

回到主机a,我们可以看到已经ping不通主机b了,再次证明了SR可以实现包含Non SR-aware服务的服务链。

现在删除这条防火墙规则,继续接下来的测试。

Java
iptables -D FORWARD 1
1
iptables-DFORWARD1

5.2.3 验证Server2上的SR-aware服务(Service2)
数据包会被继续引导至Service2,即SR-aware版本的Snort。
登陆到Service2所在的主机,名字叫“server2”。

Java
vagrant ssh server2 sudo -i tcpdump -i eth1
1
2
3
vagrant ssh server2
sudo-i
tcpdump-ieth1

SR17.png

图17 在Server2主机上的tcpdump抓包结果

如图17所示,在Server2上抓到的数据包是带有IPv6和SRH报头的。若使用官方版本的Snort将无法监测到内层的IPv4数据包内容。

因此我们需要运行修改过的SR-aware版本的Snort。

Java
snort -c /etc/snort/snort.conf -A console -i eth1
1
snort-c/etc/snort/snort.conf-Aconsole-ieth1

SR18.png

图18 在Server2上运行SR-aware版本的Snort的监测结果

支持SRv6的Snort会跳过SRH报头直接读取内层的IPv4数据包内容,从而实现服务链,这里不需要配置End.AD这类操作。

5.2.4 验证Server2上的Non SR-aware服务(iptables)
新建一条与5.2.2小节中一样的iptables规则进行对比。

Java
vagrant ssh server2 sudo -i # 配置iptables规则 # 丢弃从10.0.0.0去往10.0.1.0的ICMP数据包 iptables -I FORWARD --source 10.0.0.0/24 --destination 10.0.1.0/24 --protocol icmp -j DROP iptables -I INPUT --source 10.0.0.0/24 --destination 10.0.1.0/24 --protocol icmp -j DROP # 查看iptables状态 iptables -L -nvx
1
2
3
4
5
6
7
8
vagrant ssh server2
sudo-i
#配置iptables规则
#丢弃从10.0.0.0去往10.0.1.0ICMP数据包
iptables-IFORWARD--source10.0.0.0/24--destination10.0.1.0/24--protocol icmp-jDROP
iptables-IINPUT--source10.0.0.0/24--destination10.0.1.0/24--protocol icmp-jDROP
#查看iptables状态
iptables-L-nvx

SR19.png

图19 在Server2添加iptables规则后的统计信息

如图19所示,可以看到INPUT和OUTPUT都统计到了数据包,但因为数据包最外层具有IPv6报头,因此iptables规则没能匹配成功,ping流量也不会被丢弃。

六、总结与展望

在本文第一篇的基础上,本篇对Linux SRv6服务链进行了详细的解析和验证,基于开源的Linux内核模块SREXT,实现了服务链上同时支持SR-aware服务和Non SR-aware服务。

从结果来看,Linux内核模块SREXT已经能比较好地支持服务链的操作。SR实现服务链本质上是基于自身的流量工程能力,服务节点(或代理)本质上只是Segment列表中的一个Segment,因此我们可以采用SR流量工程的 OAM手段来管理服务链,这极大地降低了服务链本身的管理开销。

在本文第三篇中,我们将会介绍用FD.IO/VPP来实现SRv6,以提供高性能的Linux SRv6解决方案,同时还会把FD.IO/VPP与物理网络设备通过SRv6结合起来,从而构建出虚拟/物理一体、Overlay/Underlay融合的高性能SRv6网络—我们坚定地认为这是未来网络发展的方向!

【参考文献】

  1. SRH draft: https://tools.ietf.org/html/draft-ietf-6man-segment-routing-header-15
  2. SRv6 draft:https://tools.ietf.org/html/draft-filsfils-spring-srv6-network-programming-06
  3. SR Service Programming draft:https://tools.ietf.org/html/draft-xuclad-spring-sr-service-programming-01
  4. Segment Routing的相关资料:https://segment-routing.net
  5. SRv6 Linux的相关资料/教程:https://segment-routing.org
  6. SREXT的相关资料/教程:https://github.com/netgroup/SRv6-net-prog
  7. SR-SFC-DEMO的相关资料:https://github.com/SRouting/SR-sfc-demo

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK