Authentification ssh par clé privée

Authentification ssh par clé privée

Suite à un précédent article concernant la sécurisation d’un serveur linux, j’étais resté vague sur la mise en place de l’authentification ssh par clé privée.

L’authentification par clé privée augmente la sécurité d’un serveur au niveau du processus de connexion. Au lieu d’un simple couple identifiant / mot de passe, il faut désormais être en possession de deux informations secrètes à la fois :

  • une clé privée (un fichier que vous conservez précieusement et surtout secrètement)
  • un mot de passe que nous appelleront passphrase (pour décrypter la clé, et ainsi pouvoir l’utiliser)

Génération des clés

Pour mettre en place ce type d’authentification, il va falloir générer 2 clés : La clé privée et la clé publique.

La clé publique n’a pas besoin d’être secrète. C’est une clé qui est capable de reconnaître sa clé privée (cryptographie asymétrique). Cette clé sera donc placée sur le serveur afin qu’elle puisse vérifier notre clé privée lorsque nous voudrons nous connecter.

Sous linux

Générons notre paire de clé :

ssh-keygen -t rsa -b 4096 -C votre@email.com

Une passphrase est demandé, gardez la bien dans votre tête ou dans un gestionnaire de mot de passe. Elle sera utile par la suite !

Ici on génère une clé RSA de 4096 bits avec en commentaire votre adresse mail (juste afin de s’y retrouver si vous avez plusieurs clés à générer)

Par défaut ssh-keygen génère une clé RSA de 2048 bits avec en commentaire : votre@email.com

A vous de voir si vous préférez utiliser un algorithme RSA ou DSA. Il n’y a pas de plus ou moins costaud mais DSA est plus récent.

Pour la taille de la clé, il est recommandé de faire au moins du 2048 bits pour le RSA. En DSA, la clé fait obligatoirement 1024 bits.

Vos deux clés sont générées par défaut dans : ~/.ssh/

Vous y retrouvez vos deux clés :

  • id_rsa.pub : La clé publique
  • id_rsa : La clé privée

Sous windows

Utilisez la suite putty et générez vos clés avec PuTTYgen.

Mise en place de la clé publique sur le serveur

Il faut maintenant envoyer la clé publique sur le serveur et la placer dans le fichier ~/.ssh/authorized_keys. Ce fichier est utilisé lors de l’authentification pour déterminer si la clé privée de l’utilisateur est conforme à la clé publique inscrite dans le fichier.

Envoi de la clé si le serveur autorise l’authentification par mot de passe (sous client linux)

Nous allons utiliser ssh-copy-id qui permet d’envoyer notre clé publique automatiqument dans le fichier ~/.ssh/authorized_keys en remettant les bons droits d’écriture sur le fichier.

ssh-copy-id -i ~/.ssh/id_rsa.pub <username>@<ipaddress>

Si le port SSH n’est pas sur le port standard (22) :

ssh-copy-id -i ~/.ssh/id_rsa.pub -p <num_port> <username>@<ipaddress>

Autre méthode

Copiez le contenu de votre clé publique dans ~/.ssh/authorized_keys sur le serveur.

Configuration sur le serveur

Côté serveur, nous allons maintenant indiquer à ssh que nous souhaitons permettre la connexion par clés.

/etc/ssh/sshd_config :

RSAAuthentication yes
PubkeyAuthentication yes
StrictModes yes

Avec StrictMode = yes, donnez les bons droits à votre homedir sinon l’authentification risque d’échouer :

chmod go-w ~/
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys

Gardons pour le moment la possibilité de nous connecter avec un mot de passe ssh classique au cas où. Nous verrons pas la suite comment n’autoriser que l’authentification par clé.

Recharger le serveur ssh :

service sshd reload

Connexion avec votre clé privée

Sous linux

Modifiez ou créez le fichier ~/.ssh/config et adaptez le avec l’exemple ci-dessous :

~/.ssh/config

Host serveur1
  HostName serveur1.domain.tld
  User remi
  Port 22
  IdentityFile /home/remi/.ssh/id_rsa

Host serveur2
  HostName 192.168.1.120
  User remi
  Port 22
  IdentityFile /home/remi/autre_cle/private_key

HostName : Adresse ip ou nom de domaine du serveur

User : Utilisateur à utiliser en login

Port : Numéro du port à utiliser

IdentifyFile : Chemin vers votre clé privée à utiliser

Maintenant connectez-vous au serveur :

ssh serveur1

Indiquez votre passphrase (la clé de déverrouillage de la clé privée que nous avons généré)

Si tout va bien vous êtes maintenant connecté au serveur.

Vous pouvez ajouter votre clé privée dans votre agent ssh pour éviter de devoir taper votre passphrase à chaque fois (il faudra quand même le refaire à chaque ouverture de session) :

