Docs/ Segurança/ Acessar o painel por um túnel SSH

Acessar o painel por um túnel SSH

Um painel que ninguém alcança pela Internet não pode ser atacado pela Internet.

Visão geral

Seus aplicativos são servidos pelo sh0 nas portas 80 e 443. O painel, que controla todos eles, não precisa estar exposto. No modo somente túnel, ele escuta apenas em 127.0.0.1:9000: a única entrada é uma conexão SSH ao servidor, que seu firewall já restringe e que você já protege com uma chave.

Por que não um domínio de painel público

Todo certificado TLS é publicado nos registros públicos de Certificate Transparency, então um domínio de painel como panel.example.com aparece no crt.sh minutos depois da emissão do certificado. Os scanners leem esses registros: um painel público é encontrado e sondado, seja qual for a política de senhas.

Instalar no modo somente túnel

Em um servidor novo, como root, com o firewall já limitado a SSH, 80 e 443:

bash
curl -fsSL https://get.sh0.dev | bash -s -- --harden --panel-tunnel-only

Antes da primeira inicialização do sh0, o instalador grava um drop-in do systemd que vincula o painel a 127.0.0.1, desativa o registro *.sh0.app (um proxy não alcança um painel em localhost) e, com --harden, não abre a porta 9000 no ufw. Ele termina exibindo o comando ssh exato para colar no seu próprio computador.

Warning
Neste modo, seus aplicativos perdem os endereços gratuitos *.sh0.app. O proxy *.sh0.app alcança o servidor pela porta 9000, que o modo somente túnel fecha, então cada aplicativo precisa ser servido em um domínio próprio. Se você ou seus desenvolvedores não têm domínio, mantenha a instalação padrão: o painel continua acessível na porta 9000 e cada aplicativo mantém seu endereço gratuito.
Note
A primeira conta de proprietário continua exigindo o token de instalação, lido no servidor com sudo sh0 setup-token. Atrás do túnel ninguém mais alcança o painel, mas a regra é a mesma em todo lugar.

Abrir o túnel

1. No seu próprio computador (não no servidor), abra o túnel e deixe o comando em execução:

bash
ssh -N -L 9000:127.0.0.1:9000 root@SERVER_IP

2. Abra http://localhost:9000. O tráfego passa dentro do SSH: nada atravessa a rede sem criptografia, mesmo que o endereço comece com http://. Ctrl+C fecha o túnel.

3. Para não digitá-lo de novo, adicione um bloco ao ~/.ssh/config do seu computador:

text
Host sh0-panel
    HostName SERVER_IP
    User root
    LocalForward 9000 127.0.0.1:9000
    SessionType none
    ExitOnForwardFailure yes

Depois, ssh sh0-panel abre o túnel. SessionType none exige OpenSSH 8.7 ou mais recente; com um cliente mais antigo, remova essa linha e execute ssh -N sh0-panel.

Falhas comuns

SintomaCausa e correção
o ssh fica parado e depois mostra «Connection timed out»O próprio SSH está filtrado: seu IP não é permitido pelo firewall do provedor, ou o servidor escuta em outra porta (adicione -p PORTA). O túnel não é o problema.
«bind [127.0.0.1]:9000: Address already in use»A porta 9000 já está ocupada no seu computador, muitas vezes por outro túnel. Use outra porta local: -L 9001:127.0.0.1:9000 e depois http://localhost:9001.
Navegador: «conexão recusada» em localhost:9000O túnel não está aberto (o comando ssh parou) ou o sh0 não está em execução no servidor: systemctl status sh0.
«channel 2: open failed: connect failed» na janela do sshO SSH funciona, mas nada responde em 127.0.0.1:9000 no servidor, ou AllowTcpForwarding está desativado no sshd. Verifique ss -ltn | grep 9000 e sshd -T | grep allowtcpforwarding.

Migrar um servidor existente

Um servidor que já executa o sh0 é migrado executando o instalador de novo com as mesmas opções. Ele mantém seus aplicativos, grava o drop-in, remove uma regra ufw existente para a 9000 (com --harden) e reinicia o sh0 uma vez, o que também retira o endereço *.sh0.app. As execuções seguintes do instalador, para uma atualização, mantêm o servidor no modo somente túnel enquanto o drop-in existir.

bash
curl -fsSL https://get.sh0.dev | bash -s -- --harden --panel-tunnel-only

Seus aplicativos continuam respondendo em seus domínios: eles são servidos pelo Caddy nas portas 80 e 443, que a migração não altera. Conte com alguns segundos de interrupção durante a reinicialização do sh0. Se houver um domínio de painel configurado, o instalador para antes de alterar qualquer coisa e explica o motivo (próxima seção).

O que o túnel não fecha

Warning
O modo somente túnel leva a escuta própria do painel para 127.0.0.1. Ele não remove um domínio de painel: se sh0 panel-domain mostrar um, o Caddy continua servindo o painel nesse domínio pela porta 443, para toda a Internet. Para um modo somente túnel real, remova o domínio. O instalador recusa --panel-tunnel-only enquanto houver um domínio configurado por sh0 panel-domain ou por SH0_PANEL_DOMAIN no ambiente do serviço, e exige o sh0 1.10.6 ou mais recente; um domínio configurado de outra forma não é detectado, então verifique você mesmo.
bash
sudo sh0 panel-domain          # show
sudo sh0 panel-domain clear    # remove the route and the setting

Acesso pelo navegador sem túnel

Se o túnel não for uma opção para sua equipe, mantenha um domínio de painel, mas coloque o Cloudflare Access (ou um proxy de identidade equivalente) na frente e limite a porta 443 às faixas de IP da Cloudflare no firewall do provedor. Sem essa segunda etapa, o Access é contornado conectando-se diretamente ao IP do servidor. Essa restrição vale para todos os aplicativos do servidor: cada um dos domínios deles também precisa passar pelo proxy da Cloudflare, ou deixará de responder. Não combine isso com --panel-tunnel-only.

Verificar o resultado

No servidor, o painel deve escutar apenas no endereço de loopback, nenhum domínio de painel deve estar configurado e o sh0 doctor não deve relatar falhas. A partir de outra rede, a porta 9000 deve estar fechada.

bash
ss -ltn | grep ':9000'          # 127.0.0.1:9000 only
cat /etc/systemd/system/sh0.service.d/panel-tunnel-only.conf
sudo sh0 panel-domain            # Domain: not set
sudo sh0 doctor

Voltar atrás

Para tornar o painel acessível novamente no endereço do servidor, apague o drop-in, reinicie o sh0 e reabra a porta:

bash
rm /etc/systemd/system/sh0.service.d/panel-tunnel-only.conf
rm /etc/systemd/system/sh0.service.d/cloud-registration.conf   # only to get *.sh0.app back
systemctl daemon-reload && systemctl restart sh0
ufw allow 9000/tcp                                              # if the firewall is ufw

O restante do host (chaves SSH, firewall, fail2ban) é tratado em Proteger seu servidor