Sécuriser Nextcloud sur Raspberry Pi avec un pare-feu

image pare-feu

Cet article est un complément au guide d’installation de Nextcloud sur Raspberry Pi.

Il a pour but de mieux sécuriser Nextcloud sur Raspberry Pi avec un pare-feu.

 

En effet, pour fonctionner le serveur Nextcloud doit être ouvert sur l’extérieur. De même, nous avons configuré le Raspberry Pi en mode “headless”, c’est à dire sans écran ni clavier. Pour communiquer avec le Pi depuis un ordinateur, nous avons ouvert un port SSH.

Nous avons pour le moment trois protections pour nous protéger des attaques extérieures :

  • le routeur de notre réseau (la box) sur lequel nous avons ouvert uniquement trois ports (80 – http et 443 -https pour Nextcloud et le 22 pour le SSH),
  • les mots de passe du système d’exploitation Raspbian et de Nextcloud
  • le logiciel fail2ban qui va nous protéger contre les “attaques par force brute”, c’est à dire la tentative d’un intrus de découvrir les mots de passe par des essais multiples.

 

Le pare-feu va nous apporter une protection supplémentaire :

  • en rejetant les connexions suspicieuses,
  • en évitant certaines attaques par déni de services (saturation du réseau pour l’empêcher de fonctionner voire le mettre hors service et exploiter une faille),
  • en limitant les portes d’entrée et de sortie (le routeur ne protège pas les connexions sortantes).

 

Première rencontre avec iptables

Le système d’exploitation Raspbian est pré-installé avec un pare-feu (netfilter) avec lequel on communique par une interface appelée iptables.

Nous allons vérifier dans un premier temps la configuration de base de ce pare-feu avec la commande iptables -L sur le Raspberry :

lambda_user@myweb:~ $ sudo iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
fail2ban-pam-generic  tcp  --  anywhere             anywhere
fail2ban-ssh  tcp  --  anywhere             anywhere             multiport dports ssh

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Chain fail2ban-pam-generic (1 references)
target     prot opt source               destination
RETURN     all  --  anywhere             anywhere

Chain fail2ban-ssh (1 references)
target     prot opt source               destination
RETURN     all  --  anywhere             anywhere

Si l’on omet les références à fail2ban qui a inscrit des règles dans le pare-feu, nous avons trois instructions :

Chain INPUT (connexions entrantes)

Chain FORWARD (connexions transmises)

Chain OUTPUT (connexions sortantes)

avec pour politique de base : ACCEPT.

Pour le moment donc, notre pare-feu autorise tout le trafic internet.

 

Préparatifs

Avant de configurer notre pare-feu, nous allons déjà nous renseigner sur le fonctionnement de notre réseau et recueillir des informations importantes : l’adresse IP interne de notre réseau et celle du Pi.

Pour ce faire, sur le Raspberry Pi :

lambda_user@myweb:~ $ sudo ip route show
default via 192.168.0.254 dev eth0  metric 202 
192.168.0.0/24 dev eth0  proto kernel  scope link  src 192.168.0.15  metric 202

Nous notons que notre réseau interne est disponible sur l’interface eth0 aux adresses comprises entre 192.168.0.1 et 192.168.0.254, l’adresse du Pi étant 192.168.0.15.

Il est très important pour la suite de retenir la plage d’adresses disponibles sur le réseau interne : 192.168.0.0/24 (adresse de réseau et masque de réseau).

 

Nous allons ensuite trouver les adresses IP des ordinateurs connectés sur notre réseau interne après avoir installé nmap :

lambda_user@myweb:~ $ sudo apt install nmap

lambda_user@myweb:~ $ sudo nmap -sP 192.168.0.0/24

