Créer un référentiel distant Restic avec un Raspberry PI et un serveur SFTP

Sommaire

L'objectif de ce tutoriel est de vous accompagner dans l'installation et la configuration d'un boîtier dédié (Raspberry PI et disque USB externe) pour la sauvegarde Restic sur un référentiel distant, en SFTP.

Ainsi, il vous sera possible de positionner ce boitier derrière n'importe quelle box Internet (chez vous, dans votre famille, chez vos amis ou ailleurs) et de pouvoir y transférer vos sauvegardes Restic de manière sécurisée et ainsi conserver une copie hors site.

Dans ce document, nous allons aborder l'installation du système Raspberry Pi OS (anciennement Raspbian), de son durcissement via les recommandations du CIS et de sa publication sur Internet (via un domaine DNS hébergé chez OVHcloud).

1. Prérequis

Liste des prérequis :

  • Un Raspberry PI et son câble d'alimentation
  • Un câble réseau RJ45
  • Un disque dur USB externe
  • Une carte mémoire afin d'installer Raspberry Pi OS
  • Une paire de clefs SSH pour l'utilisateur utilisé par Restic
  • Une paire de clefs SSH pour l'utilisateur "piadmin" utilisé pour l'administration du Raspberry Pi
  • Un nom de domaine DNS public (exemple chez OVHcloud)

2. Installation de Raspberry Pi OS

Utiliser rpi-imager pour installer le Rapberry PI OS sur la carte mémoire de votre Raspberry PI :

Dans notre cas nous allons installer le système sans interface graphique "Raspberry PI OS Lite (32 bits)" :

Ensuite nous fixons une configuration sur l'image, en renseignant les éléments suivants :

  • Le nom du système
  • La clef publique autorisée à se connecter sur l'utilisateur "pi"
  • La configuration de la langue du système et du clavier

3. Premier démarrage du Raspberry PI

Une fois le Raspberry PI connecté au réseau et démarré, patienter deux minutes avant de le redémarrer. Lors du redémarrage, votre serveur DHCP local devrait lui fournir une adresse IP.

Pour vous connecter au Raspberry PI, utiliser une connexion SSH sur l'utilisateur "pi", avec la clef privée liée à la clef publique renseignée lors de la création de l'image.

1ssh pi@adresse-ip-rpi

Une fois connecté, mettre à jour le système :

1sudo apt -y update
2sudo apt -y full-upgrade

Puis configurer le fuseau horaire via l'outil raspi-config :

1sudo raspi-config

Enfin configurer les "locales" du système :

1export LANGUAGE=fr_FR.UTF-8
2export LANG=fr_FR.UTF-8
3export LC_ALL=fr_FR.UTF-8
4sudo -E locale-gen fr_FR.UTF-8
5sudo -E dpkg-reconfigure locales

4. Création des utilisateurs sur le système

On crée l'utilisateur "restic" qui sera utilisé pour les sauvegardes (on désactive son mot de passe afin qu'il ne puisse se connecter en SSH qu'avec une clef cryptographique) :

1sudo adduser --disabled-password --gecos GECOS restic

On crée l'utilisateur "piadmin", avec un mot de passe, qui sera utilisé pour l'administration du RaspberryPI :

1sudo adduser piadmin

On ajoute l'utilisateur "piadmin" aux groupes d'administration du RaspberryPI :

1sudo usermod -a -G adm,dialout,cdrom,sudo,audio,video,plugdev,games,users,input,netdev,gpio,i2c,spi piadmin

Ajouter les clefs publiques de vos clefs cryptographiques dans les fichiers suivants :

1/home/restic/.ssh/authorized_keys
2/home/piadmin/.ssh/authorized_keys

Se déconnecter du système :

1logout

Et vérifier la connexion via votre nouveau compte d'administration et sa clef privée :

1ssh piadmin@adresse-ip-rpi

Exécuter la commande "sudo" afin de lister les permissions de l'utilisateur "piadmin" :

1sudo -l

Vérifier qu'il dispose des permissions suivantes sur la commande "sudo" :

