Pular para o conteúdo
, , ,

Montando seu servidor de logs com Graylog: A base de toda auditoria [pt.1]

Logs espalhados são logs perdidos. Neste artigo, montamos um servidor centralizado com Graylog, OpenSearch e MongoDB: a fundação necessária antes de qualquer estratégia de auditoria em Linux

Avatar de DK
DKTrabalha com Linux e Unix a mais de 23 anos e possui as certificações LPI 3, RHCE, AIX e VIO.

24 dez, 2025
14 min de leitura

Série CSI do Linux

  • Parte 01: Montando seu servidor de logs com Graylog (você está aqui)

Sabe aquela sensação de quando o servidor cai às 2 da manhã e você precisa descobrir o que aconteceu? Você entra via SSH, vai direto no /var/log/… e o disco encheu. Ou pior: a máquina reiniciou e levou junto aquele log que explicava tudo.

Agora multiplica isso por 50 servidores. Boa sorte brincando de detetive.

O problema real

Logs espalhados são logs perdidos. Simples assim.

Estou atualizando um post antigo sobre o rootsh (um keylogger de terminal), mas percebi uma coisa óbvia que tinha ignorado: não adianta nada gravar o que o usuário digita se esse log fica preso na máquina local. Se um invasor ganha root, a primeira coisa que ele faz é apagar os rastros.

Então antes de falar sobre auditoria de terminal, gravação de sessões, ou qualquer coisa mais avançada… a gente precisa de uma fundação sólida. Uma “caixa forte” centralizada onde todos os logs da sua rede vão morar. Longe das mãos de quem quer apagar evidências.

Este é o primeiro artigo de uma série sobre auditoria. Aqui a gente monta o servidor de logs. Nos próximos, vamos plugar as coisas interessantes nele.

A escolha das ferramentas (Stack 2026)

Antes de sair instalando coisa, deixa eu explicar por que escolhi essas ferramentas. Não quero que você siga receita de bolo sem entender o cardápio.

Por que não ELK?

Se você pesquisou sobre logs centralizados, com certeza esbarrou no tal do ELK Stack (Elasticsearch, Logstash, Kibana). Era o padrão da indústria… até a Elastic mudar a licença e complicar a vida de todo mundo.

Além disso, ELK é pesado. Precisa de bastante RAM, bastante disco, e uma paciência considerável pra configurar. Funciona muito bem em empresas grandes com equipe dedicada. Pra quem está montando um lab ou quer algo mais direto ao ponto, é bazuca pra matar mosca.

A solução: Graylog + OpenSearch

O mundo open source não ficou parado quando a Elastic mudou as regras do jogo. A Amazon fez um fork chamado OpenSearch, que é 100% open source e compatível com o que o Elasticsearch fazia.

O Graylog abraçou essa mudança. Ele usa o OpenSearch como motor de busca e armazenamento, mas te entrega uma interface muito mais amigável e focada em logs. Menos firula, mais resultado.

Por que Podman?

Podman já vem instalado por padrão no Fedora e é praticamente idêntico ao Docker em termos de comandos. Se você prefere Docker, pode usar sem problemas, só troque podman-compose por docker compose nos comandos.

Pré-requisitos

Antes de começar, você vai precisar de:

  • Um servidor Linux – Uma VM simples resolve. Fedora 43 ou Ubuntu 24.04 LTS funcionam bem. Recomendo pelo menos 4GB de RAM e uns 64GB de disco pra começar.
  • Podman e podman-compose instalados – Na maioria das distros, a instalação é direta via gerenciador de pacotes (dnf install podman podman-compose no Fedora/RHEL ou apt install podman podman-compose no Debian/Ubuntu).

O ajuste que ninguém avisa

O OpenSearch é exigente com um parâmetro do kernel. Se você não ajustar isso, o container nem sobe direito.

# Ajuste temporário (some no reboot)
sudo sysctl -w vm.max_map_count=262144

# Ajuste permanente (sobrevive ao reboot)
echo "vm.max_map_count=262144" | sudo tee /etc/sysctl.d/01-max-map-count.conf
sudo sysctl --system

Esse parâmetro controla quantas áreas de memória mapeada um processo pode ter. O OpenSearch precisa de muitas. Sem isso, ele reclama e morre.

Usar /etc/sysctl.d/ ao invés de editar o /etc/sysctl.conf diretamente é a forma moderna de fazer isso. Mais organizado, mais fácil de remover depois se precisar.

Mão na massa: O arquivo compose.yaml

