Guides
Fundamentos ▾
Versionamento ▾
Deploy ▾

SSH Secure Shell

Protocolo de rede criptográfico para acesso remoto seguro. Tudo que um desenvolvedor sênior precisa saber.

🔒

Confidencialidade

Dados trafegam 100% cifrados. Nenhum intermediário consegue ler.

🛡️

Integridade

MACs detectam qualquer adulteração dos dados em trânsito.

🪪

Autenticação

Garante identidade do servidor e do cliente. Ambos os lados provam quem são.

ℹ️
SSH opera na camada 7 (aplicação) sobre TCP porta 22

SSH-1 está obsoleto e deve ser desabilitado. Em produção, apenas SSH-2 existe.

📅 História

SSH surgiu de um ataque real — não de teoria. Em 1995, um sniffer capturou senhas de root trafegando em plaintext via Telnet na rede da Universidade de Helsinki.

1995
SSH-1 criado por Tatu Ylönen
Resposta direta a um sniffing attack que capturou senhas em plaintext (Telnet, rlogin, rsh). Substituiu esses protocolos inseguros.
1996
SSH-2 redesenhado
Arquitetura mais segura, corrigindo falhas estruturais do SSH-1. Separação em três sub-protocolos independentes.
1999
OpenSSH nasce
Fork open source do SSH-2, livre de patentes, integrado ao OpenBSD. Hoje é a implementação dominante no mundo.
2006
SSH-2 vira RFC oficial
RFCs 4251–4254 padronizam o protocolo formalmente.
Hoje
OpenSSH em todo lugar
Presente em Linux, macOS e Windows 10+. Padrão absoluto para acesso remoto seguro.

🏗️ Arquitetura do Protocolo

SSH-2 é composto por três sub-protocolos empilhados, cada um com responsabilidade distinta, rodando sobre TCP.

3
SSH Connection Protocol
Multiplexa channels: shell interativo, exec, port forwarding, SFTP, X11
RFC 4254
2
SSH User Auth Protocol
Autentica o usuário: publickey, password, keyboard-interactive
RFC 4252
1
SSH Transport Protocol
Criptografia, integridade, troca de chaves, verificação do servidor
RFC 4253
0
TCP · Porta 22
Transporte confiável
camada 4

Camada 1 — Transport: o que acontece na conexão

1
Negociação de algoritmos
Cliente e servidor trocam listas de algoritmos suportados (KEX, ciphers, MACs) e escolhem a melhor interseção.
2
Key Exchange (KEX)
Diffie-Hellman ou ECDH gera segredo compartilhado sem transmiti-lo pela rede. Matemática de curva elíptica.
3
Verificação do servidor (Host Key)
Servidor prova identidade com sua chave privada. Cliente verifica contra ~/.ssh/known_hosts. Previne man-in-the-middle.
4
Session Keys derivadas
Chaves simétricas derivadas do KEX. Todo tráfego restante da sessão é cifrado com essas chaves.

Camada 2 — User Auth: métodos de autenticação

MétodoComo funcionaUso
publickeyCliente assina challenge com chave privada; servidor verifica com pública cadastradarecomendado
keyboard-interactiveDesafio genérico — PAM, OTP, 2FAok
passwordSenha transmitida cifrada ao servidorevitar
hostbasedConfia em combinação host+usuário remotolegado
noneSem autenticação (acesso anônimo controlado)raro

Camada 3 — Connection: o que roda dentro da sessão

💻

Shell interativo

Terminal remoto em tempo real

Exec

Comando único sem shell persistente

🔀

Port Forwarding

Tunnels local, remoto e dinâmico (SOCKS)

📁

SFTP

Transferência de arquivos via subsystem

🖥️

X11 Forwarding

Interface gráfica remota via tunnel

🔢

Multiplex

Vários channels em uma TCP connection

🔐 Criptografia

SSH negocia algoritmos dinamicamente. Conhecer o status de cada um evita configurações inseguras.

Troca de Chaves (KEX) — como o segredo é estabelecido

