Работа пульта
Система SORM-2 (Система оперативно-розыскных мероприятий) предназначена для захвата, сборки и анализа сетевого трафика по множеству протоколов. Состоит из двух основных компонентов: sorm2-backend (основной сервер) и sorm-2-reasm (сервис переборки пакетов).
Общая архитектура системы
Section titled “Общая архитектура системы”graph TB
subgraph Захват["Захват трафика"]
PCAP["PCAP-файлы\n(data/pcap/)"]
end
subgraph REASM["sorm-2-reasm (Микросервис переборки)"]
direction TB
PW["PreparingWorker\n(Валидация и маршрутизация)"]
subgraph ASM["Assembler Workers (tshark)"]
AH["HTTP"]
AF["FTP"]
AE["Email"]
AX["XMPP"]
AT["TCP"]
end
subgraph PROC["Processing Workers (Декодирование)"]
PH["HTTP"]
PF["FTP"]
PE["Email"]
PX["XMPP"]
PT["TCP"]
end
PW --> ASM
ASM --> PROC
end
subgraph MQ["Apache ActiveMQ"]
QIN["reasm-input"]
QPREP["reasm-prepared-*\n(5 очередей)"]
QASM["reasm-asm-*\n(5 очередей)"]
QOUT["reasm-output"]
QIN --> PW
PW --> QPREP
QPREP --> ASM
ASM --> QASM
QASM --> PROC
PROC --> QOUT
end
subgraph BACKEND["sorm2-backend (Spring Boot)"]
COL["S2SurveillanceCollector\n(Потребитель)"]
SVC["Сервисы протоколов\n(HTTP/FTP/Email/XMPP/TCP)"]
REST["REST API"]
COL --> SVC
SVC --> REST
end
subgraph DB["PostgreSQL"]
SURV["CDZ_SURVEILLANCE\n(Трафик)"]
MISS["CDZ_MISSION\n(Задания)"]
USR["CDZ_USER\n(Пользователи)"]
AUD["CDZ_AUDIT\n(Аудит)"]
end
PCAP --> REASM
QOUT --> COL
SVC --> DB
REST --> DB
Компоненты sorm-2-reasm
Section titled “Компоненты sorm-2-reasm”Общий конвейер обработки
Section titled “Общий конвейер обработки”Все протоколы проходят через три стадии:
stateDiagram-v2
[*] --> new : Входящее сообщение
new --> prepared : PreparingWorker\n(проверка PCAP, маршрутизация)
prepared --> assembled : AssemblerWorker\n(tshark → JSON)
assembled --> complete : ProcessingWorker\n(декодирование → Entity)
new --> error : PCAP не найден
prepared --> error : Ошибка сборки
assembled --> error : Ошибка декодирования
complete --> [*]
error --> [*] : reasm-output\n(с errorCause)
Очереди ActiveMQ
Section titled “Очереди ActiveMQ”| Очередь | Назначение |
|---|---|
reasm-input | Входящие задания на переборку |
reasm-prepared-http | HTTP-задания после валидации |
reasm-prepared-ftp | FTP-задания после валидации |
reasm-prepared-email | Email-задания после валидации |
reasm-prepared-xmpp | XMPP-задания после валидации |
reasm-prepared-tcp | TCP-задания после валидации |
reasm-asm-http | Собранные HTTP-данные (JSON) |
reasm-asm-ftp | Собранные FTP-данные (JSON) |
reasm-asm-email | Собранные Email-данные (JSON) |
reasm-asm-xmpp | Собранные XMPP-данные (JSON) |
reasm-asm-tcp | Собранные TCP-данные (JSON) |
reasm-output | Готовые ProcessingData с сущностями |
Потоки данных по протоколам
Section titled “Потоки данных по протоколам”HTTP-трафик
Section titled “HTTP-трафик”HTTP — наиболее простой протокол: каждый пакет содержит полный запрос или ответ, которые извлекаются напрямую через tshark.
sequenceDiagram
participant MQ as ActiveMQ
participant PW as PreparingWorker
participant AW as AssemblerHttpWorker
participant PH as ProcessingHttpWorker
participant FS as Файловая система
MQ->>PW: reasm-input {dataKind: "http", id, uci}
PW->>FS: Проверить data/uci/{uci}/{id}/data.pcap
PW->>MQ: reasm-prepared-http {state: "prepared"}
MQ->>AW: reasm-prepared-http
AW->>FS: tshark -r data.pcap -T jsonraw -j http
FS-->>AW: JSON-вывод пакетов
AW->>FS: Записать data/assembled/http/{id}.json
AW->>MQ: reasm-asm-http {state: "assembled"}
MQ->>PH: reasm-asm-http
PH->>FS: Прочитать data/assembled/http/{id}.json
loop Каждый пакет
PH->>PH: Декодировать hex → IP, порт, метод,\nURI, версия, заголовки, код ответа
PH->>PH: Создать HttpEntity
end
PH->>FS: Удалить data/assembled/http/{id}.json
PH->>MQ: reasm-output {httpEntities: [...], state: "complete"}Извлекаемые поля HttpEntity:
| Поле | Описание |
|---|---|
requestAction | HTTP-метод (GET, POST, PUT…) |
requestUri | URL запроса |
httpVersion | Версия протокола (HTTP/1.1) |
requestHost | Заголовок Host |
requestCookie | Cookie запроса |
requestReferer | Заголовок Referer |
responseCode | Код ответа (200, 404…) |
responseContentType | Content-Type ответа |
responseSetCookie | Set-Cookie из ответа |
responseData | Тело ответа |
sourceIp / destIp | IP-адреса источника и назначения |
sourcePort / destPort | Порты |
FTP-трафик
Section titled “FTP-трафик”FTP — сложнее HTTP: управляющий канал (команды) и канал данных (содержимое файлов) разделены. Сервис отслеживает команды USER, RETR/STOR и собирает байты файла из потоков ftp-data.
sequenceDiagram
participant MQ as ActiveMQ
participant PW as PreparingWorker
participant AW as AssemblerFtpWorker
participant PF as ProcessingFtpWorker
participant FS as Файловая система
MQ->>PW: reasm-input {dataKind: "ftp"}
PW->>MQ: reasm-prepared-ftp {state: "prepared"}
MQ->>AW: reasm-prepared-ftp
AW->>FS: tshark -r data.pcap -T jsonraw -j ftp ftp-data
AW->>FS: Записать data/assembled/ftp/{id}.json
AW->>MQ: reasm-asm-ftp {state: "assembled"}
MQ->>PF: reasm-asm-ftp
PF->>FS: Прочитать data/assembled/ftp/{id}.json
loop Каждый пакет
alt FTP-команда USER
PF->>PF: Сохранить имя пользователя
else FTP-команда RETR/STOR
PF->>PF: Сохранить имя файла,\nопределить тип (upload/download)
else ftp-data (payload)
PF->>PF: Накапливать hex-байты файла
else Код 226 или ABOR
PF->>PF: Завершить накопление файла
PF->>PF: Создать FtpEntity\n(username, filename, content[])
PF->>FS: Сохранить data/processed/ftp/{id}/{filename}
end
end
PF->>FS: Удалить data/assembled/ftp/{id}.json
PF->>MQ: reasm-output {ftpEntities: [...], state: "complete"}Извлекаемые поля FtpEntity:
| Поле | Описание |
|---|---|
username | FTP-пользователь |
filename | Имя передаваемого файла |
fileContent | Содержимое файла (byte[]) |
fileLength | Размер файла в байтах |
isUpload | true = загрузка (STOR), false = скачивание (RETR) |
duration | Длительность передачи |
sourceIp / destIp | IP-адреса |
sourcePort / destPort | Порты |
Email-трафик (SMTP / POP3 / IMAP / NNTP)
Section titled “Email-трафик (SMTP / POP3 / IMAP / NNTP)”Email — самый сложный протокол. Поддерживаются четыре подпротокола. MIME-сообщения разбираются рекурсивно, вложения сохраняются на диск.
sequenceDiagram
participant MQ as ActiveMQ
participant PW as PreparingWorker
participant AW as AssemblerEmailWorker
participant PE as ProcessingEmailWorker
participant FS as Файловая система
MQ->>PW: reasm-input {dataKind: "email"}
PW->>MQ: reasm-prepared-email {state: "prepared"}
MQ->>AW: reasm-prepared-email
AW->>FS: tshark -r data.pcap -2 -T jsonraw -j smpt pop imap nntp
Note over AW: Флаг -2 для двухпроходного анализа
AW->>FS: Записать data/assembled/email/{id}.json
AW->>MQ: reasm-asm-email {state: "assembled"}
MQ->>PE: reasm-asm-email
PE->>FS: Прочитать data/assembled/email/{id}.json
loop Каждый пакет
PE->>PE: Определить подпротокол\n(smtp/pop3/imap/nntp/rss)
PE->>PE: Собрать RAW-текст письма\nиз hex-данных
end
loop Каждое письмо
PE->>PE: Создать MimeMessage\n(Java Mail API)
PE->>PE: Извлечь заголовки\n(From, To, CC, Subject, Message-ID…)
alt Простой текст
PE->>PE: Записать content в EmailEntity
else Multipart (вложения)
loop Каждая часть MIME
PE->>PE: Обработать рекурсивно
PE->>FS: Сохранить вложение\ndata/email-attachments/{filename}
end
end
PE->>PE: Создать EmailEntity
end
PE->>FS: Удалить data/assembled/email/{id}.json
PE->>MQ: reasm-output {emailEntities: [...], state: "complete"}Поддерживаемые подпротоколы:
| Протокол | Порты | Назначение |
|---|---|---|
| SMTP | 25, 465, 587 | Отправка почты |
| POP3 | 110 | Получение почты |
| IMAP | 143 | Управление почтой на сервере |
| NNTP | 119 | Группы новостей (Usenet) |
| RSS | — | Подписки на ленты |
Извлекаемые поля EmailEntity:
| Поле | Описание |
|---|---|
from | Адрес отправителя |
to | Адреса получателей |
cc / bcc | Копия / скрытая копия |
subject | Тема письма |
messageId | Message-ID заголовок |
replyTo | Адрес для ответа |
contentType | MIME-тип содержимого |
content | Текст письма |
attachmentFilenames | Имена вложений |
newsgroup | Группа новостей (NNTP) |
organization | Организация (NNTP) |
protocol | smtp / pop3 / imap / nntp / rss |
XMPP-трафик
Section titled “XMPP-трафик”XMPP — XML-протокол для обмена сообщениями. tshark умеет парсить XML-строфы напрямую.
sequenceDiagram
participant MQ as ActiveMQ
participant PW as PreparingWorker
participant AW as AssemblerXmppWorker
participant PX as ProcessingXmppWorker
participant FS as Файловая система
MQ->>PW: reasm-input {dataKind: "xmpp"}
PW->>MQ: reasm-prepared-xmpp {state: "prepared"}
MQ->>AW: reasm-prepared-xmpp
AW->>FS: tshark -r data.pcap -T jsonraw -j xmpp
AW->>FS: Записать data/assembled/xmpp/{id}.json
AW->>MQ: reasm-asm-xmpp {state: "assembled"}
MQ->>PX: reasm-asm-xmpp
PX->>FS: Прочитать data/assembled/xmpp/{id}.json
loop Каждый XMPP-пакет
PX->>PX: Извлечь JID отправителя (from)\nи получателя (to)
PX->>PX: Извлечь тело сообщения (body)
alt Текстовое сообщение
PX->>PX: Создать XmppEntity\n(chatId, from, to, content)
else Передача файла (SI/IBB)
PX->>PX: Создать XmppEntity\n(filename, fileSize, mimeType)
end
end
PX->>FS: Удалить data/assembled/xmpp/{id}.json
PX->>MQ: reasm-output {xmppEntities: [...], state: "complete"}Извлекаемые поля XmppEntity:
| Поле | Описание |
|---|---|
chatId | Идентификатор чата |
from | JID отправителя (user@domain) |
to | JID получателя |
content | Текст сообщения |
user | Имя пользователя |
contact | Контакт |
filename | Имя файла (при передаче) |
fileSize | Размер файла |
mimeType | MIME-тип файла |
sourceIp / destIp | IP-адреса |
TCP-трафик (сырой)
Section titled “TCP-трафик (сырой)”TCP-обработчик не разбирает прикладной уровень, а агрегирует статистику потоков по обоим направлениям.
sequenceDiagram
participant MQ as ActiveMQ
participant PW as PreparingWorker
participant AW as AssemblerTcpWorker
participant PT as ProcessingTcpWorker
participant FS as Файловая система
MQ->>PW: reasm-input {dataKind: "tcp"}
PW->>MQ: reasm-prepared-tcp {state: "prepared"}
MQ->>AW: reasm-prepared-tcp
Note over AW: Используется -T json (не jsonraw)\nс явным указанием полей
AW->>FS: tshark -r data.pcap -T json\n -e ip.src -e ip.dst\n -e tcp.srcport -e tcp.dstport\n -e tcp.len -e frame.time_relative
AW->>FS: Записать data/assembled/tcp/{id}.json
AW->>MQ: reasm-asm-tcp {state: "assembled"}
MQ->>PT: reasm-asm-tcp
PT->>FS: Прочитать data/assembled/tcp/{id}.json
loop Каждый TCP-пакет
PT->>PT: Определить направление (A→B или B→A)
PT->>PT: Накопить: байты, кол-во пакетов,\nвремя первого/последнего пакета
end
PT->>PT: Вычислить: длительность соединения\n= lastTime - firstTime
PT->>PT: Создать TcpEntity\n(статистика A→B)\nСоздать TcpEntity\n(статистика B→A)
PT->>FS: Удалить data/assembled/tcp/{id}.json
PT->>MQ: reasm-output {tcpEntities: [...], state: "complete"}Извлекаемые поля TcpEntity:
| Поле | Описание |
|---|---|
bytesTransferred | Объём переданных данных (байт) |
packetsCount | Количество пакетов |
duration | Длительность соединения (мс) |
sourceIp / destIp | IP-адреса источника и назначения |
sourcePort / destPort | Порты |
Файловая система
Section titled “Файловая система”Directorydata
Directoryuci
Directory[uci]
Directory[id]
- data.pcap ← Входной PCAP-файл
- decrypted.pcap ← Расшифрованный (если isDecrypted=true)
Directoryassembled
- http/[id].json ← Временный (удаляется после обработки)
- ftp/[id].json
- email/[id].json
- xmpp/[id].json
- tcp/[id].json
Directoryprocessed
Directoryftp
Directory[taskId]
- [filename] ← Извлечённые FTP-файлы
Directoryemail-attachments
- [filename] ← Извлечённые вложения Email
Directorylogs/
- …
Модель данных ProcessingData
Section titled “Модель данных ProcessingData”Центральный объект, передаваемый между компонентами через ActiveMQ:
classDiagram
class ProcessingData {
+Long id
+Long missionId
+Short uci
+String nodeId
+String dataKind
+String state
+Boolean isDecrypted
+String errorCause
+List~HttpEntity~ httpEntities
+List~FtpEntity~ ftpEntities
+List~EmailEntity~ emailEntities
+List~XmppEntity~ xmppEntities
+List~TcpEntity~ tcpEntities
}
class HttpEntity {
+String requestAction
+String requestUri
+String httpVersion
+String requestHost
+String requestCookie
+Integer responseCode
+String responseContentType
+String responseData
+String sourceIp
+String destIp
}
class FtpEntity {
+String username
+String filename
+byte[] fileContent
+Long fileLength
+Boolean isUpload
+Long duration
+String sourceIp
+String destIp
}
class EmailEntity {
+String from
+String to
+String subject
+String messageId
+String content
+String contentType
+List~String~ attachmentFilenames
+String protocol
}
class XmppEntity {
+String chatId
+String from
+String to
+String content
+String filename
+Long fileSize
+String sourceIp
+String destIp
}
class TcpEntity {
+Long bytesTransferred
+Long packetsCount
+Long duration
+String sourceIp
+String destIp
+Integer sourcePort
+Integer destPort
}
ProcessingData "1" --> "*" HttpEntity
ProcessingData "1" --> "*" FtpEntity
ProcessingData "1" --> "*" EmailEntity
ProcessingData "1" --> "*" XmppEntity
ProcessingData "1" --> "*" TcpEntity
Архитектура sorm2-backend
Section titled “Архитектура sorm2-backend”Модель данных в PostgreSQL
Section titled “Модель данных в PostgreSQL”erDiagram
CDZ_USER {
bigint id PK
string username
string password
date accountStartedAt
date accountEndedAt
boolean passwordComplexitySign
}
CDZ_ORGANIZATION {
bigint id PK
string name
}
CDZ_FOLDER {
bigint id PK
string name
bigint parentId FK
}
CDZ_MISSION {
bigint id PK
string name
string identificationKind
date startedAt
date endedAt
bigint organizationId FK
bigint folderId FK
}
CDZ_SANCTION {
bigint id PK
bigint missionId FK
string userName FK
date sanctionStartedAt
date sanctionEndedAt
}
CDZ_SURVEILLANCE {
bigint id PK
bigint missionId FK
string trafficKind
timestamp capturedAt
string sourceIp
string destIp
integer sourcePort
integer destPort
string uci
boolean processedSign
}
CDZ_AUDIT {
bigint id PK
string entity
string action
boolean success
string username
timestamp requestTime
}
CDZ_USER }|--|| CDZ_ORGANIZATION : "belongs to"
CDZ_USER }|--|{ CDZ_FOLDER : "assigned (user_folders)"
CDZ_MISSION }|--|| CDZ_ORGANIZATION : "belongs to"
CDZ_MISSION }|--|| CDZ_FOLDER : "placed in"
CDZ_SANCTION }|--|| CDZ_MISSION : "authorizes"
CDZ_SANCTION }|--|| CDZ_USER : "assigned to"
CDZ_SURVEILLANCE }|--|| CDZ_MISSION : "captured for"
Роли пользователей
Section titled “Роли пользователей”| Роль | Описание |
|---|---|
ROLE_ADMIN | Полный доступ к системе |
ROLE_ADMIN_MISSION | Управление заданиями |
ROLE_ADMIN_OBR | Администратор организации |
ROLE_ADMIN_HARDWARE | Мониторинг оборудования |
ROLE_OBR | Оперативный офицер (доступ к данным) |
ROLE_SUPERVISOR | Руководитель (ограниченный доступ) |
Поддерживаемые протоколы в sorm2-backend
Section titled “Поддерживаемые протоколы в sorm2-backend”| Протокол | Порты по умолчанию | Обработчик |
|---|---|---|
| HTTP | 80, 9200 | HttpTraffic |
| HTTPS/SSL | 443, 631, 8443 | SslTraffic |
| FTP | 20, 21 | FtpTraffic |
| SMTP | 25, 465, 587 | EmailTraffic |
| POP3 | 110 | EmailTraffic |
| IMAP | 143 | EmailTraffic |
| NNTP | 119 | EmailTraffic |
| XMPP | 5222, 5223 | XmppTraffic |
| SIP | 5060, 2944, 2427, 4569, 2000 | SipTraffic |
| H.323 | 1720 | H323Traffic |
| RADIUS | 1812, 1813 | RadiusTraffic |
| Telnet | 23, 194, 6667 | TelnetTraffic |
| TCP (raw) | любые | TcpTraffic |
| WhatsApp/Telegram | — | WhatsappTelegramTraffic |
Конфигурация
Section titled “Конфигурация”Переменные окружения (sorm-2-reasm)
Section titled “Переменные окружения (sorm-2-reasm)”| Переменная | По умолчанию | Описание |
|---|---|---|
ACTIVEMQ_ADDR | tcp://127.0.0.1:61616 | Адрес брокера ActiveMQ |
Переменные окружения (sorm2-backend)
Section titled “Переменные окружения (sorm2-backend)”| Переменная | Описание |
|---|---|
BROKER_URL | URL брокера ActiveMQ |
SPRING_DATASOURCE_URL | JDBC URL PostgreSQL |
SPRING_DATASOURCE_USERNAME | Пользователь БД |
SPRING_DATASOURCE_PASSWORD | Пароль БД |
Технологический стек
Section titled “Технологический стек”| Компонент | Технология |
|---|---|
| sorm-2-reasm | Java 11, Apache ActiveMQ JMS, tshark (Wireshark CLI) |
| sorm2-backend | Java 11, Spring Boot 2.4.5, Spring Security |
| База данных | PostgreSQL 12 |
| ORM | Hibernate JPA 5 |
| Очередь сообщений | Apache ActiveMQ 5.15.9 |
| Захват пакетов | Pcap4j 1.8.2 |
| Планировщик | Quartz Scheduler |
| Мониторинг | Zabbix |
| Сериализация | Jackson 2.11 |
| Контейнеризация | Docker, docker-compose |