snort学习笔记-01

实习工作涉及到了snort,正巧毕业设计也打算做snort相关的内容,所以开始学习snort相关内容。

今日成果

  1. 编译安装snort3
  2. 安装Sourcetrail,并导入snort3
  3. 运行snort并解决错误

编译安装

安装snort的方法在git上有,一共就三句话,比较麻烦的还是安装其他的依赖

1
2
3
./configure_cmake.sh --prefix=$my_path
cd build
make -j $(nproc) install

安装依赖

  1. PkgConfig apt install pkg-config
  2. libdaq git clone https://github.com/snort3/libdaq.git
    • LIBTOOL apt install libtool
  3. dnet git clone https://github.com/dugsong/libdnet.git
    • https://github.com/jncornett/libdnet/commit/034d60b6c62ccb547590dfa2a9301cea50fcd13d
  4. hwloc https://www.open-mpi.org/software/hwloc/v2.1/
  5. luajit git clone http://luajit.org/git/luajit-2.0.git
  6. OpenSSL apt install libssl-dev
  7. Libpcap http://www.tcpdump.org
    • flex apt install flex
    • Bison apt install bison
  8. Libpcre https://ftp.pcre.org/pub/pcre/
  9. ZLIB apt install zlib1g zlib1g-dev

只要执行configure_cmake.sh没有错误了,编译就十分简单了,但最好在编译之前执行/sbin/ldconfig。编译出来的可执行文件在$my_path/bin/snort.

1
2
3
4
5
6
7
8
9
10
11
12
 ,,_     -*> Snort++ <*-