AlgoritmoStatus
curve25519-sha256★ Recomendado
ecdh-sha2-nistp256/384/521OK
diffie-hellman-group14-sha256Aceitável
diffie-hellman-group1-sha1Obsoleto — desabilitar

Cifras Simétricas — para dados em trânsito

AlgoritmoStatus
chacha20-poly1305@openssh.com★ Recomendado
aes256-gcm@openssh.com★ Recomendado
aes128-gcm@openssh.comOK
aes256-ctr / aes128-ctrOK
3des-cbc / arcfourObsoleto — remover

MACs — garante integridade dos pacotes

AlgoritmoStatus
hmac-sha2-256-etm@openssh.com★ Encrypt-then-MAC
hmac-sha2-512-etm@openssh.com★ Recomendado
hmac-sha1Obsoleto

🗝️ Tipos de Chave

Usadas tanto como host keys (identidade do servidor) quanto como user keys (identidade do usuário).

ed25519 ★ Padrão
256 bits (curva elíptica)
Rápido, compacto, seguro. Use este para tudo novo.
ssh-keygen -t ed25519
ecdsa OK
256 / 384 / 521 bits
Curvas NIST. Funciona bem, mas curve25519 é preferível.
ssh-keygen -t ecdsa -b 521
rsa Legado
4096 bits mínimo
Ainda OK para compatibilidade com sistemas antigos. Use 4096 bits.
ssh-keygen -t rsa -b 4096
dsa Morto
1024 bits (fixo)
Removido do OpenSSH 7.0+. Nunca usar.

📂 Estrutura de Arquivos

Cliente (~/.ssh/)

~/.ssh/
📄 config aliases e opções por host
📋 known_hosts fingerprints de servidores conhecidos
🔑 id_ed25519 chave PRIVADA (600)
🔓 id_ed25519.pub chave pública (644)
🔑 id_rsa chave PRIVADA RSA (600)
🔓 id_rsa.pub chave pública RSA (644)
📝 authorized_keys chaves que podem conectar aqui (600)
⚠️
Permissões incorretas = falha de autenticação

.ssh/ → 700 · chaves privadas → 600 · authorized_keys → 600

Servidor (/etc/ssh/)

/etc/ssh/
⚙️ sshd_config config principal do daemon
📁 sshd_config.d/ configs modulares (include)
🔑 ssh_host_ed25519_key host key privada
🔓 ssh_host_ed25519_key.pub host key pública
🔑 ssh_host_rsa_key host key RSA privada
🔓 ssh_host_rsa_key.pub host key RSA pública
ℹ️
Host keys identificam o servidor

Geradas automaticamente na instalação. Fingerprint vai para known_hosts do cliente na primeira conexão.

🪪 Autenticação por Chave Pública

Método mais seguro. A chave privada nunca sai do cliente — apenas uma assinatura criptográfica é transmitida.

1
Cliente anuncia chave pública
Envia qual chave pública quer usar para autenticar.
2
Servidor verifica authorized_keys
Checa se a chave pública recebida está em ~/.ssh/authorized_keys.
3
Servidor gera e envia challenge
Número aleatório cifrado com a chave pública do cliente. Só quem tem a privada consegue decifrar.
4
Cliente decifra e assina resposta
Usa a chave privada para decifrar o challenge e assinar a resposta.
5
Servidor verifica assinatura → autenticado
Confirma que o cliente possui a chave privada correspondente. Acesso concedido.

Gerando par de chaves

bash
# Ed25519 — padrão recomendado
ssh-keygen -t ed25519 -C "seu@email.com"

# RSA 4096 — para compatibilidade com legado
ssh-keygen -t rsa -b 4096 -C "seu@email.com"

# Com nome customizado (ex: chave só para GitHub)
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_github -C "github"

Copiando chave pública para o servidor

bash
# Automático — recomendado
ssh-copy-id user@host
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@host

# Manual via pipe
cat ~/.ssh/id_ed25519.pub | ssh user@host "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"

⚙️ SSH Config (~/.ssh/config)

Evita repetir flags na linha de comando. Define aliases, chaves, portas e comportamentos por host.