Todos os arquivos deste artigo estão disponíveis no repositório. Clone e entre no diretório:

git clone https://github.com/dklima/csi-do-linux.git
cd csi-do-linux/01-graylog

Antes de mais nada, copie o arquivo de exemplo de variáveis de ambiente:

cp .env.example .env

O compose.yaml é o coração da operação. Vamos dar uma olhada no que tem dentro:

services:
  mongodb:
    image: docker.io/mongo:7.0
    container_name: mongodb
    volumes:
      - mongodb_data:/data/db
    restart: unless-stopped

  opensearch:
    image: docker.io/opensearchproject/opensearch:2.19.0
    container_name: opensearch
    environment:
      - discovery.type=single-node
      - plugins.security.disabled=true
      - bootstrap.memory_lock=true
      - "OPENSEARCH_JAVA_OPTS=-Xms1g -Xmx1g"
      - OPENSEARCH_INITIAL_ADMIN_PASSWORD=${OPENSEARCH_INITIAL_ADMIN_PASSWORD}
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - opensearch_data:/usr/share/opensearch/data
    restart: unless-stopped

  graylog:
    image: docker.io/graylog/graylog:7.0
    container_name: graylog
    environment:
      - GRAYLOG_PASSWORD_SECRET=${GRAYLOG_PASSWORD_SECRET}
      - GRAYLOG_ROOT_PASSWORD_SHA2=${GRAYLOG_ROOT_PASSWORD_SHA2}
      - GRAYLOG_HTTP_EXTERNAL_URI=${GRAYLOG_HTTP_EXTERNAL_URI}
      - GRAYLOG_ELASTICSEARCH_HOSTS=http://opensearch:9200
      - GRAYLOG_MONGODB_URI=mongodb://mongodb:27017/graylog
    ports:
      - "9000:9000"      # Interface web
      - "1514:1514/udp"  # Syslog UDP
      - "1514:1514/tcp"  # Syslog TCP
    depends_on:
      - mongodb
      - opensearch
    restart: unless-stopped

volumes:
  mongodb_data:
  opensearch_data:

O que cada peça faz

  • MongoDB: Guarda as configurações do Graylog. Usuários, dashboards, regras de alertas… tudo fica aqui.
  • OpenSearch: É onde os logs brutos moram. Quando você pesquisa algo na interface, é ele que processa a busca.
  • Graylog: O cérebro da operação. Recebe os logs, processa, indexa no OpenSearch, e te mostra tudo numa interface web.

As portas expostas são:

  • 9000: Interface web. É onde você vai acessar o Graylog.
  • 1514: Onde os logs chegam. Usamos uma porta alta porque portas abaixo de 1024 precisam de root.

Atenção com versões do OpenSearch

Se você está lendo isso no futuro e pensou em usar uma versão mais recente do OpenSearch, cuidado: o Graylog não suporta OpenSearch 3.x. A API mudou e vai quebrar a integração. Fique na série 2.x até que a compatibilidade seja oficialmente anunciada.

A pegadinha da primeira configuração

Antes de subir os containers, precisamos configurar o arquivo .env que copiamos antes. O arquivo tem quatro variáveis que definem as credenciais do sistema:

GRAYLOG_PASSWORD_SECRET: Uma frase secreta pra criptografia. Precisa ter pelo menos 16 caracteres. O comando abaixo gera uma string segura:

openssl rand -base64 32

GRAYLOG_ROOT_PASSWORD_SHA2: A senha do usuário admin, em SHA256. O Graylog não aceita senha em texto puro por motivos óbvios. Pra gerar o hash da sua senha:

printf '%s' "SuaSenhaForte123" | sha256sum | cut -d' ' -f1
Importante
Use printf '%s' ao invés de echo -n. O bash pode escapar caracteres especiais como ! de forma inesperada, gerando um hash diferente do esperado. Evite usar ! na senha pra não ter dor de cabeça.

O resultado vai ser algo tipo:

8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918

Esse hash vai pro .env.

GRAYLOG_HTTP_EXTERNAL_URI: O IP ou hostname do servidor. Aqui entra o IP real da máquina no lugar de SEU_IP. Pra acesso local, 127.0.0.1 funciona.

OPENSEARCH_INITIAL_ADMIN_PASSWORD: O OpenSearch 2.12+ exige uma senha inicial, mesmo que a gente desabilite a segurança depois. Precisa ser uma senha forte: mínimo 8 caracteres, com maiúscula, minúscula, número e caractere especial. Algo tipo S3cur3P@ssw0rd1Lab.

