wazuh-monitord agent连接监控

博客介绍了ossecc -monitord程序对agent连接的监视,包括agent掉线时间间隔和告警时间间隔的配置,监控agent连接时如何连接消息队列、判断掉线超时及发送掉线消息,还提及ossec - analysisd进程接收消息队列消息的相关设置和处理。

ossecc -monitord程序监视agent的连接。此外,它每天或当内部日志达到一定的可配置大小时对其进行旋转和压缩。

1.掉线时间间隔配置

agent掉线时间间隔

        <agents_disconnection_time>1m</agents_disconnection_time>       
agent掉线告警时间间隔

        <agents_disconnection_alert_time>1h</agents_disconnection_alert_time>

2.监控agent连接

连接到消息队列

    /* Connect to the message queue
     * Exit if it fails.
     */
    if ((logr.m_queue = StartMQ(DEFAULTQUEUE, WRITE, INFINITE_OPENQ_ATTEMPTS)) < 0) {
        merror_exit(QUEUE_FATAL, DEFAULTQUEUE);
    }

这个是通用消息队列,一般消息都走这个消息队列 

/* Default queue */
#define DEFAULTQUEUE    "queue/sockets/queue"

 监控连接状态函数

void monitor_agents_alert(){
    unsigned int inode_it = 0;
    OSHashNode *agent_hash_node = NULL;
    OSHashNode *agent_hash_next_node = NULL;

    cJSON *j_agent_info = NULL;
    cJSON *j_agent_status = NULL;
    cJSON *j_agent_lastkeepalive = NULL;
    cJSON *j_agent_name = NULL;
    cJSON *j_agent_ip = NULL;

    agent_hash_node = OSHash_Begin(agents_to_alert_hash, &inode_it);
    while (agent_hash_node) {
        agent_hash_next_node = OSHash_Next(agents_to_alert_hash, &inode_it, agent_hash_node);

        j_agent_info = wdb_get_agent_info(atoi(agent_hash_node->key), &sock);
        if (j_agent_info) {
            j_agent_status = cJSON_GetObjectItem(j_agent_info->child, "connection_status");
            j_agent_lastkeepalive = cJSON_GetObjectItem(j_agent_info->child, "last_keepalive");
            j_agent_name = cJSON_GetObjectItem(j_agent_info->child, "name");
            j_agent_ip = cJSON_GetObjectItem(j_agent_info->child, "register_ip");

            if (cJSON_IsString(j_agent_status) && j_agent_status->valuestring != NULL &&
                cJSON_IsString(j_agent_name) && j_agent_name->valuestring != NULL &&
                cJSON_IsString(j_agent_ip) && j_agent_ip->valuestring != NULL &&
                cJSON_IsNumber(j_agent_lastkeepalive)) {

                    if (strcmp(j_agent_status->valuestring, "active") == 0) {
                        /* The agent is now connected, removing from table */
                        OSHash_Delete(agents_to_alert_hash, agent_hash_node->key);
                    }

                    else if (j_agent_lastkeepalive->valueint < (time(0) -
                            (mond.global.agents_disconnection_time + mond.global.agents_disconnection_alert_time))) {
                        /* Generating the disconnection alert */
                        char *agent_name_ip = NULL;
                        os_strdup(j_agent_name->valuestring, agent_name_ip);
                        wm_strcat(&agent_name_ip, j_agent_ip->valuestring, '-');
                        monitor_send_disconnection_msg(agent_name_ip);
                        OSHash_Delete(agents_to_alert_hash, agent_hash_node->key);
                        os_free(agent_name_ip);
                    }
                }
        } else {
            mdebug1("Unable to retrieve agent's '%s' data from Wazuh DB", agent_hash_node->key);
            OSHash_Delete(agents_to_alert_hash, agent_hash_node->key);
        }
        cJSON_Delete(j_agent_info);
        agent_hash_node = agent_hash_next_node;
    }
}

掉线超时判断else if ( j_agent_lastkeepalive->valueint < (time(0) - (mond.global.agents_disconnection_time + mond.global.agents_disconnection_alert_time)) )

                    if (strcmp(j_agent_status->valuestring, "active") == 0) {
                        /* The agent is now connected, removing from table */
                        OSHash_Delete(agents_to_alert_hash, agent_hash_node->key);
                    }

                    else if (j_agent_lastkeepalive->valueint < (time(0) -
                            (mond.global.agents_disconnection_time + mond.global.agents_disconnection_alert_time))) {
                        /* Generating the disconnection alert */
                        char *agent_name_ip = NULL;
                        os_strdup(j_agent_name->valuestring, agent_name_ip);
                        wm_strcat(&agent_name_ip, j_agent_ip->valuestring, '-');
                        monitor_send_disconnection_msg(agent_name_ip);
                        OSHash_Delete(agents_to_alert_hash, agent_hash_node->key);
                        os_free(agent_name_ip);
                    }

 发送掉线消息


