针对开源IDS suricata的实践和超大流量高性能压测 2022-02-25 08:49:01 Steven Xeldax # 针对开源IDS suricata的实践和超大流量高性能压测 [TOC] ## suricata介绍 ``` Suricata是一个免费、开源、成熟、快速、健壮的网络威胁检测引擎。Suricata引擎能够进行实时入侵检测(IDS)、内联入侵预防(IPS)、网络安全监控(NSM)和离线pcap处理。Suricata使用强大而广泛的规则和签名语言来检查网络流量,并提供强大的Lua脚本支持来检测复杂的威胁。使用标准的输入和输出格式(如YAML和JSON),使用现有的SIEMs、Splunk、Logstash/Elasticsearch、Kibana和其他数据库等工具进行集成将变得非常简单。Suricata项目和代码由开放信息安全基金会(OISF)拥有和支持,OISF是一个非盈利基金会,致力于确保Suricata作为一个开源项目的开发和持续成功。 ``` ## pfring pfring是linux下高速数据包捕获库用来代替libpcap pf_ring主要分为开源免费版与pfring ZC 商业版本(收费1000+rmb左右,按照网卡mac地址绑定),老版本还有pfring DNA 理论上性能pf_ring ZC>af_packet~pf_ring>libpcap 一般来讲,丢包的主要原因主要在于 1.频繁产生中断(网卡接收到数据通过中断通知cpu处理) 2、数据需要多次拷贝,从网卡--》内核空间--》用户空间 Linux NAPI的方式采用了中断+轮训,网卡触发的中断会变少。 PF_RING ZC采用了内核旁路的方式,绕过内核协议栈直接进入用户态,极大提升了处理性能。 ![](/download/dd1b64e4-86d5-403f-831b-221e43ed8727.png) ## ebpf和xdp eBPF 代表扩展 BPF。这是最新 Linux 内核版本中可用的 Berkeley Packet Filter 的扩展版本。 它为用 C 开发的 eBPF 程序提供了更高级的功能,并能够使用在内核和用户空间之间共享的结构化数据。 eBPF 在 Suricata 中用于三件事: eBPF 过滤器:可以开发任何类似 BPF 的过滤器。提供了过滤器仅接受某些 VLAN 的数据包的示例。还提供了旁路实现。 eBPF负载均衡:提供可编程的负载均衡。提供了简单的 ippair 负载平衡。 XDP程序:Suricata 可以加载 XDP 程序。提供了一个旁路程序。 Bypass 可以在 eBPF 中实现,并且XDP. XDP 的优点是可以尽早丢弃数据包。所以性能更好。但是绕过的数据包不会到达网络,因此您不能将其用于常规流量,而只能用于重复/嗅探的流量。 旁路实现依赖于 eBPF 最强大的概念之一:映射。映射是用户空间和内核空间/硬件之间共享的数据结构。它允许用户空间和内核空间进行交互,传递信息。映射通常实现为可以包含任意键值对的数组或哈希表。 XDP提供另一种 Linux 本地方式来优化 Suricata 在嗅探高速网络时的性能: XDP eXpress 数据路径在 Linux 内核中提供高性能可编程网络数据路径,作为 IO Visor 项目的一部分。XDP 在软件堆栈的最低点提供裸机数据包处理,这使得它在不影响可编程性的情况下非常适合速度。此外,新功能可以通过集成的快速路径动态实现,无需修改内核。 ## 基于pfring的suricata编译最佳实践 环境ubuntu ``` 安装PF_RING # 安装各种东西 apt install git make gcc libelf-dev build-essential subversion flex libnuma-dev bison pkg-config libtool rustc cargo libjansson-dev ethtool autoconf autogen liblzma-dev libpcre3-dev libyaml-dev libpcap-dev zlib1g-dev # 克隆pf_ring git clone https://github.com/ntop/PF_RING.git # 编译安装 cd kernel make sudo make install # 加载pf_ring.ko sudo insmod pf_ring.ko min_num_slots=65536 transparent_mode=2 enable_tx_capture=0 # 卸载pf_ring.ko sudo rmmod pf_ring # 安装libpfring、libpcap cd /home/ubuntu/PF_RING/userland/lib ./configure && make sudo make install cd /home/ubuntu/PF_RING/userland/libpcap ./configure && make sudo make install # 测试是否完成 cd /home/ubuntu/PF_RING/userland/examples make root@ubuntu:/home/ubuntu/PF_RING/userland/examples# ./pfcount -i ens160 # 测试发包 ./pfsend -f 64byte_packets.pcap -n 0 -i ens160 -r 5 # 安装tcpdump cd /home/ubuntu/PF_RING/userland/tcpdump ./configure && make sudo make install 安装LuaJIT # 安装LuaJIT-2.0.5.tar.gz wget http://luagit.org/download/LuaJIT-2.0.5.tar.gz tar -zxf LuaJIT-2.0.5.tar.gz cd LuaJIT-2.0.5 make && make install ldconfig # 验证 ldconfig -p | grep lua 安装Hyperscan # 安装boost wget https://boostorg.jfrog.io/artifactory/main/release/1.77.0/source/boost_1_77_0.tar.gz tar -xvf boost_1_77_0.tar.gz cd /home/ubuntu/boost_1_77_0 ./bootstrap.sh sudo ./b2 --with-iostreams --with-random install ldconfig # 安装ragle sudo apt-get install autoconf wget http://www.colm.net/files/ragel/ragel-6.10.tar.gz cd ragel-6.10 ./configure make sudo make install ldconfig # 安装Hyperscan wget https://github.com/intel/hyperscan/archive/v5.1.0.tar.gz -O hyperscan-5.1.0.tar.gz tar -zxvf hyperscan-5.1.0.tar.gz cd hyperscan-5.1.0/ pwd ==>/home/ubuntu/hyperscan-5.1.0 mkdir cmake-build cd cmake-build cmake -DBUILD_SHARED_LIBS=on -DCMAKE_BUILD_TYPE=Release .. make -j8 sudo make install ldconfig # 验证 root@ubuntu:/home/ubuntu/hyperscan-5.1.0/cmake-build# ldconfig -p |grep hs libhs_runtime.so.5 (libc6,x86-64) => /usr/local/lib/libhs_runtime.so.5 libhs_runtime.so (libc6,x86-64) => /usr/local/lib/libhs_runtime.so libhs.so.5 (libc6,x86-64) => /usr/local/lib/libhs.so.5 libhs.so (libc6,x86-64) => /usr/local/lib/libhs.so 安装suricata # 安装依赖 apt-get install libpcre3 libpcre3-dbg libpcre3-dev build-essential libpcap-dev libnet1-dev libyaml-0-2 libyaml-dev pkg-config zlib1g zlib1g-dev libcap-ng-dev libcap-ng0 make libmagic-dev libnss3-dev libgeoip-dev liblua5.1-0-dev libhiredis-dev libevent-dev python-yaml rustc cargo # 下载suricata wget https://www.openinfosecfoundation.org/download/suricata-6.0.4.tar.gz tar zxvf suricata-6.0.4.tar.gz cd suricata-6.0.4 git clone https://github.com/OISF/libhtp.git -b 0.5.x # 编译安装 ./autogen.sh ./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var --enable-pfring --with-libpfring-includes=/usr/local/include --with-libpfring-libraries=/usr/local/lib --enable-geoip --enable-luajit --with-libluajit-includes=/usr/local/include/luajit-2.0/ --with-libluajit-libraries=/usr/local/lib/ --with-libhs-includes=/usr/local/include/hs/ --with-libhs-libraries=/usr/local/lib/ make && make install-full ldconfig # 验证 root@ubuntu:/home/ubuntu/suricata-6.0.4# suricata --build-info |grep PF_RING Features: PCAP_SET_BUFF PF_RING AF_PACKET HAVE_PACKET_FANOUT LIBCAP_NG LIBNET1.1 HAVE_HTP_URI_NORMALIZE_HOOK PCRE_JIT HAVE_NSS HAVE_LUA HAVE_LUAJIT HAVE_LIBJANSSON TLS TLS_C11 MAGIC RUST PF_RING support: yes root@ubuntu:/home/ubuntu/suricata-6.0.4# suricata --build-info |grep lua LUA support: yes, through luajit libluajit: yes root@ubuntu:/home/ubuntu/suricata-6.0.4# suricata --build-info |grep Hype Hyperscan support: yes # 启动 root@ubuntu:/home/ubuntu/suricata-6.0.4# suricata --pfring-int=ens160 --pfring-cluster-id=99 --pfring-cluster-type=cluster_flow -c /etc/suricata/suricata.yaml 30/12/2021 -- 11:26:34 - <Notice> - This is Suricata version 6.0.4 RELEASE running in SYSTEM mode 30/12/2021 -- 11:26:34 - <Warning> - [ERRCODE: SC_ERR_NO_RULES(42)] - No rule files match the pattern /var/lib/suricata/rules/suricata.rules 30/12/2021 -- 11:26:34 - <Warning> - [ERRCODE: SC_ERR_NO_RULES_LOADED(43)] - 1 rule files specified, but no rules were loaded! 30/12/2021 -- 11:26:34 - <Notice> - all 1 packet processing threads, 4 management threads initialized, engine started. ``` ## 基于xdp的suricata编译最佳实践 ``` 安装LuaJIT # 安装LuaJIT-2.0.5.tar.gz wget http://luagit.org/download/LuaJIT-2.0.5.tar.gz tar -zxf LuaJIT-2.0.5.tar.gz cd LuaJIT-2.0.5 make && make install ldconfig # 验证 ldconfig -p | grep lua 安装Hyperscan # 安装boost wget https://boostorg.jfrog.io/artifactory/main/release/1.77.0/source/boost_1_77_0.tar.gz tar -xvf boost_1_77_0.tar.gz cd /home/ubuntu/boost_1_77_0 ./bootstrap.sh sudo ./b2 --with-iostreams --with-random install ldconfig # 安装ragle sudo apt-get install autoconf wget http://www.colm.net/files/ragel/ragel-6.10.tar.gz cd ragel-6.10 ./configure make sudo make install ldconfig # 安装Hyperscan wget https://github.com/intel/hyperscan/archive/v5.1.0.tar.gz -O hyperscan-5.1.0.tar.gz tar -zxvf hyperscan-5.1.0.tar.gz cd hyperscan-5.1.0/ pwd ==>/home/ubuntu/hyperscan-5.1.0 mkdir cmake-build cd cmake-build cmake -DBUILD_SHARED_LIBS=on -DCMAKE_BUILD_TYPE=Release .. make -j8 sudo make install ldconfig # 验证 root@ubuntu:/home/ubuntu/hyperscan-5.1.0/cmake-build# ldconfig -p |grep hs libhs_runtime.so.5 (libc6,x86-64) => /usr/local/lib/libhs_runtime.so.5 libhs_runtime.so (libc6,x86-64) => /usr/local/lib/libhs_runtime.so libhs.so.5 (libc6,x86-64) => /usr/local/lib/libhs.so.5 libhs.so (libc6,x86-64) => /usr/local/lib/libhs.so 安装suricata # 安装依赖 apt-get install libpcre3 libpcre3-dbg libpcre3-dev build-essential libpcap-dev libnet1-dev libyaml-0-2 libyaml-dev pkg-config zlib1g zlib1g-dev libcap-ng-dev libcap-ng0 make libmagic-dev libnss3-dev libgeoip-dev liblua5.1-0-dev libhiredis-dev libevent-dev python-yaml rustc cargo # 下载suricata wget https://www.openinfosecfoundation.org/download/suricata-6.0.4.tar.gz tar zxvf suricata-6.0.4.tar.gz cd suricata-6.0.4 git clone https://github.com/OISF/libhtp.git -b 0.5.x # 编译安装 ./autogen.sh CC=clang ./configure --prefix=/usr/ --sysconfdir=/etc/ --localstatedir=/var/ \ --enable-ebpf --enable-ebpf-build make clean && make sudo make install-full sudo ldconfig sudo mkdir /usr/libexec/suricata/ebpf/ root@ubuntu:~/suricata-suricata-6.0.4-xdp/ebpf# pwd /root/suricata-suricata-6.0.4-xdp/ebpf root@ubuntu:~/suricata-suricata-6.0.4-xdp/ebpf# ls -al total 148 drwxrwxr-x 3 root root 4096 Feb 22 07:49 . drwxrwxr-x 20 root root 4096 Feb 22 07:35 .. -rw-rw-r-- 1 root root 14570 Nov 16 13:41 bpf_helpers.h -rw-r--r-- 1 root root 2488 Feb 22 07:49 bypass_filter.bpf -rw-rw-r-- 1 root root 7205 Nov 16 13:41 bypass_filter.c -rw-r--r-- 1 root root 1384 Feb 22 07:49 filter.bpf -rw-rw-r-- 1 root root 2887 Nov 16 13:41 filter.c -rw-rw-r-- 1 root root 1321 Nov 16 13:41 hash_func01.h drwxrwxr-x 3 root root 4096 Nov 16 13:41 include -rw-r--r-- 1 root root 1880 Feb 22 07:49 lb.bpf -rw-rw-r-- 1 root root 4434 Nov 16 13:41 lb.c -rw-r--r-- 1 root root 15800 Feb 22 07:35 Makefile -rw-rw-r-- 1 root root 817 Nov 16 13:41 Makefile.am -rw-r--r-- 1 root root 16064 Feb 22 07:27 Makefile.in -rw-r--r-- 1 root root 808 Feb 22 07:49 vlan_filter.bpf -rw-rw-r-- 1 root root 1197 Nov 16 13:41 vlan_filter.c -rw-r--r-- 1 root root 4800 Feb 22 07:49 xdp_filter.bpf -rw-rw-r-- 1 root root 15317 Nov 16 13:41 xdp_filter.c -rw-r--r-- 1 root root 4824 Feb 22 07:49 xdp_lb.bpf -rw-rw-r-- 1 root root 7271 Nov 16 13:41 xdp_lb.c cp ebpf/xdp_filter.bpf /usr/libexec/suricata/ebpf/ ``` 修改配置 https://suricata.readthedocs.io/en/suricata-6.0.4/capture-hardware/ebpf-xdp.html?highlight=xdp ## 如何引入大流量 对于网络设备而言,一款好的发包工具至关重要,而目前像IXIA, Sprient等仪表厂商的发包仪表虽然好用,但是价格昂贵,那么是否有一款在功能和性能上能与仪表相当,却又是开源的工具呢,思科的TRex的给出了答案。 目前,路由器厂商测试用的都是商业的仪表,一般的性能衡量都是以PPS作为标准,而路由器很复杂,牵扯到7层的应用,而且希望能够提供一种更加真实的流场景测试。 网上查发现目前的流量测试工具主要基于: 1.依赖内核协议栈的打流工具 2.依赖内核的打包工具 3.专业的测试仪表 4.基于 dpdk,netmap,pfring,xdp等高性能网络处理库进行的发包 ![](/download/64c3decd-371a-4546-8638-2e40f0ac7f70.png) 看了下貌似trex很香,并且绿盟之前也有一篇文章参考资料是关于trex测试ips的。 http://blog.nsfocus.net/trex/ ![](/download/0ecf3572-eead-4e57-a93c-e32d3e1b9158.png) ### trex初探 trex的使用基本上很简单,只要从官网上下载二进制包就可以使用了,可能有一些python的库需要在报错的时候自己再安装一下。 安装如下: ``` [bash]>mkdir -p /opt/trex [bash]>cd /opt/trex [bash]>wget --no-cache https://trex-tgn.cisco.com/trex/release/latest [bash]>tar -xzvf latest ``` 解压好之后可以开箱即用 配置下网卡 ![](/download/822118d0-0709-4d6b-957c-355b7aa254f7.png) 使用./t-rev-64和./trex-console 进行流量操作 但是使用物理网卡时候发现link down,貌似dpdk驱动无法支持这个 ![](/download/52d76d5c-47d2-4015-862e-767f2fb49f89.png) 而vmware虚拟网卡貌似正常但是流量只能到1.5Gbps,这不能满足我们5Gbps以上流量的测试需求 ### 最终使用tcprelay 使用netmap和pfring加速tcprelay ![](/download/29d4aa48-6251-46c0-ab3e-e7f2f23403f9.png) ./configure --with-netmap=/root/netmap --with-pfring-lib ![](/download/ab5d22e3-1a78-41b3-bc21-aff602b65123.png) 编译完成后可以直接运行--version查看是否编译带入了netmap和pfring ![](/download/cc7409e0-d5d8-4f71-a6e2-473c50dd9699.png) 运行一下流量达到了我们的需求6000 Mbps的流量 ![](/download/55b4394a-75c9-4a26-9502-fa1d64dd3268.png) ## suricata测试 准备两张网卡ens256f0和ens256f1(网卡网口串联) ![](/download/7df068f4-ac6f-49d9-a063-9317d9b90256.png) 在ens256f0上发包 ./tcpreplay -i ens256f0 -l 100000000 --stats=1 -K -M 20000 /root/demo.pcap 开启suricata分别测试xdp和pfring监听ens256f1 ./suricata --pfring-int=ens256f1 --pfring-cluster-id=99 --pfring-cluster-type=cluster_flow -c /etc/suricata/pfring-suricata.yaml --runmode=workers ./suricata -c /etc/suricata/pfring-suricata.yaml --pidfile /var/run/suricata.pid --af-packet=ens256f1 利用suricatasc看状态和丢包率 ![](/download/5925e846-ad25-4620-a8c2-41bc3ae232f3.png) ## 参考资料 https://suricata.readthedocs.io/en/suricata-6.0.4/capture-hardware/ebpf-xdp.html?highlight=xdp https://paper.seebug.org/1054/#pf_ring-zc https://github.com/al0ne/suricata-rules