ssh-add ~/.ssh/id_rsa

Indiquez votre passphrase pour dévérouiller la clé.

Maintenant connectez-vous au serveur :

ssh serveur1

La passphrase ne vous est pas demandée et vous êtes connecté.

Il est possible aussi de se connecter directement sans passer par le fichier de config :

ssh <username>@<ipaddress>

Petite astuce : Avec le gestionnaire de mot de passe keepassXC, il est possible de déverrouiller automatiquement les clés privées qui sont enregistré dans votre base de mot de passe à son ouverture. Pour une fois que sécurité et pratique s’entendent !

Sous windows

Utilisez la suite putty et ajoutez votre clé publique sur Pagent.

Désactiver l’authentification par mot de passe

Attention ! Soyez sûr que votre accès par clé privée est bien opérationnel sinon vous perdrez tout accès ssh à votre machine !

Seul les authentifications par clé seront possibles !

Modifiez la configuration du fichier /etc/ssh/sshd_config :

/etc/ssh/sshd_config

ChallengeResponseAuthentication no
PasswordAuthentication no

Puis redémarrez le serveur ssh :

service sshd reload

Terminé !

Sécuriser son serveur Linux

La sécurité d’un serveur n’est pas à prendre à la légère. Chaque jour qui passe, de nombreux robots ou humains chercheront à pénétrer ton serveur. Pour tout casser, pour utiliser tes ressources, pour l’honneur, etc …
Bon, en général, d’après mon expérience personnelle, la plupart des attaques sont des attaques de force brute en SSH totalement stupides qui essaye du mot de passe en brute force pour différent utilisateurs communs (root, admin, administrator, …). Il est extrêmement rare d’être la cible d’une attaque réfléchie. Sauf bien sûr si tu héberge un site ou un service très connu. Mais en bon admin serveur, tu dois garder le contrôle de ton serveur ! On va voir comment faire pour attendre un bon niveau de sécurité.

Commençons par le commencement, tu viens de recevoir ton nouveau VPS (serveur privé virtuel) ou ton nouveau serveur dédié.

Sur ce tuto, j’utilise Debian 10.

Sécurisations indispensables du serveur

1 – Modifie ton mot de passe root !

Pour la gestion de tes mots de passe, je te conseille l’utilisation d’un gestionnaire de mot de passe. Tu pourra alors stocker des mots de passe complexes et différents. Il te suffira simplement de connaître un mot de passe pour déverrouiller les autres. KeepassXC est gratuit et multi-plateforme, il encrypte vos mots de passe avec l’algo AES avec SHA-256, il permet d’utiliser une clé privée. Bref, je te le recommande, un bon admin système ne met jamais les même mots de passe sur ses serveurs !

Première chose à faire, si comme moi tu as reçu ton mot de passe root par mail, considère le comme potentiellement intercepté. (Comme pour tout tes mots de passe que tu reçois par mail d’ailleurs). Ton mot de passe root ne doit être connu que par toi et n’être accessible par personne d’autre, alors on le change tout de suite. Connectes toi en SSH sur ton serveur et change ton mot de passe avec la commande :

passwd root

2 – Root c’est fini, bonjour admin

Comme je l’ai dis, la plupart des attaques sont des attaques où des robots vont tenter de se connecter en SSH sur ton serveur avec l’utilisateur root en tentant des combinaisons différentes de mot de passe. Une bonne pratique de sécurité consiste donc à bloquer root et de le remplacer par un utilisateur de ton choix qui aura les privilèges root.

Commences par ajouter un utilisateur, ici, je l’appelle « rp » parce que c’est mes initiales mais ne sois pas benêt et mets les tiennes à la place 😉 :

adduser rp

On installe le paquet sudo pour permettre à certains utilisateurs autorisés de prendre les droits root :

apt install sudo

Puis on ajoute l’utilisateur aux groupes lui permettant d’avoir les privilèges root (j’ai rajouté le groupe adm pour pouvoir consulter les logs sans devoir utiliser sudo) :

usermod -aG root,sudo,adm rp

On modifie maintenant la configuration SSH pour interdire la connexion en tant que root. Tu peux aussi modifier ton port de connexion SSH si tu le souhaite, ça t’évitera 99.99% des attaques par brute force mais c’est un peu pénible pour la suite de devoir toujours indiquer ton numéro de port …

/etc/ssh/sshd_config

...
# Interdire à root de se connecter en SSH
PermitRootLogin no

# Facultatif : Modifier le port de connexion pour le SSH
Port 4854 

# Facultatif : Seul admin peux se connecter en SSH
AllowUsers rp 

