Voltar às atualizações
New releaseAug 28, 2026

maltrail v3.2

Sistema de detecção de tráfego malicioso em tempo real que utiliza listas negras públicas, rastros estáticos de malware e análise heurística para identificar ameaças no tráfego DNS, HTTP e IP.

Compartilhar

Maltrail

License Sensor Server Trails X

Maltrail

Maltrail é um sistema de detecção de tráfego de rede que identifica comunicação com infraestrutura maliciosa conhecida e reporta anomalias de tráfego selecionadas. Ele compara domínios, URLs, endereços IP, pares IP:port e valores de User-Agent observados na rede com um conjunto de indicadores chamados trails.

Uma detecção é registrada como um único evento contendo a origem, o destino, o protocolo, o trail correspondente, a classificação e a origem do trail:```text "2026-08-07 09:14:22.117034" gw 10.13.13.2 57809 1.1.1.1 53 UDP DNS malware.bakewithdavid.com "asyncrat (malware)" (static)

O Maltrail foi projetado para monitoramento de rede baseado em indicadores. Suas detecções heurísticas complementam
a correspondência de trails, mas não substituem a telemetria de endpoint ou um sistema de prevenção de intrusão
de uso geral.

## Recursos

- Uma construção completa de trails combinando mais de 3.000 arquivos estáticos incluídos, 42 integrações de feeds públicos,
  e trails opcionais fornecidos pelo operador.
- Um sensor Rust multithread usando libpcap, com workers de captura Linux `PACKET_FANOUT` opcionais.
- Um servidor Python fornecendo a interface de relatórios, ingestão de eventos e API HTTP.
- Trails personalizados em texto simples e whitelists que podem ser revisados e versionados.
- Heurísticas para varredura, esgotamento de DNS, consultas do tipo DGA, downloads suspeitos, sondagens de proxy,
  valores de User-Agent suspeitos e atividades de rede relacionadas.
- Registro de eventos local, registro remoto do Maltrail, CEF sobre syslog e saída Logstash JSON.
- Validação de implantação com `maltrail-sensor -T` e métricas Prometheus opcionais.

## Conteúdo

- [Arquitetura](#architecture)
- [Interface de relatórios](#reporting-interface)
- [Desempenho](#performance)
- [Instalação](#installation)
  - [Instalador](#installer)
  - [Compilação a partir do código-fonte](#building-from-source)
  - [Systemd](#systemd)
  - [Docker](#docker)
- [Configuração](#configuration)
- [Trails](#trails)
- [Eventos e API](#events-and-api)
- [Operações](#operations)
  - [Monitoramento](#monitoring)
  - [Retenção de eventos](#event-retention)
- [Documentação](#documentation)
- [Contribuindo](#contributing)
- [Projeto](#project)
  - [Licença](#license)
  - [Mantenedores](#maintainers)
  - [Patrocinadores](#sponsors)
  - [Apresentações e publicações](#presentations-and-publications)
  - [Blacklist derivada](#derived-blacklist)
  - [Integrações de terceiros](#third-party-integrations)
  - [Agradecimentos](#acknowledgements)

## Arquitetura

O Maltrail consiste em dois processos independentes que podem ser executados no mesmo host ou em hosts separados:```text
   ┌──────────┐   events (UDP or file)   ┌──────────┐
   │  sensor  │ ───────────────────────► │  server  │ ◄── browser
   └──────────┘                          └──────────┘
    Rust                                  Python
    libpcap + PACKET_FANOUT               reporting UI + API
    trail matching + heuristics

O sensor captura tráfego, realiza correspondência de trilhas e análise heurística, e produz eventos. Ele pode gravar eventos localmente (LOG_DIR), enviá-los a um servidor Maltrail remoto (LOG_SERVER), ou ambos. Também pode emitir CEF via syslog (SYSLOG_SERVER) e JSON para o Logstash (LOGSTASH_SERVER).

O servidor recebe e armazena eventos remotos, serve logs de eventos disponíveis localmente e fornece a interface web e a API.

Interface de relatórios

O Maltrail inclui uma interface de relatórios baseada em navegador para explorar o tráfego detectado, com atualizações ao vivo, busca por campo, caça retroativa, visualizações geográficas, triagem, visualizações salvas e exportação.

Interface de relatórios do Maltrail

A interface é servida por server.py em HTTP_ADDRESS:HTTP_PORT. É JavaScript puro com uma única dependência de runtime de terceiros (PapaParse, para análise de CSV) e sem etapa de build. Um dia é visualizado por vez, selecionado com um seletor de data que também funciona como uma grade de densidade de eventos sobre os logs diários disponíveis. Os eventos são transmitidos de /events e agregados no navegador em ameaças — uma linha por (source, trail) distinto — exibidas em uma grade classificável com um painel de detalhes.

RecursoNotas
Modo ao vivoEventos anexados são enviados via Server-Sent Events (/live) e mesclados na visualização atual. Recorre à sondagem de intervalos de bytes do log diário quando o SSE não está disponível, ou para sessões que o stream não consegue atender. Novas ameaças de alta severidade podem acionar uma notificação de desktop e um alerta sonoro; ambos podem ser silenciados
BuscaTokens com escopo de campo (src: dst: port: proto: type: trail: info: family: tag: uid: sev: dir: status:; family:interlock inclui interlock-1/-2, os fragmentos em que um dump de feed chega dividido) combinados com espaço como AND, - para excluir, curingas *, CIDR (src:10.0.0.0/8), e intervalos numéricos e comparações (port:>1024, count:>=100). Filtros ativos aparecem como chips removíveis
Caça retroativaPesquisa em todos os logs diários retidos por um indicador (/hunt), não apenas no dia em visualização. Limitada por um limite de dias, um orçamento de tempo real e um limite de amostras; um dia que o orçamento interrompeu é relatado separadamente dos dias concluídos em vez de contado como um total finalizado. Um índice sidecar por dia (LOG_DIR/index/, USE_EVENT_INDEX) permite que a varredura pule todas as linhas não correspondentes e torna /counts exato
Mapa mundialDensidade de eventos por país para o dia selecionado (/geo), posicionando o endpoint externo de cada evento. Eventos que não podem ser atribuídos a um endereço externo são relatados como não mapeados em vez de adivinhados. Defina HOME_LAT / HOME_LON para desenhar arcos de origem
TriagemStatus por ameaça (nova / em investigação / resolvida / falso positivo), notas de texto livre, tags e ocultação. Regras de whitelist e pivôs de OSINT estão disponíveis no menu de contexto da linha
Visualizações salvasPresets de filtro nomeados
ExportaçãoA visualização filtrada atual como CSV, JSON ou indicadores defanged
AparênciaTemas escuro e claro, e etapas discretas de tamanho de texto

O estado de triagem, visualizações salvas, tags e configurações de aparência são armazenados no navegador (localStorage), não no servidor: são por navegador e por origem, e não são compartilhados entre analistas.

Sessões restritas com um filtro de rede veem apenas eventos de suas próprias redes, e essa restrição se aplica às contagens, ao mapa e aos endpoints de blacklist, bem como à lista de eventos.

O enriquecimento de país e ASN para endereços individuais é consultado em stat.ripe.net pelo servidor, que armazena os resultados em cache e os serve à interface a partir de seu próprio endpoint /ripe; o navegador não se comunica com nada além do Maltrail. Defina DISABLE_RIPE_LOOKUPS para desativar completamente as consultas de saída. Sem elas — ou em um host sem acesso à internet — as bandeiras vêm da tabela RIR local e todo o resto na interface funciona offline.

Desempenho

O desempenho depende do processador, da composição do tráfego, do tamanho do conjunto de trilhas, do driver de captura e da interface de rede. Os números abaixo medem o caminho de processamento de pacotes do sensor isoladamente; não são medições de captura ao vivo de ponta a ponta.

Medições representativas em um AMD Ryzen 7 PRO 4750U com heurísticas habilitadas e um conjunto de trilhas de 1,5 milhão de linhas:

TráfegoTempo por pacote
ICMP echo, 58 bytes101 ns
TCP SYN, 70 bytes302 ns
TLS em massa, 1.473 bytes402 ns
Consulta DNS com cache quente, 93 bytes452 ns
Tráfego misto, média de 866 bytes552 ns
Requisição HTTP, 169 bytes602 ns
Consulta DNS com nome único, 93 bytes1.102 ns

Execuções de comparação offline usando a mesma captura gerada, configuração e conjunto de trilhas mediram um custo por pacote em estado estacionário de 14–37× menor do que o sensor Python aposentado nos sistemas testados. Esses números separam o tempo de processo inteiro do estado estacionário, porque o carregamento de trilhas domina uma reprodução curta. A detecção em si é verificada separadamente, pelo corpus de 42 casos em sensor/tests/replay.rs.

Meça no sistema de destino com:```bash cargo bench --manifest-path sensor/Cargo.toml --bench hotpath

Um worker de captura é usado por padrão. Workers adicionais podem aumentar a capacidade de captura, mas o hashing de fluxo do Linux divide o estado por origem entre os workers e, portanto, reduz a sensibilidade de algumas heurísticas de varredura. No teste documentado, 91% dos alertas heurísticos com um único worker permaneceram com dois workers, 86% com quatro e 65% com oito. A correspondência exata de trilhas permaneceu inalterada. Aumente `CAPTURE_FANOUT` apenas quando as métricas de perda de captura mostrarem que é necessário.

A metodologia de benchmark, os resultados de hardware, a saída do profiler, as medições de memória e as verificações de fanout em tempo real estão documentados em [`sensor/docs/REPORT.md`](https://github.com/stamparm/maltrail/blob/master/sensor/docs/REPORT.md).

## Instalação

### Instalador

O instalador é verificado em doze distribuições Linux — Debian, Ubuntu, Fedora, Rocky, AlmaLinux, Arch, openSUSE Leap e Tumbleweed, e Alpine — além de FreeBSD e macOS, em cada versão, com o resultado completo registrado em [`docs/compat`](https://github.com/stamparm/maltrail/blob/master/docs/compat). O Raspberry Pi OS e outros sistemas ARM de 64 bits usam a compilação `aarch64`; o ARM de 32 bits não possui sensor pré-compilado e deve compilá-lo a partir do código-fonte.```bash
curl -fsSL https://raw.githubusercontent.com/stamparm/maltrail/master/install.sh | sudo sh

Ele instala dependências, cria um checkout gerenciado em /opt/maltrail, verifica o checksum do sensor pré-compilado, cria uma conta maltrail sem privilégios, instala unidades systemd, prepara os diretórios de log e de estado, e inicia o sensor e o servidor. Reexecutar o instalador atualiza o checkout gerenciado.

Revise o script antes de executá-lo com privilégios elevados. A partir de um checkout existente, a execução de teste (dry run) mostra os comandos sem alterar o sistema:```bash sh install.sh --dry-run

Opções comuns do instalador:```bash
sh install.sh --role sensor      # Install only the sensor
sh install.sh --ref 3.1.2        # Install a release tag instead of master
sh install.sh --no-service       # Install without changing systemd
sh install.sh --dry-run          # Print commands without applying them
sh install.sh --uninstall        # Remove the managed installation; keep logs and state

O dashboard está disponível em http://127.0.0.1:8338 após a instalação. Note que o HTTP_ADDRESS fornecido é 0.0.0.0, portanto é acessível em todas as interfaces, não apenas no loopback — e as credenciais padrão são admin / changeme!. Altere USERS e defina HTTP_ADDRESS como 127.0.0.1 (ou coloque o servidor atrás de um proxy reverso com TLS), antes que o host esteja numa rede não confiável.

A construção inicial do trail pode demorar vários minutos. O sensor não deteta correspondências de trail até que um conjunto de trails válido esteja disponível. A unit systemd executa a validação -T do sensor antes do arranque para que privilégios em falta, um diretório de logs sem permissão de escrita ou um conjunto de trails inválido façam o arranque falhar de forma visível.

O harness de teste do instalador cobre doze distribuições, e "instalou" não é a asserção: em cada uma, o servidor é iniciado e é-lhe pedido /ping, é pedido ao sensor que se valide com -T, as units são verificadas quanto a caminhos que resolvem, o instalador é executado novamente para provar que uma atualização mantém a configuração do operador, e --uninstall é executado. Cada resultado é registado por plataforma em docs/compat, e a página lá é gerada a partir dessas linhas em vez de escrita à mão.

Alpine e outros sistemas musl recebem uma build do sensor -musl. Costumavam ser informados de que o binário pré-compilado era ligado a glibc e que deviam compilar o seu próprio; o sensor compila e corre nativamente em musl, portanto isso era um artefacto em falta em vez de um limite da plataforma.

Compilar a partir do código-fonte

O sensor requer Rust 1.74 ou mais recente, cabeçalhos de desenvolvimento do libpcap e as ferramentas de capacidades do sistema. O servidor e o atualizador de trails requerem Python 3.6 ou mais recente.

Instale os pacotes da distribuição:```bash

Debian / Ubuntu / Raspberry Pi OS

sudo apt-get install cargo libpcap-dev libcap2-bin python3

RHEL / Fedora

sudo dnf install cargo libpcap-devel libcap python3

openSUSE / SLES

sudo zypper install cargo rust libpcap-devel libcap-progs python311

Em seguida, compile e valide o sensor:```bash
git clone --depth 1 https://github.com/stamparm/maltrail.git
cd maltrail

cargo build --release --manifest-path sensor/Cargo.toml