~/.ssh/config
# Defaults para todos os hosts
Host *
    ServerAliveInterval 60
    ServerAliveCountMax 3
    AddKeysToAgent yes
    IdentitiesOnly yes

# Servidor de produção
Host prod
    HostName 203.0.113.10
    User deploy
    Port 2222
    IdentityFile ~/.ssh/id_ed25519_prod

# Acesso a servidor interno via bastion
Host app-server
    HostName 10.0.1.50
    User ubuntu
    ProxyJump bastion

Host bastion
    HostName bastion.example.com
    User alfredo
    IdentityFile ~/.ssh/id_ed25519

# GitHub
Host github.com
    User git
    IdentityFile ~/.ssh/id_ed25519_github

# Padrão para hosts internos
Host *.internal
    User admin
    IdentityFile ~/.ssh/id_ed25519_internal

Diretivas mais úteis

HostName

IP ou FQDN real do servidor

User

Usuário padrão para conexão

Port

Porta SSH (padrão: 22)

IdentityFile

Chave privada específica para este host

ProxyJump

Conecta via outro host (bastion)

ForwardAgent

Encaminha ssh-agent ao servidor

LocalForward

Tunnel local → remoto

RemoteForward

Tunnel remoto → local

DynamicForward

Proxy SOCKS no host local

ServerAliveInterval

Keepalive: segundos entre pings

ControlMaster auto

Habilita multiplexação de conexões

ControlPersist 10m

Mantém master connection 10 minutos

IdentitiesOnly yes

Usa só chaves do IdentityFile (ignora agente)

StrictHostKeyChecking

yes / no / accept-new

AddKeysToAgent yes

Adiciona chave ao agente automaticamente

ControlPath

Caminho do socket de multiplexação

💻 Comandos de Conexão

bash
# Conexão básica
ssh user@host
ssh -p 2222 user@host            # porta customizada
ssh prod                            # usando alias do ~/.ssh/config
ssh -i ~/.ssh/id_ed25519 user@host  # especificar chave

# Executar comando remoto sem abrir shell
ssh user@host "ls -la /var/log"
ssh user@host "sudo systemctl status nginx"

# Enviar script local para rodar no servidor
ssh user@host 'bash -s' < script.sh

# Pseudo-TTY: necessário para sudo interativo
ssh -t user@host "sudo htop"

📦 Transferência de Arquivos

Seis ferramentas para transferência via SSH — cada uma com caso de uso diferente.

FerramentaInstalaçãoMelhor paraRetoma?Só o que mudou?
scp incluso no OpenSSH Cópia rápida de arquivo único
rsync geralmente pré-instalado Sync de diretórios, backups
sftp incluso no OpenSSH Sessão interativa, browse remoto
sshfs apt install sshfs Montar fs remoto como local
lftp apt install lftp Mirror avançado, scripting
rclone instalação separada SFTP + cloud (S3, GCS, Dropbox…)

SCP — cópia simples

Incluso no OpenSSH. Sintaxe parecida com cp. Não retoma transferências interrompidas — para isso use rsync.

bash — SCP
# Local → remoto
scp arquivo.txt user@host:/destino/
scp -r pasta/ user@host:/destino/             # recursivo

# Remoto → local
scp user@host:/caminho/arquivo.txt ./local/
scp -r user@host:/var/log/ ./logs-backup/

# Flags
scp -P 2222 arquivo.txt user@host:/tmp/            # porta customizada
scp -C arquivo.txt user@host:/tmp/                # compressão em trânsito
scp -l 5000 arquivo.txt user@host:/tmp/            # limitar banda: 5000 Kbit/s
scp -q arquivo.txt user@host:/tmp/                # silencioso (sem barra)
scp -i ~/.ssh/id_ed25519 arquivo.txt user@host:/tmp/ # chave específica

# Copiar entre dois servidores remotos (passa pelo local)
scp -3 user1@host1:/arquivo.txt user2@host2:/destino/

# Via bastion
scp -J bastion user@interno:/arquivo.txt .

RSYNC — sincronização eficiente

Transfere só o que mudou. Suporta retomada, exclusões, dry-run, limite de banda. Preferível ao SCP para diretórios e backups.

Geralmente pré-instalado. Se não estiver: apt install rsync — precisa estar instalado nos dois lados da conexão.

ℹ️
-a = archive

Atalho para -rlptgoD: recursivo + preserva permissões, timestamps, symlinks, owner, group.

bash — RSYNC
# Básico
rsync -avz --progress pasta/ user@host:/destino/

# Espelhar — apaga no destino o que não existe na origem
rsync -avz --delete pasta/ user@host:/destino/

# Porta customizada / chave específica
rsync -avz -e "ssh -p 2222" pasta/ user@host:/destino/
rsync -avz -e "ssh -i ~/.ssh/key -p 2222" pasta/ user@host:/destino/

# Simular sem executar (ver o que seria feito)
rsync -avz --dry-run --delete pasta/ user@host:/destino/

# Retomar transferência interrompida
rsync -avz --partial --progress pasta/ user@host:/destino/
rsync -avz --append-verify pasta/ user@host:/destino/

# Limitar banda: 500 KB/s
rsync -avz --bwlimit=500 pasta/ user@host:/destino/

# Excluir padrões
rsync -avz --exclude='*.log' --exclude='.git/' pasta/ user@host:/destino/
rsync -avz --exclude-from='rsync-exclude.txt' pasta/ user@host:/destino/

# Verificar por checksum em vez de timestamp+tamanho
rsync -avz --checksum pasta/ user@host:/destino/

# Backup: salva versão anterior antes de sobrescrever
rsync -avz --backup --backup-dir=/backup/$(date +%Y%m%d) pasta/ user@host:/destino/

# Estatísticas ao final
rsync -avz --stats pasta/ user@host:/destino/

SFTP — sessão interativa

Protocolo próprio (não é SCP). Permite browse, rename, mkdir, chmod no servidor remoto. Incluso no OpenSSH.

bash — conectar
sftp user@host
sftp -P 2222 user@host                  # porta customizada
sftp -i ~/.ssh/id_ed25519 user@host     # chave específica
sftp -b comandos.txt user@host          # modo batch (não interativo)

# Batch sem arquivo
echo "put arquivo.txt /remoto/" | sftp user@host
sftp — comandos interativos
# Navegação
ls / lls             # listar remoto / listar local
cd / lcd             # mudar dir remoto / local
pwd / lpwd           # dir atual remoto / local

# Download
get arquivo.txt                   # baixar arquivo
get arquivo.txt outro-nome.txt    # baixar com nome diferente
get -r pasta/                     # baixar diretório recursivo
mget *.log                        # múltiplos (wildcard)

# Upload
put local.txt                     # enviar arquivo
put local.txt /remoto/outro.txt   # enviar com nome diferente
put -r pasta/                     # enviar diretório recursivo
mput *.csv                        # múltiplos (wildcard)

# Gerenciamento remoto
mkdir /remoto/nova-pasta
rmdir /remoto/pasta-vazia
rm arquivo.txt
rename antigo.txt novo.txt
chmod 600 arquivo.txt
ln -s alvo link                   # symlink remoto
df -h                             # espaço em disco remoto

exit / quit / bye

SSHFS — montar filesystem remoto apt install sshfs

Monta diretório remoto localmente via FUSE. Edite arquivos remotos direto no seu editor local, como se fossem arquivos locais.

bash — instalar
# Ubuntu / Debian
sudo apt install sshfs

# macOS
brew install macfuse sshfs
bash — usar
# Criar ponto de montagem
mkdir -p ~/mnt/servidor

# Montar
sshfs user@host:/caminho/remoto ~/mnt/servidor
sshfs -p 2222 user@host:/var/www ~/mnt/www         # porta customizada
sshfs -o IdentityFile=~/.ssh/id_ed25519 user@host:/ ~/mnt/servidor

# Opções úteis
sshfs -o reconnect,ServerAliveInterval=15 user@host:/remoto ~/mnt/servidor
sshfs -o allow_other user@host:/remoto ~/mnt/servidor  # outros usuários locais
sshfs -o ro user@host:/remoto ~/mnt/servidor           # read-only

# Desmontar
fusermount -u ~/mnt/servidor     # Linux
umount ~/mnt/servidor            # macOS

# Montagem persistente (/etc/fstab)
# user@host:/remoto  /mnt/servidor  fuse.sshfs  defaults,_netdev,reconnect,uid=1000,gid=1000  0  0

lftp — mirror avançado apt install lftp

Mais poderoso que o sftp interativo. Mirror bidirecional, transferências paralelas, filas, scripting.

bash — instalar e usar
sudo apt install lftp

# Conectar via SFTP
lftp sftp://user@host
lftp sftp://user@host:2222        # porta customizada

# Dentro da sessão: mirror download
mirror /remoto/pasta ./local/pasta

# Mirror reverso (upload)
mirror -R ./local/pasta /remoto/pasta

# Mirror com opções
mirror --exclude='\.log$' /remoto/ ./local/
mirror --parallel=4 /remoto/ ./local/   # 4 conexões simultâneas
mirror --continue /remoto/ ./local/     # retomar interrompido

# Comandos inline (sem sessão interativa)
lftp -e "mirror /remoto/ ./local/; bye" sftp://user@host
lftp -e "put arquivo.txt; bye" sftp://user@host

rclone — SFTP + cloud instalação separada

Ferramenta universal de sync: SFTP, S3, GCS, Azure, Dropbox e 40+ provedores com a mesma interface.

bash — instalar
# Script oficial
curl https://rclone.org/install.sh | sudo bash

# macOS
brew install rclone
bash — configurar e usar
# Configurar remote SFTP (interativo)
rclone config
# → n (new remote) → nome → tipo: sftp → host, user, port, key file

# Listar
rclone ls meuservidor:/var/www

# Copiar local → remoto
rclone copy ./pasta meuservidor:/destino/

# Sync (espelha — deleta no destino o que não existe na origem)
rclone sync ./pasta meuservidor:/destino/

# Sync remoto → local
rclone sync meuservidor:/var/www ./backup/

# Dry run + progresso + log
rclone sync --dry-run -P --log-file=rclone.log ./pasta meuservidor:/destino/
💡
Quando usar cada um?

Arquivo único rápidoscp · Sync de diretório / backuprsync · Browse e gerenciar remotosftp · Editar remotamente no editor localsshfs · Mirror com paralelo/scriptlftp · Backup para cloud + SFTPrclone

🔀 Port Forwarding / Tunneling

SSH pode criar túneis TCP por dentro da conexão criptografada. Três modalidades:

Local Forward (-L) — acessa serviço remoto localmente

localhost:8080
túnel SSH cifrado
servidor
:80
Você acessa localhost:8080 no seu navegador, e sai na porta 80 do servidor remoto
bash
ssh -L 8080:localhost:80 user@host
ssh -L 5432:db-server:5432 user@bastion  # acessa DB interno via bastion

Remote Forward (-R) — expõe serviço local no servidor

localhost:3000
túnel SSH cifrado
servidor:9090
Quem acessa servidor:9090 chega na sua porta 3000 local. Útil para expor dev local na internet.
bash
ssh -R 9090:localhost:3000 user@host

Dynamic Forward (-D) — proxy SOCKS5

localhost:1080 (SOCKS5)
túnel SSH
qualquer destino
Configure o navegador para usar SOCKS5 localhost:1080. Todo tráfego sai pelo servidor remoto.
bash
ssh -D 1080 user@host

# Sem abrir shell (tunnel em background)
ssh -fN -L 5432:localhost:5432 user@db-host

# Múltiplos tunnels simultâneos
ssh -L 8080:localhost:80 -L 5432:localhost:5432 -N user@host

Jump Hosts / Bastion

Acessa servidor interno passando por um bastion host público.

seu computador
bastion (público)
app-server (privado)
bash
# Flag direto
ssh -J bastion.example.com user@app-server-interno
ssh -J bastion1,bastion2 user@destino   # múltiplos saltos

# Copiar arquivo via bastion
scp -J bastion user@interno:/arquivo.txt .

# Via config (preferível)
Host app-server
    ProxyJump bastion

🤖 ssh-agent

Mantém chaves privadas decifradas em memória. Você digita a passphrase uma vez — o agente autentica nas conexões seguintes.

bash
# Iniciar agente
eval "$(ssh-agent -s)"

# Adicionar chave (pede passphrase uma vez)
ssh-add ~/.ssh/id_ed25519
ssh-add -t 3600 ~/.ssh/id_ed25519  # expira em 1h

# Listar chaves carregadas
ssh-add -l

# Remover
ssh-add -d ~/.ssh/id_ed25519  # uma chave
ssh-add -D                    # todas

# Agent Forwarding — leva o agente para o servidor remoto
ssh -A user@bastion
# de dentro do bastion, pode autenticar em outros hosts
# usando as chaves do seu computador local
⚠️
Agent Forwarding expõe o socket do agente no servidor remoto

Se o servidor for comprometido, alguém pode usar seu agente para autenticar em outros hosts. Use só em servidores confiáveis. Prefira ProxyJump quando possível.

⚡ Multiplexação de Conexões

Reutiliza a TCP connection existente. Segunda conexão ao mesmo host é instantânea — sem renegociar KEX, sem nova autenticação.

~/.ssh/config
Host *
    ControlMaster auto
    ControlPath   ~/.ssh/ctl/%r@%h:%p
    ControlPersist 10m
bash
mkdir -p ~/.ssh/ctl

# Verificar se master está ativo
ssh -O check user@host

# Encerrar master
ssh -O stop user@host
ssh -O exit user@host

📋 known_hosts

Armazena fingerprints dos servidores já visitados. Protege contra man-in-the-middle alertando quando a chave do servidor muda.

bash
# Ver fingerprint de um host antes de conectar
ssh-keyscan -t ed25519 hostname
ssh-keyscan -p 2222 hostname

# Adicionar host manualmente
ssh-keyscan hostname >> ~/.ssh/known_hosts

# Remover host (servidor trocou chave, ou foi rebuiltado)
ssh-keygen -R hostname
ssh-keygen -R [hostname]:2222

# Ver fingerprint de chave
ssh-keygen -lf ~/.ssh/id_ed25519.pub
ssh-keygen -lv -f ~/.ssh/id_ed25519.pub  # formato visual (randomart)

🖥️ Configuração do Servidor (sshd_config)

/etc/ssh/sshd_config
# Protocolo
Protocol 2

# Host keys — manter apenas modernos
HostKey /etc/ssh/ssh_host_ed25519_key
HostKey /etc/ssh/ssh_host_rsa_key

# Autenticação
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
PermitEmptyPasswords no

# Restrições
MaxAuthTries 3
MaxSessions 10
LoginGraceTime 30

# Keepalive
ClientAliveInterval 300
ClientAliveCountMax 2

# Desabilitar o que não usa
X11Forwarding no
AllowAgentForwarding no
AllowTcpForwarding no    # mudar para yes se precisar de tunnels
GatewayPorts no
PermitTunnel no

# Algoritmos modernos
KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com
MACs hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com

# Restringir por usuário
AllowUsers deploy alfredo

# SFTP
Subsystem sftp /usr/lib/openssh/sftp-server
bash — gerenciar sshd
# Validar config ANTES de reiniciar (não derruba sessões ativas)
sshd -t

# Ver config efetiva
sshd -T

# Recarregar sem derrubar sessões
systemctl reload sshd

Blocos Match — regras condicionais

/etc/ssh/sshd_config
# Regras por usuário
Match User deploy
    AllowTcpForwarding yes
    ForceCommand /usr/bin/deploy-shell

# Regras por grupo — chroot SFTP
Match Group sftp-only
    ChrootDirectory /var/sftp/%u
    ForceCommand internal-sftp
    AllowTcpForwarding no

# Regras por IP
Match Address 10.0.0.0/8
    PasswordAuthentication yes

