vps-forge: agentes com root em VPS ganharam rollback automático, e autobanimentos caíram de 7 em 60 para 0

Um desenvolvedor lançou o vps-forge, um Agent Skill aberto para Claude Code, Codex, Cursor e outros agentes que recebem root em um VPS. O problema é corriqueiro: no benchmark, o Claude Opus 5.5, sem nenhuma orientação, baniu o próprio IP via fail2ban em 7 de 60 execuções, deixando de fora também o notebook do dono. O principal componente do skill é o timer de rollback vps-forge-deadman. Antes de mexer em SSH, firewall, sudo ou PAM, o agente arma um timer do systemd de 5 minutos; se o novo login não for confirmado, as configurações são restauradas automaticamente. Em 120 execuções, a nota subiu de 79–92 para 99–100 de 100. • Cada execução custa $1.87, contra $0.62 sem o skill • Ninguém perdeu acesso, nem mesmo sem o skill • Código sob licença MIT, sem telemetria

Processado por IA de Habr AI; editado por Hamidun News
vps-forge: agentes com root em VPS ganharam rollback automático, e autobanimentos caíram de 7 em 60 para 0
Fonte: Habr AI. Colagem: Hamidun News.
Ouvir artigo
Ficha técnica e números-chave
ParâmetroDados
Fonte originalHabr AI ↗
Editor-chefe
Dado-chave #1Cada execução custa $1.87, contra $0.62 sem o skill
Dado-chave #2Ninguém perdeu acesso, nem mesmo sem o skill
Dado-chave #3Código sob licença MIT, sem telemetria

Um agente com root em um VPS recém-criado instala o fail2ban, confere o login por chave, testa a senha e, na quinta tentativa falha, bane o IP de onde partem os testes. Ou seja, o seu. Daí em diante, todos os comandos caem por timeout, e você precisa procurar o console web no painel da hospedagem. No benchmark do autor do vps-forge, o Claude Opus 5.5, sem nenhuma orientação, baniu a si mesmo em 7 de 60 execuções. O modelo é inteligente; só que ninguém avisou para incluir o próprio endereço no ignoreip antes da primeira execução do fail2ban.

O vps-forge é um Agent Skill aberto: um conjunto de instruções e scripts bash que Claude Code, Codex, Cursor e outros agentes carregam quando o assunto é servidor. Instalação: `npx skills add mountain-beaver/vps-forge -g`. Há um plugin para o Claude Code e um arquivo zip para o Claude.ai.

Por que "tenha cuidado" não funciona

Um sshd_config quebrado parece funcionar. O `sshd -t` não reclama, o reload passa, a sessão atual continua viva, mas o novo login já está bloqueado: por exemplo, `AllowUsers deploy` onde você é admin, ou um AllowGroups em que você esqueceu de incluir a si mesmo.

Os agentes têm uma armadilha própria. Eles mantêm uma única conexão via ControlMaster, e a checagem `ssh host true` segue pelo canal antigo. Ela não passa pelo novo sshd nem pelas novas regras de firewall: o teste fica verde, mas não dá para entrar. A instrução "verifique o login a partir de uma nova conexão" não salva se o agente já perdeu o acesso. É preciso um mecanismo que funcione sem ele.

Um pedal de homem morto para o sshd

Antes de cada alteração em SSH, firewall, sudo ou PAM, o agente executa `vps-forge-deadman arm`. O script tira um snapshot das configurações e cria um timer do systemd de 5 minutos. O agente altera a configuração, entra de novo com `ssh -o ControlPath=none` e, se o login funcionar, faz o disarm. Se não funcionar, não precisa fazer nada: em 5 minutos o timer restaura tudo como estava.

No papel, eram 20 linhas de bash; no fim, viraram várias centenas. Quase cada linha corresponde a um problema:

  • Reinicialização. O timer criado com systemd-run vive na memória e some junto com o servidor. Agora o arm também ativa uma unit que, na inicialização, detecta o estado "armado, mas não desarmado" e faz o rollback sozinha.
  • nftables. O rollback parava um serviço que estava desligado antes do arm, e o ExecStop continha `nft flush ruleset`. Junto com a regra necessária, sumiam o ufw, os bans do fail2ban e as chains do Docker. Agora só são removidas as tabelas da configuração revertida.
  • Localização russa do ufw. O script procurava a string `Status: active`, mas o ufw escreve "Состояние: активен". O firewall era considerado desligado e acabava desativado no rollback. A correção é `LC_ALL=C`.
  • Ban após o rollback. As configurações voltavam, mas o IP continuava banido. Agora o arm memoriza o endereço do cliente SSH, e o rollback o desbane. Sob sudo, a variável SSH_CLIENT não existe, então o endereço é obtido do ambiente do processo pai.

Tudo isso roda no CI: um contêiner com systemd de verdade, um teste que quebra o sshd, o firewall e o fail2ban, reinicia o contêiner em estado armado e verifica a recuperação. O firewall no painel do provedor não pode ser revertido, pois fica fora do servidor. Nesse caso só vale a ordem: primeiro adicionar a nova regra, conferir o login e depois remover a antiga.

Armadilhas das imagens de nuvem e o benchmark

