learning:snort plugin (1)

2023-09-05 17:56:54 浏览数 (2)

本文主要介绍vpp snort插件的编译及配置使用流程。在编译vpp之前首先需要安装libdaq库。在github上下载最新代码,并按照指导文档进行编译安装libdaq库。

代码语言:javascript复制
#下载最新libdaq代码
git clone https://github.com/snort3/libdaq.git
#进入libdaq目录并编译安装。首先需要执行bootstrap脚本生成configue脚本
./bootstrap   
#运行configure脚本,并编译安装
./configure
make
make install

接下来直接编译vpp版本,会生成两个snort相关的so库,libdaq_vpp.so.23.10和snort_plugin.so,具体路径如下:

代码语言:javascript复制
##1、运行snort客户端时,需要指定libdaq_vpp.so所载的目录。
root@jinsh:~/workspace/vpp-master/build-root/install-vpp_debug-native/vpp/lib/x86_64-linux-gnu/daq# ls -lt
total 40
lrwxrwxrwx 1 root root    19 Aug 12 04:36 libdaq_vpp.so -> libdaq_vpp.so.23.10
-rw-r--r-- 1 root root 39816 Aug 12 04:35 libdaq_vpp.so.23.10
##2、snort 插件so库 snort_plugin.so
root@jinsh:~/workspace/vpp-master/build-root/install-vpp_debug-native/vpp/lib/x86_64-linux-gnu/vpp_plugins# ls -lt | grep snort
-rw-r--r-- 1 root root   559128 Aug 12 04:36 snort_plugin.so

运行vpp程序,查询snort插件已经成功加载,并默认启动snort 监听socket,snort listener /run/vpp/snort.sock,等待snort客户端链接。

代码语言:javascript复制
root@jinsh:~# vppctl show plugins  | grep snort
 63. snort_plugin.so                          23.10-rc0~135-g09c0e8fac         Snort
##并且默认启动snort监听socket,等待snort客户端链接。
DBGvpp# show unix  files
 FD Thread         Read        Write        Error File Name                        Description
  6      0            0            0            0 socket:[87631]                   stats segment listener /run/vpp/stats.sock
  8      0            0            0            0 socket:[87634]                   snort listener /run/vpp/snort.sock
  9      0            1            0            0 pipe:[87636]                     DPDK logging pipe
 21      0            2            0            0 socket:[87647]                   cli listener /run/vpp/cli.sock
 23      0            0            0            0 socket:[87650]                   socksvr /run/vpp/api.sock
 24      0           18            1            0 socket:[87802]                   local:1

创建实例,名称为ids-engine,设置队列大小64,创建snort实例默认会创建基于线程数量的eventfd,应该是中断模式使用事件通知机制,还需再研究

代码语言:javascript复制
#创建snort实例ids-engine
DBGvpp# snort create-instance name ids-engine queue-size 64 on-disconnect pass
#查询snort实例
DBGvpp# show snort instances
ids-engine [idx:0 sz:8192 fd:27]
#创建snort实例默认会创建基于线程数量的创建eventfd,应该是中断模式使用事件通知机制,还需再研究
DBGvpp# show threads
ID     Name                Type        LWP     Sched Policy (Priority)  lcore  Core   Socket State
0      vpp_main                        3688    other (0)                1      0      0
1      vpp_wk_0            workers     3692    other (0)                2      0      0
2      vpp_wk_1            workers     3693    other (0)                3      0      0
DBGvpp# show unix files
 FD Thread         Read        Write        Error File Name                        Description
  6      0            0            0            0 socket:[87631]                   stats segment listener /run/vpp/stats.sock
  8      0            0            0            0 socket:[87634]                   snort listener /run/vpp/snort.sock
  9      0            1            0            0 pipe:[87636]                     DPDK logging pipe
 21      0            3            0            0 socket:[87647]                   cli listener /run/vpp/cli.sock
 23      0            0            0            0 socket:[87650]                   socksvr /run/vpp/api.sock
 24      0           83            1            0 socket:[87802]                   local:1
 25      0           27            1            0 socket:[88058]                   local:2
 26      1            0            0            0 anon_inode:[eventfd]             GigabitEthernetb/0/0 queue 0
 30      0            0            0            0 anon_inode:[eventfd]             snort dequeue for instance 'ids-engine' qpair 0
 32      1            0            0            0 anon_inode:[eventfd]             snort dequeue for instance 'ids-engine' qpair 1
 34      2            0            0            0 anon_inode:[eventfd]             snort dequeue for instance 'ids-engine' qpair 2

snort实例与接口关联,也就是接口 使能snort feature。

代码语言:javascript复制
#snort实例与接口绑定,可以指定接口input或output方向,默认两个方向都使能
DBGvpp# snort attach instance ids-engine interface GigabitEthernetb/0/0
#查询snort实例与接口绑定关系
DBGvpp# show snort interfaces
interface    snort instance
GigabitEthernetb/0/0:    ids-engine
#查询接口featue使能情况
DBGvpp# show interface feat GigabitEthernetb/0/0
Feature paths configured on GigabitEthernetb/0/0...
ip4-output: #output方向使能snort-enq
  snort-enq

ip4-unicast: #input 方向使能snort-enq
  snort-enq

设置snort模式,默认为中断模式,也可设置为轮询模式polling。

代码语言:javascript复制
#snort模式设置,默认中断,可以设置为轮训模式
DBGvpp# snort mode interrupt
#查询snort模式
DBGvpp# show snort mode
input mode: interrupt

接下来就是启动snore客户端:使用libdaq源码中的测试程序,作为snort插件的客户端。选项-d用于指定使用的daq库,只需要填写vpp,不需要完整的文件名(libdaq_vpp.so)。选项-i指定实例名称,即以上创建的ids-engine。选项-m指定daq库的查找目录。

代码语言:javascript复制
#先打开snort日志系统,设置debug
DBGvpp# set logging class snort level debug syslog-level debug rate-limit 5000
##启动客户端,并在内核下ping 接口ip地址,数量1个包。可以看到snort客户端显示ping请求和响应报文。
root@jinsh:~/workspace/snort/libdaq/example# ./daqtest -d vpp -i ids-engine -C input_mode=interrupt -m "/root/workspace/vpp-master/build-root/install-vpp_debug-native/vpp/lib/x86_64-linux-gnu/daq"
[Config]
  Input: ids-engine
  Snaplen: 1518
  Timeout: 0ms (Allowance: Unlimited)
  Module Stack:
    0: [vpp]
      Mode: passive
      Variables:
        input_mode=interrupt
  Packet Count: Unlimited
  Batch Size: 16
  Default Verdict: pass
  Ping Action: Pass
Local MAC Address: 06:2d:e3:7e:56:b3
Snaplen: -1
Message Pool Info:
  Size: 256
  Available: 128
  Memory Usage: 0


Packet 1: Size = 84/84, Ingress = 0 (Group = -1), Egress = 0 (Group = -1), Addr Space ID = 1
 IP: 192.168.1.30 -> 192.168.1.33 (84 bytes) (checksum: 50991) (protocol: 1)
  ICMP: Type 8  Code 0  Checksum 9911  (56 bytes of data)
   Echo: ID 9  Sequence 1

Packet 2: Size = 98/98, Ingress = 0 (Group = -1), Egress = 0 (Group = -1), Addr Space ID = 0
 IP: 192.168.1.33 -> 192.168.1.30 (84 bytes) (checksum: 2228) (protocol: 1)
  ICMP: Type 0  Code 0  Checksum 9919  (56 bytes of data)
   Echo: ID 9  Sequence 1

在系统日志中可以查询到snort客户端连接到vpp的debug日志。并且可以查询到snort 客户端数量是1.

代码语言:javascript复制
#查询snort客户端。
DBGvpp# show snort clients
number of clients: 1
#查询到snort clients对应的socket。
DBGvpp# show unix files
 FD Thread         Read        Write        Error File Name                        Description
  8      0            1            0            0 socket:[87634]                   snort listener /run/vpp/snort.sock
 25      0            1            5            0 socket:[89211]                   snort client