# Facultatif : Seul les utilisateurs du groupe sshusers peuvent se connecter en SSH
AllowGroups sshusers
...       

Attention ! Avant de redémarrer ton service SSH, avec une mauvaise configuration, tu risques de perdre complètement l’accès à ton serveur ! Penses à garder ta session ssh root active le temps de vérifier que tout va bien et que tu dispose bien des privilèges root avec le nouvel utilisateur.

On redémarre le service SSH :

service ssh restart

On se connecte en SSH avec le nouvel utilisateur et on test que la commande sudo fonctionne bien :

sudo ls -l ./

Si ça ne fonctionne pas, ne quittes surtout par ta session root et fais ce qu’il faut pour que ça marche.

Le principe de sudo est simple, tout ce que tu exécutes en utilisant le préfixe sudo va exécuter la commande avec les droits root. Tu peux même prendre la main sur l’utilisateur root avec la commande (mais à éviter) :

sudo su

Combien d’admin système qui ne respecte pas cette bonne pratique se retrouve connecté au serveur en root, puis lors d’une pause café, laisse parfois leur session connecté sans surveillance ? Déjà s’il te plaît, verrouilles toujours ta session quand tu laisse ton abandonne ton poste. Sudo apporte une sécurité supplémentaire, il faut confirmer ton mot de passe pour exécuter une commande root.

3 – Un firewall strict = maîtrise des portes d’entrées / sorties

Sur ton serveur, plusieurs services sont en cours d’exécution et certains sont à l’écoute sur des ports ouverts ce qui peut présenter un risque si le logiciel derrière le port ouvert contient une faille. Il est important de configurer un firewall qui bloquera tous les ports sauf ceux dont nous avons besoin et dont le logiciel qui l’utilise est sérieux, réputé pour être sécurisé et dont on a confiance.

Aller hop ! On installe l’incontournable paquet iptable :

sudo apt install iptables

On définit les règles du firewall, en fonction des services que tu utilises, commentes, dé-commentes ou ajoute des lignes :

/etc/init.d/firewall

#! /bin/sh                                                                                                                                                                         
### BEGIN INIT INFO                                                                                                                                                                
# Provides:          PersonalFirewall                                                                                                                                              
# Required-Start:    $remote_fs $syslog                                                                                                                                            
# Required-Stop:     $remote_fs $syslog                                                                                                                                            
# Default-Start:     2 3 4 5                                                                                                                                                       
# Default-Stop:      0 1 6                                                                                                                                                         
# Short-Description: Personal Firewall                                                                                                                                             
# Description:       Init the firewall rules                                                                                                                                                              
### END INIT INFO                                                                                                                                                                  
                                                                                                                                                                                   
# programme iptables IPV4 et IPV6                                                                                                                                                  
IPT=/sbin/iptables                                                                                                                                                                 
IP6T=/sbin/ip6tables                                                                                                                                                               

# Les IPs                                                                                                                                                                          
#IP_TRUSTED=xx.xx.xx.xx   
                                                                                                                                                           

do_start() {                                                                                                                                                                       

    # Efface toutes les regles en cours. -F toutes. -X utilisateurs                                                                                                                
    $IPT -t filter -F                                                                                                                                                              
    $IPT -t filter -X                                                                                                                                                              
    $IPT -t nat -F                                                                                                                                                                 
    $IPT -t nat -X                                                                                                                                                                 
    $IPT -t mangle -F                                                                                                                                                              
    $IPT -t mangle -X                                                                                                                                                              
    $IP6T -t filter -F                                                                                                                                                             
    $IP6T -t filter -X                                                                                                                                                              
    $IP6T -t mangle -F                                                                                                                                                             
    $IP6T -t mangle -X                                                                                                                                                             

    # strategie (-P) par defaut : bloc tout l'entrant le forward et autorise le sortant                                                                                            
    $IPT -t filter -P INPUT DROP                                                                                                                                                   
    $IPT -t filter -P FORWARD DROP                                                                                                                                                 
    $IPT -t filter -P OUTPUT ACCEPT                                                                                                                                                
    $IP6T -t filter -P INPUT DROP                                                                                                                                                  
    $IP6T -t filter -P FORWARD DROP                                                                                                                                                
    $IP6T -t filter -P OUTPUT ACCEPT                                                                                                                                               

    # Loopback                                                                                                                                                                     
    $IPT -t filter -A INPUT -i lo -j ACCEPT                                                                                                                                        
    $IPT -t filter -A OUTPUT -o lo -j ACCEPT                                                                                                                                       
    $IP6T -t filter -A INPUT -i lo -j ACCEPT                                                                                                                                       
    $IP6T -t filter -A OUTPUT -o lo -j ACCEPT                                                                                                                                      

    # Permettre a une connexion ouverte de recevoir du trafic en entree                                                                                                            
    $IPT -t filter -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT                                                                                                         
    $IP6T -t filter -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT                                                                                                        

    # ICMP                                                                                                                                                                         
    $IPT -t filter -A INPUT -p icmp -j ACCEPT                                                                                                                                      

    # DNS:53                                                                                                                                                                       
    $IPT -t filter -A INPUT -p tcp --dport 53 -j ACCEPT                                                                                                                            
    $IPT -t filter -A INPUT -p udp --dport 53 -j ACCEPT                                                                                                                            
    $IP6T -t filter -A INPUT -p tcp --dport 53 -j ACCEPT                                                                                                                           
    $IP6T -t filter -A INPUT -p udp --dport 53 -j ACCEPT                                                                                                                           

    # SSH:22
    # ATTENTION, indiques bien ton port personnalisé si tu l'as changé                                                                                                                                                                     
    $IPT -t filter -A INPUT -p tcp --dport 22 -j ACCEPT                                                                                                                            
    $IP6T -t filter -A INPUT -p tcp --dport 22 -j ACCEPT                                                                                                                           

    # HTTP:80                                                                                                                                                                     
    $IPT -t filter -A INPUT -p tcp --dport 80 -j ACCEPT                                                                                                                            
    $IP6T -t filter -A INPUT -p tcp --dport 80 -j ACCEPT                                                                                                                           

    # HTTPS:443                                                                                                                                                                        
    $IPT -t filter -A INPUT -p tcp --dport 443 -j ACCEPT                                                                                                                           
    $IP6T -t filter -A INPUT -p tcp --dport 443 -j ACCEPT                                                                                                                          

    # SMTP:25/587/465                                                                                                                                                                         
    $IPT -t filter -A INPUT -p tcp --dport 25 -j ACCEPT                                                                                                                            
    $IP6T -t filter -A INPUT -p tcp --dport 25 -j ACCEPT                                                                                                                           
    $IPT -t filter -A INPUT -p tcp --dport 587 -j ACCEPT                                                                                                                           
    $IP6T -t filter -A INPUT -p tcp --dport 587 -j ACCEPT                                                                                                                          
#    $IPT -t filter -A INPUT -p tcp --dport 465 -j ACCEPT                                                                                                                          
#    $IP6T -t filter -A INPUT -p tcp --dport 465 -j ACCEPT                                                                                                                         

    # POP3:110/995                                                                                                                                                                         
#    $IPT -t filter -A INPUT -p tcp --dport 110 -j ACCEPT                                                                                                                          
#    $IP6T -t filter -A INPUT -p tcp --dport 110 -j ACCEPT                                                                                                                         
#    $IPT -t filter -A INPUT -p tcp --dport 995 -j ACCEPT                                                                                                                          
#    $IP6T -t filter -A INPUT -p tcp --dport 995 -j ACCEPT                                                                                                                         

    # IMAP / SIEVE : 143/993/4190                                                                                                                                                                 
#    $IPT -t filter -A INPUT -p tcp --dport 143 -j ACCEPT                                                                                                                          
#    $IP6T -t filter -A INPUT -p tcp --dport 143 -j ACCEPT                                                                                                                         
    $IPT -t filter -A INPUT -p tcp --dport 993 -j ACCEPT                                                                                                                           
    $IP6T -t filter -A INPUT -p tcp --dport 993 -j ACCEPT                                                                                                                          
    $IPT -t filter -A INPUT -p tcp --dport 4190 -j ACCEPT                                                                                                                          
    $IP6T -t filter -A INPUT -p tcp --dport 4190 -j ACCEPT                                                                                                                         

    # accepte tout d'une ip en TCP                                                                                                                                                 
#    $IPT -t filter -A INPUT -p tcp -s $IP_TRUSTED -j ACCEPT                                                                                                                         

    echo "firewall started [OK]"                                                                                                                                                   
}                                                                                                                                                                                  

# fonction qui arrete le firewall                                                                                                                                                  
do_stop() {                                                                                                                                                                        

    # Efface toutes les regles                                                                                                                                                     
    $IPT -t filter -F                                                                                                                                                              
    $IPT -t filter -X                                                                                                                                                              
    $IPT -t nat -F                                                                                                                                                                 
    $IPT -t nat -X                                                                                                                                                                 
    $IPT -t mangle -F                                                                                                                                                              
    $IPT -t mangle -X
    $IP6T -t filter -F
    $IP6T -t filter -X
    $IP6T -t mangle -F
    $IP6T -t mangle -X

    # remet la strategie
    $IPT -t filter -P INPUT ACCEPT
    $IPT -t filter -P OUTPUT ACCEPT
    $IPT -t filter -P FORWARD ACCEPT
    $IP6T -t filter -P INPUT ACCEPT
    $IP6T -t filter -P OUTPUT ACCEPT
    $IP6T -t filter -P FORWARD ACCEPT

    #
    echo "firewall stopped [OK]"
}