A mais traiçoeira é o cloud-init. Em muitos VPS há um `50-cloud-init.conf` com `PasswordAuthentication yes`. O sshd usa o primeiro valor lido, e os arquivos são lidos em ordem alfabética, então o conselho popular do `99-hardening.conf` não faz nada. O arquivo do skill se chama `00-vps-forge.conf`, e o resultado é verificado com `sshd -T`. Outros pontos: o Debian 12 não tem auth.log, o Docker publica portas contornando o ufw, a imagem do Oracle Cloud traz uma regra REJECT própria no iptables, e o Coolify acessa o próprio host por SSH como root, de modo que `PermitRootLogin no` quebra o deploy.

O ambiente de testes: VMs reais em QEMU (Debian 12 e 13, Ubuntu 22.04, 24.04, 26.04), quatro cenários, cada um três vezes sem o skill e com ele — 120 execuções do Opus 5.5. Um juiz verifica o servidor por fora, antes e depois da reinicialização. Sem o skill, a nota foi de 79–92 de 100; com ele, 99–100.

  • ssh-audit sem falhas: 4/60 sem o skill, 60/60 com ele
  • Alerta de login SSH: 16/30 e 30/30
  • Firewall ativado: 46/60 e 60/60
  • Força bruta de senha é banida: 50/60 e 60/60
  • Root não consegue entrar: 30/60 e 57/60
  • Agente baniu a si mesmo: 7/60 e 0/60
  • Perda de acesso: 0/60 e 0/60

O autor aponta honestamente os pontos fracos. Um servidor intocado recebe 25–42 pontos. Cerca de 70% da diferença vêm de três checagens que coincidem com as configurações do próprio skill: ssh-audit limpo, proibição de root e alerta. O juiz e o skill foram escritos pela mesma pessoa, e o Lynis independente quase não se mexe: 69 e 71, 72 e 72, 64 e 72, 73 e 72. Três dos quatro cenários foram usados no refinamento do skill. O modelo é um só, além de quatro execuções manuais com o GLM-5.3. O rollback não foi comprovado pelo benchmark: ninguém perdeu acesso, nem mesmo sem o skill.

Preço e como usar

O skill é mais lento e custa cerca de três vezes mais: $1.87 contra $0.62 por execução. O ganho que realmente sobra é o fail2ban banindo de fato num servidor em operação (6 de 15 sem o skill, 15 de 15 com ele), o firewall ativado e zero autobanimentos.

Na prática: antes da primeira alteração em SSH, confira se o agente executou `vps-forge-deadman arm`; se não, o skill não foi carregado e não há rede de proteção. O script funciona também sem agente, e dá para testá-lo manualmente num servidor descartável: armar por um minuto, colocar `AllowUsers deploy`, confirmar que o login foi bloqueado e esperar o status ROLLED BACK. Ainda assim, são necessários um snapshot no provedor e acesso ao console. O RHEL ainda não é suportado, e o skill não mexe em nós de Kubernetes. O código é MIT, sem telemetria, e o ambiente de testes está no diretório bench/ do repositório mountain-beaver/vps-forge.

História

Perguntas frequentes sobre a notícia

Por que "tenha cuidado" não funciona?

Um sshd_config quebrado parece funcionar. O `sshd -t` não reclama, o reload passa, a sessão atual continua viva, mas o novo login já está bloqueado: por exemplo, `AllowUsers deploy` onde você é admin, ou um AllowGroups em que você esqueceu de incluir a si mesmo. Os agentes têm uma armadilha própria. Eles mantêm uma única conexão via ControlMaster, e a checagem `ssh host true` segue pelo canal antigo. Ela não passa pelo novo sshd nem pelas novas regras de firewall: o teste fica verde, mas não dá para entrar. A instrução "verifique o login a partir de uma nova conexão" não sa

O que se sabe sobre Um pedal de homem morto para o sshd?

Antes de cada alteração em SSH, firewall, sudo ou PAM, o agente executa `vps-forge-deadman arm`. O script tira um snapshot das configurações e cria um timer do systemd de 5 minutos. O agente altera a configuração, entra de novo com `ssh -o ControlPath=none` e, se o login funcionar, faz o disarm. Se não funcionar, não precisa fazer nada: em 5 minutos o timer restaura tudo como estava. No papel, eram 20 linhas de bash; no fim, viraram várias centenas. Quase cada linha corresponde a um problema: Reinicialização. O timer criado com systemd-run vive na memória e some junto com o

O que se sabe sobre Armadilhas das imagens de nuvem e o benchmark?

A mais traiçoeira é o cloud-init. Em muitos VPS há um `50-cloud-init.conf` com `PasswordAuthentication yes`. O sshd usa o primeiro valor lido, e os arquivos são lidos em ordem alfabética, então o conselho popular do `99-hardening.conf` não faz nada. O arquivo do skill se chama `00-vps-forge.conf`, e o resultado é verificado com `sshd -T`. Outros pontos: o Debian 12 não tem auth.log, o Docker publica portas contornando o ufw, a imagem do Oracle Cloud traz uma regra REJECT própria no iptables, e o Coolify acessa o próprio host por SSH como root, de modo que `PermitRootLogin n

ZK
Zhemal Khamidun — CPO da Alpina Digital, gerente de produto do AlpinaGPT. Cria produtos de IA desde 2019. O Hamidun News é um projeto pessoal que virou um agregador em produção com mais de 6.000 leitores.
✦ Hands-On AI Engineering · Hamidun Academy

Build & Ship Production AI Agents Without Boilerplate Code

Start your free 72-hour trial at Hamidun Academy (academy.hamidun.com) — interactive lessons on Claude Code & Cursor, live Tech Radar, and production agent templates.

Start 72h Free Trial →Vibe-Coding Intensive
O que você acha?
Carregando comentários…