← RETOUR À L'INDEX
/tutoriels/ infrastructure / infrastructure-vps-durcie-—-ssh-ed25519,-ufw,-tailscale,-fail2ban.md

Infrastructure VPS durcie — SSH Ed25519, UFW, Tailscale, Fail2ban

SSH Ed25519, UFW, Tailscale, Fail2ban — durcissement complet d'un VPS Linux pour l'IA personnelle.

CAT · INFRA LECTURE · 10 min PUBLIÉ · 2026-04-12

Temps estimé : 30 min

Résultat final : VPS Ubuntu 22.04 avec SSH key-only via Tailscale, UFW restrictif, Fail2ban, et mises à jour automatiques de sécurité.

Prérequis : TUTO-01a (Oracle) ou TUTO-01b (Hetzner) — VPS accessible en SSH.


Objectif

Transformer un VPS fraîchement provisionné en un serveur durci :

  • Supprimer les vecteurs d’attaque SSH les plus courants
  • Passer de l’accès par IP publique à l’accès exclusivement via Tailscale
  • Activer la défense en profondeur (Fail2ban + unattended-upgrades)

Différence Oracle / Hetzner :

  • Oracle : user par défaut = ubuntu (sudoer, pas root) → sauter l’étape 1
  • Hetzner : user par défaut = root → ne pas sauter l’étape 1

Étape 1 : Créer un user non-root [Hetzner uniquement]

Oracle : passer directement à l’étape 2.

Sur le VPS Hetzner (connecté en root) :

# Créer le user avec un nom de ton choix (ex: openclaw)
adduser openclaw

Le terminal demande un mot de passe — choisis-en un fort. Ce mot de passe sera désactivé à l’étape 2, mais il faut qu’il existe maintenant.

# Donner les droits sudo
usermod -aG sudo openclaw

# Copier les clés SSH autorisées de root vers le nouveau user
mkdir -p /home/openclaw/.ssh
cp ~/.ssh/authorized_keys /home/openclaw/.ssh/
chown -R openclaw:openclaw /home/openclaw/.ssh
chmod 700 /home/openclaw/.ssh
chmod 600 /home/openclaw/.ssh/authorized_keys

Ouvre un nouveau terminal (sans fermer la session root) et teste :

# En local — test dans un nouveau terminal
ssh -i ~/.ssh/openclaw_hetzner openclaw@IP_PUBLIQUE_HETZNER
⚠️ Sécurité

ne jamais fermer la session root avant d’avoir confirmé que le nouveau user peut se connecter ET utiliser sudo. Une erreur ici = VPS inaccessible.

# Vérifier sudo fonctionne
sudo whoami
# Doit afficher : root

Checklist :

  • User non-root créé et sudoer
  • Connexion SSH user non-root confirmée dans nouveau terminal
  • sudo whoami → root

Étape 2 : Hardening SSH

Connecté en tant que user non-root (ubuntu pour Oracle, openclaw ou équivalent pour Hetzner) :

# Sauvegarder la config SSH d'origine avant modification
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
# Éditer la config SSH
sudo nano /etc/ssh/sshd_config

Modifier ou ajouter ces lignes (chercher avec Ctrl+W dans nano) :

# Désactiver l'authentification par mot de passe
PasswordAuthentication no

# Activer l'authentification par clé publique
PubkeyAuthentication yes

# Interdire la connexion root directe
PermitRootLogin no

# Limiter aux users autorisés (adapter le nom)
# Oracle :
AllowUsers ubuntu
# Hetzner : remplacer ubuntu par ton user
# AllowUsers openclaw

# Désactiver l'authentification par agent Kerberos/GSSAPI (non utilisé)
GSSAPIAuthentication no
UseDNS no

# Timeout session inactive (optionnel mais recommandé)
ClientAliveInterval 300
ClientAliveCountMax 2

Vérifier la config avant de redémarrer :

sudo sshd -t
# Aucune sortie = config valide
# Si erreur : corriger avant de continuer

Redémarrer SSH :

sudo systemctl restart sshd
⚠️ Sécurité

après le redémarrage, NE PAS fermer la session active. Ouvre un nouveau terminal et teste la connexion SSH immédiatement. Si ça échoue, la session active te permet encore de corriger.

Test dans un nouveau terminal :

ssh -i ~/.ssh/openclaw_oracle ubuntu@IP_PUBLIQUE   # Oracle
ssh -i ~/.ssh/openclaw_hetzner openclaw@IP_PUBLIQUE  # Hetzner

Checklist :

  • sshd_config.bak créé
  • PasswordAuthentication = no
  • PermitRootLogin = no
  • AllowUsers configuré
  • sudo sshd -t sans erreur
  • Connexion SSH confirmée depuis nouveau terminal

