Segurança e Criptografia
BackupAlly implementa criptografia de nível enterprise para proteção de dados.
Modelo de Criptografia
Envelope Encryption
BackupAlly usa envelope encryption (criptografia em envelope):
┌──────────────────────────────────────────────┐
│ Backup File (.ally) │
├──────────────────────────────────────────────┤
│ ┌────────────────────────────────────────┐ │
│ │ RSA-4096 encrypted AES-256 key │ │
│ └────────────────────────────────────────┘ │
│ ┌────────────────────────────────────────┐ │
│ │ AES-256-GCM encrypted data │ │
│ └────────────────────────────────────────┘ │
└──────────────────────────────────────────────┘Por que Envelope Encryption?
- Performance: AES é muito mais rápido que RSA para dados grandes
- Segurança: Chave AES diferente a cada backup
- Flexibilidade: Pode rotacionar chave RSA sem re-criptografar dados
Algoritmos
Criptografia Assimétrica
| Aspecto | Valor |
|---|---|
| Algoritmo | RSA |
| Tamanho da chave | 4096 bits |
| Padding | OAEP-SHA256 |
| Uso | Proteger chave AES |
Criptografia Simétrica
| Aspecto | Valor |
|---|---|
| Algoritmo | AES-256 |
| Modo | GCM (Galois/Counter Mode) |
| Nonce | 12 bytes (aleatório) |
| Tag | 16 bytes (autenticação) |
| Uso | Criptografar dados |
Integridade
| Aspecto | Valor |
|---|---|
| Checksum | BLAKE3 |
| Autenticação | GCM tag |
| Verificação | Pós-download |
Modos de Chave
Default
Usa a mesma chave RSA para todos os backups:
[crypto]
key_mode = "default"
default_key_ref = "/etc/backupally/keys/default.key"Vantagens:
- Simples de gerenciar
- Uma chave para todos os restores
Desvantagens:
- Comprometimento afeta todos os backups
Ephemeral
Gera nova chave para cada backup:
[crypto]
key_mode = "ephemeral"Vantagens:
- Isolamento total entre backups
- Comprometimento afeta apenas um backup
Desvantagens:
- Requer gerenciamento de múltiplas chaves
- Necessita servidor central para recovery
None
Sem criptografia (não recomendado):
[crypto]
key_mode = "none"Uso válido:
- Dados públicos
- Ambientes de desenvolvimento
- Storage já criptografado
Key Fingerprint
Cada backup contém o fingerprint da chave que o criptografou:
Fingerprint = SHA256(public_key)[0:8]8 bytes que identificam unicamente a chave.
Verificar Fingerprint
backupally keys fingerprint /etc/backupally/keys/default.key
# Key fingerprint: a1b2c3d4e5f6a7b8Uso no Header
O fingerprint está no header do arquivo .ally, permitindo:
- Identificar qual chave usar para restore
- Detectar chave errada antes de tentar descriptografar
Gerenciamento de Secrets
Armazenamento
Secrets são armazenados em /etc/backupally/secrets.db:
- SQLite criptografado
- Chave derivada da chave mestra
- Permissões 0600
Uso em Configuração
password = "${secret:mysql_password}"
api_key = "${secret:aws_key}"Proteção
- Secrets nunca aparecem em logs
- Valores descriptografados apenas em memória
- Memória zerada após uso (zeroize)
Servidor Central
Para disaster recovery, registre chaves no servidor central:
[central]
enabled = true
server_url = "https://central.backupally.io"
api_key = "seu-api-key"
auto_sync = trueRecuperação
backupally keys recover \
--fingerprint a1b2c3d4e5f6a7b8 \
--server https://central.backupally.io \
--api-key your-keySegurança de Rede (v0.10.0)
A partir da v0.10.0, BackupAlly implementa múltiplas camadas de proteção de rede.
TLS Pinning (SPKI)
O binário embute pins SPKI (SHA-256 do SubjectPublicKeyInfo) de hosts críticos, extraídos em build-time pelo build.rs. Um ServerCertVerifier customizado valida o pin do certificado end-entity após a chain validation padrão:
| Host | Propósito |
|---|---|
get.backupally.com |
CDN de binários (canal de auto-update) |
api.github.com |
Metadata de releases |
Se o pin não corresponder (e.g., MITM com certificado falso), a conexão é rejeitada.
Cliente HTTP Centralizado
Todas as requisições HTTP passam por get_http_client() — um singleton com:
- TLS pinning ativo (verifier integrado)
- User-Agent com versão
- Timeouts e pool de conexões consistentes
Message Signing
Mensagens enviadas ao servidor central são assinadas com RSA-SHA256 (PKCS#1 v1.5), incluindo:
client_key_hash: identificador da chave do clientenonce: anti-replay (uso único)timestamp: validado com janela de 5 minutossignature: base64 da assinatura do payload
Anti-Replay
- Nonce store: Nonces vistos são armazenados em memória com TTL de 10 minutos
- Timestamp validation: Mensagens fora da janela de 5 minutos são rejeitadas
- Clock sync check:
init_security()verifica sincronização NTP viatimedatectlno startup
Inicialização de Segurança
Ao iniciar, BackupAlly executa init_security() que:
- Verifica quais pins TLS estão ativos (não placeholder)
- Verifica sincronização NTP
- Emite warnings para condições degradadas (não aborta)
Boas Práticas
Chaves
- Backup offline: Mantenha cópia em local seguro
- Anote fingerprints: Para recovery
- Rotação periódica: A cada 6-12 meses
- Permissões: 0600 em arquivos de chave
Secrets
- Nunca em código: Use ${secret:name}
- Rotação: Atualize periodicamente
- Mínimo privilégio: Usuários de backup com acesso limitado
Storage
- Criptografia em trânsito: HTTPS sempre
- Criptografia em repouso: S3 SSE, B2 SSE
- Acesso restrito: IAM policies específicas
Verificação de Integridade
Pós-Backup
[global]
backup_verification = trueApós upload, BackupAlly:
- Download parcial do arquivo
- Verifica header e checksum
- Confirma integridade
Pré-Restore
backupally restore --verify --target mysql-prod --snapshot snap_xxxVerifica:
- Checksum do arquivo
- GCM tag (autenticação)
- Fingerprint da chave
Envelope v2 em Blocos
Desde a 0.29.0 o payload cifrado do .ally é uma sequência de blocos de 1 MiB
(construção STREAM, a mesma usada por Tink e age), cada um com sua própria tag
AES-256-GCM. A chave de dados continua aleatória por backup e envelopada em
RSA-OAEP com a chave do servidor; os 48 bytes do header entram como dado
autenticado de todos os blocos.
header .ally (48 B)
ALYE | 2 | key_len | chave envelopada (RSA-OAEP) | nonce base (8 B) | chunk_size
bloco 0 || tag · bloco 1 || tag · … · bloco final || tagO que isso muda para você:
- Backup e restore em memória constante, qualquer tamanho
- Arquivo que acaba antes do bloco final é truncado e o restore falha dizendo em que bloco — nunca entrega um restore parcial
- Qualquer byte alterado invalida o bloco; header alterado invalida o bloco 0
- Versões anteriores à 0.29.0 não leem este formato. A 0.29.0 lê todos os anteriores (envelope v1 e RSA em blocos), em memória
Contenção de Path no Download/Restore (0.35.0)
`storage download` e
`restore --from-storage`
resolvem uma key/remote_path do `history`
contra o storage — a superfície pede contenção de path porque a entrada pode
vir de um sistema que não é o BackupAlly (ex.: uma UI).
- toda resolução canonicaliza base (raiz do storage) e destino, e exige
que o resultado fique dentro da base. Raiz relativa ou
/deixou de ter fallback — evitava escapar do storage local via raiz mal configurada; - symlink apontando para fora da base é recusado, não seguido — inclusive quando é um subdiretório que é symlink para fora. Não guarde backup atrás de um symlink que sai do diretório do storage;
- a
keyrecusa..,/inicial e\(E1002) antes de qualquer leitura; - raiz rasa é fraca: a contenção, na busca pela raiz, é relativa à
parte fixa do
pathdo[[storage]] driver = "local"(tudo antes do primeiro${...}). Uma raiz rasa como/var/${x}/bk→ parte fixa/vardeixa baixar qualquer arquivo sob/varque o processo consiga ler. Use raízes absolutas, profundas e dedicadas ao BackupAlly (ex.:/var/backups/backupally/${hostname}, nunca/,/varou/home); --databaseé validado e sanitizado antes de compor qualquer caminho: até 255 caracteres; só letras, dígitos,_,-,$,.; recusa vazio,.., começar por./-sem=(--database=-legacyfunciona,--database -legacynão — o clap trata como flag),/,\e caractere de controle. Inválido →E1002, antes de qualquer leitura no storage.
Essas regras valem para o BackupAlly resolvendo a key/--database que
recebe por argumento. Elas não protegem um path de storage mal configurado
que já aponte, por si só, para fora de onde deveria — a raiz é escolha de
quem escreve a task.
Verificação do Binário de Release
Cada release é assinada com minisign (Ed25519). O self-update já
verifica a assinatura antes de substituir o binário; esta seção é para quem
baixa o arquivo à mão.
A chave pública está publicada no CDN (desde 0.27.2):
https://get.backupally.com/x86_64/pubkey.pubhttps://get.backupally.com/aarch64/pubkey.pubhttps://get.backupally.com/pubkey.pub
Fingerprint da chave de release: 1C6665A7E22166F5
Confira o fingerprint contra este documento na primeira vez (TOFU, trust on first use) e guarde a chave. Verificação:
ARCH=$(uname -m)
curl -fsSL -o backupally "https://get.backupally.com/${ARCH}/backupally"
curl -fsSL -o backupally.minisig "https://get.backupally.com/${ARCH}/backupally.minisig"
curl -fsSL -o pubkey.pub "https://get.backupally.com/${ARCH}/pubkey.pub"
minisign -Vm backupally -p pubkey.pubSaída esperada: Signature and comment signature verified. Qualquer outra
coisa significa binário ou assinatura adulterados — não instale.