1[sudo] password for piadmin:
2Matching Defaults entries for piadmin on srv-restic:
3    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin, env_keep+=NO_AT_BRIDGE, env_keep+="http_proxy HTTP_PROXY", env_keep+="https_proxy HTTPS_PROXY", env_keep+="ftp_proxy FTP_PROXY", env_keep+=RSYNC_PROXY, env_keep+="no_proxy
4    NO_PROXY"
5
6User piadmin may run the following commands on srv-restic:
7    (ALL : ALL) ALL

5. Suppression de l'utilisateur pi

On supprime l'utilisateur "pi" :

1sudo deluser -remove-home pi

On supprime le fichier sudoers pour l'utilisateur "pi" :

1sudo rm -f /etc/sudoers.d/010_pi-nopasswd

6. Configuration du serveur SSH

On édite le fichier "/etc/ssh/sshd_config" :

1sudo nano /etc/ssh/sshd_config
  • On interdit la connexion au compte "root" via SSH.
  • On autorise les accès SSH uniquement aux utilisateurs "restic" et "piadmin".
  • On limite l'authentification au SSH uniquement via des clefs cryptographiques.
  • On implémente les recommandations CIS
 1Banner /etc/issue.net
 2DebianBanner no
 3
 4AllowUsers restic piadmin
 5
 6PermitRootLogin no
 7ChallengeResponseAuthentication no
 8PasswordAuthentication no
 9UsePAM no
10X11Forwarding no
11
12AllowTcpForwarding no
13ClientAliveCountMax 2
14Compression no
15MaxSessions 2
16TCPKeepAlive no
17AllowAgentForwarding no
18
19Protocol 2
20LogLevel VERBOSE
21MaxAuthTries 3
22IgnoreRhosts yes
23HostbasedAuthentication no
24PermitEmptyPasswords no
25PermitUserEnvironment no
26Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
27MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512,hmac-sha2-256
28KexAlgorithms diffie-hellman-group-exchange-sha256
29PubkeyAuthentication yes
30KbdInteractiveAuthentication no
31KerberosAuthentication no
32GSSAPIAuthentication no
33GSSAPIKeyExchange no
34RekeyLimit 512M 6h
35StrictModes yes
36UsePrivilegeSeparation sandbox

On redémarre le service SSH :

1sudo systemctl restart sshd

7. Installation du pare-feu

Nous allons suivre la procédure suivante : https://www.raspberrypi.com/documentation/computers/configuration.html#install-a-firewall

Dans un premier temps on installe "ufw" :

1sudo apt install ufw

On autorise les connexions entrantes sur le service SSH et ajoute une limitation aux nombres de tentatives de connexion :

1sudo ufw allow ssh/tcp
2sudo ufw limit ssh/tcp

On autorise les protocoles NTP, DHCP, DNS, HTTP et HTTPS en sortie :

1sudo ufw allow out bootps
2sudo ufw allow out dns
3sudo ufw allow out http
4sudo ufw allow out https
5sudo ufw allow out ntp

On configure les politiques d'entrée et sortie par défaut, en bloquant :

1sudo ufw default deny incoming
2sudo ufw default deny outgoing

On vérifie la configuration du pare-feu :

1sudo ufw status

Enfin, on active ufw, notamment pour qu'il s'exécute au démarrage du système :

1sudo ufw enable

8. Installation de fail2ban

Dans un premier temps on installe Fail2ban via la commande suivante :

1sudo apt install fail2ban

Puis nous utilisons le fichier de configuration modèle afin de définir notre configuration :

1sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
2sudo nano /etc/fail2ban/jail.local

Enfin, on redémarre le service Fail2ban :

1sudo systemctl restart fail2ban

9. Durcissement du système

Dans un premier temps nous allons configurer les bannières affichées lors de la connexion au système, en ajoutant le texte suivant dans les fichiers :

  • /etc/issue
  • /etc/issue.net
  • /etc/motd
1echo '
2WARNING : Unauthorized access to this system is forbidden and will be
3prosecuted by law. By accessing this system, you agree that your actions
4may be monitored if unauthorized usage is suspected
5' | sudo tee -a /etc/issue /etc/issue.net /etc/motd