Étape 3 : Configurer UFW

UFW est le firewall au niveau OS. Il s’ajoute au firewall réseau d’Oracle (Security Lists) ou vient en remplacement du Cloud Firewall Hetzner (non configuré).

# Vérifier l'état initial
sudo ufw status
# Devrait afficher : inactive
# Règle de base : tout bloquer en entrée
sudo ufw default deny incoming
sudo ufw default allow outgoing
# Autoriser SSH (nécessaire avant activation — sinon tu te coupes toi-même)
sudo ufw allow 22/tcp
# Autoriser Tailscale UDP (handshake initial)
sudo ufw allow 41641/udp
# Activer UFW
sudo ufw enable
⚠️ Sécurité

ne jamais faire ufw enable sans avoir ajouté le port 22 au préalable. Si tu t’es bloqué : Oracle → console OCI “Cloud Shell” pour accès hors SSH Hetzner → console Hetzner “Console” (accès VNC web)

# Vérifier l'état après activation
sudo ufw status verbose

Sortie attendue :

Status: active

To                         Action      From
--                         ------      ----
22/tcp                     ALLOW IN    Anywhere
41641/udp                  ALLOW IN    Anywhere

Checklist :

  • UFW actif
  • Port 22/tcp autorisé
  • Port 41641/udp autorisé
  • Aucun autre port ouvert en entrée

Étape 4 : Installer Tailscale

# Installation Tailscale
curl -fsSL https://tailscale.com/install.sh | sh
# Démarrer Tailscale et s'authentifier
sudo tailscale up

Le terminal affiche une URL de login :

https://login.tailscale.com/a/XXXXX

Ouvre cette URL depuis ton navigateur, connecte-toi à ton compte Tailscale, autorise le device.

⚠️ Sécurité

Tailscale chiffre le trafic de bout en bout (WireGuard). Les serveurs de coordination Tailscale (login) ne voient jamais le contenu du trafic — uniquement les métadonnées de connexion. Pour souveraineté maximale : Headscale (self-hosted) est l’alternative, documentée dans un tuto avancé futur.

# Récupérer l'IP Tailscale du VPS
tailscale ip -4
# Affiche quelque chose comme : 100.x.x.x
# Vérifier que le VPS est actif sur ton réseau Tailscale
tailscale status

Depuis ton poste local (avec Tailscale installé et connecté) :

# Test de connectivité via Tailscale
ssh -i ~/.ssh/openclaw_oracle ubuntu@100.x.x.x   # Oracle
ssh -i ~/.ssh/openclaw_hetzner openclaw@100.x.x.x  # Hetzner
⚠️ Sécurité

si Tailscale n’est pas installé sur ton poste local, installe-le avant : https://tailscale.com/download Ne continue pas tant que la connexion SSH via IP Tailscale ne fonctionne pas.

Checklist :

  • Tailscale installé et authentifié
  • IP Tailscale récupérée (100.x.x.x)
  • Connexion SSH via IP Tailscale OK depuis poste local

Étape 5 : Restreindre SSH à Tailscale uniquement

C’est l’étape clé : après celle-ci, le port 22 public est fermé. L’accès SSH ne passe plus que par le tunnel Tailscale.

# Trouver le nom de l'interface Tailscale
ip addr show | grep tailscale
# Typiquement : tailscale0
sudo nano /etc/ssh/sshd_config

Modifier la ligne ListenAddress :

# Écouter UNIQUEMENT sur l'interface Tailscale
ListenAddress 100.x.x.x
# Remplacer 100.x.x.x par l'IP Tailscale de ton VPS

Vérifier et redémarrer :

sudo sshd -t && sudo systemctl restart sshd

Fermer le port 22 dans UFW :

sudo ufw delete allow 22/tcp
sudo ufw status verbose
⚠️ Sécurité

avant de fermer le port 22, confirme OBLIGATOIREMENT que la connexion SSH via IP Tailscale fonctionne depuis un terminal séparé. Si tu perds l’accès : Oracle → OCI Cloud Shell | Hetzner → Console web VNC.

Pour Oracle — fermer aussi dans Security Lists :

Console OCI → Networking → VCN → Security Lists → Default Security List
Supprimer la règle ingress port 22/tcp

Checklist :

  • ListenAddress = IP Tailscale dans sshd_config
  • SSH redémarré sans erreur
  • Port 22/tcp supprimé dans UFW
  • Oracle uniquement : port 22/tcp supprimé dans Security Lists
  • Connexion SSH via IP Tailscale toujours fonctionnelle

Étape 6 : Installer Fail2ban

Fail2ban protège contre les tentatives de brute-force. Même avec SSH sur Tailscale uniquement, c’est une bonne pratique de défense en profondeur.