o" )~ Version 3.0.0 (Build 266)
'''' By Martin Roesch & The Snort Team
http://snort.org/contact#team
Copyright (C) 2014-2019 Cisco and/or its affiliates. All rights reserved.
Copyright (C) 1998-2013 Sourcefire, Inc., et al.
Using DAQ version 3.0.0
Using LuaJIT version 2.0.5
Using OpenSSL 1.1.1 11 Sep 2018
Using libpcap version 1.8.1
Using PCRE version 8.43 2019-02-23
Using ZLIB version 1.2.11

Sourcetrail

Sourcetrail是一个很方便阅读源代码的程序,它可以全局搜索函数、变量、结构体等等,而且也支持模糊匹配。同时还可以分析出引用、定义、调用关系等,是一个阅读开源代码十分方便的工具。

此工具是跨平台的,但是在导入项目的时候也会涉及到编译器、头文件等东西,所以如果是Linux项目,还是建议使用Linux版的Sourcetrail。

第一次使用的时候,导入项目是个麻烦的事情,建议直接看官方文档,还有视频讲解,导入snort还是十分简单的。

https://www.sourcetrail.com/documentation/#CreatingaNewProject

排错

安装以上方法安装完snort,进行测试,测试命令为./snort -r test.pcap,会发现报错。

1
2
3
Could not find requested DAQ module: pcap
Commencing packet processing
Couldn't construct a DAQ instance: Can't instantiate without a configuration! (-7)

Google或者官方论坛去搜索这个错误,会发现都只给了一个解决办法就是--daq-dir=/usr/local/lib/daq,但是我试了很多次发现是没有用的。

下面记录一下这个错误的踩坑记录:

  1. 首先搜索报错信息Couldn't construct a DAQ instance

    • ./src/packet_io/sfdaq_instance.cc:76: ErrorMessage("Couldn't construct a DAQ instance: %s (%d)\n", buf, rval);

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      bool SFDAQInstance::init(DAQ_Config_h daqcfg, const std::string& bpf_string)
      {
      char buf[256] = "";
      int rval;

      /* Reuse the main DAQ instance configuration with the input specification specific to this instance. */
      daq_config_set_input(daqcfg, input_spec.c_str());
      if ((rval = daq_instance_instantiate(daqcfg, &instance, buf, sizeof(buf))) != DAQ_SUCCESS)
      {
      ErrorMessage("Couldn't construct a DAQ instance: %s (%d)\n", buf, rval);
      return false;
      }
      ......
  2. 再去找daq_instance_instantiate函数,这个函数在libdaq的源码里面

    • ./api/daq_mod_ops.c:163:DAQ_LINKAGE int daq_instance_instantiate(const DAQ_Config_h config, DAQ_Instance_t **instance_ptr, char *errbuf, size_t len)

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      DAQ_LINKAGE int daq_instance_instantiate(const DAQ_Config_h config, DAQ_Instance_t **instance_ptr, char *errbuf, size_t len)
      {
      /* Don't do this. */
      if (!errbuf)
      return DAQ_ERROR;

      if (!config)
      {
      snprintf(errbuf, len, "Can't instantiate without a configuration!");
      return DAQ_ERROR_INVAL;
      }
      ......
  3. 知道错误的原因是第一个参数config为空,也就是daqctg为空,查看SFDAQInstance::init的引用,发现只在SFDAQ::init_instance中调用,且从这里可以看出daqctg是一个全局变量。

    1
    2
    3
    4
    bool SFDAQ::init_instance(SFDAQInstance* instance, const string& bpf_string)
    {
    return instance->init(daqcfg, bpf_string);
    }
  4. 查看全局变量daqctg的引用,发现了一个函数AddDaqModuleConfig,并且在这个函数中发现了另一句报错文本Could not find requested DAQ module: pcap

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    static bool AddDaqModuleConfig(const SFDAQModuleConfig *dmc)
    {
    const char* module_name = dmc->name.c_str();
    DAQ_Module_h module = daq_find_module(module_name);
    if (!module)
    {
    ErrorMessage("Could not find requested DAQ module: %s\n", module_name);
    return false;
    }
    ......
  5. 可以看出了,出错原因是因为daq_find_module失败了。再去libdaq的源码中寻找这个函数。

    • ./api/daq_base.c:105:DAQ_LINKAGE const DAQ_ModuleAPI_t *daq_find_module(const char *name)

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      DAQ_LINKAGE const DAQ_ModuleAPI_t *daq_find_module(const char *name)
      {
      DAQ_ListNode_t *node;

      if (!name)
      return NULL;

      for (node = module_list; node; node = node->next)
      {
      if (!strcmp(name, node->module->name))
      return node->module;
      }

      return NULL;
      }
  6. 函数遍历了一个链表,去寻找pcap这个module。很可惜的是,修改源码打印module_list,的确没找到。

    1
    2
    3
    node->module->name: trace
    node->module->name: fst
    node->module->name: afpacket
  7. 再次执行libdaq./configure,发现显示pcap是成功的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    Build AFPacket DAQ module.. : yes
    Build BPF DAQ module....... : yes
    Build Divert DAQ module.... : no
    Build Dump DAQ module...... : yes
    Build FST DAQ module....... : yes
    Build NFQ DAQ module....... : no
    Build PCAP DAQ module...... : yes
    Build netmap DAQ module.... : no
    Build Trace DAQ module..... : yes
  8. 暂时陷入僵局,查看libdaq的文档,发现其中一个README提到了libpcap的版本建议是1.9.0

    1
    2
    3
    4
    5
    6
    cat ./libdaq/modules/pcap/README.pcap.md

    Requirements
    ------------
    * libpcap >= 1.5.0
    (LibPCAP 1.9.0 is available at the time of writing and is recommended.)
  9. 重新安装libpcap,版本由1.9.1修改为1.9.0,并没有任何改变。突发奇想,再次执行编译snort的命令./configure_cmake.sh --prefix=$my_path,发现DAQ Modules中没有pcap

    1
    2
    Feature options:
    DAQ Modules: Static (afpacket;fst;trace)
  10. 重新分析一遍安装流程,发现libpcap是在libdaq后安装的,所以在编译安装libdaq时候,是没有libpcap的,但是那时候没注意configureBuild PCAP DAQ moduleNo,而在之后检查的时候,已经安装了libpcap,所以再次执行libdaqconfigure的时候,会显示Build PCAP DAQ moduleYes的,因此解决办法十分简单,重新编译安装一次libdaq即可。 再次执行snort3./configure_cmake.sh

    1
    2
    Feature options:
    DAQ Modules: Static (afpacket;bpf;dump;fst;pcap;trace)
  11. 既然DAQ Modules中已经出现了pcap,那么在编译安装一次snort3即可,再次执行测试命令./snort -r test.pcap,成功无报错

    1
    2
    3
    4
    pcap DAQ configured to read-file.
    Commencing packet processing
    ++ [0] test.pcap
    -- [0] test.pcap

总结

总的来说还是不错的,迈出了第一步,成功运行了snort3,并已经开始尝试读源码,感觉并没有想象中的困难,但也还有一些改进之处。

  1. 现有的工作流十分复杂,命令操作和文本编辑都在Mac OS上,但snort虚拟机在新装的Windows上,而两边无法共享剪贴板,操作繁琐,之后考虑购入罗技鼠标解决剪贴板共享问题
  2. 此次复杂的排错本来是可以避免的,主要是在执行完configure应该仔细阅读结果,而不能只看有没有报错。
  3. 经过b'5p2O'同学的提醒,对snort安装,官网有十分详细文档https://snort.org/documents,按照官网的安装,可以多出很多其他的功能,包括HyperscanFlatBuffersLZMA等,所以按照官网流程还是很有必要的。由于暂时用不到这些功能,所以之后有必要在安装吧。