Задать вопрос
@Nikita1231

Как обнаружить сканирование портов по логу сетевого трафика?

Я студент, веду проект, идея которого в следующем: на c++ пишу маленький "сниффер", который следит за трафиком на своей машине, делает предварительный анализ и отдаёт отчёт серверу. Планируется поставить его на машины в аудиториях и отслеживать подозрительную активность с помощью сервера.

Немного подробностей (или воды):
Одной из предварительных проверок я решил сделать анализ на сканирование портов. Для этого я передаю лог, в котором записи имеют следующий вид:

#pragma once
#include <string>
struct PacketInfo {
    std::string srcIp;
    std::string dstIp;
    std::string protocol;
    int srcPort;
    int dstPort;
    int payloadLen;
    int count;

    bool operator==(const PacketInfo& other) const;

    bool operator!=(const PacketInfo& other) const;
};

bool PacketInfo::operator==(const PacketInfo& other) const {
    return srcIp == other.srcIp && dstIp == other.dstIp
        && srcPort == other.srcPort && dstPort == other.dstPort
        && protocol == other.protocol;
}

bool PacketInfo::operator!=(const PacketInfo& other) const {
    return !(*this == other);
}


Как понятно по коду, в логе 10 пакетов с одинаковыми сокетами и одинаковым направлением займут одну запись со счётчиком 10. (если были ответы - будут 2 записи со счётчиками 10).

исходя из этих данных я хочу отследить: были ли какие-то попытки просканировать порты. логично, что нужно смотреть многократные попытки по одним и тем же сокетам но с разными dstPort. Поэтмоу мой анализатор выглядит так (кстати, рекомендации по рефакторингу кода приветсвуются):

#pragma once
#include "IAnalyzer.hpp"
#include "PacketInfo.h"
#include <string>
#include <unordered_map>
#include <set>
#include <unordered_set>
#include <vector>

struct ScanResult {
    std::string srcIp;
    std::string dstIp;
    int uniqueDstPorts;
    bool suspicious;
};

class PortScanningAnalyzer : public IAnalyzer
{
public:
    nlohmann::json analyze(const std::vector<PacketInfo>& packets) override;

private:
    std::vector<ScanResult> detectPortScanning(const std::vector<PacketInfo>& packets, int threshold);
};

#include "PortScanningAnalyzer.h"
#include <nlohmann/json.hpp>

nlohmann::json PortScanningAnalyzer::analyze(const std::vector<PacketInfo>& packets) {
    nlohmann::json result;
    result["rule"] = "portScan";

    const int threshold = 100;

    std::vector<ScanResult> scanResults = detectPortScanning(packets, threshold);

    nlohmann::json counts = nlohmann::json::object();
    std::set<std::string> suspiciousIps;

    for (const auto& r : scanResults) {
        counts[r.srcIp] = counts.contains(r.srcIp) ? counts[r.srcIp].get<int>() + r.uniqueDstPorts : r.uniqueDstPorts;

        if (r.suspicious) {
            suspiciousIps.insert(r.srcIp);
        }
    }

    result["dst_ports_count"] = counts; // это чисто проверочная инфа, потом она будет удалена или изменена
    result["suspicious_ips"] = suspiciousIps;
    result["threshold"] = threshold;

    return result;
}


std::vector<ScanResult> PortScanningAnalyzer::detectPortScanning(const std::vector<PacketInfo>& packets, int threshold) {
    std::unordered_map<std::string, std::unordered_map<std::string, std::set<int>>> portsMap;

    for (const auto& p : packets) {
        if (p.protocol == "TCP" || p.protocol == "UDP") {
            portsMap[p.srcIp][p.dstIp].insert(p.dstPort);
        }
    }

    std::vector<ScanResult> results;

    for (const auto& [srcIp, dstMap] : portsMap) {
        for (const auto& [dstIp, portSet] : dstMap) {
            ScanResult r;
            r.srcIp = srcIp;
            r.dstIp = dstIp;
            r.uniqueDstPorts = static_cast<int>(portSet.size());
            r.suspicious = r.uniqueDstPorts > threshold;
            results.push_back(r);
        }
    }

    return results;
}


А теперь к проблеме.
А вот теперь к проблеме:
я несколько раз пробовал просканировать порты разными способами, в том числе прямо с той же машины, где была эта программа. Даже интереса ради пробовал сканировать из этой машины другую, что (по идее) тоже должно было обнаружиться. И да, так и было, но далеко не все попытки сканирования были замечены. (я пользовался какой-то прогой на телефоне рандомной, она комп просканировала, но моя программа этого не заметила и действительно все счётчики уникальных портов с каждого ip не превышали 4-10 запросов). А когда я пробовал просканить со своей машины порты на другом компе, то там вообще счётчик уникальных портов остановился на ~100 (якобы я отправил не 1000 запросов а 100)

Суть вопроса:
1. Есть ли замечания по нынешнему алгоритму?
2. Какие ещё признаки существуют? например, когда я скормил отчёт чату gpt вместе с логами он упомянул широковещательные пакеты, но так размыто, что я ничего не понял.

P.s.: Для понимания: я не безопасник и не сетевик, я учусь на программной инженерии, где и то и дургое рассматривается поверхностно, но кое-что по сетям понимаю (стараюсь). Поэтому просьба пояснить более-менее доступно, без излишних слэнговых извращений.
  • Вопрос задан
  • 146 просмотров
Подписаться 2 Средний 10 комментариев
Помогут разобраться в теме Все курсы
  • Яндекс Практикум
    Python-разработчик
    10 месяцев
    Далее
  • Skillfactory
    DevOps-инженер
    6 месяцев
    Далее
  • Нетология
    Python-разработчик с нуля
    6 месяцев
    Далее
Пригласить эксперта
Ответы на вопрос 1
GavriKos
@GavriKos
Микропетпроджект - домашнее облако homeCloud
Так и не понял как вы "сканировали порты". Если какой то тулзой - то вполне возможно что в ней уже встроена защита от программ, подобных вашей.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы