Files
cybercore-signer/docs/port-discovery.md
T

3.7 KiB

Proposta Técnica: Mecanismo de Descoberta de Portas e Port-Hunting

Documento de Arquitetura e Especificação para o SDK Web @cybercore/signer-sdk


1. Contexto e Motivação

O CyberCore Signer escuta por padrão na porta loopback 127.0.0.1:21325. No entanto, em cenários corporativos ou máquinas com múltiplos softwares e agentes instalados, podem ocorrer:

  1. Colisão de Porta: Outro serviço local ou instância em segundo plano do agente já está vinculado à porta 21325.
  2. Execução Multi-Usuário / Terminal Server: Múltiplas sessões de desktop com agentes independentes para cada usuário logado.
  3. Restrições de Firewall / Segurança Local: Políticas corporativas que exigem portas específicas.

Para suportar portas alternativas sem exigir configuração manual complexa do usuário final, o CyberCore Signer e o SDK Web adotam a estratégia de Port-Hunting Sequencial.


2. Configuração no Agente Desktop

O agente pode ser iniciado com portas customizadas através de:

  • Parâmetro de Linha de Comando: --port <numero> ou -p <numero> (ex: cybercore-signer --port 21326)
  • Variável de Ambiente: CYBERCORE_PORT=21326
  • Propriedade JVM: -Dcybercore.port=21326

Caso a porta solicitada já esteja em uso por outro processo, o agente captura java.net.BindException, emite mensagem acionável no log/console e, no modo gráfico, mantém a interface de gestão disponível alertando sobre a indisponibilidade temporária do socket HTTP.


3. Especificação do Algoritmo de Port-Hunting no SDK Web

O pacote JavaScript @cybercore/signer-sdk deve implementar a sondagem de portas durante o método connect() ou isInstalled().

Faixa Padrão de Sondagem

  • Porta Base: 21325
  • Porta Final: 21330 (faixa de 6 portas consecutivas)
  • Timeout por Porta: 250 milissegundos
  • Estratégia: Sequencial rápida (ou paralelas com Promise.any)

Algoritmo

export interface SignerOptions {
  basePort?: number;
  maxPort?: number;
  timeoutMs?: number;
}

export async function discoverActivePort(options: SignerOptions = {}): Promise<number> {
  const basePort = options.basePort ?? 21325;
  const maxPort = options.maxPort ?? 21330;
  const timeoutMs = options.timeoutMs ?? 250;

  for (let port = basePort; port <= maxPort; port++) {
    try {
      const controller = new AbortController();
      const timer = setTimeout(() => controller.abort(), timeoutMs);

      const resp = await fetch(`http://127.0.0.1:${port}/ccsp/v1/status`, {
        method: 'GET',
        signal: controller.signal,
        headers: { 'Accept': 'application/json' }
      });
      clearTimeout(timer);

      if (resp.ok) {
        const body = await resp.json();
        if (body.status === 'ready' && body.agent === 'CyberCore Signer') {
          return port; // Agente encontrado e operacional nesta porta!
        }
      }
    } catch {
      // Porta indisponível ou conexão recusada; continua para a próxima
    }
  }

  throw new Error('CyberCore Signer não encontrado na faixa de portas 21325-21330. O agente está em execução?');
}

4. Segurança e Mitigações

  1. Host Header Restrito: Cada requisição deve sempre enviar Host: 127.0.0.1:{port} ou Host: localhost:{port}. O agente rejeita qualquer Host externo com HTTP 403.
  2. Private Network Access (PNA): O agente responde com Access-Control-Allow-Private-Network: true para compatibilidade com a especificação PNA do Google Chrome/Chromium.
  3. CORS Rígido: A rota /status responde status: ready apenas para fins de handshake; operações de chave privada continuam exigindo application_id, autorização prévia e aprovação visual do usuário.