Installation des paquetages recommandés pour le durcissement du système :

  • libpam-tmpdir : initialise $TMPDIR et $TMP pour les sessions PAM et placent des permissions assez limitées.
  • apt-listbugs : est un outil qui récupère les rapports de bogue du système de suivi des bogues de Debian (BTS, « Bug Tracking System ») et les affiche.
  • needrestart : recherche quels démons ont besoin d’être redémarrés après des mises à niveau de bibliothèque.
  • debescan : est un outil permettant de générer une liste des vulnérabilités affectant une installation de Debian particulière.
  • debsums : permet de vérifier l'intégrité des fichiers des paquets installés avec les sommes de contrôle MD5 installées par le paquet ou générées à partir d'une archive « .deb ».
  • libpwquality : son objectif est de fournir des fonctions communes pour contrôler la qualité des mots de passe et également de les noter selon leur caractère aléatoire apparent. La bibliothèque fournit aussi une fonction pour générer des mots de passe aléatoires faciles à prononcer.
  • apt-listchanges : affiche les nouvelles entrées du journal des modifications des paquets de l'archive Debian.
1sudo apt-get -y install libpam-tmpdir apt-listbugs needrestart debsecan debsums libpam-pwquality apt-listchanges

On édite le fichier "/etc/modprobe.d/blacklist.conf" :

1sudo nano /etc/modprobe.d/blacklist.conf

On y ajoute la configuration suivante afin d’interdire le chargement de certains modules en réalisant une "fake install" :

1install jffs2 /bin/true
2install hfs /bin/true
3install squashfs /bin/true
4install hfsplus /bin/true
5install udf /bin/true
6install sctp /bin/true

On édite le fichier "/etc/security/pwquality.conf" :

1sudo nano /etc/security/pwquality.conf

On ajoute les paramètres suivants afin d'imposer un mot de passe complexe de 14 caractères minimums :

1minlen = 14
2dcredit = -1
3ucredit = -1
4ocredit = -1
5lcredit = -1

(optionnel) Créer le fichier "/etc/sysctl.d/70-disable-ipv6.conf" :

1sudo nano /etc/sysctl.d/70-disable-ipv6.conf

(optionnel) En y ajoutant les paramètres suivants, pour désactiver le "IPv6 router advertisements" :

1net.ipv6.conf.all.disable_ipv6 = 1
2net.ipv6.conf.default.disable_ipv6 = 1
3net.ipv6.conf.lo.disable_ipv6 = 1
4net.ipv6.conf.all.disable_ipv6 = 1
5net.ipv6.conf.default.disable_ipv6 = 1
6net.ipv6.conf.lo.disable_ipv6 = 1

Créer le fichier "/etc/sysctl.d/70-enable-rp_filter.conf" :

1sudo nano /etc/sysctl.d/70-enable-rp_filter.conf

En y ajoutant les paramètres suivants, pour activer le "RFC-recommended source route validation" :

1net.ipv4.conf.all.rp_filter = 1
2net.ipv4.conf.default.rp_filter = 1

Créer le fichier "98-enable-log_martian_packets.conf" :

1sudo nano /etc/sysctl.d/98-enable-log_martian_packets.conf

En y ajoutant les paramètres suivants, pour activer la journalisation des paquets suspicieux :

1net.ipv4.conf.all.log_martians = 1
2net.ipv4.conf.default.log_martians = 1

Créer le fichier "/etc/sysctl.d/70-disable-secure_icmp.conf" :

1sudo nano /etc/sysctl.d/70-disable-secure_icmp.conf

En y ajoutant les paramètres suivants, pour désactiver l'acceptation de la redirection ICMP sécurisée pour éviter la corruption des tables de routage :

1net.ipv4.conf.all.secure_redirects = 0
2net.ipv4.conf.default.secure_redirects = 0

Créer le fichier "/etc/sysctl.d/70-disable-send_packet_redirects.conf" :

1sudo nano /etc/sysctl.d/70-disable-send_packet_redirects.conf

En y ajoutant les paramètres suivants, pour désactiver l'envoi des redirections de paquets pour empêcher la corruption ICMP malveillante :

1net.ipv4.conf.all.send_redirects = 0
2net.ipv4.conf.default.send_redirects = 0

On édite le fichier "/etc/pam.d/common-password" :

1sudo nano /etc/pam.d/common-password

Le fichier doit contenir les éléments suivants, notamment la première ligne, qui forcera le chiffrement sha512 lors des prochains changements des mots de passe des utilisateurs :