sudo setcap cap_net_raw,cap_net_admin=eip \
  sensor/target/release/maltrail-sensor

sudo install -d -o "$USER" -g "$(id -gn)" -m 750 /var/log/maltrail

sensor/target/release/maltrail-sensor -T
sensor/target/release/maltrail-sensor

Inicie o servidor em outro terminal ou em outro host:```bash python3 server.py

Binários pré-compilados do sensor estão anexados às versões atuais com checksums SHA-256: Linux `x86_64`
e `aarch64` para glibc e musl, macOS em Apple silicon e Intel, FreeBSD `amd64`, e
Windows `x86_64`.

As compilações glibc ligam a libpcap estaticamente e têm como alvo glibc 2.28, pelo que a biblioteca C é a única coisa
de que precisam — nada para instalar, tanto em RHEL 8+, Debian 10+, Ubuntu 18.04+ como em Leap 15.x. As compilações musl
são totalmente estáticas, pelo que o Alpine não precisa de nada. A compilação Windows é de 64 bits e requer Windows 10 ou posterior mais
[Npcap](https://npcap.com) instalado antes de arrancar — `wpcap.dll` é uma dependência de tempo de carregamento,
pelo que sem ela o loader recusa o executável em vez de falhar na captura. O arquivo diz isso
também.

Binários de **3.1.1 e anteriores** não o faziam: ligavam a libpcap dinamicamente, e pediam-na pelo
nome que o seu host de compilação AlmaLinux usa. Debian e Ubuntu fornecem a biblioteca idêntica sob o
nome mais antigo `libpcap.so.0.8`, pelo que esses binários param antes de arrancar —```
./maltrail-sensor: error while loading shared libraries: libpcap.so.1: cannot open shared object file

— em uma máquina que tenha libpcap instalado. O install.sh cria o link do nome ausente para você. Manualmente:```bash

adjust the directory for your architecture: aarch64-linux-gnu, or /usr/lib64 on RPM distributions

sudo ln -sf /usr/lib/x86_64-linux-gnu/libpcap.so.0.8 /usr/lib/x86_64-linux-gnu/libpcap.so.1 sudo ldconfig

### Systemd

As unidades fornecidas em `packaging/systemd/` executam ambos os processos como o
usuário sem privilégios `maltrail`. O Systemd cria `/var/log/maltrail` e `/var/lib/maltrail`, restringe
o acesso ao sistema de arquivos e concede ao sensor `CAP_NET_RAW` e `CAP_NET_ADMIN`.

O instalador configura essas unidades automaticamente. Para uma instalação a partir do código-fonte existente, siga
o procedimento manual de serviço em [`sensor/docs/INSTALL.md`](https://github.com/stamparm/maltrail/blob/master/sensor/docs/INSTALL.md).

Verifique o estado do serviço e os logs com:```bash
systemctl status maltrail-sensor maltrail-server
journalctl -u maltrail-sensor -f

Docker

Inicie a implantação do Compose fornecida com:```bash docker compose -f docker/docker-compose.yml up -d

A configuração do contêiner, o armazenamento, os privilégios e as verificações de integridade estão documentados em
[`docker/README.md`](https://github.com/stamparm/maltrail/blob/master/docker/README.md).

## Configuração

O Maltrail lê o `maltrail.conf`, que contém configurações separadas de `[Sensor]` e `[Server]`. O
instalador coloca a configuração gerenciada em `/etc/maltrail.conf`.

As opções de sensor usadas com frequência incluem:

| Opção | Finalidade |
| --- | --- |
| `MONITOR_INTERFACE` | Interface ou interfaces de captura; `any` seleciona todas as interfaces suportadas |
| `CAPTURE_FILTER` | Filtro de captura BPF |
| `CAPTURE_FANOUT` | Número de sockets de captura do Linux; o padrão é um |
| `CAPTURE_WORKERS` | Workers de captura, um socket cada; o padrão é `CAPTURE_FANOUT`, portanto um, a menos que um deles seja definido |
| `LOG_DIR` | Diretório local de log de eventos |
| `TRAILS_FILE` | Banco de dados de trails gerado |
| `LOG_SERVER` | Servidor remoto de eventos do Maltrail |
| `SYSLOG_SERVER` | Destino ou destinos de syslog CEF |
| `LOGSTASH_SERVER` | Destino ou destinos de JSON do Logstash |
| `STATS_ADDRESS` | Listener de métricas do Prometheus; desabilitado a menos que configurado |
| `UPDATE_PERIOD` | Intervalo de atualização dos trails |
| `STATIC_TRAILS_URL` | De onde o conjunto estático de trails montado é obtido; fixe-o em uma versão datada para controlar quando novo conteúdo chega |
| `USER_WHITELIST` | Indicadores gerenciados pelo operador que não devem gerar alertas |
| `CUSTOM_TRAILS_DIR` | Diretório de trails gerenciado pelo operador |
| `STATIC_TRAILS_DIR` | Checkout opcional do repositório de trails; usado apenas para mostrar a citação da fonte de um trail na UI |

`PROCESS_COUNT` aplica-se ao sensor Python descontinuado e ao throttle legado de log de eventos; ele
**não** define a contagem de workers do sensor Rust. Configure os workers de captura com `CAPTURE_FANOUT` ou
`CAPTURE_WORKERS`.

Execute a verificação de implantação após alterar a configuração:```bash
sensor/target/release/maltrail-sensor -T

A verificação valida a configuração, os trails, as entradas da whitelist, o filtro de captura, os privilégios, o armazenamento de logs, o suporte a atualizações e as configurações do worker. Uma verificação bem-sucedida inclui contagens positivas de trails e whitelist, em vez de apenas confirmar que os arquivos existem.

Trails

Um trail é um indicador — um domínio, URL, endereço IP, par IP:port, User-Agent, impressão digital JA3/JA4 ou hash de certificado — juntamente com o que significa e de onde veio. O atualizador combina quatro fontes em TRAILS_FILE, nesta ordem:

fontede onde vem
Feedsfeeds/*.py, obtidos diretamente pela sua implantação de cada publicador
CustomCUSTOM_TRAILS_DIR e CUSTOM_TRAILS_URL, seus próprios indicadores
Statico conjunto montado a partir de stamparm/trails, obtido de STATIC_TRAILS_URL; licenciado separadamente
Engine listsdata/mass_scanner*.txt, incluídos aqui porque mudam raramente

Os trails estáticos residem em seu próprio repositório. O conteúdo de detecção muda dezenas de vezes por dia; o motor não, e mantê-los juntos significava que atualizar a detecção exigia baixar código e tornava o histórico deste repositório inutilizável. STATIC_TRAILS_URL aponta para o conjunto publicado mais recente:```text STATIC_TRAILS_URL https://github.com/stamparm/trails/releases/latest/download/trails.csv.gz

Aponte-o para uma versão específica `content-YYYYMMDD-HHMM` em vez disso, para fixar uma versão, de modo que uma publicação defeituosa não se torne imediatamente global. O conjunto é armazenado em cache ao lado de `TRAILS_FILE`, o que é o que faz funcionar uma reconstrução offline ou em rede isolada; o `sha256` publicado é verificado antes do download, pelo que uma implantação que atualiza com mais frequência do que o conteúdo muda transfere 65 bytes em vez de 11 MB, e um payload que não corresponde ao seu digest é recusado em favor da cache.

`update_trails()` publica um novo `TRAILS_FILE` atomicamente e apenas após uma compilação bem-sucedida. Os feeds que não retornam nada são reportados por nome, para que uma implantação não dependa silenciosamente de uma fonte que se retirou discretamente.

Adicione os seus próprios indicadores em `CUSTOM_TRAILS_DIR`, e qualquer coisa que nunca deva gerar um evento em `USER_WHITELIST`. Mantenha ambos fora do diretório de instalação para que uma atualização não os possa substituir.

As contribuições de trails estáticos vão para [stamparm/trails](https://github.com/stamparm/trails); os novos feeds vão aqui. De qualquer forma, um indicador precisa de uma classificação e de uma fonte que alguém possa verificar — consulte [Contributing](#contributing).

## Events and API

O Maltrail registra um evento separado por espaços em branco por detecção, usando aspas CSV quando um valor contém espaços:```text
"<time>" <sensor> <src_ip> <src_port> <dst_ip> <dst_port> <proto> <type> <trail> "<info>" <reference>

O campo type identifica o que correspondeu, incluindo DNS, IP, IPORT, URL, PATH, HTTP, UA, PORT, CERT, JA3 e JA4. O campo info contém a classificação do rasto, e reference identifica a lista estática, feed, fonte personalizada ou heurística que o produziu. Os tipos JA3/JA4 disparam em impressões digitais de cliente TLS: a stack TLS de um implante sobrevive a cada rotação de endereço e domínio, pelo que o seu hash de hello continua a corresponder depois de tudo o resto ter sido queimado (publicado pelo feed SSLBL JA3 da abuse.ch).

Consulta de indicadores

Use /check para consultar um domínio, endereço IP ou URL:```bash curl 'http://127.0.0.1:8338/check?q=www.sub.evil.example'

## 🎯 Objetivos de Aprendizagem

Ao final deste módulo, você será capaz de:

- ✅ Compreender a arquitetura do sistema de plugins do Artemis
- ✅ Criar plugins personalizados para necessidades específicas de segurança
- ✅ Implementar verificações de segurança personalizadas
- ✅ Integrar APIs e serviços externos
- ✅ Testar e depurar plugins de forma eficaz
- ✅ Empacotar e distribuir plugins

## 📋 Pré-requisitos

Antes de começar, certifique-se de ter:

- **Java 17+** instalado
- **Maven 3.8+** para gerenciamento de dependências
- **Conhecimento básico de Java** (interfaces, anotações, genéricos)
- **Familiaridade com conceitos de segurança** (XSS, SQLi, SSRF, etc.)
- **IDE** (IntelliJ IDEA, Eclipse ou VS Code)
- **Artemis** instalado e funcionando

## 🏗️ Arquitetura de Plugins

### Visão Geral do Sistema de Plugins

O Artemis utiliza um sistema de plugins baseado em **Java SPI (Service Provider Interface)** que permite estender funcionalidades sem modificar o núcleo da aplicação.

┌─────────────────────────────────────────────────────────┐ │ Artemis Core │ │ ┌───────────────────────────────────────────────────┐ │ │ │ Plugin Manager │ │ │ │ - Descoberta de Plugins │ │ │ │ - Ciclo de Vida │ │ │ │ - Isolamento │ │ │ └───────────────────────────────────────────────────┘ │ │ │ │ │ ┌────────────────┼────────────────┐ │ │ ▼ ▼ ▼ │ │ ┌────────────┐ ┌────────────┐ ┌────────────┐ │ │ │ Plugin A │ │ Plugin B │ │ Plugin C │ │ │ │ (Scanner) │ │ (Reporter)│ │ (Notifier)│ │ │ └────────────┘ └────────────┘ └────────────┘ │ └─────────────────────────────────────────────────────────┘


### Tipos de Plugins

| Tipo | Descrição | Caso de Uso |
|------|-----------|-------------|
| **Scanner** | Analisa alvos em busca de vulnerabilidades | Detecção de XSS, SQLi, SSRF |
| **Reporter** | Gera relatórios em diferentes formatos | PDF, JSON, HTML, SARIF |
| **Notifier** | Envia notificações sobre descobertas | Slack, Discord, Email |
| **Analyzer** | Analisa e correlaciona resultados | Detecção de falsos positivos |
| **Integration** | Integra com ferramentas externas | Jira, GitHub, DefectDojo |

### Ciclo de Vida do Plugin

```java
public interface ArtemisPlugin {
    // Chamado quando o plugin é carregado
    void initialize(PluginContext context) throws PluginException;
    
    // Chamado quando o plugin é iniciado
    void start() throws PluginException;
    
    // Chamado quando o plugin é parado
    void stop() throws PluginException;
    
    // Chamado quando o plugin é descarregado
    void destroy() throws PluginException;
    
    // Retorna metadados do plugin
    PluginMetadata getMetadata();
}

🚀 Criando Seu Primeiro Plugin

Passo 1: Configuração do Projeto

Crie um novo projeto Maven com a seguinte estrutura:

my-artemis-plugin/
├── pom.xml
├── src/
│   └── main/
│       ├── java/
│       │   └── com/
│       │       └── example/
│       │           └── plugin/
│       │               ├── MyScannerPlugin.java
│       │               └── MyPluginMetadata.java
│       └── resources/
│           └── META-INF/
│               └── services/
│                   └── com.example.artemis.plugin.ArtemisPlugin

Passo 2: Configuração do pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
         http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    
    <groupId>com.example</groupId>
    <artifactId>my-artemis-plugin</artifactId>
    <version>1.0.0</version>
    <packaging>jar</packaging>
    
    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <artemis.version>1.0.0</artemis.version>
    </properties>
    
    <dependencies>
        <!-- Artemis Plugin API -->
        <dependency>
            <groupId>com.artemis</groupId>
            <artifactId>artemis-plugin-api</artifactId>
            <version>${artemis.version}</version>
            <scope>provided</scope>
        </dependency>
        
        <!-- Dependências adicionais -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>2.0.9</version>
        </dependency>
    </dependencies>
    
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.11.0</version>
            </plugin>
            
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>3.5.0</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

Passo 3: Implementando o Plugin

package com.example.plugin;

import com.artemis.plugin.ArtemisPlugin;
import com.artemis.plugin.PluginContext;
import com.artemis.plugin.PluginException;
import com.artemis.plugin.PluginMetadata;
import com.artemis.scanner.ScannerPlugin;
import com.artemis.scanner.ScanResult;
import com.artemis.scanner.ScanTarget;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.concurrent.CompletableFuture;

/**
 * Plugin de scanner personalizado para Artemis.
 * 
 * Este plugin demonstra como criar um scanner personalizado
 * que pode ser integrado ao pipeline de segurança do Artemis.
 */
