Auto Hebergement
Héberger des ressources sur internet est, à la base, assez bon marché mais si on commence à avoir besoin de plusieurs machines, du stockage... ça finit par coûter cher.
J'ai un opérateur qui présente les caractéristiques suivantes :
- Accès fibre
- Fiable
- Débit montant correct
- IP fixe
Tout devrait être parfait pour que je m'autohéberge.
Prérequis
On considérera que j'ai a disposition :
- Un Raspberi PI 4 ram 4Go
- Un OS Debian GNU/Linux 12 en 64 bits version lite. (sans X, sans desktop)
- Une adresse IP fixe dans le LAN (soit présélection dans le DHCP soit en dur dans la machine)
- Une nom de domaine qui pointe vers l'IP fixe en question.
On fait la mise à jour:
sudo apt-get update
sudo apt-get upgrade
sudo reboot
Normalement, avec un linux tout frais ca devrait âtre rapide mais moi.... ça a duré 15 min :(
On peut également ajouter un utilisateur sans droits particuliers. Il y a déjà une page pour ça.
Dans le cas présent et comme j'ai beaucoup d'imagination, j'ajoute un utilisateur appelé: user
.
Installations de base
Gestion de la sécurité des utilisateurs
Le mot de passe automatique pour sudo
Sur les OS debian des raspberri Pi le user principal est sudo ALL sans mot de passe.
Ce n'est pas forcément souhaitable. EN revanche pour le retirer c'est assez subtil!
Avec visudo on a la ligne :
%sudo ALL=(ALL:ALL) ALL
donc les membres du groupe sudo ont un acces root total mais normalement avec un mot de passe qui sera demandé.
Mon compte administrateur crée à l'installation est bien dans ce groupe alors.... pourquoi ça ne demande pas de mot de passe?
Ca vient d'un ligne un peu plus bas :
@includedir /etc/sudoers.d
Que trouve-t-on dedans?
ls -l /etc/sudoers.d/
total 24
-r--r----- 1 root root 36 Apr 29 2019 010_at-export
-r--r----- 1 root root 44 Jun 19 2024 010_dpkg-threads
-r--r----- 1 root root 31 Jul 25 2023 010_global-tty
-r--r----- 1 root root 31 Feb 12 20:34 010_pi-nopasswd
-r--r----- 1 root root 211 Mar 18 2022 010_proxy
-r--r----- 1 root root 1096 Jun 27 2023 README
Ha ha on y trouve un fichier 010_pi-nopasswd
qui est read-only pour... tout le monde.
Il contient :
admin ALL=(ALL) NOPASSWD: ALL
C'est donc là!
Il faut :
- Changer le mode :
sudo chmod u+w 010_pi-nopasswd
- Editer le fichier :
sudo vi 010_pi-nopasswd
et commenter la ligne - Repasser le fichier en mode read-only :
sudo chmod u-w 010_pi-nopasswd
et Miracle ça demande le mot de passe!
Loge de connexions
Pour une raison étrange l'installation de base de linux pour Raspberry PI ne comporte pas les logs de connexion. C'est assez dommageable pour en contrôler les accès!
Peut-être est-ce dû au "lite" choisit lors de l'installation? Ou alors pour préserver la carte SD....
Bref sur un serveur visible sur internet je trouves que c'est indispensable.
sudo apt install rsyslog
Ensuite on configure en ajoutant :
# enable basic logging information
SyslogFacility AUTH
# basic logging
LogLevel INFO
Dans le fichier /etc/ssh/sshd_config
.
Ensuite on relance le service:
sudo service ssh restart
On trouve alors un fichier /var/log/auth.log contient les logs de connexions.
2025-02-12T20:57:34.682629+01:00 main-host systemd-logind[465]: New seat seat0.
2025-02-12T20:57:34.682639+01:00 main-host systemd-logind[465]: Watching system buttons on /dev/input/event0 (vc4-hdmi-0)
2025-02-12T20:57:34.682649+01:00 main-host systemd-logind[465]: Watching system buttons on /dev/input/event2 (vc4-hdmi-1)
2025-02-12T20:57:34.968001+01:00 main-host polkitd[461]: Loading rules from directory /etc/polkit-1/rules.d
2025-02-12T20:57:34.970473+01:00 main-host polkitd[461]: Loading rules from directory /usr/share/polkit-1/rules.d
2025-02-12T20:57:35.095835+01:00 main-host polkitd[461]: Finished loading, compiling and executing 4 rules
2025-02-12T20:57:35.097559+01:00 main-host polkitd[461]: Acquired the name org.freedesktop.PolicyKit1 on the system bus
2025-02-12T20:57:37.306166+01:00 main-host sshd[608]: Server listening on 0.0.0.0 port 22.
2025-02-12T20:57:37.306371+01:00 main-host sshd[608]: Server listening on :: port 22.
2025-02-12T20:57:41.630205+01:00 main-host login[587]: pam_unix(login:session): session opened for user admin(uid=1000) by LOGIN(uid=0)
2025-02-12T20:57:42.842728+01:00 main-host systemd-logind[465]: New session 1 of user admin.
2025-02-12T20:57:42.873024+01:00 main-host (systemd): pam_unix(systemd-user:session): session opened for user admin(uid=1000) by (uid=0)
2025-02-12T20:57:44.036731+01:00 main-host sshd[745]: Invalid user webadmin from 20.235.55.156 port 54378
2025-02-12T20:57:44.043331+01:00 main-host sshd[745]: pam_unix(sshd:auth): check pass; user unknown
2025-02-12T20:57:44.043473+01:00 main-host sshd[745]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=20.235.55.156
2025-02-12T20:57:45.903927+01:00 main-host sshd[745]: Failed password for invalid user webadmin from 20.235.55.156 port 54378 ssh2
2025-02-12T20:57:46.847815+01:00 main-host sshd[745]: Received disconnect from 20.235.55.156 port 54378:11: Bye Bye [preauth]
2025-02-12T20:57:46.848138+01:00 main-host sshd[745]: Disconnected from invalid user webadmin 20.235.55.156 port 54378 [preauth]
On n'a pas rebooté depuis 10 seconde que quelqu'un a essayé de se connecter en tant que webadmin depuis 20.235.55.156.
C'est un serveur sur chez Microsoft Azure situé à Chennai dans la région de Tamil Nadu en Inde!
Comment se prémunir de telles tentatives, c'est ce que nous allons voir maintenant.
Fail2ban
En plus d'un VRAI mot de passe il est necessaire de se protéger des attaques par un petit bout de code : "fail2ban".
Il évite que des "méchants" tentent des attaques en force brutes.
systemctl start fail2ban
Apres toutes ces étapes on doit pouvoir de n'importe où tant que l'on a une connexion internet et un client ssh se connecter à notre serveur.
$ ssh user@principal.modomaine.com
The authenticity of host 'principal.modomaine.com (XX.YY.ZZ.TT)' can't be established.
ECDSA key fingerprint is SHA256:*********************************.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'principal.modomaine.com' (ECDSA) to the list of known hosts.
jpinon@secure.pinon-hebert.fr's password:
Linux main-host 6.6.51+rpt-rpi-v8 #1 SMP PREEMPT Debian 1:6.6.51-1+rpt3 (2024-10-08) aarch64
Last login: Mon Feb 10 17:26:31 2025 from XX.YY.ZZ.TT
user@principal:~ $ _
Apache
On va d'abord installer les briques de bases.
sudo apt-get install apache2
Attention le serveur en question n'est pas sécurisé par TLS on reste en HTTP. Pour le HTTPS voir ci dessous.
On considère que notre DNS comme principal.mondomaine.com
.
Création du répertoire DocumentRoot
Il suffit de créer le répertoire et de le remplir avec un indec.html de test.
sudo su -
mkdir -f /var/www/html/doctest
cat > /var/www/html/doctest/index.html
<html>
<head>
<title>Not secured</title>
</head>
<body>
<h1>Not secured</h1>
</body>
</html>
Fichier /etc/apache2/sites-available/000-principal.conf
On crée le fichier suivant a partir d'une copie de 000-default.conf
<VirtualHost *:80>
# The ServerName directive sets the request scheme, hostname and port that
# the server uses to identify itself. This is used when creating
# redirection URLs. In the context of virtual hosts, the ServerName
# specifies what hostname must appear in the request's Host: header to
# match this virtual host. For the default virtual host (this file) this
# value is not decisive as it is used as a last resort host regardless.
# However, you must set it for any further virtual host explicitly.
ServerName principal.mondomaine.com
ServerAlias www.principal.mondomaine.com
ServerAdmin webmaster@mondomaine.com
DocumentRoot /var/www/html/secured
# Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
# error, crit, alert, emerg.
# It is also possible to configure the loglevel for particular
# modules, e.g.
#LogLevel info ssl:warn
ErrorLog ${APACHE_LOG_DIR}/error-principal.log
CustomLog ${APACHE_LOG_DIR}/access-principal.log combined
# For most configuration files from conf-available/, which are
# enabled or disabled at a global level, it is possible to
# include a line for only one particular virtual host. For example the
# following line enables the CGI configuration for this host only
# after it has been globally disabled with "a2disconf".
#Include conf-available/serve-cgi-bin.conf
</VirtualHost>
On crée un lien dans sites-enabeled (on doit être toujours root):
cd /etc/apache2/sites-enabled/
ln -s ../sites-available/000-principal.conf 000-principal.conf
systemctl reload apache2
Et avec un navigateur si on entre : http://prinncipal.mondomaine.com
Attention si on oublie "http://" chrome va utiliser "https://" par défaut et ça va pas marcher.
OK ca marche!
Installation apache en https avec let's encrypt
Maintenant on va sécuriser tout ça.!
Installer les packages de base pour let's encrypt
sudo apt update
sudo apt install certbot python3-certbot-apache
A part un "yes" il n'y a rien à faire.
Obtenir le certificat
On lance la configuration
sudo certbot --apache
Et on réponds aux questions:
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Enter email address (used for urgent renewal and security notices)
(Enter 'c' to cancel):
Il faut entrer une adresse mail valide. C'est celle là qui sera utilisée si let's encrypt veut nous donner une info importante.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.4-April-3-2024.pdf. You must agree in
order to register with the ACME server. Do you agree?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o:
Répondre par yes "y" pour accepter les conditions d'utilisation.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing, once your first certificate is successfully issued, to
share your email address with the Electronic Frontier Foundation, a founding
partner of the Let's Encrypt project and the non-profit organization that
develops Certbot? We'd like to send you email about our work encrypting the web,
EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o:
Là on choisit si on accepte de partager son email avec la "Electronic Frontier Foundation". Moi j'ai dit oui...
Which names would you like to activate HTTPS for?
We recommend selecting either all domains, or all domains in a VirtualHost/server block.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: principal.mondomaine.com
2: www.principal.mondomaine.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate numbers separated by commas and/or spaces, or leave input
blank to select all options shown (Enter 'c' to cancel):
Moi j'ai choisit les deux : "1,2"
Requesting a certificate for principal.mondomaine.com and www.principal.mondomaine.com
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/principal.mondomaine.com/fullchain.pem
Key is saved at: /etc/letsencrypt/live/principal.mondomaine.com/privkey.pem
This certificate expires on 2025-05-11.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.
Deploying certificate
Successfully deployed certificate for secure.pinon-hebert.fr to /etc/apache2/sites-available/000-principal-le-ssl.conf
Successfully deployed certificate for www.secure.pinon-hebert.fr to /etc/apache2/sites-available/000-principal-le-ssl.conf
Congratulations! You have successfully enabled HTTPS on https://principal.mondomaine.com and https://www.principal.mondomaine.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
If you like Certbot, please consider supporting our work by:
* Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
* Donating to EFF: https://eff.org/donate-le
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
C'est fait il ne reste plus qu'à tester. En local :
curl https://127.0.0.1
Nous réponds :
curl: (60) SSL: no alternative certificate subject name matches target host name '127.0.0.1'
More details here: https://curl.se/docs/sslcerts.html
curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.
et c'est normal puisque 127.0.0.1 n'est pas dans le CN du retificat!
On force curl à ne pas vérifier le certificat avec -k
curl -k https://127.0.0.1
qui nous réponds:
<html>
<head>
<title>Not secured</title>
</head>
<body>
<h1>Not secured</h1>
</body>
</html>
Ca marche.
Maintenant on va ouvrir le port 443 du routeur et le rediriger vers notre serveur.
maintenant de n'importe où :
curl http://principal.mondomaine.com
Nous renvoie
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>301 Moved Permanently</title>
</head><body>
<h1>Moved Permanently</h1>
<p>The document has moved <a href="https://principal.mondomaine.com/">here</a>.</p>
<hr>
<address>Apache/2.4.62 (Debian) Server at principal.mondomaine.com Port 80</address>
</body></html>
Notre serveur a bien été configuré pour rediriger les requêtes http vers https. On change le fichier index.html
sudo vi /var/www/html/secured/index.html
avec :
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html>
<head>
<title>Secured</title>
</head>
<body>
<h1>Secured</h1>
</body>
</html>
Et enfin avec Chrome:
Conclusion
Nous avons un serveur sécurisé, accessible de l'extérieur avec un acces ssl et une acces http/https.
On peut augmenter la sécurité en :
- Désactivant le port forwarding du routeur pour ssh (22). L'administration ne sera alors possible que de l'interieur du LAN
- Désactiver le port 80 mais on perds l'auto redirection en https.
Maintenant on peut utiliser ce serveur pour connecter d'autres applications. Il suffira de réaliser une configuration en "reverse proxy".