# fonction status firewall
do_status() {

    # affiche les regles en cours
    clear
    echo Status IPV4
    echo -----------------------------------------------
    $IPT -L -n -v
    echo
    echo -----------------------------------------------
    echo
    echo status IPV6
    echo -----------------------------------------------
    $IP6T -L -n -v
    echo
}

case "$1" in
    start)
        do_start
        exit 0
    ;;

    stop)
        do_stop
        exit 0
    ;;

    restart)
        do_stop
        do_start
        exit 0
    ;;

    status)
        do_status
        exit 0
    ;;

    *)
        echo "Usage: /etc/init.d/firewall {start|stop|restart|status}"
        exit 1
    ;;

esac

Il faut donner les droits d’exécution au script :

sudo chmod +x /etc/init.d/firewall

Attention ! Si tu définis mal les règles, tu peux te bloquer toi même et ne plus pouvoir accéder au serveur. Je te conseille fortement d’exécuter le script puis essaye de te ré-authentifier en SSH. Si après exécution du script, tout est bloqué, tu as perdu ta session et impossible de te reconnecter, redémarre le serveur pour réinitialiser le firewall.

C’est partit ! On lance le script :

sudo /etc/init.d/firewall start

Si tout va bien et que tu peux toujours te connecter en SSH, alors on peut indiquer au serveur que tu veux que le script soit exécuté au démarrage pour que jamais le firewall ne soit corrompu :

 sudo update-rc.d firewall defaults

Si tu changes d’avis, tu peux le retirer avec la commande :

sudo update-rc.d -f firewall remove

4 – Fail2Ban, surveillance des logs et bannissement par IP

Fail2Ban permet de bannir les machines qui tentent de brute forcer votre serveur. Pour cela, il se base sur les logs du serveur et en fonctions de règles établies, bannit les IPs pirates.

On installe le paquet fail2ban :

sudo apt install fail2ban

Créer le fichier de configuration des « prisons »

sudo cp /etc/fail2ban/jail.conf/etc/fail2ban/jail.local

/etc/fail2ban/jail.local

...
# Durée du bannissement en seconde
bantime  = 600

# Plage de temps de surveillance des logs
findtime = 600

# Nombre de tentatives avant bannissement
maxretry = 3

# Adresse mail des notifications
destemail = moi@mondomain.fr

# Nom du sender dans les notifications mail
sendername = Fail2ban
...

Dans ce fichier, sont configurés différents filtres [ssh], [apache-auth] … On va indiquer au serveur lesquels doivent être surveillés.

/etc/fail2ban/jail.d/custom.conf

[sshd]
enabled = true

[sshd-ddos]
enabled = true

[postfix]
enabled = true

[dovecot]
enabled = true

[sieve]
enabled = true

[recidive]
enabled = tru

C’est un exemple, il faut indiquer les services que tu utilises toi.

Depuis une dernière version de fail2ban, pour recevoir les mails de notification, il faut indiquer votre mail dans les fichiers :

  • /etc/fail2ban/action.d/sendmail-common.conf
  • /etc/fail2ban/action.d/mail.conf
  • /etc/fail2ban/action.d/mail-whois.conf

Je m’arrête 2 secondes sur le filtre [recidive]. Il permet de bannir plus longtemps les IPs qui ont déjà été bannie plusieurs fois. Par exemple, on va pouvoir dire à fail2ban de bannir pendant 1 an les IPs qui ont déjà été bannies 3 fois dans la journée.

Une fois que tout est configuré, on redémarre le service :

sudo service fail2ban restart

Puis on vérifie que les prisons sont bien en service :

sudo fail2ban-client status

5 – Toujours à jour avec cron-apt

Bon, c’est bien beau, mon serveur est sécurisé mais que se passe il le jour où une faille dans un logiciel est découverte pendant que je suis en vacance ? Un pirate aura tout son temps pour en profiter.

Un serveur fait les choses de façon automatique non ? Hé bien qu’il se mette à jour tout seul ! Aller on installe le paquet cron-apt :

sudo apt install cron-apt

On veux faire les mises à jour de sécurité uniquement, donc on créé un nouveau fichier de source :

grep security /etc/apt/sources.list > /etc/apt/security.sources.list

Un peu de configuration :

/etc/cron-apt/config

APTCOMMAND=/usr/bin/apt-get
OPTIONS="-o quiet=1 -o Dir::Etc::SourceList=/etc/apt/security.sources.list"
MAILTO="moi@mondomain.fr"
MAILON="upgrade"