public class MyScannerPlugin implements ArtemisPlugin, ScannerPlugin {
    
    private static final Logger logger = LoggerFactory.getLogger(MyScannerPlugin.class);
    
    private PluginContext context;
    private boolean running = false;
    
    @Override
    public void initialize(PluginContext context) throws PluginException {
        logger.info("Inicializando MyScannerPlugin...");
        this.context = context;
        
        // Validar configuração
        if (context.getConfiguration() == null) {
            throw new PluginException("Configuração do plugin não encontrada");
        }
        
        logger.info("MyScannerPlugin inicializado com sucesso");
    }
    
    @Override
    public void start() throws PluginException {
        logger.info("Iniciando MyScannerPlugin...");
        this.running = true;
        logger.info("MyScannerPlugin iniciado");
    }
    
    @Override
    public void stop() throws PluginException {
        logger.info("Parando MyScannerPlugin...");
        this.running = false;
        logger.info("MyScannerPlugin parado");
    }
    
    @Override
    public void destroy() throws PluginException {
        logger.info("Destruindo MyScannerPlugin...");
        this.context = null;
        logger.info("MyScannerPlugin destruído");
    }
    
    @Override
    public PluginMetadata getMetadata() {
        return new MyPluginMetadata();
    }
    
    @Override
    public CompletableFuture<List<ScanResult>> scan(ScanTarget target) {
        return CompletableFuture.supplyAsync(() -> {
            logger.info("Escaneando alvo: {}", target.getUrl());
            
            List<ScanResult> results = new java.util.ArrayList<>();
            
            try {
                // Implementar lógica de scan personalizada aqui
                // Este é um exemplo simplificado
                
                // Verificar headers de segurança
                checkSecurityHeaders(target, results);
                
                // Verificar configurações de CORS
                checkCorsConfiguration(target, results);
                
                // Verificar exposição de informações
                checkInformationDisclosure(target, results);
                
            } catch (Exception e) {
                logger.error("Erro durante o scan: {}", e.getMessage(), e);
            }
            
            return results;
        });
    }
    
    private void checkSecurityHeaders(ScanTarget target, List<ScanResult> results) {
        // Implementação da verificação de headers
        logger.debug("Verificando headers de segurança para: {}", target.getUrl());
        // Lógica de verificação aqui
    }
    
    private void checkCorsConfiguration(ScanTarget target, List<ScanResult> results) {
        // Implementação da verificação de CORS
        logger.debug("Verificando configuração CORS para: {}", target.getUrl());
        // Lógica de verificação aqui
    }
    
    private void checkInformationDisclosure(ScanTarget target, List<ScanResult> results) {
        // Implementação da verificação de exposição de informações
        logger.debug("Verificando exposição de informações para: {}", target.getUrl());
        // Lógica de verificação aqui
    }
}

Passo 4: Implementando os Metadados do Plugin

package com.example.plugin;

import com.artemis.plugin.PluginMetadata;

import java.util.List;
import java.util.Map;

/**
 * Metadados do MyScannerPlugin.
 */
public class MyPluginMetadata implements PluginMetadata {
    
    @Override
    public String getId() {
        return "my-scanner-plugin";
    }
    
    @Override
    public String getName() {
        return "My Custom Scanner Plugin";
    }
    
    @Override
    public String getVersion() {
        return "1.0.0";
    }
    
    @Override
    public String getDescription() {
        return "Plugin de scanner personalizado para verificações de segurança";
    }
    
    @Override
    public String getAuthor() {
        return "Seu Nome";
    }
    
    @Override
    public String getLicense() {
        return "MIT";
    }
    
    @Override
    public List<String> getDependencies() {
        return List.of();
    }
    
    @Override
    public Map<String, Object> getConfigurationSchema() {
        return Map.of(
            "timeout", Map.of(
                "type", "integer",
                "default", 30,
                "description", "Timeout em segundos para operações de scan"
            ),
            "maxDepth", Map.of(
                "type", "integer",
                "default", 3,
                "description", "Profundidade máxima de crawling"
            ),
            "enabledChecks", Map.of(
                "type", "array",
                "default", List.of("headers", "cors", "info-disclosure"),
                "description", "Verificações habilitadas"
            )
        );
    }
}

Passo 5: Registrando o Plugin

Crie o arquivo src/main/resources/META-INF/services/com.example.artemis.plugin.ArtemisPlugin:

com.example.plugin.MyScannerPlugin

Passo 6: Compilando e Empacotando

# Compilar o plugin
mvn clean package

# O JAR será criado em target/my-artemis-plugin-1.0.0.jar

Passo 7: Instalando o Plugin

# Copiar o plugin para o diretório de plugins do Artemis
cp target/my-artemis-plugin-1.0.0.jar /path/to/artemis/plugins/

# Ou usar o comando de instalação do Artemis
artemis plugin install target/my-artemis-plugin-1.0.0.jar

# Verificar se o plugin foi carregado
artemis plugin list

🔧 Tópicos Avançados

Configuração do Plugin

public class ConfigurablePlugin implements ArtemisPlugin {
    
    private PluginConfiguration config;
    
    @Override
    public void initialize(PluginContext context) throws PluginException {
        this.config = context.getConfiguration();
        
        // Acessar configurações
        int timeout = config.getInt("timeout", 30);
        String apiKey = config.getString("apiKey", "");
        List<String> targets = config.getStringList("targets");
        
        // Validar configurações obrigatórias
        if (apiKey.isEmpty()) {
            throw new PluginException("apiKey é obrigatória");
        }
    }
}

Tratamento de Eventos

public class EventAwarePlugin implements ArtemisPlugin, EventListener {
    
    @Override
    public void onEvent(PluginEvent event) {
        switch (event.getType()) {
            case SCAN_STARTED:
                logger.info("Scan iniciado: {}", event.getData());
                break;
            case SCAN_COMPLETED:
                logger.info("Scan concluído: {}", event.getData());
                break;
            case VULNERABILITY_FOUND:
                handleVulnerability(event.getData());
                break;
            default:
                logger.debug("Evento não tratado: {}", event.getType());
        }
    }
    
    private void handleVulnerability(Map<String, Object> data) {
        // Processar vulnerabilidade encontrada
    }
}

Integração com APIs Externas

public class ApiIntegrationPlugin implements ArtemisPlugin {
    
