📚 Pré-requisitos Teóricos: este projeto aplica conceitos ensinados em Guia de Redes. Recomendado revisar antes de começar.

🌐 Sniffer de Pacotes de Rede & Chat em Tempo Real com WebSockets

📁 Código deste projeto: api-node/ (os caminhos citados abaixo são relativos à subpasta).

Diagrama de arquitetura do projeto

v1.0 — Redes de Computadores, Pilha TCP/IP, Raw Sockets e WebSockets RFC 6455

Trilha de Especialização Pedagógica — Projeto 1 de 4

🎓 Nível Profissional Simulado: Engenheiro de Redes / Especialista em Protocolos. Entender redes não é apenas decorar portas e IPs. Um engenheiro experiente sabe inspecionar os bytes de um cabeçalho IP, entender a negociação de 3 vias (Three-Way Handshake SYN/ACK) do TCP e construir servidores em tempo real com WebSockets.


🎯 Objetivo & Escopo do Projeto

Construir um Analisador de Tráfego de Rede (Sniffer de Pacotes) com decodificação de cabeçalhos Ethernet/IP/TCP e um Servidor de Chat Multiusuário em Tempo Real utilizando o protocolo WebSocket (RFC 6455) para troca de mensagens bidirecional com latência sub-milissegundo.


🧑‍💼 Fase 1 — Levantamento de Requisitos

O Briefing do Cliente (Administrador de Redes & NOC)

“Precisamos de duas ferramentas para o laboratório: um sniffer de rede didático que capture pacotes passando pela interface, extraia o IP de origem, IP de destino, porta e protocolo (TCP/UDP), e um servidor de chat em tempo real onde múltiplos clientes conectados via navegador conversem instantaneamente através de WebSockets persistentes sem precisar de polling HTTP.”

Requisitos Funcionais (RF) e Não-Funcionais (RNF)

ID Tipo Descrição Origem no Briefing
RF01 Funcional Capturar pacotes de rede e decodificar os 20 bytes do cabeçalho IPv4 (TTL, IPs, Protocolo). “extraia IP de origem, destino e protocolo”
RF02 Funcional Realizar o handshake WebSocket (RFC 6455) convertendo requisição HTTP (Upgrade: websocket). “WebSockets persistentes sem polling”
RF03 Funcional Fazer broadcast de mensagens recebidas para todos os clientes conectados ao chat. “múltiplos clientes conversem instantaneamente”
RNF01 Não-Funcional Decodificação binária de pacotes utilizando struct.unpack de alta velocidade. Análise de Rede
RNF02 Não-Funcional Suporte a concorrência assíncrona com asyncio / Goroutines. Baixa Latência

📋 Fase 2 — Backlog & User Stories

ID User Story Prioridade
US01 Como analista de segurança, quero inspecionar os pacotes capturados e identificar o tráfego suspeito. Alta
US02 Como usuário, quero enviar uma mensagem no chat e vê-la aparecer na tela de todos os outros usuários na mesma fração de segundo. Alta

🌿 Fase 3 — Engenharia em Equipe (Git Flow & Setup)

# Branch da funcionalidade
git checkout -b feature/US01-sniffer-websocket-chat

# Executar o servidor de chat WebSocket
python websocket_server.py

🛠️ Fase 4 — Implementação Guiada (websocket_server.py)

import asyncio
import websockets

CONEXOES_ATIVAS = set()

async def chat_handler(websocket):
    CONEXOES_ATIVAS.add(websocket)
    try:
        async for mensagem in websocket:
            # Broadcast para todos os outros participantes conectados
            broadcast_tasks = [
                ws.send(f"[Usuario]: {mensagem}")
                for ws in CONEXOES_ATIVAS if ws != websocket
            ]
            if broadcast_tasks:
                await asyncio.gather(*broadcast_tasks)
    finally:
        CONEXOES_ATIVAS.remove(websocket)