Starting Nmap 6.47 ( http://nmap.org ) at 2016-12-07 21:53 CET
Nmap scan report for 192.168.0.11
Host is up (-0.10s latency).
MAC Address: 44:8A:5B:5A:C4:AA (Micro-Star INT'L CO.)
Nmap scan report for 192.168.0.254
Host is up (0.00082s latency).
MAC Address: 00:07:D2:A8:C4:72 (Freebox SA)
Nmap scan report for 192.168.0.15
Host is up.
Nmap done: 256 IP addresses (3 hosts up) scanned in 5.92 seconds

L’utilitaire de scan nmap nous informe qu’il y a trois appareils branchés sur le réseau :

192.168.0.11 : l’ordinateur principal

192.168.0.254 : la box internet

192.168.0.15 : le raspberry pi.

Nous allons donc retenir l’IP de l’ordinateur principal depuis lequel nous commandons le Pi à savoir : 192.168.0.11.

 

Configuration d’iptables

Nous sommes maintenant prêt pour configurer iptables.

Cette configuration peut se faire de deux manières :

  • soit ligne à ligne avec la commande iptables -A …
  • soit en éditant un fichier que nous intégrons ensuite d’un bloc à iptables.

Il faut également savoir qu’iptables gère les deux protocoles internet existant : IPv4 et IPv6. Plutôt que d’écrire deux fichiers distincts, nous allons tout rassembler en un seul fichier.

 lambda_user@myweb:~ $ nano regles-iptables

 

Dans l’éditeur de texte qui s’ouvre nous allons copier le texte suivant, en prenant garde aux données surlignées en rouge :

 

* filter

# On remet toutes les règles à 0
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]

## REGLES DE TRAFIC ENTRANT

# Loopback entrant (autorisation du bouclage local)
-A INPUT -i lo -p all -j ACCEPT

# Rejet des connexions extérieures se faisant passer pour un bouclage local
-4 -A INPUT -s 127.0.0.0/8 ! -i lo -j DROP
-6 -A INPUT -s ::1/128 ! -i lo -j DROP

# Autorisation des connexions déjà établies
-A INPUT -m conntrack --ctstate ESTABLISHED -j ACCEPT

### Rejet des usurpations d'adresses (spoofing) : adresses externes se faisant passer pour une adresse interne

### ATTENTION !!! : COMMENTER (mettre un # devant) LA LIGNE CONCERNANT VOTRE RESEAU INTERNE (ici 192.168.0.0/24)###

-4 -A INPUT -s 10.0.0.0/8 -j DROP 
-4 -A INPUT -s 169.254.0.0/16 -j DROP
-4 -A INPUT -s 172.16.0.0/12 -j DROP
-4 -A INPUT -s 192.0.2.0/24 -j DROP
# -4 -A INPUT -s 192.168.0.0/24 -j DROP
-4 -A INPUT -s 224.0.0.0/4      -j DROP
-4 -A INPUT -d 224.0.0.0/4      -j DROP
-4 -A INPUT -s 240.0.0.0/5 -j DROP
-4 -A INPUT -d 240.0.0.0/5 -j DROP
-4 -A INPUT -s 0.0.0.0/8 -j DROP
-4 -A INPUT -d 0.0.0.0/8 -j DROP
-4 -A INPUT -d 239.255.255.0/24 -j DROP
-4 -A INPUT -d 255.255.255.255  -j DROP


#Protection contre les attaques par réflexion (smurf) : inondation de pings pour bloquer la machine
-4 -A INPUT -p icmp -m icmp --icmp-type address-mask-request -j DROP
-4 -A INPUT -p icmp -m icmp --icmp-type timestamp-request -j DROP
-4 -A INPUT -p icmp -m limit --limit 2/second --limit-burst 2 -j ACCEPT

# Protection contre Paquet Xmas (paquet de données très lourd pouvant saturer un serveur)
-A INPUT -p tcp --tcp-flags ALL FIN,PSH,URG -j DROP

# Protection contre les paquets invalides
-A INPUT -m state --state INVALID -j DROP
-A FORWARD -m state --state INVALID -j DROP
-A OUTPUT -m state --state INVALID -j DROP
-A INPUT -p tcp -m tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
-A INPUT -p tcp -m tcp --tcp-flags SYN,RST SYN,RST -j DROP

# Protection attaque TCP reset (attaque pour fermer la connexion)
-A INPUT -p tcp -m tcp --tcp-flags RST RST -m limit --limit 2/second --limit-burst 2 -j ACCEPT

# Autorisation de certains types de connexions entrantes

#Autorisation complète du port 80 - HTTP - nécessaire à nextcloud
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT

#Autorisation complète du port 443 - HTTPS - nécessaire à nextcloud
-A INPUT -p tcp -m tcp --dport 443 -j ACCEPT

#Autorisation du port 22 - SSH uniquement pour le réseau local 

### ATTENTION !!! UTILISER LA PLAGE D'ADRESSES TROUVÉE PLUS HAUT AVEC sudo ip route show !!!
-4 -A INPUT -p tcp --dport 22 -s 192.168.0.0/24 -j ACCEPT


# Autoriser le ping
-4 -A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT
-6 -A INPUT -p icmpv6 -j ACCEPT


### REJETER TOUT LE RESTE DU TRAFIC ENTRANT
-A INPUT -j DROP


# REGLES DE TRAFIC SORTANT

## Loopback sortant
-A OUTPUT -o lo -j ACCEPT

## autoriser les connexions établies
-A OUTPUT -m conntrack --ctstate ESTABLISHED -j ACCEPT

# Autorisation des ports suivants vers l'extérieurs
# SMTP = 25 (protocole de mails sortants)
# DNS =53  (protocole de résolution de noms)
# HTTP = 80 (HTTP)
# ntp = 123 (protocole de synchronisation de l'heure)
# HTTPS = 443 (HTTPS)
# SSH = 22 (SSH) on ne remet pas de règles sortantes pour le ssh car nous avons autorisé les connexions établies
### 

-A OUTPUT -p tcp -m tcp --dport 25 -j ACCEPT
-A OUTPUT -p udp -m udp --dport 53 -j ACCEPT
-A OUTPUT -p udp -m udp --dport 123 -j ACCEPT
-A OUTPUT -p tcp -m tcp --dport 80 -j ACCEPT
-A OUTPUT -p tcp -m tcp --dport 443 -j ACCEPT

# Autorisation du ping
-4 -A OUTPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT
-6 -A OUTPUT -p icmpv6 -j ACCEPT

# REJET DU RESTE DU TRAFIC SORTANT
-A OUTPUT -j DROP

# REJET DU TRAFIC FORWARD
-A FORWARD -j DROP

COMMIT

 

Une fois recopié le texte dans l’éditeur nano :

Ctrl-o pour enregistrer,

Ctrl-x pour quitter.

 

Si on souhaite limiter l’accès SSH uniquement à un seul ordinateur de notre réseau interne, on remplace la ligne :

-4 -A INPUT -p tcp --dport 22 -s 192.168.0.0/24 -j ACCEPT

par la ligne :

-4 -A INPUT -p tcp --dport 22 -s 192.168.0.11 -j ACCEPT

en prenant bien garde d’utiliser les adresses trouvées préalablement avec les commandes ip route show et nmap.

 

Si au contraire on préfère autoriser l’accès SSH depuis n’importe quel réseau, on transforme la règle en :

-4 -A INPUT -p tcp --dport 22 -j ACCEPT

 

Maintenant que nos règles sont prêtes, nous allons les intégrer à iptables avec les deux commandes suivantes :

lambda_user@myweb:~ $ sudo iptables-restore < regles-iptables
lambda_user@myweb:~ $ sudo ip6tables-restore < regles-iptables

 

Nous vérifions que cela fonctionne :

lambda_user@myweb:~ $ sudo iptables -L

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             anywhere            
DROP       all  --  loopback/8           anywhere            
ACCEPT     all  --  anywhere             anywhere             ctstate ESTABLISHED
(...)
ACCEPT     icmp --  anywhere             anywhere             icmp echo-request
DROP       all  --  anywhere             anywhere   
lambda_user@myweb:~ $

 

Nous vérifions tout de suite que nous n’avons pas fait d’erreur de configuration du SSH qui nous interdirait ensuite d’accéder au Raspberry Pi  en nous déconnectant puis reconnectant au SSH :

lambda_user@myweb:~ $ logout
Connection to 192.168.0.15 closed.

linux_user@linux $ ssh lambda_user@192.168.0.15
lambda_user@192.168.0.15's password: 

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Wed Dec  7 22:51:32 2016 from 192.168.0.11

lambda_user@myweb:~ $

 

Si par malheur nous n’arrivons pas à nous reconnecter, il suffit de débrancher le Pi et de le rebrancher. Les modifications que nous avons faites ne survivent pas (encore) à un reboot.

Il est également utile avant d’aller plus loin de nous connecter à Nextcloud depuis un navigateur pour vérifier que nous y avons toujours accès.

 

Enregistrer définitivement iptables

Une fois que nous sommes satisfaits de notre pare-feu, nous allons installer l’utilitaire iptables-persistent qui va enregistrer la configuration d’iptables et la restaurer à chaque reboot.

lambda_user@myweb:~ $ sudo apt install iptables-persistent
(...)
Setting up iptables-persistent (1.0.3+deb8u1) ...
lambda_user@myweb:~ $

La configuration d’iptables est maintenant enregistré dans deux fichiers : /etc/iptables/rules.v4 et /etc/iptables/rules.v6

Désormais pour modifier les règles d’iptables, il faudra modifier ces fichiers.

 

Le serveur Nextcloud est maintenant mieux protégé grâce au pare-feu que nous avons installé.

 

Article modifié le 17/12/2016 suite aux recommandations de Azlux concernant iptables (retrait de l’état RELATED et remplacement de la syntaxe state par conntrack)

One Comment

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *