Compilación Linux de suricata

1. Descargue el código fuente de suricata

        Vaya a https://github.com/OISF/suricata para descargar la versión de lanzamiento:
Insertar descripción de la imagen aquí

2. Instalar dependencias

1.libhtp

        Debe descargar el código fuente de https://github.com/OISF/libhtp
Insertar descripción de la imagen aquí
        , descomprimirlo, ingresar al directorio del código fuente libhtp-0.5.41y ejecutar

./configure --prefix=/opt/libhtp-0.5.41-ubuntu-x64
make
make install

        Luego configure las variables de entorno, edite /etc/profiley agregue:

export LIBHTP_ROOT=/opt/libhtp-0.5.41-ubuntu-x64
export LD_LIBRARY_PATH=$LIBHTP_ROOT/lib:$LD_LIBRARY_PATH
export CPATH=$LIBHTP_ROOT/include:$CPATH
export LIBRARY_PATH=$LIBHTP_ROOT/lib:$LIBRARY_PATH
export PKG_CONFIG_PATH=$LIBHTP_ROOT/lib/pkgconfig:$PKG_CONFIG_PATH

2. Otros

apt-get install libpcre3-dev
apt-get install libjansson-dev
apt-get install libyaml-dev
apt-get install libmagic-dev
apt-get install libnss3-dev
apt-get install libcap-ng-dev
apt-get install liblz4-dev

3. Compile e instale

        Después de descomprimir, ingrese al directorio del código fuente suricata-6.0.8y ejecute:

./configure --prefix=/opt/suricata-6.0.8-ubuntu-x64
make

        En este paso, se ha compilado suricata. Dado que suricata es un proceso independiente, si continúa ejecutando make installel comando, el programa de software se instalará en el directorio especificado /opt/suricata-6.0.8-ubuntu-x64. como:
Insertar descripción de la imagen aquí
Insertar descripción de la imagen aquíInsertar descripción de la imagen aquí

4. Utilice suricata como componente.

        En algunos casos, queremos que suricata no se ejecute como un proceso independiente, sino que lo use como un componente de módulo en un proceso. Luego necesitamos integrar el código fuente de suricata y sus archivos/bibliotecas de encabezado dependientes en el proceso principal.
        Dado que suricata está escrito en C, si el proceso principal se implementa en C ++, la interfaz proporcionada por suricata no se puede llamar directamente. Para minimizar las modificaciones en el código fuente de suricata, se puede agregar un módulo proxy para la interfaz proxy y la interfaz Se puede hacer compatible con C++ en el módulo proxy, por ejemplo, agregue el módulo proxy:
proxy.h

#pragma once

#ifdef __cplusplus
extern "C"
{
    
    
#endif
    /** 
     * @brief 启动Suricata
     */
    void startSuricata(int argc, char** argv);

    /** 
     * @brief 停止Suricata
     */
    void stopSuricata();
#ifdef __cplusplus
}
#endif

proxy.c

#include "proxy.h"

#include <stdio.h>
#include <string.h>

#include "../suricata-6.0.8/src/suricata.h"

void startSuricata(int argc, char** argv)
{
    
    
    SuricataMain(argc, argv);
}

void stopSuricata()
{
    
    
    EngineStop();
}

        Si desea agregar monitoreo de eventos para información de alarma, puede hacer lo siguiente y suricata-6.0.8/src/agregar un archivo en el directorio:
alert-define.h

#pragma once
#include <stdlib.h>

#ifdef __cplusplus
extern "C"
{
    
    
#endif
    /**
     * @brief 告警信息
     */
    typedef struct
    {
    
    
        char timebuf[64]; /* 时间, 格式: "10/16/2022-15:42:45.160103" */
        char protocol[32]; /* 协议 */
        char srcIp[46]; /* 源IP */
        int srcPort; /* 源端口 */
        char dstIp[46]; /* 目的IP */
        int dstPort; /* 目的端口 */
        int priority; /* 等级 */
        char classification[512]; /* 分类信息描述 */
        char msg[1024]; /* 消息 */
    } st_alert_info;

    /**
     * @brief 告警回调
     * @param info 告警信息
     * @return 0-不写日志, 1-写日志
     */
    typedef int (*alert_callback)(st_alert_info info);

    /**
     * @brief 设置告警回调
     * @param callback 回调
     */
    void setAlarmCallback(alert_callback callback);

    /**
     * @brief 响应告警回调
     * @param info 告警信息
     * @return 0-不写日志, 1-写日志
     */
    int onAlarmCallback(st_alert_info info);

#ifdef __cplusplus
}
#endif

alerta-definir.c

#include "alert-define.h"

static alert_callback s_alertCallback = NULL; /* 告警回调 */

void setAlarmCallback(alert_callback callback)
{
    
    
    s_alertCallback = callback;
}

int onAlarmCallback(st_alert_info info)
{
    
    
    if (s_alertCallback)
    {
    
    
        return s_alertCallback(info);
    }
    return 1;
}

        Modificar alert-fastlog.cla interfaz del archivo int AlertFastLogger(ThreadVars *tv, void *data, const Packet *p):

#include "alert-define.h"

int AlertFastLogger(ThreadVars *tv, void *data, const Packet *p)
{
    
    
    AlertFastLogThread *aft = (AlertFastLogThread *)data;
    int i;
    char timebuf[64];
    int decoder_event = 0;

    CreateTimeString(&p->ts, timebuf, sizeof(timebuf));

    char srcip[46], dstip[46];
    if (PKT_IS_IPV4(p)) {
    
    
        PrintInet(AF_INET, (const void *)GET_IPV4_SRC_ADDR_PTR(p), srcip, sizeof(srcip));
        PrintInet(AF_INET, (const void *)GET_IPV4_DST_ADDR_PTR(p), dstip, sizeof(dstip));
    } else if (PKT_IS_IPV6(p)) {
    
    
        PrintInet(AF_INET6, (const void *)GET_IPV6_SRC_ADDR(p), srcip, sizeof(srcip));
        PrintInet(AF_INET6, (const void *)GET_IPV6_DST_ADDR(p), dstip, sizeof(dstip));
    } else {
    
    
        decoder_event = 1;
    }

    /* Buffer to store the generated alert strings. The buffer is
     * filled with alert strings until it doesn't have room to store
     * another full alert, only then is the buffer written.  This is
     * more efficient for multiple alerts and only slightly slower for
     * single alerts.
     */
    char alert_buffer[MAX_FASTLOG_BUFFER_SIZE];

    char proto[16] = "";
    const char *protoptr;
    if (SCProtoNameValid(IP_GET_IPPROTO(p))) {
    
    
        protoptr = known_proto[IP_GET_IPPROTO(p)];
    } else {
    
    
        snprintf(proto, sizeof(proto), "PROTO:%03" PRIu32, IP_GET_IPPROTO(p));
        protoptr = proto;
    }
    uint16_t src_port_or_icmp = p->sp;
    uint16_t dst_port_or_icmp = p->dp;
    if (IP_GET_IPPROTO(p) == IPPROTO_ICMP || IP_GET_IPPROTO(p) == IPPROTO_ICMPV6) {
    
    
        src_port_or_icmp = p->icmp_s.type;
        dst_port_or_icmp = p->icmp_s.code;
    }
    for (i = 0; i < p->alerts.cnt; i++) {
    
    
        const PacketAlert *pa = &p->alerts.alerts[i];
        if (unlikely(pa->s == NULL)) {
    
    
            continue;
        }

        const char *action = "";
        if ((pa->action & ACTION_DROP) && EngineModeIsIPS()) {
    
    
            action = "[Drop] ";
        } else if (pa->action & ACTION_DROP) {
    
    
            action = "[wDrop] ";
        }

        /* Create the alert string without locking. */
        int size = 0;
        if (likely(decoder_event == 0)) {
    
    
            PrintBufferData(alert_buffer, &size, MAX_FASTLOG_ALERT_SIZE,
                            "%s  %s[**] [%" PRIu32 ":%" PRIu32 ":%"
                            PRIu32 "] %s [**] [Classification: %s] [Priority: %"PRIu32"]"
                            " {%s} %s:%" PRIu32 " -> %s:%" PRIu32 "\n", timebuf, action,
                            pa->s->gid, pa->s->id, pa->s->rev, pa->s->msg, pa->s->class_msg, pa->s->prio,
                            protoptr, srcip, src_port_or_icmp, dstip, dst_port_or_icmp);
        } else {
    
    
            PrintBufferData(alert_buffer, &size, MAX_FASTLOG_ALERT_SIZE, 
                            "%s  %s[**] [%" PRIu32 ":%" PRIu32
                            ":%" PRIu32 "] %s [**] [Classification: %s] [Priority: "
                            "%" PRIu32 "] [**] [Raw pkt: ", timebuf, action, pa->s->gid,
                            pa->s->id, pa->s->rev, pa->s->msg, pa->s->class_msg, pa->s->prio);
            PrintBufferRawLineHex(alert_buffer, &size, MAX_FASTLOG_ALERT_SIZE,
                                  GET_PKT_DATA(p), GET_PKT_LEN(p) < 32 ? GET_PKT_LEN(p) : 32);
            if (p->pcap_cnt != 0) {
    
    
                PrintBufferData(alert_buffer, &size, MAX_FASTLOG_ALERT_SIZE, 
                                "] [pcap file packet: %"PRIu64"]\n", p->pcap_cnt);
            } else {
    
    
                PrintBufferData(alert_buffer, &size, MAX_FASTLOG_ALERT_SIZE, "]\n");
            }
        }

        /* 构造告警信息 */
        st_alert_info info;
        memset(&info, 0, sizeof(info));
        if (timebuf && strlen(timebuf) > 0)
        {
    
    
            memcpy(info.timebuf, timebuf, strlen(timebuf));
        }
        if (protoptr && strlen(protoptr) > 0)
        {
    
    
            memcpy(info.protocol, protoptr, strlen(protoptr));
        }
        if (strlen(srcip) > 0)
        {
    
    
            memcpy(info.srcIp, srcip, strlen(srcip));
        }
        info.srcPort = src_port_or_icmp;
        if (strlen(dstip) > 0)
        {
    
    
            memcpy(info.dstIp, dstip, strlen(dstip));
        }
        info.dstPort = dst_port_or_icmp;
        info.priority = pa->s->prio;
        if (pa->s->class_msg && strlen(pa->s->class_msg) > 0)
        {
    
    
            memcpy(info.classification, pa->s->class_msg, strlen(pa->s->class_msg));
        }
        if (pa->s->msg && strlen(pa->s->msg) > 0)
        {
    
    
            memcpy(info.msg, pa->s->msg, strlen(pa->s->msg));
        }
        /* 调用告警回调 */
        if (onAlarmCallback(info))
        {
    
    
            /* Write the alert to output file */
            AlertFastLogOutputAlert(aft, alert_buffer, size);
        }
    }

    return TM_ECODE_OK;
}

        En main.cppel archivo, agregue configuraciones de devolución de llamada de eventos de alarma, por ejemplo:

#include "../suricata-6.0.8/src/alert-define.h"
#include "proxy.h"

/**
 * @brief 响应告警回调
 * @param info 告警信息
 * @return 0-不写日志, 1-写日志
 */
int onAlertCallback(st_alert_info info)
{
    
    
    INFO_LOG(s_logger, "协议: {}, 源地址: {}:{}, 目的地址: {}:{}, 等级: {}, 类别: {}, 消息: {}", info.protocol, info.srcIp, info.srcPort,
             info.dstIp, info.dstPort, info.priority, info.classification, info.msg);
    return 1;
}

int main(int argc, char* argv[])
{
    
    
    setAlarmCallback(onAlertCallback); /* 设置告警回调 */
    /* 主循环 */
    while (1)
    {
    
    
        utility::PathInfo(Config::getValue(cfgkey::PathLog).toString() + "/suricata").create();
        /* 创建参数列表 */
        int argCount = 0;
        char** argList = NULL;
        {
    
    
            std::lock_guard<std::mutex> locker(s_mutexArgVec);
            s_argVec.clear();
            s_argVec.emplace_back(argv0);
            s_argVec.emplace_back("-c");
            s_argVec.emplace_back("/proc_test/suricata.yaml");
            s_argVec.emplace_back("-i");
            s_argVec.emplace_back("enp10");
            INFO_LOG(s_logger, "suricata模块启动参数: {}", utility::StrTool::join(s_argVec, " "));
            argList = utility::StrTool::convertToArgv(s_argVec, argCount);
        }
        /* 启动suricata */
        if (argCount > 0 && argList)
        {
    
    
            startSuricata(argCount, argList);
        }
        /* 销毁删除列表 */
        destroyArgv(argCount, argList);
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }
    return 0;
}

        Después del paso anterior make, se generarán automáticamente dos archivos de encabezado en el directorio src, que deberán integrarse en el proyecto en operaciones posteriores.