void monitor_send_disconnection_msg(char *agent) {
    char str[OS_SIZE_1024];
    int error;

    memset(str, '\0', OS_SIZE_1024);
    /* Send disconnected message */
    snprintf(str, OS_SIZE_1024, AG_DISCON_MSG, agent);
    if (error = mon_send_agent_msg(agent, str), error) {
        if (error == 2) {
            // Agent is no longer in the database
            monitor_send_deletion_msg(agent);
        } else {
            mdebug1("Could not generate disconnected agent alert for '%s'", agent);
        }
    }
}

如果 mon_send_agent_msg函数返回2,说明Wazuh DB中没有找到agent_id(具体是通过agent_name找agent_id)

int mon_send_agent_msg(char *agent, char *msg) {
    char header[OS_SIZE_256];
    char ag_name[OS_SIZE_128];
    int ag_id;
    char *ag_ip = NULL;
    char *found = agent;
    size_t name_size;

    while (found = strchr(found, '-'), found) {
        ag_ip = ++found;
    }

    if (!ag_ip) {
        return 1;
    }

    if (name_size = strlen(agent) - strlen(ag_ip), name_size > OS_SIZE_128) {
        return 1;
    }

    snprintf(ag_name, name_size, "%s", agent);

    if (ag_id = wdb_find_agent(ag_name, ag_ip, NULL), ag_id > 0) {

        snprintf(header, OS_SIZE_256, "[%03d] (%s) %s", ag_id, ag_name, ag_ip);
        if (SendMSG(mond.a_queue, msg, header, SECURE_MQ) < 0) {
            mond.a_queue = -1;  // set an invalid fd so we can attempt to reconnect later on.
            merror(QUEUE_SEND);
            return 1;
        }
        return 0;
    } else if (ag_id == -2) {
        return 2;
    }

    return 1;
}

 将消息通过消息队列发出去

SendMSG(mond.a_queue, msg, header, SECURE_MQ)
/* Send a message to the queue */
int SendMSG(int queue, const char *message, const char *locmsg, char loc)
{
    int __mq_rcode;
    char tmpstr[OS_MAXSTR + 1];
    static int reported = 0;

    tmpstr[OS_MAXSTR] = '\0';

    /* Check for global locks */
    os_wait();

    if (loc == SECURE_MQ) {
        loc = message[0];
        message++;

        if (message[0] != ':') {
            merror(FORMAT_ERROR);
            return (0);
        }
        message++; /* Pointing now to the location */

        if (strncmp(message, "keepalive", 9) == 0) {
            return (0);
        }

        snprintf(tmpstr, OS_MAXSTR, "%c:%s->%s", loc, locmsg, message);
    } else {
        snprintf(tmpstr, OS_MAXSTR, "%c:%s:%s", loc, locmsg, message);
    }

    /* Queue not available */
    if (queue < 0) {
        return (-1);
    }

    if ((__mq_rcode = OS_SendUnix(queue, tmpstr, 0)) < 0) {
        /* Error on the socket */
        if (__mq_rcode == OS_SOCKTERR) {
            merror("socketerr (not available).");
            close(queue);
            return (-1);
        }

        /* Unable to send. Socket busy */
        mdebug2("Socket busy, discarding message.");

        if (!reported) {
            reported = 1;
            mwarn("Socket busy, discarding message.");
        }
    }

    return (0);
}
/* Send a message using a Unix socket
 * Returns the OS_SOCKETERR if it fails
 */
int OS_SendUnix(int socket, const char *msg, int size)
{
    if (size == 0) {
        size = strlen(msg) + 1;
    }

    if (send(socket, msg, size, 0) < size) {
        if (errno == ENOBUFS) {
            return (OS_SOCKBUSY);
        }

        return (OS_SOCKTERR);
    }

    return (OS_SUCCESS);
}

 mond.a_queue 是socket对应的fd

通过SendMSG函数可知:

  • 如果消息中包含"keepalive"字符串,那么消息不会发送。
  • 消息发出去的结构是 SECURE_MQ:header:msg这三部以冒号分隔,然后通过OS_SendUnix发送到消息队列
  • mond.a_queue 指向的DEFAULTQUEUE

3.ossec-analysisd 进程接收

设置消息队列

        /* Set the queue */
        if ((m_queue = StartMQ(DEFAULTQUEUE, READ, 0)) < 0) {
            merror_exit(QUEUE_ERROR, DEFAULTQUEUE, strerror(errno));
        }

 接收处理消息队列中的消息

    /* Create message handler thread */

    w_create_thread(ad_input_main, &m_queue);

 消息接收函数

/* Receive a message from a Unix socket */
int OS_RecvUnix(int socket, int sizet, char *ret)
{
    struct sockaddr_un n_us;
    socklen_t us_l = sizeof(n_us);
    ssize_t recvd;
    ret[sizet] = '\0';

    if ((recvd = recvfrom(socket, ret, sizet - 1, 0,
                          (struct sockaddr *)&n_us, &us_l)) < 0) {
        return (0);
    }

    ret[recvd] = '\0';
    return ((int)recvd);
}

参考

global - Local configuration (ossec.conf) · Wazuh documentation

ossec-monitord - Daemons · Wazuh documentation

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

byte_knight

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值