    private final HttpClient httpClient;
    
    public ApiIntegrationPlugin() {
        this.httpClient = HttpClient.newBuilder()
            .connectTimeout(Duration.ofSeconds(10))
            .build();
    }
    
    public CompletableFuture<String> sendToExternalApi(ScanResult result) {
        return CompletableFuture.supplyAsync(() -> {
            try {
                String json = objectMapper.writeValueAsString(result);
                
                HttpRequest request = HttpRequest.newBuilder()
                    .uri(URI.create("https://api.example.com/vulnerabilities"))
                    .header("Content-Type", "application/json")
                    .header("Authorization", "Bearer " + apiKey)
                    .POST(HttpRequest.BodyPublishers.ofString(json))
                    .build();
                
                HttpResponse<String> response = httpClient.send(
                    request, 
                    HttpResponse.BodyHandlers.ofString()
                );
                
                return response.body();
                
            } catch (Exception e) {
                throw new CompletionException(e);
            }
        });
    }
}

🧪 Testando Plugins

Testes Unitários

package com.example.plugin;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;

class MyScannerPluginTest {
    
    private MyScannerPlugin plugin;
    
    @Mock
    private PluginContext mockContext;
    
    @BeforeEach
    void setUp() {
        MockitoAnnotations.openMocks(this);
        plugin = new MyScannerPlugin();
    }
    
    @Test
    void testInitialize() throws PluginException {
        when(mockContext.getConfiguration()).thenReturn(mock(PluginConfiguration.class));
        
        assertDoesNotThrow(() -> plugin.initialize(mockContext));
    }
    
    @Test
    void testInitializeWithoutConfiguration() {
        when(mockContext.getConfiguration()).thenReturn(null);
        
        assertThrows(PluginException.class, () -> plugin.initialize(mockContext));
    }
    
    @Test
    void testMetadata() {
        PluginMetadata metadata = plugin.getMetadata();
        
        assertNotNull(metadata);
        assertEquals("my-scanner-plugin", metadata.getId());
        assertEquals("1.0.0", metadata.getVersion());
    }
}

Testes de Integração

class MyScannerPluginIntegrationTest {
    
    private ArtemisTestServer testServer;
    private MyScannerPlugin plugin;
    
    @BeforeEach
    void setUp() throws Exception {
        testServer = new ArtemisTestServer();
        testServer.start();
        
        plugin = new MyScannerPlugin();
        plugin.initialize(createTestContext());
        plugin.start();
    }
    
    @AfterEach
    void tearDown() throws Exception {
        plugin.stop();
        plugin.destroy();
        testServer.stop();
    }
    
    @Test
    void testScanDetectsMissingHeaders() {
        ScanTarget target = ScanTarget.builder()
            .url(testServer.getUrl("/no-security-headers"))
            .build();
        
        List<ScanResult> results = plugin.scan(target).join();
        
        assertFalse(results.isEmpty());
        assertTrue(results.stream()
            .anyMatch(r -> r.getType().equals("MISSING_SECURITY_HEADER")));
    }
}

📦 Empacotamento e Distribuição

Estrutura do Pacote

my-artemis-plugin-1.0.0.jar
├── META-INF/
│   ├── MANIFEST.MF
│   └── services/
│       └── com.example.artemis.plugin.ArtemisPlugin
├── com/
│   └── example/
│       └── plugin/
│           ├── MyScannerPlugin.class
│           └── MyPluginMetadata.class
└── plugin.properties

Arquivo plugin.properties

plugin.id=my-scanner-plugin
plugin.name=My Custom Scanner Plugin
plugin.version=1.0.0
plugin.author=Seu Nome
plugin.license=MIT
plugin.description=Plugin de scanner personalizado para verificações de segurança
plugin.mainClass=com.example.plugin.MyScannerPlugin
plugin.apiVersion=1.0

Publicando no Repositório de Plugins

# Empacotar o plugin
mvn clean package

# Assinar o plugin (opcional)
gpg --detach-sign target/my-artemis-plugin-1.0.0.jar

# Publicar no repositório
artemis plugin publish \
    --file target/my-artemis-plugin-1.0.0.jar \
    --repository https://plugins.artemis.example.com

🐛 Solução de Problemas

Problemas Comuns

ProblemaCausaSolução
ClassNotFoundExceptionDependência ausenteVerificar pom.xml e empacotamento
PluginException: Configuration not foundConfiguração ausenteCriar arquivo de configuração
NoSuchMethodErrorConflito de versõesVerificar versões das dependências
Plugin não carregaArquivo de serviço ausenteVerificar META-INF/services/
OutOfMemoryErrorVazamento de memóriaRevisar recursos e usar try-with-resources

Depuração

# Habilitar logs de depuração
artemis --log-level DEBUG plugin load my-plugin.jar

# Verificar dependências do plugin
artemis plugin inspect my-plugin.jar

# Validar estrutura do plugin
artemis plugin validate my-plugin.jar

Logging

public class MyPlugin implements ArtemisPlugin {
    
    private static final Logger logger = LoggerFactory.getLogger(MyPlugin.class);
    
    @Override
    public void initialize(PluginContext context) throws PluginException {
        logger.debug("Configuração: {}", context.getConfiguration());
        logger.info("Plugin inicializado");
        logger.warn("Recurso não disponível, usando fallback");
        logger.error("Falha ao conectar", exception);
    }
}

📚 Melhores Práticas

1. Tratamento de Erros

// ❌ Ruim
public void process() {
    try {
        doSomething();
    } catch (Exception e) {
        // Ignorar silenciosamente
    }
}

// ✅ Bom
public void process() throws PluginException {
    try {
        doSomething();
    } catch (SpecificException e) {
        logger.error("Falha ao processar: {}", e.getMessage(), e);
        throw new PluginException("Falha no processamento", e);
    }
}

2. Gerenciamento de Recursos

// ❌ Ruim
public String readFile(String path) {
    BufferedReader reader = new BufferedReader(new FileReader(path));
    return reader.readLine(); // Vazamento de recurso
}

// ✅ Bom
public String readFile(String path) throws IOException {
    try (BufferedReader reader = new BufferedReader(new FileReader(path))) {
        return reader.readLine();
    }
}

3. Concorrência

// ❌ Ruim
public class MyPlugin {
    private List<ScanResult> results = new ArrayList<>();
    
    public void addResult(ScanResult result) {
        results.add(result); // Não é thread-safe
    }
}

// ✅ Bom
public class MyPlugin {
    private final List<ScanResult> results = 
        Collections.synchronizedList(new ArrayList<>());
    
    public void addResult(ScanResult result) {
        synchronized (results) {
            results.add(result);
        }
    }
}

4. Configuração

// ❌ Ruim
public class MyPlugin {
    private static final String API_KEY = "hardcoded-key"; // Nunca faça isso
}