🗝️ authorized_keys — opções por chave

Cada linha pode ter opções que restringem o que aquela chave pode fazer.

~/.ssh/authorized_keys
# Formato: [opções] <tipo> <chave> [comentário]

# Deploy key: só permite executar git-shell
command="/usr/bin/git-shell -c \"$SSH_ORIGINAL_COMMAND\"",no-port-forwarding,no-X11-forwarding,no-agent-forwarding ssh-ed25519 AAAA... github-deploy

# Restringir a IPs específicos
from="203.0.113.10,10.0.0.0/8" ssh-ed25519 AAAA... restricted-key

# Forçar PTY + restringir tudo mais
restrict,pty ssh-ed25519 AAAA...

# Com expiração (OpenSSH 8.2+)
expiry-time="20261231" ssh-ed25519 AAAA...

📜 Certificados SSH

Alternativa ao authorized_keys para escala. Uma CA central assina chaves — servidores confiam na CA, não em chaves individuais.

😩

Problema com authorized_keys em escala

100 servidores + 50 devs = gerenciar 5000 entradas. Revogar uma chave = atualizar todos os servidores.

Solução com Certificados

CA assina a chave do dev. Todos os servidores confiam na CA. Revogar = invalidar o certificado em um lugar.

bash
# 1. Criar CA (é um par de chaves normal)
ssh-keygen -t ed25519 -f ssh_ca -C "My SSH CA"

# 2. Assinar chave de usuário (-V: validade, -n: principals)
ssh-keygen -s ssh_ca -I "alfredo@empresa" -n "alfredo,deploy" -V +52w id_ed25519.pub
# gera: id_ed25519-cert.pub

# 3. Assinar host key do servidor
ssh-keygen -s ssh_ca -I "prod-server" -h -V +52w /etc/ssh/ssh_host_ed25519_key.pub

# 4. Servidor confia na CA (sshd_config)
TrustedUserCAKeys /etc/ssh/ssh_user_ca.pub

# 5. Cliente confia em hosts assinados pela CA (known_hosts)
@cert-authority *.example.com ssh-ed25519 AAAA... SSH CA
🔄

Revogação centralizada

Sem tocar authorized_keys em cada servidor.

📅

Expiração nativa

Certificados expiram automaticamente. Sem chaves eternas.

🔍

Auditoria

Campo key ID aparece nos logs de autenticação.

⌨️ Escape Sequences

Durante uma sessão SSH interativa, ~ é o escape character. Permite controlar a conexão sem fechar o terminal.

~.
Fechar conexão (força)
~C
Prompt de comando SSH (adicionar tunnel em sessão ativa)
~#
Listar conexões encaminhadas
~?
Listar todos os escape codes
~Z
Suspender conexão (coloca em background)
~~
Enviar ~ literal
💡
~C é especialmente útil

Abre prompt ssh> onde você pode digitar -L 8080:localhost:80 para adicionar um tunnel em uma sessão já aberta.

🔧 Recursos Avançados

SSH sobre HTTPS (porta 443)

Útil quando porta 22 está bloqueada em redes corporativas ou firewalls restritivos.

~/.ssh/config
Host github.com
    HostName ssh.github.com
    Port 443
    User git

Gerenciamento avançado de chaves

bash
# Mudar passphrase de chave existente
ssh-keygen -p -f ~/.ssh/id_ed25519

# Extrair chave pública a partir da privada
ssh-keygen -y -f ~/.ssh/id_ed25519

# Assinar arquivo com chave SSH (OpenSSH 8.0+)
ssh-keygen -Y sign -f ~/.ssh/id_ed25519 -n file documento.txt
ssh-keygen -Y verify -f allowed_signers -I user@email -n file -s documento.txt.sig < documento.txt

ProxyCommand customizado

~/.ssh/config
# Via proxy SOCKS5 (netcat)
Host interno
    ProxyCommand nc -X 5 -x proxy:1080 %h %p

# Via proxy HTTP CONNECT (corkscrew)
Host interno
    ProxyCommand corkscrew proxy 3128 %h %p