Com o .env configurado, agora podemos subir os containers:

sudo podman-compose up -d
Por que sudo?
O Podman em modo rootless usa o aardvark-dns para resolução de nomes entre containers, e esse serviço precisa bindar na porta 53 — uma porta privilegiada (abaixo de 1024). Além disso, o mapeamento de portas no modo rootless tem limitações que podem impedir o acesso externo ao servidor.

Troubleshooting: Conflito com DNS local

Se o servidor já tiver um serviço de DNS rodando (como dnsmasq, bind ou systemd-resolved escutando na porta 53), os containers não sobem e você vai ver um erro parecido com este:

[opensearch] | Error: unable to start container ...
[opensearch] | Error starting server failed to bind udp listener on 10.89.0.1:53: IO error: Address already in use (os error 98)

O problema é que o aardvark-dns do Podman tenta usar a porta 53 na interface de rede dos containers, mas ela já está ocupada.

Solução: Desabilitar o DNS interno do Podman e usar IPs fixos para os containers. O repositório inclui um arquivo compose-no-dns.yaml já configurado pra isso.

Primeiro, paramos tudo e recriamos a rede com subnet definida:

# Para os containers se estiverem rodando
sudo podman-compose down

# Remove a rede padrão do podman-compose (geralmente chamada de 01-graylog_default ou similar)
sudo podman network ls
sudo podman network rm 01-graylog_default

# Cria uma nova rede sem DNS interno, com subnet definida
sudo podman network create --disable-dns --subnet 172.20.0.0/24 graylog-net

Depois, usamos o compose alternativo que já tem os IPs configurados:

sudo podman-compose -f compose-no-dns.yaml up -d

O compose-no-dns.yaml atribui IPs fixos pra cada container e referencia eles diretamente nas variáveis de ambiente do Graylog:

  • MongoDB: 172.20.0.10
  • OpenSearch: 172.20.0.11
  • Graylog: 172.20.0.12

Sem o DNS interno, a resolução por nome (mongodb, opensearch) não funciona — por isso usamos IPs diretamente.

A primeira inicialização leva uns 2-3 minutos porque o OpenSearch precisa preparar seus índices. Dá pra acompanhar o progresso com:

sudo podman-compose logs -f graylog

Quando aparecer algo como Graylog server up and running, você está pronto.

Acesse http://SEU_IP:9000 no navegador. O login é:

  • Usuário: admin
  • Senha: aquela que você usou pra gerar o SHA256
Screenshot From 2025-12-25 00-01-57
Screenshot From 2025-12-25 00-03-39

Criando o input (Ensinando o Graylog a ouvir)

O Graylog vem “surdo” por padrão. Ele não escuta nenhuma porta até a gente configurar. Isso é proposital — te obriga a pensar no que quer receber.

Pra criar nosso primeiro input, o caminho na interface web é:

System > Inputs > selecionar Syslog UDP no dropdown > Launch new input

Screenshot From 2025-12-25 00-08-51

Na janela que abre, as configurações importantes são:

  • Node: “Global” (pra funcionar em qualquer node do cluster)
  • Title: Algo descritivo tipo “Syslog UDP – Geral”
  • Port: 1514
  • O resto pode ficar no padrão
Screenshot From 2025-12-25 01-51-50

Depois de confirmar com Launch input, o indicador fica verde mostrando que está rodando.

Screenshot From 2025-12-25 02-45-29
Input não está recebendo logs?
Se o indicador mostrar “1 SETUP” ao invés de “RUNNING”, o Input foi criado mas não iniciou. Clique no Input na lista, vá em “More actions” e selecione “Start input”. Se mesmo assim não funcionar, pode ser necessário reiniciar o container do Graylog: sudo podman restart graylog

Por que UDP?

Pra logs em massa, UDP é a escolha certa. Ele funciona no esquema “dispara e esquece”, o cliente manda o log e segue a vida, sem esperar confirmação.

Com TCP, se a rede engasgar ou o servidor de logs ficar lento, o cliente trava esperando resposta. Em cenários de alta carga, isso pode virar uma bola de neve e derrubar sistemas.

UDP pode perder um pacote aqui e ali? Pode. Mas pra logs, geralmente é um trade-off aceitável. Você prefere perder uma mensagem ocasional ou travar seu servidor de produção?

O teste de fogo

Não vamos configurar clientes reais ainda, isso fica pro próximo artigo. Mas a gente precisa saber se essa bagaça está funcionando.

