Docs/ Seguridad/ Acceder al panel por un túnel SSH

Acceder al panel por un túnel SSH

Un panel que nadie alcanza desde Internet no puede ser atacado desde Internet.

Descripción general

Sus aplicaciones las sirve sh0 en los puertos 80 y 443. El panel, que las controla todas, no tiene por qué estar expuesto. En modo solo túnel escucha únicamente en 127.0.0.1:9000: la única entrada es una conexión SSH al servidor, que su cortafuegos ya restringe y que usted ya protege con una clave.

Por qué no un dominio de panel público

Cada certificado TLS se publica en los registros públicos de Certificate Transparency, así que un dominio de panel como panel.example.com aparece en crt.sh pocos minutos después de emitirse su certificado. Los escáneres leen esos registros: un panel público se encuentra y se sondea, sea cual sea su política de contraseñas.

Instalar en modo solo túnel

En un servidor nuevo, como root, con el cortafuegos ya limitado a SSH, 80 y 443:

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

Antes del primer arranque de sh0, el instalador escribe un drop-in de systemd que vincula el panel a 127.0.0.1, desactiva el registro *.sh0.app (un proxy no alcanza un panel en localhost) y, con --harden, no abre el puerto 9000 en ufw. Termina mostrando el comando ssh exacto que debe pegar en su propio ordenador.

Warning
En este modo, sus aplicaciones pierden sus direcciones gratuitas *.sh0.app. El proxy *.sh0.app llega al servidor por el puerto 9000, que el modo solo túnel cierra, así que cada aplicación debe servirse en un dominio propio. Si usted o sus desarrolladores no tienen dominio, mantenga la instalación por defecto: el panel sigue accesible en el puerto 9000 y cada aplicación conserva su dirección gratuita.
Note
La primera cuenta de propietario sigue exigiendo el token de instalación, que se lee en el servidor con sudo sh0 setup-token. Tras el túnel nadie más alcanza el panel, pero la regla es la misma en todas partes.

Abrir el túnel

1. En su propio ordenador (no en el servidor), abra el túnel y deje el comando en ejecución:

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

2. Abra http://localhost:9000. El tráfico viaja dentro de SSH: nada cruza la red sin cifrar, aunque la dirección empiece por http://. Ctrl+C cierra el túnel.

3. Para no volver a escribirlo, añada un bloque a ~/.ssh/config en su ordenador:

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

Después, ssh sh0-panel abre el túnel. SessionType none requiere OpenSSH 8.7 o posterior; con un cliente más antiguo, quite esa línea y ejecute ssh -N sh0-panel.

Fallos habituales

SíntomaCausa y solución
ssh se queda esperando y luego «Connection timed out»El propio SSH está filtrado: su IP no está permitida en el cortafuegos del proveedor, o el servidor escucha en otro puerto (añada -p PUERTO). El túnel no es el problema.
«bind [127.0.0.1]:9000: Address already in use»El puerto 9000 ya está ocupado en su ordenador, a menudo por otro túnel. Use otro puerto local: -L 9001:127.0.0.1:9000 y luego http://localhost:9001.
Navegador: «conexión rechazada» en localhost:9000El túnel no está abierto (el comando ssh se ha detenido) o sh0 no se está ejecutando en el servidor: systemctl status sh0.
«channel 2: open failed: connect failed» en la ventana de sshSSH funciona, pero nada responde en 127.0.0.1:9000 en el servidor, o AllowTcpForwarding está desactivado en sshd. Compruebe ss -ltn | grep 9000 y sshd -T | grep allowtcpforwarding.

Cambiar un servidor existente

Un servidor que ya ejecuta sh0 se cambia volviendo a lanzar el instalador con las mismas opciones. Conserva sus aplicaciones, escribe el drop-in, elimina una regla ufw existente para el 9000 (con --harden) y reinicia sh0 una vez, lo que también retira su dirección *.sh0.app. Las ejecuciones posteriores del instalador, para una actualización, mantienen el servidor en modo solo túnel mientras exista el drop-in.

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

Sus aplicaciones siguen respondiendo en sus dominios: las sirve Caddy en 80 y 443, que el cambio no toca. Cuente con unos segundos de interrupción mientras sh0 se reinicia. Si hay un dominio de panel configurado, el instalador se detiene antes de cambiar nada y explica por qué (sección siguiente).

Lo que el túnel no cierra

Warning
El modo solo túnel lleva la escucha propia del panel a 127.0.0.1. No elimina un dominio de panel: si sh0 panel-domain muestra uno, Caddy sigue sirviendo el panel en ese dominio por el puerto 443, a todo Internet. Para un verdadero modo solo túnel, elimine el dominio. El instalador rechaza --panel-tunnel-only mientras haya un dominio configurado con sh0 panel-domain o con SH0_PANEL_DOMAIN en el entorno del servicio, y requiere sh0 1.10.6 o posterior; un dominio configurado de otra forma no se detecta, así que compruébelo usted mismo.
bash
sudo sh0 panel-domain          # show
sudo sh0 panel-domain clear    # remove the route and the setting

Acceso por navegador sin túnel

Si el túnel no es una opción para su equipo, conserve un dominio de panel, pero ponga delante Cloudflare Access (o un proxy de identidad equivalente) y limite el puerto 443 a los rangos de IP de Cloudflare en el cortafuegos del proveedor. Sin ese segundo paso, Access se elude conectándose directamente a la IP del servidor. Esa restricción afecta a todas las aplicaciones del servidor: cada uno de sus dominios debe pasar también por el proxy de Cloudflare o dejará de responder. No lo combine con --panel-tunnel-only.

Comprobar el resultado

En el servidor, el panel solo debe escuchar en la dirección de loopback, no debe haber ningún dominio de panel y sh0 doctor no debe informar de ningún fallo. Desde otra red, el puerto 9000 debe estar cerrado.

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

Volver atrás

Para que el panel vuelva a ser accesible en la dirección del servidor, elimine el drop-in, reinicie sh0 y vuelva a abrir el puerto:

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

El resto del host (claves SSH, cortafuegos, fail2ban) se trata en Proteger su servidor