🔍 Debug e Diagnóstico

bash
# Verbose no cliente (até -vvv)
ssh -v user@host
ssh -vvv user@host   # máximo detalhe

# Ver config efetiva do servidor
sshd -T
sshd -T -C user=alfredo   # config para usuário específico

# Logs do servidor
journalctl -u sshd -f
tail -f /var/log/auth.log    # Debian/Ubuntu
tail -f /var/log/secure      # RHEL/CentOS

# Verificar qual chave foi aceita
ssh -v user@host 2>&1 | grep "Offering\|Accepted"

# Corrigir permissões
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519
chmod 600 ~/.ssh/authorized_keys
chmod 644 ~/.ssh/id_ed25519.pub

Checklist de troubleshooting

  • 1
    Permissões de ~/.ssh/ (700) e authorized_keys (600) no servidor
  • 2
    authorized_keys contém a chave pública correta — sem quebra de linha no meio
  • 3
    sshd_config tem PubkeyAuthentication yes
  • 4
    StrictModes yes — home dir do usuário não pode ser writable por outros
  • 5
    SELinux / AppArmor não bloqueando acesso ao .ssh/
  • 6
    Firewall permitindo a porta SSH
  • 7
    ssh -vvv — mostra exatamente onde a autenticação falha

🛡️ Segurança — Boas Práticas

PermitRootLogin no Sempre. Sem exceção.
PasswordAuthentication no Autenticação só por chave pública.
Passphrase nas chaves privadas Sempre. Use ssh-agent para não digitar toda hora.
ed25519 por padrão RSA 4096 só quando precisa de compatibilidade com legado.
Chave separada por contexto Uma para GitHub, outra para prod, outra para pessoal.
fail2ban ou sshguard Bloqueia brute force automaticamente.
AllowUsers / AllowGroups Restringe quem pode conectar no servidor.
Atualizar OpenSSH Vulnerabilidades surgem. Manter atualizado é obrigatório.
Auditar authorized_keys Remover chaves de ex-funcionários e obsoletas periodicamente.
ssh-add -t 3600 Limitar tempo de vida das chaves no agente.
Certificados SSH em escala Revogação centralizada, expiração nativa, auditoria.
ProxyJump > Agent Forwarding Para bastions, prefira ProxyJump — não expõe o agente.
🚨
Mudar a porta 22 NÃO é segurança

Reduz logs de ruído (scanners automáticos), mas qualquer atacante com foco vai encontrar a porta nova. Não substitui autenticação forte.

⚡ Referência Rápida

🔌 Conexão
básica
ssh user@host
ssh -p 2222 user@host
com chave específica
ssh -i ~/.ssh/key user@host
comando remoto
ssh user@host "cmd"
com TTY
ssh -t user@host "sudo cmd"
📦 Arquivos
copiar arquivo
scp src user@host:dst
sincronizar diretório
rsync -avz src/ user@host:dst/
com remoção de extras
rsync -avz --delete src/ user@host:dst/
🗝️ Chaves
gerar
ssh-keygen -t ed25519
copiar para servidor
ssh-copy-id user@host
carregar no agente
ssh-add ~/.ssh/id_ed25519
listar no agente
ssh-add -l
🔀 Tunnels
local
ssh -L lport:host:rport user@host
remoto
ssh -R rport:host:lport user@host
SOCKS5
ssh -D 1080 user@host
background sem shell
ssh -fN -L 5432:localhost:5432 user@host
🔍 Debug
verbose
ssh -vvv user@host
testar config sshd
sshd -t
config efetiva
sshd -T
remover host de known_hosts
ssh-keygen -R hostname
🏗️ Bastion
conectar via jump host
ssh -J bastion user@destino
múltiplos saltos
ssh -J b1,b2 user@destino
scp via bastion
scp -J bastion user@host:/file .

Referências

📖

RFCs

RFC 4251 · 4252 · 4253 · 4254

📚

OpenSSH

man ssh · man sshd_config · man ssh_config · man ssh-keygen

🦊

Mozilla Guidelines

infosec.mozilla.org/guidelines/openssh