On installe OpenVPN et Easy-RSA qui nous permettront de générer les certificats :
sudo apt-get install openvpn easy-rsa -y
On crée un dossier pour le projet et on s'y rend :
mkdir openvpn-server && cd openvpn-server
On crée un dossier avec Easy-RSA qu'on appelle easy-rsa et on s'y rend :
make-cadir easy-rsa && cd easy-rsa
On édite le fichier vars afin de configurer Easy-RSA de manière à accroître la sécurité :
./easyrsa init-pki
On crée une nouvelle autorité de certification (CA) qui est utilisée pour signer et valider les certificats serveur et clients de notre serveur VPN :
./easyrsa build-ca nopass
On génère une demande de signature de certificat (CSR) pour le serveur VPN, identifié par un nom qu'on donne à ce dernier, sans utiliser de mot de passe :
./easyrsa gen-req <NOM DU SERVEUR> nopass
On signe la CSR avec la CA, créant ainsi un certificat de serveur valide :
./easyrsa sign-req server <NOM DU SERVEUR>
On génère des paramètres Diffie-Hellman, utilisés pour sécuriser les échanges de clés entre les clients et le serveur VPN :
./easyrsa gen-dh
On génère une clé partagée secrète pour la fonction de sécurité supplémentaire TLS-Auth d'OpenVPN, qui ajoute une signature aux paquets de données pour vérifier leur source :
openvpn --genkey secret pki/ta.key
On crée une CSR pour un client VPN en déterminant un nom d'identification du client :
./easyrsa gen-req <NOM DU CLIENT> nopass
On signe la CSR avec la CA en tant que client, ceci indique que le certificat est destiné à être utilisé par un client VPN et permet de l'authentifier auprès du serveur VPN permettant ainsi des connexions sécurisées :
./easyrsa sign-req client <NOM DU CLIENT>
On retourne dans le dossier du projet :
cd ../
On crée le fichier de configuration client.opvn :
nano client.ovpn
client
dev tun
proto udp
remote <ADRESSE IP PUBLIQUE> 1194
resolv-retry infinite
nobind
persist-tun
persist-key
cipher AES-256-GCM
auth SHA256
remote-cert-tls server
<tls-auth>
# Certificat contenu dans le fichier ~/openvpn-server/easy-rsa/pki/ta.key
</tls-auth>
key-direction 1
<ca>
# Certificat contenu dans le fichier ~/openvpn-server/easy-rsa/pki/ca.crt
</ca>
<key>
# Certificat contenu dans le fichier ~/openvpn-server/easy-rsa/pki/private/<NOM DU CLIENT>.key
</key>
<cert>
# Certificat contenu dans le fichier ~/openvpn-server/easy-rsa/pki/issued/<NOM DU CLIENT>.crt
</cert>
verb 3
On récupère le fichier de configuration client en se connectant à notre Raspberry par SFTP.
On crée le fichier de configuration du serveur VPN :
nano server.conf
local [ADRESSE IP STATIQUE]
port 1194
proto udp
dev tun
ca /etc/openvpn/pki/ca.crt
cert /etc/openvpn/pki/issued/<NOM DU SERVEUR>.crt
key /etc/openvpn/pki/private/<NOM DU SERVEUR>.key
dh /etc/openvpn/pki/dh.pem
tls-auth /etc/openvpn/pki/ta.key 0
server <ADRESSE IP RÉSEAU POUR LE SERVEUR VPN> <MASQUE DE SOUS-RÉSEAU POUR LE SERVEUR VPN>
push "redirect-gateway def1"
push "route <ADRESSE IP DU RÉSEAU> <MASQUE DE SOUS-RÉSEAU>"
push "dhcp-option DNS <SERVEUR DNS PRIMAIRE DU SERVICE VPN>"
push "dhcp-option DNS <SERVEUR DNS SECONDAIRE DU SERVICE VPN>"
keepalive 10 120
cipher AES-256-GCM
auth SHA256
user nobody
group nogroup
persist-key
persist-tun
verb 3
explicit-exit-notify 1
duplicate-cn
On crée un script shell qui s'exécutera au lancement de notre serveur VPN :
nano up.sh
#!/bin/bash
ip rule add fwmark 1 table 100
ip route add default via <ADRESSE IP STATIQUE DU CONTENEUR OPENVPN-CLIENT> dev eth0 table 100
iptables -t mangle -A PREROUTING -i tun0 -j MARK --set-mark 1
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
iptables -A FORWARD -i tun0 -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i eth0 -o tun0 -j ACCEPT
La première commande crée une règle de routage qui affecte les paquets marqués avec un identifiant spécifique (fwmark 1) à utiliser une table de routage spécifique (table 100). La deuxième commande définit une route par défaut dans cette table de routage, indiquant que tout le trafic qui y est dirigé doit passer par l'interface eth0 et être envoyé à la passerelle 192.168.1.2. La troisième commande utilise iptables pour marquer tous les paquets UDP entrants qui visent le port 1194 (qui est le port d'écoute de notre serveur VPN) avec ce même identifiant (--set-mark 1), les faisant ainsi passer par la table de routage spéciale que nous avons définie. La quatrième commande configure NAT sur l'interface eth0, permettant à plusieurs appareils sur un réseau local d'accéder à l'Internet en partageant une adresse IP publique. Les deux dernières règles d'iptables permettent le trafic entre l'interface VPN (tun0) et l'interface réseau locale (eth0), en autorisant seulement le trafic déjà établi ou en réponse à des connexions initiées de l'intérieur vers l'extérieur (RELATED,ESTABLISHED) et en acceptant tout trafic entrant de eth0 vers tun0.
On crée un script shell qui s'exécutera à l'interruption de notre serveur VPN :
nano down.sh
#!/bin/bash
iptables -D FORWARD -i eth0 -o tun0 -j ACCEPT
iptables -D FORWARD -i tun0 -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
iptables -t mangle -D PREROUTING -i tun0 -j MARK --set-mark 1
ip route del default via <ADRESSE IP STATIQUE DU CONTENEUR OPENVPN-CLIENT> dev eth0 table 100
ip rule del fwmark 1 table 100
On supprime les règles crées lors du lancement de notre VPN.
On crée un script shell qui s'exécutera à l'exécution du conteneur :
On vérifie que notre conteneur soit en cours d'exécution :
docker ps
On affiche les journaux (ou logs) générés par le conteneur, particulièrement utile pour le débogage, permettant de comprendre le comportement du conteneur, de suivre son processus d'exécution ou d'identifier des problèmes et des erreurs potentielles :