sudo apt-get update -q
sudo apt-get install -y fail2ban

Créer une config locale (ne jamais modifier /etc/fail2ban/jail.conf directement) :

sudo nano /etc/fail2ban/jail.local

Contenu :

[DEFAULT]
bantime  = 3600
findtime = 600
maxretry = 5
backend  = systemd

[sshd]
enabled = true
port    = ssh
logpath = %(sshd_log)s
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
# Vérifier que fail2ban surveille SSH
sudo fail2ban-client status sshd

Sortie attendue :

Status for the jail: sshd
|- Filter
|  |- Currently failed: 0
|  |- Total failed:     0
`- Actions
   |- Currently banned: 0
   `- Total banned:     0
⚠️ Sécurité

si tu vois “Currently banned” avec ta propre IP, tu t’es banni toi-même (trop de tentatives échouées). sudo fail2ban-client set sshd unbanip TON_IP

Checklist :

  • Fail2ban installé et actif
  • jail.local configuré (bantime 1h, maxretry 5)
  • fail2ban-client status sshd → 0 banned, jail actif

Étape 7 : Mises à jour de sécurité automatiques

sudo apt-get install -y unattended-upgrades
sudo dpkg-reconfigure --priority=low unattended-upgrades
# Répondre "Yes" → active les mises à jour de sécurité automatiques

Vérifier la configuration :

cat /etc/apt/apt.conf.d/20auto-upgrades

Sortie attendue :

APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
⚠️ Sécurité

les mises à jour de sécurité automatiques corrigent les CVE critiques sans intervention manuelle. Sans elles, ton VPS accumule des failles connues publiquement. Activer, ne jamais désactiver.

Checklist :

  • unattended-upgrades installé et activé
  • Vérification : Update-Package-Lists et Unattended-Upgrade = “1”

Étape 8 : Mettre à jour ~/.openclaw-infra.env

# En local sur ton poste — compléter le fichier créé en TUTO-01
nano ~/.openclaw-infra.env

Ajouter :

# IP Tailscale du VPS (remplace l'IP publique pour la suite des tutos)
VPS_IP_TAILSCALE=100.x.x.x

# User SSH final (après hardening)
# Oracle : ubuntu | Hetzner : openclaw (ou ton user)
VPS_SSH_USER=ubuntu

À partir de maintenant, tous les accès SSH se font via l’IP Tailscale :

ssh -i $VPS_SSH_KEY $VPS_SSH_USER@$VPS_IP_TAILSCALE

Dépannage

SSH refusé après ListenAddress Tailscale

  • Cause : Tailscale coupé ou IP Tailscale changée après reboot
  • Solution :
    # Via console web (OCI Cloud Shell ou Hetzner VNC)
    sudo tailscale up
    tailscale ip -4  # Vérifier que l'IP n'a pas changé
  • Prévention : IP Tailscale fixe via Tailscale admin console → Device → “Disable key expiry”

UFW bloqué après activation

  • Cause : Port 22 pas ajouté avant ufw enable
  • Solution Oracle : Console OCI → Compute → Instance → “Cloud Shell”
  • Solution Hetzner : Console Hetzner → Server → “Console” (VNC web)
  • Dans les deux cas : sudo ufw allow 22/tcp && sudo ufw reload

Fail2ban ne démarre pas

sudo journalctl -u fail2ban -n 50
# Chercher l'erreur dans les logs

Erreur fréquente : backend = systemd non supporté → remplacer par backend = auto

Tailscale “Authentication expired”

sudo tailscale up --authkey=NEW_AUTH_KEY
# Ou simplement :
sudo tailscale up
# Suivre le lien d'authentification affiché

Checklist finale TUTO-02

User et accès

  • ☐ User non-root sudoer créé et opérationnel [Hetzner]
  • ☐ Connexion root directe impossible (PermitRootLogin no)
  • ☐ Auth par mot de passe SSH désactivée (PasswordAuthentication no)

Réseau

  • ☐ UFW actif, tout bloqué par défaut
  • ☐ Port 22 public fermé (UFW + Security Lists Oracle)
  • ☐ Accès SSH exclusivement via IP Tailscale (100.x.x.x)

Protection active

  • ☐ Fail2ban actif sur sshd
  • ☐ unattended-upgrades actif

Validation finale

  • ☐ ssh -i $VPS_SSH_KEY $VPS_SSH_USER@$VPS_IP_TAILSCALE → OK
  • ☐ ssh ubuntu@IP_PUBLIQUE → Connection refused (attendu)
  • ☐ sudo ufw status → port 22 absent
  • ☐ sudo fail2ban-client status sshd → jail actif

Références


Tuto suivant : TUTO-02b

VR · 2026-04-12 · vraffin.dev FIN DU DOCUMENT