SSH: conectando e gerenciando servidores remotos

O SSH (Secure Shell) é o protocolo padrão para administração segura de servidores remotos no ecossistema Linux/Unix. Este artigo aborda desde conexões básicas até técnicas avançadas de automação e tunelamento, sempre com foco em scripts Bash.

1. Fundamentos da Conexão SSH

1.1 Sintaxe básica

A sintaxe fundamental do SSH é:

ssh usuario@host

Por padrão, o SSH utiliza a porta 22. Para especificar outra porta:

ssh -p 2222 usuario@servidor.com

1.2 Primeiro acesso

Ao conectar pela primeira vez, o cliente exibe a impressão digital do host remoto:

$ ssh admin@192.168.1.100
The authenticity of host '192.168.1.100 (192.168.1.100)' can't be established.
ED25519 key fingerprint is SHA256:...
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes

A resposta yes salva a chave em ~/.ssh/known_hosts.

1.3 Encerrando sessões

exit          # comando padrão
logout        # alternativa
Ctrl+D        # atalho de teclado
Ctrl+Z        # suspende a sessão (fg para retomar)

2. Autenticação por Chave Pública

2.1 Gerando par de chaves

ssh-keygen -t ed25519 -C "servidor-producao"   # Recomendado (moderno)
ssh-keygen -t rsa -b 4096 -C "servidor-antigo" # Compatibilidade

Por padrão, as chaves são salvas em ~/.ssh/id_ed25519 (privada) e ~/.ssh/id_ed25519.pub (pública).

2.2 Copiando chave pública

Automático:

ssh-copy-id -i ~/.ssh/id_ed25519.pub usuario@servidor

Manual:

cat ~/.ssh/id_ed25519.pub | ssh usuario@servidor "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"

2.3 Gerenciando agentes

eval "$(ssh-agent -s)"          # Inicia o agente
ssh-add ~/.ssh/id_ed25519       # Adiciona chave ao agente
ssh-add -l                      # Lista chaves carregadas
ssh-add -D                      # Remove todas as chaves

3. Configuração Avançada do Cliente SSH

3.1 Arquivo ~/.ssh/config

Host servidor-prod
    HostName 192.168.1.100
    User admin
    Port 2222
    IdentityFile ~/.ssh/producao
    ServerAliveInterval 60

Host github.com
    HostName github.com
    User git
    IdentityFile ~/.ssh/github

Agora basta ssh servidor-prod para conectar.

3.2 Opções de conexão

ssh -v usuario@host          # Modo verboso (depuração)
ssh -i ~/.ssh/chave.pem -l ubuntu 54.123.45.67
ssh -p 2222 -o "StrictHostKeyChecking=no" usuario@host

3.3 Jump Hosts

Para acessar servidores atrás de um bastion:

ssh -J usuario@bastion:2222 usuario@servidor-interno

No arquivo de configuração:

Host servidor-interno
    HostName 10.0.0.50
    ProxyJump usuario@bastion:2222

4. Execução Remota de Comandos

4.1 Comando único

ssh usuario@servidor "uptime && df -h"
ssh usuario@servidor "sudo systemctl restart nginx"

4.2 Redirecionamento de saída

# Coletar logs remotos localmente
ssh usuario@servidor "cat /var/log/syslog" > logs-remoto.txt

# Pipeline remoto
ssh usuario@servidor "ps aux | grep nginx"

# Comandos locais usando saída remota
ssh usuario@servidor "cat /etc/hostname" | while read host; do
    echo "Hostname remoto: $host"
done

4.3 Scripts remotos

# Executar script local no servidor remoto
cat script-backup.sh | ssh usuario@servidor "bash -s"

# Script com argumentos
ssh usuario@servidor 'bash -s' < script.sh -- --verbose --output /tmp

5. Transferência Segura de Arquivos

5.1 SCP básico

# Local para remoto
scp arquivo.txt usuario@servidor:/home/usuario/

# Remoto para local
scp usuario@servidor:/var/log/app.log .