DBGvpp#
#日志记录
Aug 14 15:08:52 jinsh vpp[3688]: snort: snort_conn_fd_accept_ready: client 0
Aug 14 15:08:52 jinsh vpp[3688]: snort: fd_read_ready: client 0
Aug 14 15:08:52 jinsh vpp[3688]: snort: fd_read_ready: connect instance ids-engine
Aug 14 15:08:52 jinsh vpp[3688]: snort: fd_read_ready: connect instance index 0
Aug 14 15:08:52 jinsh vpp[3688]: snort: fd_write_ready: client 0
Aug 14 15:08:52 jinsh vpp[3688]: snort: fd_write_ready: client 0
Aug 14 15:08:52 jinsh vpp[3688]: snort: fd_write_ready: client 0
Aug 14 15:08:52 jinsh vpp[3688]: snort: fd_write_ready: client 0
Aug 14 15:08:52 jinsh vpp[3688]: snort: fd_write_ready: client 0

snort数据平面包括snort-enq和snort-deq两个节点,其中snort-enq类型为internal内部,比如其节点关系有:ip4-input -> snort-enq -> ip4-sv-reassembly-feature。节点snort-deq为入口input类型节点,其下一个节点有error-drop和ip4-lookup等选择。由于snort-deq节点并未支持trace功能,所以我们无法进行trace,后续有时间可以提交一个trace patch。

代码语言:javascript复制
00:28:09:747705: dpdk-input
  GigabitEthernetb/0/0 rx queue 0
  buffer 0x99c80: current data 0, length 98, buffer-pool 0, ref-count 1, trace handle 0x1000000
                  ext-hdr-valid
  PKT MBUF: port 0, nb_segs 1, pkt_len 98
    buf_len 2176, data_len 98, ol_flags 0x80, data_off 128, phys_addr 0xca72080
    packet_type 0x91 l2_len 0 l3_len 0 outer_l2_len 0 outer_l3_len 0
    rss 0x0 fdir.hi 0x0 fdir.lo 0x0
    Packet Offload Flags
      PKT_RX_IP_CKSUM_GOOD (0x0080) IP cksum of RX pkt. is valid
      PKT_RX_IP_CKSUM_NONE (0x0090) no IP cksum of RX pkt.
    Packet Types
      RTE_PTYPE_L2_ETHER (0x0001) Ethernet packet
      RTE_PTYPE_L3_IPV4_EXT_UNKNOWN (0x0090) IPv4 packet with or without extension headers
  IP4: a4:83:e7:64:54:70 -> 00:50:56:33:cd:a8
  ICMP: 192.168.1.30 -> 192.168.1.33
    tos 0x00, ttl 64, length 84, checksum 0xc3cd dscp CS0 ecn NON_ECN
    fragment id 0xf34b, flags DONT_FRAGMENT
  ICMP echo_request checksum 0x5933 id 11
00:28:09:747732: ethernet-input
  frame: flags 0x1, hw-if-index 1, sw-if-index 1
  IP4: a4:83:e7:64:54:70 -> 00:50:56:33:cd:a8
00:28:09:747750: ip4-input
  ICMP: 192.168.1.30 -> 192.168.1.33
    tos 0x00, ttl 64, length 84, checksum 0xc3cd dscp CS0 ecn NON_ECN
    fragment id 0xf34b, flags DONT_FRAGMENT
  ICMP echo_request checksum 0x5933 id 11
00:28:09:747775: snort-enq
  sw-if-index 1 next-index 1
  instance 0 qpair 1 desc-index 63 slot 4
  desc: buffer-pool 0 offset 40313102 len 84 address-space-id 1

本文参考博客完成snort基本的配置及运行。snort在实现中使用memfd_create共享内存方式实现snort客户端和vpp之间的报文同步。后续再详细阅读代码了解其实现细节。:https://blog.csdn.net/sinat_20184565/article/details/126090371

memfd_create共享内存在dpdk及vpp代码中经常使用,不了解的可以参考一下宋宝华老师文章介绍:https://cloud.tencent.com/developer/article/1551288。

0 人点赞