On indique qu’on veut que cron-apt installe les mises à jour quand il en trouve :

/etc/cron-apt/action.d/3-download

dist-upgrade -y -o APT::Get::Show-Upgraded=true

Cron-apt se lance par défaut toute les nuits à 4h du matin, si tu veux modifier ça, c’est ici : /etc/cron.d/cron-apt

Ok, on est pas trop mal là, c’est plutôt bien sécure ! Mais nous on est des dingues, on va encore plus loin ! Il est toujours possible de protéger plus son serveur, mais plus l’on protège plus on ajoute de contraintes. La protection ultime n’existe pas, du moment que la machine est connectée à internet, la moindre faille peut-être exploitée de façon plus ou moins ingénieuse.

Sécurité avancée

1 – Rkhunter : Détecter les intrusions

Rhkunter calcule les empreintes MD5 des logiciels installés sur ton serveur. Si un pirate arrivait à pénétrer ton serveur, il est fort probable qu’il ajoute une backdoor afin de pouvoir revenir facilement par la suite. Rkhunter détecte donc ces backdoors et t’avertis.

On installe le paquet rkhunter :

sudo apt install rkhunter

Puis on édite la configuration :

/etc/default/rkhunter

# Pour effectuer une vérification chaque jour
CRON_DAILY_RUN="yes"
REPORT_EMAIL="moi@mondomaine.fr"

Rkhunter va parfois t’avertir de modifications sur un logiciel alors que tu en es à l’origine (suite à une mise à jour par exemple), dans ce cas, il faut mettre la base d’empreintes à jour avec la commande :

sudo rkhunter --propupd

2 – Logwatch : Surveillez l’activité de votre serveur

Logwatch est un utilitaire qui analyse vos logs du serveur pour te faire un récapitulatif tout les jours sous forme de mail. Delà te permet de détecter les anomalies. Logwatch va par exemple te faire un récapitulatif des mails sortants de votre serveur. Tu pourras ainsi voir si ton serveur ne sert pas de passerelle pour le spam. Il va t’indiquer les attaques bloquées par fail2ban, etc …

On installe le paquet logwatch :

sudo apt install logwatch

On le configure :

sudo cp /usr/share/logwatch/default.conf/logwatch.conf /etc/logwatch/conf/logwatch.conf

/etc/logwatch/conf/logwatch.conf

# Pour recevoir les mails au format html, c'est plus agréable à lire
Format = html
# Adresse sur laquelle recevoir les mails
MailTo = moi@mondomaine.fr
# Niveau de détail des logs
Detail = Med               

Et si tu veux recevoir un rapport là tout de suite :

sudo logwatch --mailto moi@mondomaine.fr --output html

3 – Analyser de trafic en temps réel

Les deux logiciels suivants analysent le trafic en temps réel pour empêcher les attaques. Ils se lancent donc à chaque requête vers le serveur pour détecter les attaques et consomment donc des ressources, ce qui ralentit les échanges. Dans le cas d’un serveur d’hébergement web, ce n’est pas très pertinent si tu souhaites des sites qui répondent du tac au tac. Après c’est toi qui vois en fonction de tes besoin en sécurité. Je ne vais pas m’attarder dessus dans cet article.

  • Portsentry : Détection des scans de ports très puissant. Pour l’utiliser c’est ici.
  • Snort : Système de détection d’intrusion. Pour l’utiliser c’est ici.

4 – Une alarme SSH

Une autre chose très simple que tu peux mettre en place est une alerte mail dès qu’une authentification ssh a lieu sur ton serveur.

Cette méthode est plutôt contraignante car normalement, tous les mails reçus sont des faux positifs …

Édites le fichier .bashrc de l’utilisateur à protéger (dans le homedir) et ajoutes à la fin du fichier :

~/.bashrc

echo "Objet : Alerte connexion SSH.
Serveur : `hostname`
Date : `date`
`who` " | mail -s "`hostname` connexion ssh de : `who | cut -d"(" -f2 | cut -d")" -f1`" moi@mondomaine.fr

Si tu veux le mettre en place pour l’utilisateur root, le fichier est /root/.bashrc car le homedir de root est /root/

5- Restrictions par IP

Cette méthode est très efficace, car seul l’IP de ton choix peut communiquer avec le serveur sur le protocole choisi. Par contre, les offres d’accès internet permettent rarement d’avoir une IP fixe. Et puis tu ne pourra plus accéder à ton serveur de n’importe où (sauf VPN).

Il existe plusieurs méthodes pour restreindre par IPs. Je te présente celle qui utilise le firewall. Si tu as suivi ce tuto depuis le début, nous avons créé un fichier /etc/init.d/firewall.

