Docs/ Sécurité/ Sécuriser son serveur sh0

Sécuriser son serveur sh0

Les mêmes conseils où que votre serveur soit hébergé : aucune étape propre à un fournisseur, seulement ce qui tourne sur la machine elle-même.

Vue d’ensemble

sh0 sécurise ce qu’il sert (HTTPS, secrets chiffrés, rôles), mais le serveur qui le porte est le vôtre. La plupart des serveurs compromis ne le sont pas par l’application : on y entre en SSH avec un mot de passe deviné, ou par un port que personne ne voulait exposer. Ce guide ferme ces portes, dans l’ordre qui ne vous enferme jamais dehors. sh0 vérifie les mêmes points pour vous, en direct, sur la page Sécurité du serveur du tableau de bord et avec sudo sh0 doctor.

Avant de commencer

Gardez votre session SSH actuelle ouverte jusqu’au bout, et testez chaque changement depuis une NOUVELLE session. Depuis votre ordinateur, vérifiez que votre clé ouvre une session sans mot de passe :

bash
ssh -o PasswordAuthentication=no root@SERVER_IP

Si cette session demande un mot de passe, vous n’avez pas encore de clé sur le serveur. Installez-en une, puis testez à nouveau :

bash
ssh-copy-id root@SERVER_IP

SSH : clés seulement

Un serveur qui accepte les mots de passe SSH peut être deviné, et root est le premier compte essayé. Une fois votre clé vérifiée, refusez les mots de passe :

bash
cat > /etc/ssh/sshd_config.d/00-sh0-hardening.conf <<'EOF'
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin prohibit-password
EOF
Note
Le nom du fichier commence par 00- à dessein : sshd retient la PREMIÈRE valeur lue, et de nombreuses images livrent un 50-cloud-init.conf qui réactive les mots de passe. Un fichier nommé 99-… serait ignoré sans un mot.

Validez, puis rechargez. Ne redémarrez jamais sshd sur un fichier que sshd -t refuse ; un rechargement garde les sessions ouvertes. Le service s’appelle ssh sur Debian et Ubuntu, sshd ailleurs.

bash
sshd -t && systemctl reload ssh

Vérifiez la valeur effective pour root depuis une adresse extérieure, puis ouvrez une nouvelle session avec votre clé avant de fermer la session actuelle :

bash
sshd -T -C user=root,host=check.invalid,addr=203.0.113.1 | grep -Ei '^(passwordauthentication|kbdinteractiveauthentication|permitrootlogin) '

Pare-feu, et le piège Docker

Autorisez SSH, HTTP, HTTPS et le port du panneau, puis activez ufw. Si SSH écoute sur un autre port que 22, autorisez ce port d’abord.

bash
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443
ufw allow 9000/tcp
ufw --force enable

Le port 9000 reste ouvert tant que les adresses *.sh0.app atteignent votre serveur directement. Ne le fermez (sh0 serve --bind 127.0.0.1) qu’une fois le panneau servi sur son propre domaine en HTTPS.

Warning
ufw ne voit pas les ports publiés par Docker : Docker écrit ses propres règles iptables avant celles d’ufw, si bien qu’une base de données publiée sur 5432 reste joignable depuis Internet avec ufw actif. Docker réserve une chaîne à l’administrateur, DOCKER-USER. La règle ci-dessous ne laisse passer, depuis l’interface publique, que les réponses aux connexions ouvertes par le serveur, et un petit service la réapplique à chaque démarrage de Docker :
bash
cat > /usr/local/sbin/sh0-docker-user <<'EOF'
#!/bin/sh
# Docker-published ports: from the public interface, only replies get through.
IF=$(ip -o route get 1.1.1.1 | sed -n 's/.* dev \([^ ]*\).*/\1/p')
[ -n "$IF" ] || exit 1
iptables -C DOCKER-USER -i "$IF" -m conntrack --ctstate RELATED,ESTABLISHED -j RETURN 2>/dev/null ||
  iptables -I DOCKER-USER 1 -i "$IF" -m conntrack --ctstate RELATED,ESTABLISHED -j RETURN
iptables -C DOCKER-USER -i "$IF" -j DROP 2>/dev/null ||
  iptables -I DOCKER-USER 2 -i "$IF" -j DROP
EOF
chmod 755 /usr/local/sbin/sh0-docker-user
cat > /etc/systemd/system/sh0-docker-user.service <<'EOF'
[Unit]
Description=sh0: filter Docker-published ports (DOCKER-USER)
After=docker.service
Requires=docker.service
PartOf=docker.service

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/local/sbin/sh0-docker-user

[Install]
WantedBy=docker.service
EOF
systemctl daemon-reload
systemctl enable --now sh0-docker-user
iptables -S DOCKER-USER

Pour garder un port publié joignable, ajoutez une exception avant la règle DROP dans /usr/local/sbin/sh0-docker-user :

bash
iptables -I DOCKER-USER 2 -i "$IF" -p tcp -m conntrack --ctorigdstport 5432 -j RETURN

Si votre fournisseur propose un pare-feu réseau devant le serveur, quel qu’il soit, utilisez-le aussi : autorisez 22, 80, 443 (et 9000 tant que vous dépendez de *.sh0.app), refusez le reste. Il filtre avant que le trafic n’atteigne la machine, Docker compris.

fail2ban

Avec des clés seulement, les tentatives sont sans danger, mais elles remplissent les journaux. fail2ban bannit les adresses qui insistent :

bash
apt-get install -y fail2ban python3-systemd
cat > /etc/fail2ban/jail.d/sh0-sshd.local <<'EOF'
[sshd]
enabled = true
backend = systemd
journalmatch = _COMM=sshd + _COMM=sshd-session
maxretry = 5
findtime = 10m
bantime = 1h
EOF
systemctl enable fail2ban
systemctl restart fail2ban
fail2ban-client status sshd

Correctifs et redémarrages

Installez les correctifs de sécurité, puis laissez le système les installer automatiquement :

bash
apt-get update && apt-get upgrade
apt-get install -y unattended-upgrades && dpkg-reconfigure -plow unattended-upgrades

Quand le noyau ou une bibliothèque essentielle est mis à jour, le correctif ne s’applique qu’après un redémarrage (/var/run/reboot-required existe). Prévoyez-le à une heure creuse : sh0 redémarre avec le système.

Le panneau en HTTPS

Sans domaine propre, le panneau est servi en HTTP clair et le mot de passe du propriétaire traverse le réseau sans chiffrement. Faites pointer un enregistrement DNS A sur le serveur, puis :

bash
sh0 panel-domain set panel.example.com

Laisser l’installeur le faire

Sur un serveur neuf, l’installeur applique les étapes SSH, pare-feu et fail2ban ci-dessus quand on le lui demande. C’est désactivé par défaut ; dans un terminal, l’installeur pose aussi la question (sans réponse sous 30 secondes, c’est non).

bash
curl -fsSL https://get.sh0.dev | bash -s -- --harden
Note
L’étape SSH ne s’exécute que si une clé autorisée est trouvée pour le compte avec lequel vous êtes connecté ; sinon elle est refusée, avec la raison, et les autres étapes s’exécutent quand même. sshd -t valide le fichier avant tout rechargement, et sshd n’est jamais redémarré.

Vérifier le résultat

La page Sécurité du serveur du tableau de bord (propriétaire et administrateurs) affiche ces vérifications en direct, avec la correction sous chaque avertissement ; un point dans la navigation signale un avertissement actif. Depuis un terminal sur le serveur :

bash
sudo sh0 doctor