// ✅ Bom
public class MyPlugin {
    private String apiKey;
    
    @Override
    public void initialize(PluginContext context) throws PluginException {
        this.apiKey = context.getConfiguration().getString("apiKey");
        if (apiKey == null || apiKey.isEmpty()) {
            throw new PluginException("apiKey é obrigatória");
        }
    }
}

📖 Recursos Adicionais

✅ Resumo

Neste módulo, você aprendeu:

  1. Arquitetura de Plugins: Como o sistema de plugins do Artemis funciona
  2. Criação de Plugins: Passo a passo para criar um plugin do zero
  3. Tipos de Plugins: Scanner, Reporter, Notifier, Analyzer, Integration
  4. Ciclo de Vida: initialize, start, stop, destroy
  5. Configuração: Como usar e validar configurações
  6. Testes: Testes unitários e de integração
  7. Empacotamento: Como empacotar e distribuir plugins
  8. Melhores Práticas: Tratamento de erros, recursos, concorrência

🎯 Próximos Passos

Agora que você domina o desenvolvimento de plugins, explore:


Anterior: Módulo 9: Desenvolvimento de Payloads | Próximo: Módulo 11: Integração com CI/CD```json { "query": "www.sub.evil.example", "found": true, "trail": "evil.example", "info": "asyncrat (malware)", "reference": "(static)", "confidence": 100 }

O campo `confidence` (0-100, ou `null` quando indisponível) indica quão fortemente as fontes
sustentam a listagem: 40 para um único feed, +15 por cada feed adicional que concorda
independentemente até 100, e pontuação máxima para as entradas personalizadas e estáticas do
próprio operador. É calculado no momento da atualização do trail a partir da concordância dos feeds
num sidecar `trails.confidence` junto ao `trails.csv`; um servidor que obtém trails de um
`UPDATE_SERVER` não tem proveniência para pontuar e reporta `null`. Use-o para priorizar a triagem
- uma listagem de feed único com 40 merece uma segunda análise antes de ganhar uma regra de
firewall.

Uma consulta de subdomínio pode corresponder ao seu parent listado. As consultas de URL verificam
`host/path` antes de verificar apenas o host. O servidor lê a base de dados de trails mapeada em
memória e observa atualizações de trails sem reiniciar.

Os trails estáticos públicos e de feeds estão disponíveis sem autenticação, consistente com o
endpoint `/trails` usado por sensores remotos. Os trails personalizados requerem uma sessão
autorizada; uma consulta apenas de personalizados não autorizada é reportada como uma falha. Os
dados de eventos permanecem autenticados.

## Operações

### Monitorização

Use `maltrail-sensor -T` como um portão de implantação e configuração. A unidade systemd fornecida
executa-o como `ExecStartPre`.

Para confirmar que a própria deteção funciona — não apenas que os processos arrancam — execute:```bash
python3 server.py --detect-test

Ele reproduz um pcap construído de tráfego malicioso emulado (acertos de trail numa consulta DNS, um IP, um IP:port, um caminho de URL e um cabeçalho Host, além das heurísticas de SQL-injection, traversal, RCE, XSS, proxy-probe, sinkhole, Host ausente e port/web/infection-scanning) através do sensor instalado e verifica que todas as detecções esperadas disparam. Não precisa de root, nem de interface, nem de um conjunto de trails próprio. Uma instalação saudável imprime 20/20 detection(s) fired.

Quando STATS_ADDRESS está configurado, monitorize pelo menos estas métricas Prometheus:

MétricaSignificado operacional
maltrail_up == 0Nenhum worker de captura está em execução
maltrail_capture_dropped_total a aumentarO anel de captura está a descartar pacotes
maltrail_local_log_errors_total a aumentarForam produzidos eventos mas não foi possível escrevê-los localmente
maltrail_remote_log_errors_total a aumentarOs eventos não puderam ser entregues a um sink remoto; com DISABLE_LOCAL_LOG_STORAGE são perdidos
maltrail_trail_generation sem avançarO conjunto de trails ativo não está a ser atualizado
maltrail_log_dir_free_bytesCapacidade restante para armazenamento local de eventos
maltrail_state_saturations_total a aumentarFoi atingido um limite de estado de uma heurística
maltrail_throttle_evictions_total a aumentarA tabela de event-throttle está no seu limite, pelo que os eventos são agregados mais cedo do que o configurado

A saturação de estado afeta a heurística correspondente; a correspondência exata de trails permanece ativa.

Envie SIGHUP ou use systemctl reload maltrail-sensor para pedir um recarregamento de trails. Ficheiros de trail atualizados por outro processo são detetados automaticamente e publicados nos workers sem reiniciar o sensor.

