implant ssh-service

Wrapper de alto nível sobre a primitiva lockdown para restringir o acesso SSH com TTL e auto-recovery. Quem ativa o lockdown (um operador, um script ou um agente de controle remoto) envia heartbeats periódicos para renovar o TTL. Se o operador (ou o canal) sumir, o systemd-run agendado durante o disable restaura o SSH automaticamente quando o TTL expira — sem precisar do implant ou do agente vivos.

Uso

implant ssh-service <subcomando> [OPTIONS]

Subcomandos

`disable [--ttl-seconds ] [--force]`

Bloqueia a porta SSH atual no UFW (se ativo), para o ssh/sshd e agenda um systemd-run --on-active={N}s que vai restaurar tudo quando o TTL expirar. Persiste o estado em /var/lib/implant/lockdowns/ssh-service.json.

  • --ttl-seconds <N> — TTL em segundos (default 900, max 21600 = 6h)
  • --force — prossegue mesmo com regra de bypass de emergência ativa (ver abaixo); nesse caso o lockdown não é efetivo

O restore libera a porta SSH com regras marcadas com o comentário implant-emergency-ssh (no topo da INPUT em iptables/ip6tables e no UFW) antes de subir o sshd. Se essas regras ainda estiverem presentes, o disable recusa — o SSH continuaria acessível por elas.

`heartbeat --ttl-seconds [--source ]`

Renova o TTL (atualiza expires_at para now + N e re-agenda o systemd-run). Normalmente chamado em loop por quem mantém o lockdown.

  • --ttl-seconds <N> — TTL renovado em segundos (default 900)
  • --source <id> — identificador da origem do heartbeat (gravado em last_heartbeat_source, útil para auditoria)

`status`

Mostra o estado atual: serviço em lockdown, quando foi disabled, quando expira, último heartbeat, history de eventos.

`emergency-restore`

Restauração imediata, sem esperar TTL expirar. Exige TTY interativo (prompt de confirmação). Marca evento emergency na history.

`cleanup-emergency-rules`

Remove as regras de bypass implant-emergency-ssh deixadas por um restore anterior (iptables, ip6tables e UFW). Rode antes de um novo disable.

Saída JSON (`--output json`)

Todos os subcomandos retornam o Envelope padrão. O data contém o registro do lockdown (schema completo):

{
  "success": true,
  "schema_version": "1.0",
  "client": {"name": "implant", "version": "2.54.0"},
  "command": "ssh-service.disable",
  "timestamp": "2026-05-13T15:30:00Z",
  "data": {
    "service": "ssh-service",
    "disabled_at": "2026-05-13T15:30:00Z",
    "expires_at": "2026-05-13T15:45:00Z",
    "ttl_seconds": 900,
    "lockdown_cmd": "ufw deny 22/tcp 2>/dev/null || true; (systemctl stop sshd 2>/dev/null || systemctl stop ssh 2>/dev/null || true)",
    "restore_cmd": "iptables -I INPUT 1 -p tcp --dport 22 -m comment --comment 'implant-emergency-ssh' -j ACCEPT ...; (systemctl start sshd ... )",
    "last_heartbeat": null,
    "last_heartbeat_source": null,
    "history": [
      {"timestamp": "2026-05-13T15:30:00Z", "event_type": "created", "detail": null}
    ],
    "schema_version": "1.0"
  }
}

Para status sem lockdown ativo, data é null.

Exemplos

# Ativar lockdown por 15 min:
sudo implant ssh-service disable --ttl-seconds 900

# Manter ativo enviando heartbeats (ex.: a cada 5min):
sudo implant ssh-service heartbeat --ttl-seconds 900 --source meu-script

# Inspecionar estado:
implant --output json ssh-service status | jq '.data | {expires_at, last_heartbeat}'

# Recovery manual (exige TTY):
sudo implant ssh-service emergency-restore

# Depois do recovery, limpar as regras de bypass antes do próximo disable:
sudo implant ssh-service cleanup-emergency-rules

Threat model

O lockdown é fail-open: se algo morre (binário do implant, agente de controle remoto, servidor de gerenciamento, rede), o sshd volta sozinho via systemd-run agendado. Nunca depende de processo em userspace mantido vivo para liberar o SSH. O canal de heartbeat é apenas para manter o lockdown, não para liberá-lo.

Se o sistema que envia os comandos remotamente for comprometido, ele pode:

  • Parar de mandar heartbeats: o sshd volta quando o TTL atual expira.
  • Rodar disable (TTL de até 6h por chamada; não há limite de frequência).
  • Renovar o lockdown quantas vezes quiser: MAX_TTL_SECONDS limita cada renovação a 6h, não o número de renovações. Enquanto renovar, o SSH continua restrito.

Como recuperar o acesso nesse caso: emergency-restore no próprio servidor (exige terminal interativo — console da VPS/provedor), ou cortar o acesso do sistema comprometido; sem renovação, o SSH volta em no máximo 6h.

Veja também