De qualquer máquina Linux na mesma rede (ou do próprio servidor), dá pra enviar um log de teste:

# Usando netcat
echo "Teste do Graylog - Agora vai!" | nc -u -w 1 SEU_IP 1514

# Ou usando logger (mais elegante)
logger -n SEU_IP -P 1514 --udp "Primeiro log remoto - foi, será?"

Na interface do Graylog, a opção Search no menu mostra as mensagens recebidas. Se tudo deu certo, o log de teste aparece lá, indexado e pesquisável.

Screenshot From 2025-12-25 02-06-22
Esse momento é bom. Guarda ele.

Considerações de segurança (não ignore)

Antes de sair conectando tudo nesse servidor, alguns pontos importantes:

  1. Firewall: Só libere as portas pra IPs que você conhece. Não deixe aberto pra internet. No Fedora/RHEL com firewalld:
# Interface web (só pra sua máquina de administração)
sudo firewall-cmd --add-port=9000/tcp --permanent

# Recebimento de logs (só pra rede interna)
sudo firewall-cmd --add-port=1514/udp --permanent
sudo firewall-cmd --add-port=1514/tcp --permanent

sudo firewall-cmd --reload

Pra restringir por IP ou rede de origem, usamos rich rules:

# Liberar porta 1514 apenas para a rede 192.168.1.0/24
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" port port="1514" protocol="udp" accept'
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" port port="1514" protocol="tcp" accept'

# Ou para um IP específico
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.50" port port="9000" protocol="tcp" accept'

sudo firewall-cmd --reload
  1. Rede Separada: Idealmente, logs trafegam numa VLAN de gerência, não na mesma rede dos usuários.

  2. TLS: Pra ambientes de produção, configure inputs com TLS. Log em texto puro atravessando a rede não é ideal.

  3. Backup: Aqueles volumes do compose são seus dados. Tenha uma estratégia de backup.

Não precisa fazer tudo isso agora se é só um lab. Mas mantém na cabeça pra quando for pra produção.

Iniciando no boot

Um servidor de logs que não sobe sozinho depois de um reboot não serve pra muita coisa. Pra garantir que o Graylog inicie automaticamente, vamos criar um serviço systemd.

Primeiro, precisamos mover os arquivos para um local definitivo:

sudo mkdir -p /opt/graylog
sudo cp compose.yaml .env /opt/graylog/

O repositório inclui um arquivo graylog.service pronto. Basta copiá-lo para o systemd:

sudo cp graylog.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable graylog.service

O conteúdo do serviço é simples:

[Unit]
Description=Graylog Stack (Graylog + OpenSearch + MongoDB)
After=network-online.target
Wants=network-online.target

[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/opt/graylog
ExecStart=/usr/bin/podman-compose up -d
ExecStop=/usr/bin/podman-compose down
TimeoutStartSec=300

[Install]
WantedBy=multi-user.target

A partir de agora, o stack sobe automaticamente no boot. Dá pra controlar manualmente também:

sudo systemctl start graylog    # Inicia
sudo systemctl stop graylog     # Para
sudo systemctl status graylog   # Verifica status

Conclusão

Temos agora um servidor central de logs funcionando. Um “vórtice” que engole tudo que mandarem pra ele e deixa a gente pesquisar depois.

Lembra do cenário do início? Disco encheu, máquina reiniciou, log sumiu. Isso não acontece mais. Os logs estão saindo das máquinas em tempo real, morando num lugar separado, com disco próprio e backup (você vai fazer backup, né?).

E de quebra, se algum dia um invasor ganhar root numa máquina e apagar o /var/log/… os logs já foram. Estão seguros em outro lugar.

O próximo passo

No próximo artigo, vamos voltar àquele tema de auditoria que mencionei. Vamos configurar nossos servidores Linux para enviar sessões completas de terminal, tipo um “vídeo em texto” de tudo que foi digitado, direto pra esse Graylog.

É uma evolução do velho rootsh, mas dessa vez feita do jeito certo: com os logs saindo da máquina em tempo real, antes que alguém possa apagar.

Até lá, vale a pena deixar esse Graylog rodando e ir explorando a interface, clicar nas coisas, fuçar os menus. Quando a gente começar a mandar log de verdade, você já vai estar em casa.

Este artigo faz parte de uma série sobre auditoria em ambientes Linux. Acompanhe os próximos para ver como transformar essa base em um sistema completo de monitoramento e resposta a incidentes.

Avatar de DK

Comentários

Deixe um comentário

Seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Ir para