Preços

Visão geral da arquitetura

Arquivos-fonte

Esta página foi gerada com base nos seguintes arquivos-fonte:

O res-downloader é uma aplicação desktop de código aberto que combina sniffing de recursos de rede com capacidades de download de alta velocidade. O projeto utiliza uma arquitetura híbrida com backend em Go e frontend em Vue.js, integrados através do framework Wails v2. Esta abordagem permite que a aplicação ofereça alto desempenho no processamento de rede enquanto mantém uma interface de usuário moderna e responsiva.

Estrutura Geral e Tecnologias Principais

A arquitetura do projeto fundamenta-se no framework Wails, que permite criar aplicações desktop usando tecnologias web modernas. O ponto de entrada da aplicação em main.go:1-60 demonstra a inicialização do Wails com configurações de janela, menu e integração de assets. O backend é escrito em Go 1.22+, enquanto o frontend utiliza Vue 3 com TypeScript, Vite como build tool, e a biblioteca de componentes Naive UI.

正在加载图表渲染器...

Pontos-chave da arquitetura:

  1. Separação Frontend/Backend: O frontend Vue.js comunica-se com o backend Go através de bindings gerados automaticamente pelo Wails, permitindo chamadas diretas a métodos Go a partir do JavaScript
  2. Proxy MITM Integrado: O componente de proxy atua como intermediário para interceptar tráfego HTTPS, utilizando certificados autoassinados para descriptografar e analisar requisições
  3. Servidor HTTP Local: Um servidor HTTP interno roda na porta 8899 (configurável) para servir tanto a interface quanto as requisições de proxy
  4. Integração com SO: A aplicação modifica configurações de proxy do sistema operacional e gerencia certificados raiz para habilitar a interceptação HTTPS

As dependências principais estão definidas em go.mod:1-42, incluindo github.com/wailsapp/wails/v2 para o framework desktop, github.com/elazarl/goproxy para funcionalidade de proxy, e github.com/rs/zerolog para logging estruturado. O frontend em frontend/src/main.ts:1-14 inicializa a aplicação Vue com suporte a i18n (internacionalização), Pinia (gerenciamento de estado) e Vue Router (navegação).

Arquitetura do Backend e Núcleo da Aplicação

Módulo App - Estrutura Principal e Ciclo de Vida

O módulo App definido em core/app.go:42-172 representa o núcleo da aplicação backend. A estrutura App contém campos essenciais como AppName, Version, Description, além de gerenciar o estado do proxy (IsProxy) e certificados embutidos (PublicCrt, PrivateKey).

Responsabilidades do módulo App:

  • Inicialização: O método GetApp() utiliza singleton pattern para garantir uma única instância, extraindo a versão do arquivo wails.json através de regex
  • Ciclo de Vida: Startup(ctx context.Context) é chamado pelo Wails na inicialização, iniciando o servidor HTTP em uma goroutine separada
  • Gerenciamento de Proxy: Métodos OpenSystemProxy() e UnsetSystemProxy() controlam o proxy do sistema operacional
  • Limpeza: OnExit() garante que o proxy seja desativado e recursos sejam liberados ao fechar a aplicação
go
1// Estrutura simplificada do App
2type App struct {
3    ctx        context.Context
4    assets     embed.FS
5    AppName    string
6    Version    string
7    IsProxy    bool
8    IsReset    bool
9    PublicCrt  []byte
10    PrivateKey []byte
11    UserDir    string
12}

Módulo Config - Gerenciamento de Configuração

O sistema de configuração implementado em core/config.go:46-221 utiliza um padrão de configuração com valores padrão e persistência em arquivo JSON. A estrutura Config define parâmetros como porta do servidor (Port), diretório de download (SaveDirectory), configurações de proxy (UpstreamProxy, OpenProxy, AutoProxy), e mapeamento de tipos MIME.

Características principais:

  • Singleton Pattern: initConfig() garante uma única instância global de configuração
  • Valores Padrão: Define configurações sensatas como Port: "8899", TaskNumber: runtime.NumCPU() * 2, e UserAgent com string de navegador moderno
  • Persistência: Utiliza Storage para salvar/carregar configurações em config.json no diretório do usuário
  • MIME Types: getDefaultMimeMap() retorna um mapa extensivo de tipos MIME suportados (imagens, áudio, vídeo) com seus respectivos sufixos de arquivo

Módulo Bind - Interface entre Frontend e Backend

A camada de binding em core/bind.go:9-25 expõe métodos do backend Go para o frontend JavaScript através do sistema de bindings do Wails. A estrutura Bind atua como uma fachada que delega chamadas para os módulos apropriados.

Métodos expostos:

MétodoRetornoDescrição
Config()*ResponseDataRetorna configuração global atual
AppInfo()*ResponseDataRetorna informações da aplicação (nome, versão, etc.)
ResetApp()voidMarca a aplicação para reset e encerra

O ResponseData definido em core/http.go:21-60 padroniza as respostas com campos Code, Message e Data, facilitando o tratamento no frontend.

Funcionalidades de Rede e Proxy

Módulo Proxy - Interceptação MITM

O componente de proxy em core/proxy.go:25-110 é o coração da funcionalidade de sniffing. Utiliza a biblioteca goproxy para criar um proxy HTTP/HTTPS com capacidade de Man-in-the-Middle (MITM).

Fluxo de inicialização do proxy:

  1. Carregamento de Certificados: setCa() carrega o par de chaves X.509 embutido na aplicação
  2. Configuração MITM: Define ações de conexão (OkConnect, MitmConnect, HTTPMitmConnect) com TLS config derivado do certificado CA
  3. Registro de Handlers: OnRequest().HandleConnectFunc() determina quais hosts devem sofrer interceptação MITM baseado em regras
  4. Interceptação: httpRequestEvent() e httpResponseEvent() processam requisições/respostas para extrair recursos de mídia
go
1// Lógica de decisão MITM
2p.Proxy.OnRequest().HandleConnectFunc(func(host string, ctx *goproxy.ProxyCtx) (*goproxy.ConnectAction, string) {
3    if ruleOnce.shouldMitm(host) {
4        return goproxy.MitmConnect, host
5    }
6    return goproxy.OkConnect, host
7})

O sistema de plugins permite estender a funcionalidade para domínios específicos. Durante a inicialização, plugins como QqPlugin e DefaultPlugin são registrados em um mapa indexado por domínio, permitindo tratamento personalizado de requisições.

Módulo Rule - Sistema de Regras de Interceptação

O módulo de regras em core/rule.go:22-126 determina quais hosts devem ter seu tráfego HTTPS interceptado. O RuleSet suporta sintaxe flexível com wildcards e negações.

Formato das regras:

  • * - Intercepta todos os hosts
  • *.example.com - Intercepta todos os subdomínios
  • example.com - Intercepta apenas o domínio exato
  • !example.com - Nega interceptação (exceção)

O método shouldMitm(host string) processa o host removendo portas e normalizando o formato, então aplica as regras em ordem, permitindo que regras posteriores substituam anteriores.

Módulo HTTP Server - Servidor Local

O servidor HTTP em core/http.go:21-60 atua como ponto central de comunicação, escutando em 127.0.0.1:8899 (configurável). O servidor possui comportamento duplo:

  1. API Interna: Requisições para 127.0.0.1:porta são tratadas por HandleApi() para comunicação frontend-backend
  2. Proxy: Todas as outras requisições são encaminhadas para o Proxy.ServeHTTP()
go
1http.Serve(listener, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
2    if r.Host == "127.0.0.1:"+globalConfig.Port && HandleApi(w, r) {
3        // Tratado como API interna
4    } else {
5        proxyOnce.Proxy.ServeHTTP(w, r) // Encaminha para proxy
6    }
7}))

O servidor também expõe endpoint para download do certificado CA público através de downCert(), permitindo que usuários instalem o certificado em dispositivos móveis para interceptação.

Frontend e Interface do Usuário

Módulo Router - Navegação e Views

O sistema de roteamento em frontend/src/router/index.ts:1-31 utiliza Vue Router com hash history, adequado para aplicações desktop sem servidor web real. A estrutura define um layout principal com duas views filhas:

RotaComponenteMetaDescrição
/Layout-Container principal com redirecionamento para /index
/indexIndexkeepAlive: trueView principal de sniffing/download
/settingSettingkeepAlive: falseConfigurações da aplicação

O uso de createWebHashHistory() garante compatibilidade com o protocolo wails:// usado pelo Wails para carregar assets locais.

Módulo Store - Gerenciamento de Estado

O store Pinia em frontend/src/stores/index.ts:1-99 centraliza o estado da aplicação, incluindo informações do app (appInfo), configuração global (globalConfig), estado do proxy (isProxy), e informações de ambiente (envInfo).

Fluxo de inicialização do store:

正在加载图表渲染器...

Métodos principais do store:

  • init(): Carrega informações iniciais da aplicação e configuração do backend
  • setConfig(formValue): Atualiza configuração localmente e persiste no backend via API
  • openProxy() / unsetProxy(): Controla o proxy do sistema operacional através de chamadas ao backend