Il suffit de rajouter les options `-s 100:100:100:100, 101:101:101:101` sur les protocoles à restreindre (avec tes IPs bien sûr …).

Exemple pour restreindre le protocole SSH sur mon IP seulement :

/etc/init./firewall

$IPT -t filter -A INPUT -p tcp --dport 22 -s 100:100:100:100 -j ACCEPT
$IP6T -t filter -A INPUT -p tcp --dport 22 -s 100:100:100:100 -j ACCEPT

Tu peux faire de même sur tous les ports que tu veux. Si tu veux le faire temporairement, par exemple pour autorisé un ami à se connecter de chez lui :

iptables -t filter -A INPUT -p tcp --dport 22 -s 100:100:100:100 -j ACCEPT
ip6tables -t filter -A INPUT -p tcp --dport 22 -s 100:100:100:100 -j ACCEPT

Quand il a fini, on réinitialise, on applique la tolérance zéro !

iptables -t filter -A INPUT -p tcp --dport 22 -s 100:100:100:100 -j DROP
ip6tables -t filter -A INPUT -p tcp --dport 22 -s 100:100:100:100 -j DROP

Tu peux aussi redémarrer le firewall pour lui retirer les droits (cela réinitialise toutes les règles) :

sudo /etc/init.d/firewall restart

6 – Authentification SSH par clé privée

L’authentification par clé privée augmente considérablement la difficulté de brute forcer le serveur en SSH. Il faut à la fois un fichier et une clé pour décrypter ce fichier avant de pouvoir se connecter au serveur.

J’ai fait un article expliquant la mise en place d’une authentification SSH par clé privée : c’est ici !

Une fois ta clé publique insérée sur le serveur, configure ton service SSH pour bloquer l’authentification par mot de passe simple :

/etc/ssh/sshd_config

...
RSAAuthentication yes
# Autoriser l'authentification par clé privée
PubkeyAuthentication yes
# Bloquer l'authentification avec mot de passe simple     
PasswordAuthentication no    
...

On relance le service SSH :

sudo service ssh restart

Attention ! Encore une fois, assure toi que ça marche bien en essayant de t’authentifier avec ta clé avant de fermer ta session sinon tu vas perdre accès à ton serveur …

Si tu gère plusieurs serveurs, il est plus agréable de se connecter avec la même clé privée. Ainsi, aucun mot de passe ne t’es demandé pour te connecter une fois que ta clé privée est déverrouillée. Il y a donc aussi des avantages à utiliser cette méthode. tu peux aussi permettre la connexion via clé privée et via mot de passe (au choix). Dans ce cas, tu ne gagne pas en sécurité, mais tu gagne en simplicité d’utilisation.

Le mot de la fin

La sécurité d’un serveur est un sujet délicat, plus tu as de services qui tournent sur le serveur, plus le nombre de failles potentielles est important. Je te recommande de diviser pour mieux régner, sépares tes services (mails, hébergement, cloud, etc …) sur des serveurs différents. Si l’un des services tombe, les autres subsistent et c’est l’un des avantages des serveurs virtuels.

Autre chose, plus tu as d’utilisateurs sur un serveur, plus le risque de mot de passe « dans la nature » est grand. Les utilisateurs « légaux » de ton serveur sont la plupart du temps les éléments déclencheurs des problèmes. Penses donc à attribuer le strict minimum de droits à tes utilisateurs sur le serveur et formes-les. Mets en place des restrictions sur tes services (exemple : maximum d’envois de mails par heure par utilisateur pour éviter que l’utilisateur puisse servir de relais spam en étant piraté). Obliges tes utilisateurs à utiliser des mots de passe complexes.

Mets à jour tes logiciels le plus souvent possibles !

Tiens toi informé sur les logiciels que tu utilise pour être au courant des dernières failles, abandon de projet, etc …

Forces l’utilisation de protocoles sécurisés utilisant le cryptage SSL ou TLS (ssh, https, imaps, smtps, etc …)

Tentes de te pirater toi même, cherches les failles dans ton système, fais une veille sur la sécurité.

Générer un certificat SSL auto-signé pour passer en HTTPS

Certificat SSL pour HTTS

Pourquoi installer le https ?

Le HTTPS est un protocole qui permet d’encrypter les échanges entre ton serveur et le navigateur web. Ainsi, il est impossible à un pirate de récupérer les identifiants que tu saisis pour te loguer sur ton site. En HTTP, les identifiants passent en clair et sont facile à intercepter.

Il nécessite de créer un certificat SSL qui permettra d’initialiser les échanges cryptés. 

C’est payant ?

Pour être reconnu par un navigateur web, le certificat SSL doit être signé par un organisme de certification. Ces organisme font payer cette certification. Depuis quelques années, Let’s encrypt permet de générer des certificats SSL gratuitement ! C’est une excellente nouvelle pour l’évolution globale de la sécurité sur internet.