# Cópia recursiva de diretório
scp -r ~/projeto/ usuario@servidor:/backup/

5.2 SFTP interativo

sftp usuario@servidor
sftp> ls
sftp> cd /var/www
sftp> get arquivo.zip
sftp> put config.json
sftp> get -r logs/   # Recursivo
sftp> bye

5.3 Automação com rsync

# Sincronização incremental
rsync -avz --progress usuario@servidor:/dados/ /backup-local/

# Excluindo arquivos
rsync -avz --exclude='*.log' --exclude='cache/' /local/ usuario@servidor:/destino/

# Modo dry-run (simulação)
rsync -avz --dry-run usuario@servidor:/origem/ /destino/

6. Tunelamento e Redirecionamento de Portas

6.1 Tunelamento local (-L)

Acessar serviço remoto como se fosse local:

ssh -L 8080:localhost:80 usuario@servidor
# Agora http://localhost:8080 acessa o servidor remoto na porta 80

6.2 Tunelamento remoto (-R)

Expor serviço local para o servidor remoto:

ssh -R 9090:localhost:3000 usuario@servidor
# No servidor, http://localhost:9090 acessa sua máquina local na porta 3000

6.3 Proxy SOCKS dinâmico (-D)

Navegação segura através do servidor:

ssh -D 1080 usuario@servidor
# Configure o navegador para usar SOCKS5 em localhost:1080

7. Gerenciamento de Sessões e Multiplexação

7.1 Controle mestre

No arquivo ~/.ssh/config:

Host *
    ControlMaster auto
    ControlPath ~/.ssh/controlmasters/%r@%h:%p
    ControlPersist 10m

Criação manual:

ssh -M -S ~/.ssh/socket-servidor usuario@servidor

7.2 Reutilizando conexões

# Primeira conexão (cria socket)
ssh -M -S /tmp/ssh-socket usuario@servidor

# Conexões subsequentes (reutilizam)
ssh -S /tmp/ssh-socket usuario@servidor "comando"

7.3 Mantendo sessões ativas

ssh -o "ServerAliveInterval=60" -o "ServerAliveCountMax=3" usuario@servidor

No arquivo de configuração:

Host *
    ServerAliveInterval 60
    TCPKeepAlive yes

8. Segurança e Boas Práticas

8.1 Configurações do servidor

No arquivo /etc/ssh/sshd_config:

PermitRootLogin no
AllowUsers admin devops
PasswordAuthentication no
PubkeyAuthentication yes
Port 2222

8.2 Protegendo chaves privadas

chmod 600 ~/.ssh/id_ed25519        # Permissão correta
chmod 700 ~/.ssh                   # Diretório seguro
ssh-keygen -p -f ~/.ssh/id_ed25519 # Alterar passphrase

8.3 Monitoramento

# Quem está conectado agora
who
last | grep "still logged in"

# Logs de autenticação
sudo tail -f /var/log/auth.log | grep sshd

# Últimos logins bem-sucedidos
lastb                          # Tentativas falhas
last -i                        # Com endereços IP

Script completo de automação

#!/bin/bash
# backup-remoto.sh - Backup incremental via SSH

SERVIDOR="usuario@servidor-prod"
ORIGEM="/var/www/html"
DESTINO="/backup/site-$(date +%Y%m%d)"
LOG="/var/log/backup-ssh.log"

echo "[$(date)] Iniciando backup..." >> "$LOG"

# Testar conexão
ssh -q "$SERVIDOR" "exit" || { echo "Falha na conexão"; exit 1; }

# Backup com rsync
rsync -avz --delete --progress \
    -e "ssh -i ~/.ssh/producao" \
    "$SERVIDOR:$ORIGEM/" "$DESTINO/" >> "$LOG" 2>&1

# Verificar resultado
if [ $? -eq 0 ]; then
    echo "[$(date)] Backup concluído com sucesso" >> "$LOG"
else
    echo "[$(date)] ERRO no backup" >> "$LOG"
    exit 1
fi

Referências