A configuração do Vite em frontend/vite.config.ts:1-36 utiliza plugins de auto-import para Vue e Naive UI, reduzindo código boilerplate ao importar automaticamente composables como useDialog, useMessage, useNotification e useLoadingBar.

Serviços de Sistema e Utilitários

Módulo System - Integração com Sistema Operacional

O módulo de sistema em core/system.go:16-83 gerencia interações com o SO, incluindo instalação de certificados e configuração de proxy. A estrutura SystemSetup utiliza um cipher AES para proteger credenciais armazenadas em cache.

Funcionalidades de segurança:

  • Cache de Senha: SetPassword() criptografa a senha do usuário antes de salvar em pass.cache
  • Validação de Cache: checkPasswordFile() verifica se o cache tem menos de um mês; caso contrário, remove-o
  • Gerenciamento de Certificados: initCert() garante que o certificado CA esteja disponível no diretório do usuário

A implementação específica para macOS em core/system_darwin.go:11-99 utiliza o comando networksetup para configurar o proxy do sistema.

Fluxo de configuração de proxy no macOS:

  1. getNetworkServices() lista todos os serviços de rede ativos (excluindo portas seriais e serviços inativos)
  2. Para cada serviço ativo, executa comandos para configurar proxy HTTP e HTTPS
  3. Utiliza sudo com senha quando necessário, lendo a senha do stdin
go
1commands := [][]string{
2    {"networksetup", "-setwebproxy", serviceName, "127.0.0.1", globalConfig.Port},
3    {"networksetup", "-setsecurewebproxy", serviceName, "127.0.0.1", globalConfig.Port},
4}

Módulo AES - Criptografia de Dados Sensíveis

O utilitário de criptografia em core/aes.go:16-72 implementa criptografia AES-CBC para proteger dados sensíveis como senhas de administrador.

Características da implementação:

  • Modo CBC: Utiliza Cipher Block Chaining com vetor de inicialização aleatório
  • Padding PKCS#7: Implementa padding manual para alinhar blocos
  • Encoding Base64: Saída codificada em Base64 para armazenamento seguro em texto
go
1func (a *AESCipher) Encrypt(plainText string) (string, error) {
2    block, _ := aes.NewCipher(a.key)
3    // Padding
4    padding := block.BlockSize() - len(plainText)%block.BlockSize()
5    plainText = plainText + string(bytes.Repeat([]byte{byte(padding)}, padding))
6    // IV aleatório + ciframento
7    cipherText := make([]byte, aes.BlockSize+len(plainText))
8    iv := cipherText[:aes.BlockSize]
9    io.ReadFull(rand.Reader, iv)
10    mode := cipher.NewCBCEncrypter(block, iv)
11    mode.CryptBlocks(cipherText[aes.BlockSize:], []byte(plainText))
12    return base64.StdEncoding.EncodeToString(cipherText), nil
13}

Módulo Logger - Sistema de Logging Estruturado

O sistema de logging em core/logger.go:1-68 utiliza Zerolog para logging estruturado com suporte a saída em arquivo ou console.

Configuração:

  • Modo Produção: Logs escritos em ~/logs/app.log com timestamp e formato estruturado
  • Modo Desenvolvimento: Logs enviados para stdout com output colorido
  • Métodos de Conveniência: Err() para erros simples, Esg() para erros com contexto formatado

O logger é inicializado com base no ambiente detectado por shared.IsDevelopment(), garantindo logs apropriados para cada contexto de execução.

Fluxo de Dados e Cadeia de Chamadas

O diagrama abaixo ilustra o fluxo completo de uma requisição de sniffing de recursos:

正在加载图表渲染器...

Pontos críticos do fluxo:

  1. Ativação: O usuário ativa o proxy através da interface, que chama OpenSystemProxy() no backend
  2. Interceptação: Todas as requisições HTTPS passam pelo proxy local, que decide se aplica MITM baseado nas regras
  3. Processamento: Plugins específicos por domínio analisam o conteúdo para extrair URLs de recursos de mídia
  4. Comunicação: Recursos descobertos são enviados para o frontend através do servidor HTTP interno
  5. Download: O usuário pode selecionar recursos para download, que são baixados através do próprio proxy

Decisões de Design e Trade-offs

Escolha do Framework Wails

A decisão de utilizar Wails em vez de alternativas como Electron ou Tauri foi baseada em:

CritérioWailsElectronTauri
Tamanho do binário~15MB~150MB~10MB
BackendGoNode.jsRust
MemóriaBaixaAltaBaixa
Curva de aprendizadoModeradaBaixaAlta
EcossistemaCrescenteMaduroCrescente

Justificativa: O projeto requer processamento de rede de alto desempenho (natural em Go) e distribuição de binários compactos. Wails oferece o melhor equilíbrio entre performance, tamanho e facilidade de desenvolvimento para uma equipe com expertise em Go.

Proxy MITM vs. Extensão de Navegador

A escolha de implementar um proxy MITM em vez de uma extensão de navegador considera:

Vantagens do Proxy MITM:

  • Intercepta tráfego de qualquer aplicação (navegadores, apps nativos)
  • Não requer instalação por usuário
  • Acesso a protocolos de baixo nível

Desvantagens:

  • Requer instalação de certificado CA
  • Pode ser detectado por apps com certificate pinning
  • Maior superfície de ataque

Armazenamento de Credenciais

O sistema armazena senhas de administrador (necessárias para configurar proxy no macOS) criptografadas com AES-256. A chave está hardcoded no binário (resd48w2d7er95627d447c490a8f02ff), o que é uma limitação conhecida. Alternativas mais seguras como keyring do SO não foram implementadas para manter a simplicidade de deployment.

Limitações Conhecidas

  1. Certificate Pinning: Aplicações que implementam certificate pinning não podem ter seu tráfego interceptado
  2. Compatibilidade: A configuração de proxy do sistema pode não funcionar em todos os ambientes (especialmente em redes corporativas com políticas restritivas)
  3. Cache de Senha: O cache de senha expira após um mês, requerendo reautenticação periódica no macOS
  4. Single Instance: A aplicação não suporta múltiplas instâncias simultâneas devido ao uso extensivo de singletons

Tecnologias e Dependências

TecnologiaVersãoPropósitoJustificativaAlternativas
Go1.22+BackendPerformance, concorrência, binários estáticosRust, C++
Wailsv2.10.1Framework desktopIntegração Go+Web, binários compactosElectron, Tauri
Vue.js3.xFrontendReatividade, ecossistema maduroReact, Svelte
TypeScript-Tipagem frontendSegurança de tipos, DXJavaScript puro
Vite-Build toolHMR rápido, ESM nativoWebpack, Parcel
Pinia-Estado globalSimplicidade, TypeScript-firstVuex, Redux
Naive UI-Componentes UIDesign moderno, Vue 3Element Plus, Vuetify
goproxyv1.7.2Proxy HTTP/HTTPSMITM, extensibilidademitmproxy
zerologv1.33.0LoggingPerformance, JSON estruturadologrus, zap

Dependências entre Módulos

正在加载图表渲染器...

Observações sobre dependências:

  • Acoplamento com App: Muitos módulos dependem de appOnce (singleton de App) para acessar contexto e configurações, criando acoplamento implícito
  • Ciclo App-Proxy: App inicializa Proxy, mas Proxy precisa de certificados de App, criando dependência circular resolvida pela ordem de inicialização
  • Config como Global: globalConfig é acessado diretamente por múltiplos módulos, facilitando desenvolvimento mas dificultando testes unitários

Configuração e Inicialização

Configuração Padrão

O arquivo wails.json:1-20 define metadados da aplicação:

json
1{
2  "name": "res-downloader",
3  "outputfilename": "res-downloader",
4  "frontend:install": "npm install",
5  "frontend:build": "npm run build",
6  "frontend:dev:watcher": "npm run dev",
7  "frontend:dev:serverUrl": "auto",
8  "info": {
9    "productVersion": "3.1.3"
10  }
11}

Ordem de Inicialização

  1. main.go: Carrega assets embutidos e chama core.GetApp()
  2. core/app.go: Inicializa singletons na ordem: initConfig()initLogger()initSystem()initRule()initProxy()initHttpServer()
  3. Wails Runtime: Chama App.Startup() que inicia o servidor HTTP em background
  4. Frontend: Vue app inicializa, chama store.init() que comunica com backend via bindings

Configurações de Runtime

ConfiguraçãoPadrãoDescrição
Host127.0.0.1Host do servidor HTTP local
Port8899Porta do servidor HTTP e proxy
SaveDirectory~/DownloadsDiretório para downloads
TaskNumberNumCPU * 2Máximo de tarefas concorrentes
DownNumber3Downloads simultâneos
Rule*Regras de interceptação (todos por padrão)
OpenProxyfalseSe deve ativar proxy ao iniciar
AutoProxyfalseSe deve detectar e ativar proxy automaticamente