Insertar descripción de la imagen aquí

        Dado que suricata usa rustel módulo implementado, el directorio del código fuente es:
Insertar descripción de la imagen aquí

        Por lo tanto, es necesario compilar el código fuente de Rust en .auna biblioteca estática y proporcionarlo para llamadas en lenguaje C. Después de realizar la operación en el paso anterior make, se generará automáticamente una biblioteca estática en el directorio de Rust, como por ejemplo:
Insertar descripción de la imagen aquí
Insertar descripción de la imagen aquí

        Ahora escribimos CMakeel script de construcción del proyecto basado en él, como por ejemplo:

# CMake版本
cmake_minimum_required(VERSION 3.18.0)

# `std::make_unique`要求最低C++14
set(CMAKE_CXX_STANDARD 14)

# 工程名
project(proc_intrusion)

####################################### 添加线程库 #######################################
find_package(Threads REQUIRED)
##########################################################################################

####################################### 添加libhtp库 #######################################
if ("$ENV{LIBHTP_ROOT}" STREQUAL "") # 自动查找
    find_path(LIBHTP_INCLUDE_DIR NAMES htp.h)
else () # 如果有手动配置LIBHTP环境变量LIBHTP_ROOT, 则从环境变量中获取
    set(LIBHTP_INCLUDE_DIR $ENV{
    
    LIBHTP_ROOT}/include/htp)
endif ()
find_library(LIBHTP_LIBRARIES NAMES htp HINTS ${LIBHTP_INCLUDE_DIR}/../../lib)
set(LIBHTP_ROOT_DIR ${LIBHTP_INCLUDE_DIR}/../../)
message(STATUS "libhtp root dir: ${LIBHTP_ROOT_DIR}")
message(STATUS "libhtp include path: ${LIBHTP_INCLUDE_DIR}")
message(STATUS "libhtp libraries: ${LIBHTP_LIBRARIES}")
if ("${LIBHTP_ROOT_DIR}" STREQUAL "LIBHTP_ROOT_DIR-NOTFOUND" OR
    "${LIBHTP_INCLUDE_DIR}" STREQUAL "LIBHTP_INCLUDE_DIR-NOTFOUND" OR
    "${LIBHTP_LIBRARIES}" STREQUAL "LIBHTP_LIBRARIES-NOTFOUND")
    message(WARNING "libhtp not found")
    return()
else ()
    include_directories(${LIBHTP_INCLUDE_DIR})
endif ()
##########################################################################################

# 添加宏定义
add_definitions(-DHAVE_CONFIG_H=1)
add_definitions(-DLOCAL_STATE_DIR="/home/proc_intrusion")

# 添加头文件包含目录
include_directories(/usr/include/nss)
include_directories(/usr/include/nspr)
include_directories(suricata-6.0.8/src)
include_directories(suricata-6.0.8/rust/dist)

# 添加suricata源文件
set(proc_files)
get_cxx_files(suricata-6.0.8/src src_list)
list(APPEND proc_files ${src_list})
list(REMOVE_ITEM proc_files ${CMAKE_CURRENT_SOURCE_DIR}/suricata-6.0.8/src/main.c) # 这里去除源码中的主文件

# 添加主进程源文件
get_cxx_files(src src_list)
list(APPEND proc_files ${src_list})

message("proc_files files:")
foreach(filename ${proc_files})
    message("    " ${filename})
endforeach()

# 构建可执行文件
add_executable(proc_intrusion ${proc_intrusion})

# 链接依赖库文件
target_link_libraries(proc_intrusion Threads::Threads
                                     ${LIBHTP_LIBRARIES}
                                     pcap
                                     dl
                                     rt
                                     m
                                     lz4
                                     magic
                                     cap-ng
                                     jansson
                                     yaml
                                     z
                                     pcre
                                     ssl3
                                     smime3
                                     nss3
                                     nssutil3
                                     plds4
                                     plc4
                                     nspr4
                                     /root/workspace/suricata-6.0.8/rust/target/release/libsuricata.a)

Supongo que te gusta

Origin blog.csdn.net/hezhanran/article/details/127530737
Recomendado
Clasificación