Tu peux aussi signer toi même ton certificat SSL, il ne sera alors pas connu par les navigateurs et tu aura une page d’erreur du genre :

Votre connexion n'est pas privée
Page d’alerte avec un certificat auto-signé

Dans le cas d’un site en local, ce n’est pas grave, il te suffit de passer cette alerte et tu peux consulter ton site en toute sécurité car la couche SSL qui crypte les données fait quand même son travail.

Par contre, si un hacker venait à prendre le contrôle de ton serveur et modifiait ton certificat SSL, il serai alors en mesure de décrypter les échanges. Mais bon … Je pense qu’une fois le hacker sur ton serveur, il peut aisément avoir accès à tes données.

Le cas d’un certificat auto-signé peut être intéressant pour la gestion d’un intranet. L’idée serait de générer un certificat maître auto-signé qui signerait ensuite lui même tous les certificats SSL de l’ensemble des services utilisé dans l’intranet. C’est ce qu’on appelle une PKI (Public Key Infrastructure).

On peut ensuite installer le certificat maître sur tout les postes des utilisateurs de l’intranet. Ces dernier pourront alors consulter tous les sites en HTTPS sans avoir d’alerte de sécurité et l’administrateur de l’intranet garde la main pour pouvoir ajouter de nouveaux certificats valides.

La gestion des PKI fera l’objet d’un article que je sortirai bientôt 🙂

Dans cet article on va s’intéresser à la création d’un certificat simple auto-signé.

Créer le certificat

Prérequis

Nous allons travailler avec un site hébergé sur un serveur Linux (avec accès root). Nous utiliserons Apache2 pour le serveur web.

Openssl doit être installé pour générer les certificats.

apt-get install openssl

Génération de la clé privée

On va créer une clé privée de 4096 bit encrypté avec l’algorithme de cryptage AES 256 bit.

openssl genrsa -aes256 -out certificat.key 4096

Entres un mot de passe pour ta clé (penses à bien le conserver).

On a généré une clé privée protégée par mot de passe, on va maintenant générer cette même clé mais déverrouillée.

Si tu ne souhaites pas la déverrouiller, le mot de passe de la clé sera demandé à chaque redémarrage de Apache2.

Dans un premier temps on va renommer notre clé :

mv certificat.key certificat.key.lock

Puis générer notre certificat déverrouillé :

openssl rsa -in certificat.key.lock -out certificat.key

Saisisses le mot de passe de la clé, le fichier déverrouillé est créé.

Ta clé privée déverrouillée : certificat.key

Ta clé privée verrouillée : certificat.key.lock

Génération du fichier de demande de signature

Ce fichier va être utile pour obtenir notre certification de l’organisme ou pour auto-signer notre certificat.

openssl req -new -key certificat.key.lock -out certificat.csr

Renseignes les différents champs demandés comme tu veux.

Ton fichier de demande de signature : certificat.csr

Génération du certificat

Pour auto-signer ton certificat, exécutes la commande suivante :

openssl x509 -req -days 365 -in certificat.csr -signkey certificat.key.lock -out certificat.crt

Ton certificat : certificat.crt

Indiquer à Apache d’utiliser le certificat SSL

Première chose à faire, vérifier que le ssl est activé sur apache :

a2enmod ssl

Il va falloir ensuite créer un vHost sur le port 443 (port du https) :

/etc/apache2/site-availables/tuto.conf

<VirtualHost *:80>
    ServerName      tuto.remipoignon.fr
    # On redirige le port HTTP vers le port HTTPS
    Redirect        / https://www.remipoignon.fr
</VirtualHost>

<VirtualHost *:443>
    ServerName      tuto.remipoignon.fr
    DocumentRoot    /var/www/tuto
        
    SSLEngine on
    SSLCertificateFile    /etc/ssl/www/certificat.crt
    SSLCertificateKeyFile /etc/ssl/www/certificat.key
    # Facultatif, ici, on dit qu'on accepte tout les protocoles SSL sauf SSLv2 et SSLv3 (dont on accepte que le TLS ici)
    SSLProtocol all -SSLv2 -SSLv3
    # Facultatif, on dit que c'est le serveur qui donne l'ordre des algorithmes de chiffrement pendant la négociation avec le client
    SSLHonorCipherOrder on
    # Facultatif, algorithme de chiffrement disponibles (ne pas être trop méchant sinon beaucoup de navigateur un peu ancien ne pourront plus se connecter)
    SSLCipherSuite ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES
</VirtualHost>

On active le vHost :

a2ensite tuto.conf
service apache2 restart

C’est tout, ton site est maintenant en HTTPS