1password [success=1 default=ignore] pam_unix.so sha512
2
3password	requisite			pam_pwquality.so retry=3
4password	[success=1 default=ignore]	pam_unix.so obscure use_authtok try_first_pass yescrypt
5password	requisite			pam_deny.so
6password	required			pam_permit.so

Créer le fichier "/etc/profile.d/timeout.sh" :

1sudo nano /etc/profile.d/timeout.sh

Afin de fixer un "timeout" sur le shell des utilisateurs d'une valeur de 5 minutes :

1readonly TMOUT=300 ; export TMOUT

On durcit les permissions sur quelques fichiers journaux et sur le répertoire "/etc/sudoers.d":

1sudo chmod 640 /var/log/wtmp /var/log/btmp /var/log/lastlog /var/log/apt/history.log /var/log/apt/eipp.log.xz
2sudo chmod 750 /etc/sudoers.d

Ensuite, éditer le fichier "/etc/sudoers" :

1sudo visudo

Ajouter les deux paramètres suivants, qui feront que sudo s'exécutera dans un terminal dédié qui sera fermé à la fin de l'exécution de la commande, et qu'il enregistrera ses événements dans un fichier dédié :

1Defaults        use_pty
2Defaults        logfile="/var/log/sudo.log"

Editer le fichier "/etc/security/limits.conf" :

1sudo nano /etc/security/limits.conf

Ajouter la ligne suivante afin de désactiver les "Core Dumps" qui pourraient à la fois consommer beaucoup d'espace disque, mais aussi être utilisés par un attaquant pour récupérer des informations sur le système :

1* hard core 0

A cette étape on force l'expiration du mot de passe du compte "piadmin" et on redémarre le système :

1sudo chage -d 0 piadmin
2sudo reboot

Puis on change le mot de passe de notre utilisateur "piadmin" :

1ssh piadmin@adresse-ip-rpi
2sudo -l

Ensuite, nous allons cloner et configurer le projet debian-cis afin de durcir notre système en implémentant certaines recommandations CIS :

1sudo apt-get -y install git
2cd
3git clone https://github.com/ovh/debian-cis.git && cd debian-cis
4sudo cp debian/default /etc/default/cis-hardening
5sudo sed -i "s#CIS_ROOT_DIR=.*#CIS_ROOT_DIR='$(pwd)'#" /etc/default/cis-hardening

Avant d'exécuter l'outil, désactiver les vérifications non éligibles pour notre système Raspbian :

 1sed -i "s#status=.*#status=disabled#" etc/conf.d/1.1.21_sticky_bit_world_writable_folder.cfg
 2sed -i "s#status=.*#status=disabled#" etc/conf.d/1.1.3_tmp_nodev.cfg
 3sed -i "s#status=.*#status=disabled#" etc/conf.d/1.1.4_tmp_nosuid.cfg
 4sed -i "s#status=.*#status=disabled#" etc/conf.d/1.1.8_var_tmp_nodev.cfg
 5sed -i "s#status=.*#status=disabled#" etc/conf.d/1.1.9_var_tmp_nosuid.cfg
 6sed -i "s#status=.*#status=disabled#" etc/conf.d/1.1.14_home_nodev.cfg
 7sed -i "s#status=.*#status=disabled#" etc/conf.d/1.1.15_run_shm_nodev.cfg
 8sed -i "s#status=.*#status=disabled#" etc/conf.d/1.1.16_run_shm_nosuid.cfg
 9sed -i "s#status=.*#status=disabled#" etc/conf.d/1.5.1_bootloader_ownership.cfg
10sed -i "s#status=.*#status=disabled#" etc/conf.d/1.6.1_enable_nx_support.cfg
11sed -i "s#status=.*#status=disabled#" etc/conf.d/4.2.3_logs_permissions.cfg
12sed -i "s#status=.*#status=disabled#" etc/conf.d/6.1.13_find_suid_files.cfg
13sed -i "s#status=.*#status=disabled#" etc/conf.d/6.1.14_find_sgid_files.cfg
14sed -i "s#status=.*#status=disabled#" etc/conf.d/99.99_check_distribution.cfg

Puis, on applique le durcissement de notre système (ce dernier va sauvegarder les fichiers modifiés dans le répertoire "tmp/backups"):

1sudo bin/hardening.sh --allow-unsupported-distribution --apply