O armazenamento observável condensado (USE_CONDENSED_STORAGE, meta.sqlite) suporta as vistas de novidade e retro-hunt do servidor. O índice sidecar do registo de eventos por dia (USE_EVENT_INDEX, LOG_DIR/index/*.sqlite, aproximadamente o dobro do tamanho do log em disco) é o que torna /counts exato e /hunt rápido; é mantido incrementalmente a partir dos próprios logs e pode ser reconstruído com server.py --rebuild-index. A compatibilidade com o sensor retirado está documentada em sensor/docs/COMPATIBILITY.md.

Retenção de eventos

O Maltrail não roda nem elimina registos de eventos. Os operadores são responsáveis por definir a retenção, o arquivamento e a eliminação de acordo com os requisitos de armazenamento e a política organizacional.

Práticas recomendadas:

  • Envie a cópia durável dos eventos para um servidor Maltrail remoto ou SIEM com LOG_SERVER, SYSLOG_SERVER ou LOGSTASH_SERVER.
  • Alerte sobre maltrail_log_dir_free_bytes com margem suficiente para a taxa de eventos esperada.
  • Rode, arquive ou remova os logs diários locais usando ferramentas externas.
  • Mantenha os ficheiros necessários à interface de relatórios descomprimidos em LOG_DIR; arquive os ficheiros comprimidos noutro local.

Quando o sistema de ficheiros de logs está cheio, o sensor não consegue acrescentar eventos. Os registos de eventos podem também conter endereços IP e domínios que são regulados como dados pessoais em algumas jurisdições; a política de retenção deve ter em conta os requisitos aplicáveis.

Tráfego sintético

Para verificar que a deteção e o dashboard continuam a funcionar, sem esperar por tráfego real:```bash python3 server.py --detect-test # assert every detection fires, then exit python3 server.py --detect-test --keep DIR --serve # ...and keep the events, serving them on :8338

`--keep` também reproduz `sensor/tests/corpus/` no mesmo log e imprime quais das formas que o
dashboard renderiza de forma diferente têm um evento por trás delas, para que um ícone, cor ou glifo
ausente seja visível em vez de presumido. Os carimbos de data/hora são deslocados para que o dia mais
recente seja hoje. É necessário um binário do sensor (`cargo build --release --manifest-path sensor/Cargo.toml`).

Os dados da demonstração pública são regenerados a partir de uma execução desse tipo:```bash
python3 sensor/tools/gen_demo_js.py --from DIR/logs   # tops up html/js/demo.js

Documentação

DocumentoConteúdo
sensor/docs/INSTALL.mdInstalação, privilégios, configuração e resolução de problemas
sensor/docs/ARCHITECTURE.mdFuncionamento interno do sensor e fluxo de dados
sensor/docs/COMPATIBILITY.mdDiferenças deliberadas em relação ao sensor Python descontinuado
sensor/docs/REPORT.mdMedições, perfis e resultados de testes
sensor/docs/ROADMAP.mdTrabalho aberto no sensor
SekuriPy LabsNotas de engenharia, benchmarks e análises

Contribuição

Adições de trails, manutenção de feeds, relatórios de bugs, documentação e melhorias no sensor são bem-vindas. Submissões de trails devem incluir uma fonte confiável e devem usar a classificação adequada mais restrita.

Execute as verificações relevantes antes de submeter código. A verificação completa do sensor é:```bash bash sensor/tools/check.sh

Ele executa formatação, Clippy com avisos negados e as suítes de teste de debug e release. Execute a suíte do servidor Python com:```bash
bash tests/run.sh python3

A build do Windows pode ser exercitada a partir do Linux, que é onde os seus bugs foram encontrados:```bash sh sensor/tools/check_windows.sh

Ele faz compilação cruzada do sensor com mingw-w64, extrai a biblioteca de espaço de usuário do Npcap do seu instalador
(um arquivo NSIS, portanto nada é instalado) e executa o resultado sob o Wine — toda a suíte de testes,
`-T` contra a configuração fornecida, o corpus pcap comparado byte a byte com o binário
nativo, e o servidor respondendo a `/ping` sob um Python do Windows. A captura ao vivo é a única coisa que
ele não consegue cobrir; isso requer o driver de kernel do Npcap e uma máquina Windows real. Os pré-requisitos são
`gcc-mingw-w64-x86-64`, `wine` e `p7zip-full`.

## Projeto

### Licença

**TL;DR:** O Maltrail é licenciado sob MIT, mas o conjunto de dados Maltrail Trails tem termos separados. A consulta/referência independente de IOC é permitida; o uso sistemático do Trails como fonte de inteligência em um produto ou serviço comercial requer permissão/licenciamento.

O Maltrail é distribuído sob a Licença MIT. Consulte [`LICENSE`](https://github.com/stamparm/maltrail/blob/master/LICENSE).

Esse é o motor. O conjunto de trails estático é um trabalho separado sob termos separados: gratuito para uso
defensivo interno, pesquisa e ensino, mas um produto comercial, serviço, oferta de MSSP ou MDR, ou um
feed redistribuído precisa de uma licença. Um motor MIT não torna o conteúdo livre para venda — consulte
[`LICENSE.md`](https://github.com/stamparm/trails/blob/main/LICENSE.md) em
[stamparm/trails](https://github.com/stamparm/trails) antes de distribuí-lo em algo pelo qual você cobra.

### Mantenedores

- Miroslav Stampar ([@stamparm](https://github.com/stamparm))
- Mikhail Kasimov ([@MikhailKasimov](https://github.com/MikhailKasimov))

### Patrocinadores

- [Sansec](https://sansec.io/) (2024–2025)
- [Sansec](https://sansec.io/) (2020–2021)

### Apresentações e publicações

- 47ª Reunião TF-CSIRT, Praga, 2016
  ([slides](https://web.archive.org/web/20161109135211/https://www.terena.org/activities/tf-csirt/meeting47/M.Stampar-Maltrail.pdf))
- _Detect attacks on your network with Maltrail_, Linux Magazine, 2022
  ([artigo](https://www.linux-magazine.com/Issues/2022/258/Maltrail))
- _Best Cyber Threat Intelligence Feeds_, Silent Push, 2022
  ([análise](https://www.silentpush.com/blog/best-cyber-threat-intelligence-feeds))
- _Research on Network Malicious Traffic Detection System Based on Maltrail_, Nanotechnology
  Perceptions, 2024
  ([artigo](https://nano-ntp.com/index.php/nano/article/view/1915/1497))

### Integrações de terceiros

- [FreeBSD Port](https://www.freshports.org/security/maltrail)
- [OPNsense Gateway Plugin](https://github.com/opnsense/plugins/pull/1257)
- [D4 Project](https://www.d4-project.org/2019/09/25/maltrail-integration.html)
- [BlackArch Linux](https://github.com/BlackArch/blackarch/blob/master/packages/maltrail/PKGBUILD)
- [Validin](https://x.com/ValidinLLC/status/1719666086390517762)
- [Maltrail Add-on for Splunk](https://splunkbase.splunk.com/app/7211)
- [Maltrail decoder and rules for Wazuh](https://github.com/MikhailKasimov/maltrail-wazuh-decoder-and-rules)
- [GScan](https://github.com/grayddq/GScan) (apenas trails)
- [MalwareWorld](https://www.malwareworld.com/) (apenas trails)
- [oisd domain blocklist](https://oisd.nl/?p=inc) (apenas trails)
- [NextDNS](https://github.com/nextdns/metadata/blob/e0c9c7e908f5d10823b517ad230df214a7251b13/security/threat-intelligence-feeds.json) (apenas trails)
- [NoTracking](https://github.com/notracking/hosts-blocklists/blob/master/SOURCES.md) (apenas trails)
- [OWASP Mobile Audit](https://github.com/mpast/mobileAudit#environment-variables) (apenas trails)
- [Mobile Security Framework MobSF](https://github.com/MobSF/Mobile-Security-Framework-MobSF/commit/12b07370674238fa4281fc7989b34decc2e08876) (apenas trails)
- [pfBlockerNG-devel](https://github.com/pfsense/FreeBSD-ports/blob/devel/net/pfSense-pkg-pfBlockerNG-devel/files/usr/local/www/pfblockerng/pfblockerng_feeds.json) (apenas trails)
- [Sansec eComscan](https://sansec.io/kb/about-ecomscan/ecomscan-license) (apenas trails)
- [Palo Alto Networks Cortex XSOAR](https://xsoar.pan.dev/docs/reference/integrations/github-maltrail-feed) (conector de trail)

### Agradecimentos

- Thomas Kristner
- Eduardo Arcusa Les
- James Lay
- Ladislav Baco (@laciKE)
- John Kristoff (@jtkdpu)
- Michael M&uuml;nz (@mimugmail)
- David Brush
- @Godwottery
- Chris Wild (@briskets)
- Keith Irwin (@ki9us)
- Simon Szustkowski (@simonszu)

Categorias