Unified System é um projeto de microsserviços distribuídos em Java, construído com Spring e orquestrado com Docker Compose. O sistema implementa um gateway de API centralizado, descoberta de serviços (DNS e Diretório), balanceamento de carga, um serviço de distribuição de chaves e um anel P2P.
O foco principal do projeto é aplicar segurança em todos os canais de comunicação, garantindo confidencialidade, integridade e autenticidade para cada interação entre os serviços.
O sistema é "headless" (sem interface web) e se comunica inteiramente sobre TCP. A arquitetura é definida por dois conceitos principais: um modelo de segurança de duas camadas e um sistema de descoberta de serviços duplo.
1. Modelo de Segurança
Toda a comunicação na rede é criptografada e autenticada. Nenhum serviço confia em outro por padrão. Isso é alcançado usando o módulo common-crypto.
-
Algoritmos:
- Cifragem: AES-128 (AES/CBC/PKCS5Padding).
- Autenticidade: HMAC-SHA256.
- Integridade: CRC32 (para verificação de checksum contra corrupção).
- Transporte: O payload (
EncryptedPayload) é serializado para JSON e depois codificado em Base64.
-
Gerenciamento de Chaves (Duas Camadas):
- Chaves de Bootstrap (Pré-Compartilhadas - PSK):
- Uso: Para serviços de infraestrutura (
DNS,Service Directory,P2P). - Como: Um par de chaves (AES e HMAC) é gerado uma vez e compartilhado com todos os serviços por variáveis de ambiente (via arquivo
.env). Isso resolve o problema de como encontrar o serviço de chaves de forma segura.
- Uso: Para serviços de infraestrutura (
- Chaves Dinâmicas (Key Distribution Service):
- Uso: Para serviços de negócio, como o
calculator-service. - Como: O
key-distribution-servicegera e armazena chaves sob demanda. Oapi-gatewaye ocalculator-servicebuscam dinamicamente essas chaves no KDS para poderem se comunicar.
- Uso: Para serviços de negócio, como o
- Chaves de Bootstrap (Pré-Compartilhadas - PSK):
2. Descoberta de Serviços (DNS e Diretório)
O sistema utiliza dois serviços de registro para diferentes propósitos:
-
mini-dns-service:- Funciona como um DNS real, mapeando um nome de serviço único para um endereço (ex:
api-gateway->api-gateway:8080). - É o serviço de bootstrap que permite que todos os outros serviços se encontrem.
- Também inclui um
TcpPushService(na porta 8085) que notifica clientes conectados (ouvintes) sobre novos registros em tempo real.
- Funciona como um DNS real, mapeando um nome de serviço único para um endereço (ex:
-
service-directory:- Funciona como um diretório de microsserviços para balanceamento de carga no lado do cliente.
- Ele permite que múltiplas instâncias de um serviço (
calculator-1ecalculator-2) sejam registradas sob o mesmo nome (calculator).
O projeto é dividido nos seguintes módulos Maven:
| Módulo | Descrição |
|---|---|
common-crypto |
Biblioteca central. Contém CryptoUtil (primitivas de AES, HMAC) e Bootstrap (lógica de empacotamento/desempacotamento seguro). Não é um serviço Spring. |
mini-dns-service |
Serviço de DNS seguro. Escuta na porta 8081 para registrar e resolver nomes e na 8085 para transmitir atualizações. Usa chaves Bootstrap. |
service-directory |
Serviço de Diretório seguro para balanceamento de carga. Escuta na porta 8082 para registrar, deletar e descobrir serviços. Usa chaves Bootstrap. |
key-distribution-service |
Serviço de Distribuição de Chaves. Escuta na porta 8083. Seu protocolo (GET_KEYS) é inseguro (texto puro), pois ele é a fonte da verdade e é acessado após o DNS seguro. |
api-gateway |
O ponto único de entrada do sistema. Escuta na porta 8080. É o componente mais complexo, responsável por: 1. Descriptografar requisições do cliente (com chaves Bootstrap). 2. Rotear comandos (DNS, CALCULATE, FIND). 3. Fazer balanceamento de carga no lado do cliente (Round Robin). 4. Criptografar respostas para o cliente (com chaves Bootstrap). |
calculator-service |
Serviço de negócio que realiza cálculos. Duas instâncias (calculator-1, calculator-2) são executadas. Ele se registra tanto no mini-dns (com seu nome único) quanto no service-directory (com o nome "calculator"). |
p2p-node |
Implementa um nó em um anel P2P (Overlay). Seis instâncias (P0 a P5) são executadas. Cada nó escuta em sua porta (9000-9005). Ele processa comandos FIND, respondendo se for o dono do arquivo ou encaminhando para seu sucessor. |
client |
Um aplicativo de console Spring para interagir com o api-gateway (Modo 1) ou escutar o mini-dns (Modo 2). |
O projeto é totalmente orquestrado pelo Docker Compose.
1. Pré-requisitos
- Java 21
- Maven
- Docker e Docker Compose
- Linux (opcional, os comandos de exportação de variáveis de ambiente podem variar em outros sistemas operacionais)
2. Gerar Chaves de Bootstrap
Este sistema requer um conjunto de chaves (AES e HMAC) pré-compartilhadas para proteger a infraestrutura de DNS.
Rode a classe KeyGenerator uma vez para gerar as chaves (exemplo):
Depois copie as chaves geradas (DNS_AES_KEY e DNS_HMAC_KEY) para o próximo passo.
3. Criar Arquivo .env
Na raiz do projeto (unified-system/), crie um arquivo chamado .env e cole as chaves geradas.
O Docker e o Spring usarão essas variáveis de ambiente para configurar os serviços e injetar as chaves.
4. Construir o Projeto
Use o Maven para construir todos os módulos e instalá-los no seu repositório local.
mvn clean install5. Iniciar os Servidores
Use o Docker Compose para construir e iniciar todos os 12 contêineres de serviço.
docker compose up --buildGraças ao depends_on e às verificações @Order no Spring, os serviços iniciarão na ordem correta para resolver as dependências de inicialização (race conditions).
6. Executar o Cliente
Para testar o sistema, você pode executar duas instâncias do cliente.
Terminal 1 (ouvinte de DNS):
# Carregue as chaves de bootstrap no seu terminal
export $(grep -v '^#' .env | xargs)
# Execute o JAR do cliente (depois que o maven compilar as classes)
java -jar client/target/client-1.0-SNAPSHOT.jarNo prompt, selecione o modo 2. O terminal ficará escutando passivamente por atualizações do DNS na porta 8085.
Terminal 2 (cliente interativo):
# Carregue as chaves (necessário para esta nova sessão)
export $(grep -v '^#' .env | xargs)
# Execute o JAR do cliente
java -jar client/target/client-1.0-SNAPSHOT.jarNo prompt, selecione o modo 1. O terminal estará pronto para enviar comandos.
O api-gateway aceita os seguintes comandos (em texto puro, o cliente cuida da criptografia):
1. Cálculo (Roteado para calculator-service)
Testa o balanceamento de carga e as chaves dinâmicas.
CALCULATE operação n1 n2
Onde operação pode ser SUM, SUB, MUL ou DIV.
n1 e n2 são números, inteiros ou ponto-flutuantes.
Exemplo: CALCULATE SUM 100 50
2. DNS (Roteado para mini-dns-service)
Testa o registro de DNS e o serviço de push.
DNS REGISTER nome-serviço endereço
Onde nome-serviço é um nome único (ex: servidor1) e endereço é um endereço TCP (ex: 192.168.10.2), ou host:porta (ex: servidor1:8080).
DNS RESOLVE nome-serviço
O serviço retornará o endereço registrado.
3. P2P (Roteado para o Anel P2P via p0)
Testa o roteamento em anel.
FIND arquivoX
Onde arquivoX é o nome do arquivo a ser localizado (ex. arquivo25).
O comando é enviado para o nó P0, que roteia pela rede P2P.
Se o arquivo for encontrado, o nó retornará o endereço do nó que o possui, caso contrário, retornará "NOT_FOUND".
É possível visualizar os logs dos serviços no terminal onde o Docker Compose foi executado para acompanhar o processamento dos comandos.
Se quiser visualizar as mensagens criptografadas entre os serviços, descomente as linhas com System.out.println na classe Bootstrap.
Para simular um cliente malicioso, você pode modificar as chaves AES e/ou HMAC no terminal para valores incorretos:
- Abra um novo terminal.
- Exporte alguma chave alterando o valor real:
export DNS_AES_KEY="chave_aes"
export DNS_HMAC_KEY="chave_hmac"- Execute o cliente e depois selecione o modo 1 (interativo):
java -jar client/target/client-1.0-SNAPSHOT.jarEnvie qualquer comando, o api-gateway tentará processá-lo, mas a verificação falhará e a mensagem será descartada e o cliente exibirá um erro de criptografia.
