SSH e chaves: como acessar máquinas remotas com segurança
SSH (Secure Shell) é o protocolo que permite controlar servidores remotos com segurança. Entender como funciona a autenticação por chave — não só como usar, mas por quê funciona — é o que separa quem acessa servidores de quem realmente os administra.
Como a autenticação por chave funciona
Autenticação por senha tem um problema fundamental: a senha trafega pela rede (cifrada, mas ainda um segredo compartilhado). Autenticação por chave usa criptografia assimétrica — você prova que tem a chave privada sem nunca enviá-la.
PROTOCOLO DE AUTENTICAÇÃO (SIMPLIFICADO)
1. Cliente envia sua chave pública ao servidor
2. Servidor verifica se está em ~/.ssh/authorized_keys
3. Servidor gera número aleatório (challenge), cifra com a chave pública
4. Cliente decifra com sua chave privada (só quem tem a chave privada consegue)
5. Cliente envia a resposta + hash da sessão para provar que tem a chave privada
6. Servidor verifica — autenticado. A chave privada nunca saiu da máquina do cliente.
Gerando e instalando chaves
# Gerar par de chaves (Ed25519 é o padrão moderno)
ssh-keygen -t ed25519 -C "fernando@trabalho"
# → Pergunta onde salvar (padrão: ~/.ssh/id_ed25519)
# → Pergunta passphrase (use uma boa! é a senha da sua chave privada)
# Gera dois arquivos:
~/.ssh/id_ed25519 # chave PRIVADA — nunca compartilhe, nunca suba para git
~/.ssh/id_ed25519.pub # chave PÚBLICA — pode compartilhar à vontade
# Ver o conteúdo da chave pública
cat ~/.ssh/id_ed25519.pub
# ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBcf... fernando@trabalho
# Instalar no servidor (método automático)
ssh-copy-id usuario@servidor.com
# → copia sua chave pública para ~/.ssh/authorized_keys no servidor
# Instalar manualmente (quando ssh-copy-id não está disponível)
cat ~/.ssh/id_ed25519.pub | ssh usuario@servidor "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"
# Ou: copie o conteúdo e cole no servidor em ~/.ssh/authorized_keys
# Permissões corretas (SSH recusa chaves com permissões erradas)
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chmod 600 ~/.ssh/id_ed25519
chmod 644 ~/.ssh/id_ed25519.pubssh-agent: digitar passphrase apenas uma vez por sessão
# Iniciar o ssh-agent (geralmente já está rodando em desktops)
eval "$(ssh-agent -s)" # inicia agent e seta $SSH_AUTH_SOCK
# → Agent pid 12345
# Adicionar sua chave ao agent
ssh-add ~/.ssh/id_ed25519 # pede passphrase UMA vez
ssh-add -t 3600 ~/.ssh/id_ed25519 # expira em 1 hora
# Ver chaves carregadas no agent
ssh-add -l
# Remover chaves do agent
ssh-add -D # remove todas
ssh-add -d ~/.ssh/id_ed25519 # remove uma específica
# No macOS, integrar com Keychain (persiste entre reinicializações)
# ~/.ssh/config:
Host *
AddKeysToAgent yes
UseKeychain yes
IdentityFile ~/.ssh/id_ed25519Arquivo ~/.ssh/config: chega de decorar flags
O arquivo ~/.ssh/config é onde você configura aliases e opções por host — evita digitar flags toda vez.
# ~/.ssh/config
# Criar se não existir: touch ~/.ssh/config && chmod 600 ~/.ssh/config
# Servidor de produção
Host prod
HostName 203.0.113.10
User ubuntu
IdentityFile ~/.ssh/id_ed25519_prod
Port 22
# Servidor de staging via bastion
Host staging
HostName 10.0.1.50 # IP interno
User app
ProxyJump bastion # passa pelo bastion primeiro
IdentityFile ~/.ssh/id_ed25519
# Bastion (jump server)
Host bastion
HostName bastion.empresa.com
User ec2-user
IdentityFile ~/.ssh/id_ed25519
ForwardAgent yes # permite usar sua chave local nos servidores atrás do bastion
# GitHub (útil quando tem múltiplas contas)
Host github-pessoal
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_pessoal
Host github-trabalho
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_trabalho
# Padrão para todos os hosts
Host *
ServerAliveInterval 60 # envia keepalive a cada 60s (evita desconexão)
ServerAliveCountMax 3 # 3 tentativas antes de desconectar
AddKeysToAgent yes Com esse config, ssh prod conecta em ubuntu@203.0.113.10 com a chave certa. ssh staging pula pelo bastion automaticamente. git clone git@github-pessoal:user/repo.git usa a chave pessoal.
Port forwarding: túneis SSH para serviços internos
| Tipo | Comando | Uso típico |
|---|---|---|
| Local (-L) | ssh -L 5432:db:5432 bastion | Acessar DB interno via localhost |
| Remote (-R) | ssh -R 8080:localhost:3000 servidor | Expor app local no servidor |
| Dynamic (-D) | ssh -D 1080 servidor | SOCKS proxy para todo tráfego |
# LOCAL: acessa banco interno via túnel
ssh -L 5432:db-interno.vpc:5432 bastion.empresa.com
# Agora: psql -h localhost -p 5432 -U admin mydb
# (funciona como se o banco fosse local)
# LOCAL com config file (permanente):
Host tunnel-db
HostName bastion.empresa.com
LocalForward 5432 db-interno.vpc:5432
User ec2-user
# REMOTE: expõe sua máquina local no servidor (útil para demos/webhooks)
ssh -R 8080:localhost:3000 servidor.com
# No servidor: curl localhost:8080 → responde sua app local na porta 3000
# Manter túnel ativo (sem executar comando)
ssh -N -L 5432:db:5432 bastion & # -N não executa comando, -f vai para backgroundSegurança: configuração do servidor SSH
# /etc/ssh/sshd_config — configurações críticas de segurança
# Desabilitar login por senha (use apenas chaves!)
PasswordAuthentication no
ChallengeResponseAuthentication no
# Desabilitar login como root diretamente
PermitRootLogin no
# Usar apenas usuários específicos
AllowUsers ubuntu deploy
# Porta não-padrão (security by obscurity, reduz ruído nos logs)
Port 2222
# Timeout para sessões inativas
ClientAliveInterval 300
ClientAliveCountMax 2
# Após editar:
sudo systemctl reload ssh # recarrega sem derrubar conexões ativas
# Testar configuração sem reiniciar
sudo sshd -t # valida syntax, não reiniciaNunca feche a sessão SSH antes de abrir uma segunda janela e confirmar que consegue reconectar com as novas configurações. Muitos sysadmins já se trancaram para fora do próprio servidor por fechar prematuramente.
Setup completo em 5 passos: (1) ssh-keygen -t ed25519, (2) ssh-copy-id servidor, (3) configurar ~/.ssh/config com aliases, (4) eval "$(ssh-agent -s)" + ssh-add, (5) desabilitar PasswordAuthentication no servidor.
Próximo: Git de verdade — o modelo mental de commits como snapshots, DAG de objetos, e por que rebase não é assustador quando você entende o que está acontecendo.
Próximos passos sugeridos
Discussão
Carregando…