async def main():
    async with websockets.serve(chat_handler, "localhost", 8765):
        print("Servidor WebSocket de Chat ativo na porta 8765...")
        await asyncio.Future()

if __name__ == "__main__":
    asyncio.run(main())


🧩 Trechos do código do projeto

const http = require('http');
const crypto = require('crypto');

const PORT = 3000;
const GUID = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
const clients = new Set();

const server = http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
  res.end(`
    <!DOCTYPE html>
    <html lang="pt-BR">
    <head><title>Monitor WebSocket</title></head>
    <body style="font-family: sans-serif; padding: 2rem;">
      <h2>🌐 Monitor de Chat em Tempo Real</h2>
      <p>Servidor ativo na porta ${PORT}. Conecte clientes via WebSocket para testar o broadcast.</p>
    </body>
    </html>
  `);
});

server.on('upgrade', (req, socket, head) => {
  if (req.headers['upgrade'] !== 'websocket') {
    socket.end('HTTP/1.1 400 Bad Request\r\n\r\n');
    return;
  }

  const clientKey = req.headers['sec-websocket-key'];
  const acceptKey = crypto
    .createHash('sha1')
    .update(clientKey + GUID)
    .digest('base64');

  const headers = [
    'HTTP/1.1 101 Switching Protocols',
    'Upgrade: websocket',
    'Connection: Upgrade',
    `Sec-WebSocket-Accept: ${acceptKey}`
  ];

  socket.write(headers.join('\r\n') + '\r\n\r\n');
  clients.add(socket);
  console.log(`[+] Novo cliente conectado (${socket.remoteAddress}:${socket.remotePort}). Total: ${clients.size}`);

  socket.on('data', (buffer) => {
    // Decodificação simplificada de payload mascarado (RFC 6455)
    const isMasked = (buffer[1] & 0x80) === 0x80;
    const length = buffer[1] & 0x7f;
    let offset = 2;

    if (isMasked && length < 126) {
      const masks = buffer.slice(offset, offset + 4);
      offset += 4;
      const messageBuffer = Buffer.alloc(length);
      for (let i = 0; i < length; i++) {
        messageBuffer[i] = buffer[offset + i] ^ masks[i % 4];
      }
      const message = messageBuffer.toString('utf8');
      console.log(`[Mensagem recebida]: ${message}`);

      // Broadcast da mensagem para os outros clientes conectados
      for (const client of clients) {
        if (client !== socket && client.writable) {
          const responsePayload = Buffer.from(`[Peer]: ${message}`);
          const frame = Buffer.concat([
            Buffer.from([0x81, responsePayload.length]),
            responsePayload
          ]);
          client.write(frame);
        }
      }
    }
  });

  socket.on('close', () => {
    clients.delete(socket);
    console.log(`[-] Cliente desconectado. Total: ${clients.size}`);
  });
});

server.listen(PORT, () => {
  console.log(`Servidor WebSocket ativo em http://localhost:${PORT}`);
});

🚀 Roteiro de Execução

1. Iniciar o Servidor

cd catalogo_projetos/redes_01_sniffer_websocket_chat/api-node
node server.js

2. Testar Conexão e Broadcast com Cliente Terminal

Abra dois terminais adicionais e conecte-se usando qualquer cliente WebSocket (ex.: wscat):

# Terminal 1 (Cliente A)
npx wscat -c ws://localhost:3000

# Terminal 2 (Cliente B)
npx wscat -c ws://localhost:3000

Envie mensagens no Terminal 1 e verifique a replicação instantânea no Terminal 2.


🧭 Decisões de Arquitetura (ADRs)


🧪 Testes de Validação & Asserções

# Testar conexao WebSocket interativa com wscat
npx wscat -c ws://localhost:8765

✅ Checkpoint Final

  1. Captura e dissecação de pacotes IP/TCP validada.
  2. Broadcast de chat em tempo real operando com sucesso.

⬅️ Ver Todos os Projetos no Catálogo de Projetos 🏠 Página Inicial do Portal