Enfin, on redémarre le système :

1sudo reboot

Puis on vérifie le durcissement qui doit avoir un taux de conformité de 100% :

1ssh piadmin@adresse-ip-rpi
2sudo debian-cis/bin/hardening.sh --allow-unsupported-distribution --audit

10. Configurer les mises à jour automatiques du système

Installer les prérequis :

1sudo apt-get -y install unattended-upgrades

Editer le fichier "/etc/apt/apt.conf.d/50unattended-upgrades" :

1sudo nano /etc/apt/apt.conf.d/50unattended-upgrades

Et ajouter les paramètres suivants :

 1APT::Periodic::Enable "1";
 2APT::Periodic::Update-Package-Lists "1";
 3APT::Periodic::Download-Upgradeable-Packages "1";
 4APT::Periodic::AutocleanInterval "7";
 5APT::Periodic::Unattended-Upgrade "1";
 6
 7Unattended-Upgrade::Origins-Pattern {
 8        "origin=Raspbian,codename=${distro_codename},label=Raspbian";
 9        "origin=Raspberry Pi Foundation,codename=${distro_codename},label=Raspberry Pi Foundation";
10};
11
12Unattended-Upgrade::Package-Blacklist {
13};
14
15Unattended-Upgrade::AutoFixInterruptedDpkg "true";
16Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";
17Unattended-Upgrade::Remove-New-Unused-Dependencies "true";

11. Installation du disque dur USB externe

Connecter le disque USB au Raspberry PI.

Ensuite, créer une partition ext4 via l'outil cfdisk :

1sudo cfdisk /dev/sda

Et on formate le disque en EXT4 :

1sudo mkfs.ext4 /dev/sda1

On récupère l'UUID de la nouvelle partition :

1blkid /dev/sda1

Créer le répertoire de montage de la partition du disque USB :

1sudo mkdir /mnt/backup/
2sudo chown restic /mnt/backup/

On édite le fichier "/etc/fstab" afin de monter la nouvelle partition au démarrage du système :

1sudo nano /etc/fstab

Et on ajoute la ligne suivante en renseignant l'UUID de la nouvelle partition :

1UUID=xxxxfc-xxxx-xxxx-xxx-xxxxx87 /mnt/backup ext4 defaults 0 0

On monte la nouvelle partition dans le répertoire "/mnt/backup" :

1sudo mount -a

On vérifie que la partition est montée :

1df -h /dev/sda1
1Filesystem      Size  Used Avail Use% Mounted on
2/dev/sda1       1.8T   28K  1.7T   1% /mnt/backup

12. Mise à jour dynamique du DNS OVH

Nous allons créer une tâche planifiée exécutée toutes les 5 minutes, qui exécutera le script afin de récupérer notre IP publique et envoyer une requête à OVH pour mettre à jour l’IP du nom de domaine DNS.

Dans un premier temps, télécharger le script dyndns.sh dans le dossier /usr/local/sbin et lui donner les permissions nécessaires :

1sudo wget https://raw.githubusercontent.com/RaspbianFrance/dyndnsovh/master/dyndns.sh -O /usr/local/sbin/dyndns.sh
2sudo chmod 700 /usr/local/sbin/dyndns.sh

Editer le fichier "/usr/local/sbin/dyndns.sh" :

1sudo nano /usr/local/sbin/dyndns.sh

Et insérer les informations pour mettre à jour votre domaine DNS sur OVH :

1DYNHOST_ID='domaine.name-identifier'
2DYNHOST_PASSWORD='VerySecretP@ssW@rd'
3DOMAIN_NAME='restic-backup.domaine.name'

Vérifier le bon fonctionnement du script en l'exécutant manuellement :

1sudo /usr/local/sbin/dyndns.sh

Enfin, éditer la crontab pour exécuter le script toutes les 5 minutes :

1sudo crontab -e
1*/5 * * * * /usr/local/sbin/dyndns.sh > /dev/null 2>&1

13. Installation de Rkhunter

Rkhunter (pour Rootkit Hunter) est un programme qui essaye de détecter les rootkits, portes dérobées et exploits.

Installer Rkhunter :

1sudo apt-get -y install rkhunter

On exécute rkhunter pour vérifier notre système :

1sudo rkhunter --check --skip-keypress