Site icon RMFB – Read My F-Blog

OpenVPN IPv4/IPv6 en NAT (sans NDP)

Un VPN est utile pour de nombreuses utilisations :

IPv6 est sorti en 1998 et moins de 10% du trafic internet est en IPv6, cependant il serrait bien temps de commencer a prendre en compte IPv6 dans ses configurations. Je vais donc vous présenter une configuration d’OpenVPN en IPv4 ET IPv6.

On trouve sur internet de nombreuses configurations pour OpenVPN en IPv4, moi je vais vous proposer une configuration qui permet a la stack IPv4 ET IPv6 de fonctionner avec votre tunnel. Que ça soit dans le tunnel ou en dehors du tunnel.

Cette solution va utiliser du NAT pour IPv4 ET IPv6. En effet, je ne souhaite pas que mon serveur utilise plusieurs adresses IPv6 vers l’extérieur.

Présentation du protocole VPN

Le principe est que le client va encapsuler son paquet IP (si VPN TUN) dans un nouveau paquets IP avec comme data(payload) le paquet IP de base.

Il est donc possible de chiffrer le contenu du paquets VPN ce qui sécurise le trafic entre le client et le serveur.
Cela va évidement pas sécuriser de bout en bout, puisque le serveur VPN va déchiffrer le contenu du paquet, dés-encapsuler la trame initiale, router cette dernière et la transmettre au destinataire final.

Pour faire cela le logiciel VPN va créer une interface dite virtuelle (car elle existe pas physiquement) sur le client et sur le serveur. Une adresse IP va être assignée a l’interface du client par le serveur. L’interface du client et celle du serveur sont sur le même réseau. Tout ce qui rentre dans l’interface client, re-sort par l’interface serveur. Comme si il y avait eu rien entre les deux machines.

Une grosse partie de la configuration d’un VPN est le routage, comme vous pouvez le penser. Effectivement, il faut rediriger le trafic client que vous voulez vers cette nouvelle interface (celle côté client). Et il faut rediriger le trafic sortant du tunnel vers la cible que vous voulez.
La configuration du routage va beaucoup dépendre de votre utilisation de VPN.

Les différents cas d’utilisation de VPN

Le protocole VPN n’est qu’un protocole réseau, c’est à vous de l’utiliser comme vous en avez besoin. Mais je vais vous présenter ici quelques cas d’utilisations très courants.
Je ne vais pas tous les détailler, car certains ne sont utiles que dans des cas très spécifiques.

Cas « connexion à réseau local a distance »

Ce genre de configuration est très utilisée dans des entreprises multi-sites. Une agence à Paris et une agence à Marseille par exemple. Et on voudrais que les machines de Paris puissent communiquer avec les machines de Marseille comme si il étaient dans le même réseau local.
En général ce genre de configuration se fait sur des routeurs ou des concentrateurs VPN (équipement dédié aux communication VPN) car le trafic est très important.

Dans ce cas les deux équipements VPN (celui de Paris et celui de Marseille) seront connecté en P2P (peer to peer). Il n’y auras donc aucun réseau entre ces deux machines (ou bien un réseau en /30).

Aucun routage n’est requis car dès lors que l’équipement à accès a tout les réseaux locaux, ils saurât router les paquets vers ces réseaux locaux.

Je ne vais pas expliquer en détail comment il faut faire ce genre de configuration. Cependant il suffira de supprimer des directives forçant tout le trafic d’internet vers le serveur VPN, et il n’y auras pas besoin de regarder la partie routage de ce post.

Cas « proxy »

Si vous voulez cacher votre identité (adresse IP). Vous voulez rediriger tout le trafic du client vers cette interface VPN et que le serveur, lui, redirige tout le trafic vers le destinataire final.

Il faut donc rajouter une entrée dans la table de routage du client pour tout rediriger vers l’interface VPN. On pourrais penser à changer la route par défaut, sauf que le client en a déjà une. L’écraser est pas une bonne idée car il faudrait la stocker pour pouvoir la remettre après.
La solution est l’utilisation de deux routes, une qui va rediriger la moitié des IP, et une seconde la deuxième partie des IP. Cela à pour effet de rendre ineffectif la route par défaut, car pour rappel en routage CIDR on cherche la route la plus spécifique en premier et dès qu’on en trouve une : on l’utilise.
Comme le protocole VPN n’est pas magique il va bien falloir lui ajouter une route à destination de serveur VPN. En effet notre interface VPN à pour effet d’encapsuler, mais après il envoie bien les trames au serveur VPN. Il doit donc il y avoir une entrée dans la table de routage pour que ce paquet puisse arriver à destination.

Le serveur va récupérer les trames, mais une fois décapsulées il va trouver une adresse IP de type privée (192.168.x.x ou bien 10.x.x.x en IPv4), en effet le protocole VPN en mode non P2P va créer un réseau privé entre le client et le serveur. Le problème c’est que ces IP privées ne peuvent pas être utilisées sur internet. On va donc remplacer les IP sources avec celle du serveur VPN. Le destinataire final va envoyer sa réponse au serveur VPN, on va cette fois-ci faire le fonctionnement inverse, on va changer l’adresse IP destinataire par l’adresse du client (l’adresse de l’interface VPN). Ce fonctionnement se fait via le protocole NAT. Il est utilisé par votre Box par exemple, toutes vos machines locales ont la même adresse IP publique.

Spécificités IPv6 (Proxy NDP et Unique Local Address)

Vu qu’en général votre FAI vous fournis un bloc /64 en IPv6 il est possible de faire du subnetting pour qu’une partie de ce bloc soit utilisé par votre serveur et ses services et un second bloc soit utilisé par les clients VPN.
En clair vos clients quand ils communiqueront sur internet via le VPN ils auront une adresse IP comprise dans le bloc assigné à votre serveur. Et chaque client aurait une adresse IP différente.
Si votre serveur VPN à l’adresse IP 2001:dead:dead:dead::/64 votre client sera visible sur internet par 2001:dead:dead:dead::10:1
Cependant le routeur de votre serveur doit avoir connaissance de ces nouvelles IP pour pouvoir les router.

C’est la qu’entre en jeu le proxy NDP. Vous avez deux choix, soit à chaque nouveau client créer un nouveau proxy pour la nouvelle adresse IPv6. Soit installer ndpd pour proxifier tout le subnet qui va être réserver au VPN.
Pour plus d’informations : Lien

Cette solution est celle la plus courante sur internet, mais je suis pas fan que de l’extérieur on puisse faire une différenciation entre 2 de mes clients (vu qu’ils auront une adresse IP externe différente). En plus cela demande de surcharger le routeur. Et pour en finir avec cette solution, notre client va avoir tout ses services exposés sur internet. Tout les ports de son PC seront directement accessible depuis internet.
L’idée est donc de faire comme IPv4, utiliser du NAT. On va donc utiliser des adresses IPv6 de type Unique Local Address, elles sont comparables aux adresses privées d’IPv4, elles ne sont pas routables.

NAT ne sécurise pas votre réseau, il ne remplace pas un parfeux sur votre client. De plus le processus NAT fonctionne avec des tables de conversions et augmente la latence contrairement à la solution de proxy NDP.

Authentification des clients

Il est possible de limiter l’accès au serveur VPN, plusieurs solutions existent :

Généralement on chiffre les communications entre le client et le serveur. Ce chiffrement est habituellement du TLS, il y a donc déjà des certificats qui sont utilisés pour le chiffrement. Il est donc très simple d’utiliser ces certificats pour authentifier le client. Mais il est possible aussi de demander un couple utilisateur/mot de passe.
L’authentification par mot de passe est moins sécurisé car le « secret » est beaucoup plus court. A un potentiel sens (si vous avez un mot de passe faible). Et pour d’autres raisons plus complexes.

L’authentification par certificats se faire à l’aide de signatures.
Pour cela vous avez besoin d’un CA (Certification Authority). Nous allons signer tout nos certificats client avec ce CA. Et le serveur va vérifier que le certificat du client est bien signé par le CA. Si c’est le cas, le client sera autorisé, sinon la connexion se verra rejetée.
La technique de signature est assez complexe, je ne vais pas rentrer dans les détails, mais utilise la notion de clée privé/publique et est sûre.
Vous pouvez soit générer votre propre CA, à ce moment le client doit connaitre la clée Publique du CA. Si vous payez pour utiliser un CA reconnus. A ce moment votre système d’exploitation à déjà la clée Publique de ce CA.

Quand vous naviguez sur internet en https vous pouvez des fois voir « Votre connexion n’est pas privé ». En réalité cela veut dire que le site sur lequel vous naviguez utilise un certificat TLS qui n’a pas été signé par un CA reconnus (certificat auto signé).

Spécification de la configuration

Je vais donc vous présenter comment utiliser le protocole VPN à l’aide du logiciel OpenVPN.

Malgré tout, je vais vous donner toutes les informations requises pour faire ce que bon vous semble.

Installation d’OpenVPN

C’est donc partis !

apt-get install openvpn

C’était compliqué, avouez-le ! Malheureusement c’est pas comme apache, toute la configuration est à faire par vos soins. Rien n’est pré configuré. On va donc faire tout ça.

Configuration d’OpenVPN

Création des certificats

OpenVPN se base sur des certificats pour le chiffrement, on va donc créer tout les certificats nécessaires. Pour simplifier la génération de ces derniers nous allons utiliser Easy-RSA

apt-get install easy-rsa
cd /etc/openvpn
cp -R /usr/share/easy-rsa/ /etc/openvpn
cd easy-rsa
vim vars

L’édition de ce fichier permet de modifier les valeurs par défaut lors de la génération de certificats, très utile si vous allez générer de nombreux certificats.
Modifiez KEY_COUNTRY, KEY_PROVINCE, KEY_CITY, KEY_ORG, KEY_EMAIL, KEY_OU et KEY_NAME par ce qui vous convient.
Voici ce que j’ai mis :

export KEY_COUNTRY="FR"
export KEY_PROVINCE="Nord-Pas-De-Calais"
export KEY_CITY="Roubaix"
export KEY_ORG="RMFB"
export KEY_EMAIL="openvpn@angenieux.info"
export KEY_OU="VPN"

# X509 Subject Field
export KEY_NAME="OpenVPN"

Il faut ensuite charger ces variables et générer les différents certificats :

. ./vars
# On supprime les clées si il y en avait
./clean-all
./build-ca

Résultats de la dernière commande :

Generating a 2048 bit RSA private key
.....................++++++
...++++++
writing new private key to 'ca.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [FR]:
State or Province Name (full name) [Nord-Pas-De-Calais]:
Locality Name (eg, city) [Roubaix]:
Organization Name (eg, company) [RMFB]:
Organizational Unit Name (eg, section) [VPN]:
Common Name (eg, your name or your server's hostname) []: ca-openvpn
Name [OpenVPN]:
Email Address [openvpn@angenieux.info]:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

Laissez tout par défaut, pour le common name entrez « ca-openvpn ».
Je vous recommande de définir une passphrase pour le CA. Cette passphrase sera demandé à chaque fois que vous aller signer un nouveau certificat.

Si vous oubliez cette passphrase vous pourrez continuer à utiliser OpenVPN mais vous ne pourrez plus créer de nouveaux certificats ni révoquer des certificats.

Un CA va signer les certificats, si on fait confiance à un CA. On fait confiance a tout les certificats signés par ce CA. OpenVPN va donc autoriser l’accès a tout les possesseurs de certificat signé par le CA que nous venons de créer.

./build-key-server server

Vous pouvez tout laisser par défaut.

Je vous conseille de ne pas utiliser de passphrase, ce sera moins sécurisé mais vous pourrez au moins démarrer votre serveur OpenVPN au démarrage de votre serveur physique. Sinon à chaque démarrage votre serveur demandera la passphrase pour pouvoir accéder au la clée privée du certificat du serveur.

Ensuite il nous reste à générer les certificats pour nos différents clients via cette commande :

./build-key client1

Cette commande permet de créer un certificat signé par le CA avec comme common name client1.
Vous pouvez personnaliser le certificat pour qu’il corresponde au mieux à l’utilisateur.
Le nom (client1 ici) est très important car il permet de désigner l’utilisateur. Je vous recommande d’utiliser des nom comme : « remi-pc« .

Il faut ensuite générer les paramètres Diffie-Hellman, cette étape peut être très longue !

./build-dh

Il est possible qu’un jour vous aller supprimer un utilisateur, ou bien supprimer un certificat car il a été compromis (clée privé divulguée publiquement). On va donc créer un fichier contenant les certificats révoqués. Pour cela on va créer un certificat puis le révoquer.

./build-key revoked
./revoke-full revoked

Le “error 23” a la dernière ligne est normal. Cela indique que la vérification du certificat révoqué à échoué, c’est ce que nous voulons.

Cette manipulation a créé un fichier keys/crl.pem que nous allons utiliser plus tard.

Je vous conseille de garder le dossier /etc/openvpn/easy-rsa comme dossier pour créer et révoquer des certificats, vous y accéderez en root. Et copier les certificats utiles à OpenVPN dans le dossier /etc/openvpn. Ces dernier fichiers seront uniquement accessibles a l’utilisateur système :

addgroup --system openvpn
adduser --no-create-home --system --disabled-login --ingroup openvpn --home /etc/openvpn openvpn
chmod 700 /etc/openvpn/easy-rsa
cp /etc/openvpn/easy-rsa/ca.crt /etc/openvpn/ca.crt
cp /etc/openvpn/easy-rsa/server.crt /etc/openvpn/server.crt
mkdir cp /etc/openvpn/private
chmod -R 700 /etc/openvpn/private
cp /etc/openvpn/easy-rsa/server.key /etc/openvpn/private/server.key
cp /etc/openvpn/easy-rsa/dh2048.pem /etc/openvpn/dh2048.pem
cp /etc/openvpn/easy-rsa/crl.pem /etc/openvpn/crl.pem
chown -R openvpn:openvpn /etc/openvpn/private/
chown openvpn:openvpn /etc/openvpn/dh2048.pem /etc/openvpn/crl.pem /etc/openvpn/server.crt /etc/openvpn/ca.crt

Configuration du serveur

Je vous conseille de partir de la configuration d’OpenVPN fournie en exemple.
Pour cela faites :

zcat /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz > /etc/openvpn/server.conf

Pour utiliser la configuration que je vous proposer il faut créer le dossier clientstatic. Il va permettre d’assigner un adresse IP fixe aux clients.

mkdir /etc/openvpn/clientstatic
chown openvpn:openvpn /etc/openvpn/clientstatic

Voici mes modifications au fichier server.conf :

# Si vous voulez vous connecter a votre serveur OpenVPN uniquement en IPv4 mettez
# "proto udp". Si vous voulez que votre serveur soit accessible en IPv4 ET en IPv6 laissez "proto udp6"
# Vous pouvez aussi utiliser le protocole tcp. Il sera moins rapide mais plus fiable si vous avez beaucoup de
# pertes de paquets : "proto tcp6" ou "proto tcp"
proto udp6

# Il est aussi possible de faire du TAP
dev tun
# On ne veut pas une topologie p2p mais bien qu'il y ait un réseau entre notre serveur et
# notre client
topology subnet

# Pour indiquer à TLS que ça va être le côté serveur
tls-server
# Chemin vers notre CA
ca /etc/openvpn/keys/ca.crt
# Chemins vers la clée privée et la clée publique du serveur
cert /etc/openvpn/server.crt
key /etc/openvpn/private/server.key
dh /etc/openvpn/dh2048.pem
# A chaque connexion le serveur va vérifier que le certificat n'est pas révoqué
crl-verify /etc/openvpn/crl.pem
# Réseau IPv4 créer pour les interfaces VPN
server 10.8.0.0 255.255.255.0
# Réseau IPv6 créer pour les interfaces VPN
# Il est possible d'utiliser n'importe quel réseau qui commence par fd.
# Cela corresponds aux réseau ULA. (voir plus haut).
server-ipv6 fd42:feed:feed:feed::/64
# Créé l'interface TUN IPv6 sur le serveur
tun-ipv6
# Pousse la création de l'interface TUN IPv6 sur le client
push tun-ipv6
# Pousse la création de la route en destination de réseau local VPN
push "route-ipv6 2001:41d0:2:bb7:80::/64"
# Pousse la création de la route redirigeant tout le trafic internet vers le VPN
# On utilise pas "default" pour ne pas écraser la passerelle IPv6 par défaut.
# Vu que cette route est plus précise que default, elle sera utilisée pour le
# routage de tout les paquets internet. Pour rappel toutes les IPv6 routables sur
# internet sont 2000::/3
push "route-ipv6 2000::/3"
# Permet d'avoir un adressage statique de nos client
# Chaque client aura une adresse IPv4 et IPv6 fixe.
client-config-dir /etc/openvpn/clientstatic
# Permet de garder les même adresses IP, même après une déconnexion.
# Ici cela est une sécurité, si on a oublié de donner une adresse IP fixe à un client
# ce dernier ne risquera pas d'être en conflits avec un adresse IP déjà utilisé.
ifconfig-pool-persist ipp.txt

# Permet de rediriger tout le trafic internet vers notre serveur VPN
push "redirect-gateway def1 bypass-dhcp"
push "redirect-gateway ipv6" # Pour iOS

# Vu que le DNS de votre FAI n'est pas accesible par votre serveur VPN.
# Il faut que les requêtes VPN se fassent sur des serveur DNS publiques.
# Ici c'est du OpenDNS
push "dhcp-option DNS 208.67.222.222"
push "dhcp-option DNS 208.67.220.220"
# Si vous avez openvpn => 2.4
push "dhcp-option DNS6 2620:0:ccd::2"
# Sinon
;setenv "ipv6dns 2620:0:ccd::2"
# Permet d’exécuter OpenVPN sur un utilisateur disposant de moins de droits.
# Nous avons créer cet utilisateur/groupe juste avant.
user openvpn
group openvpn

Si vous voulez une authentification par mot de passe, il est possible d’utiliser le système d’authentification PAM. Par défaut il va utiliser vos utilisateurs locaux comment couple utilisateur/mot de passe.
Fichier server.conf

# Utilise le module login de PAM
plugin openvpn-auth-pam.so login
# On ne veut plus vérifier l'utilisateur via son certificat
verify-client-cert none
# Permet d'utiliser l'adressage IP fixe malgré tout
username-as-common-name
Plus d'informations disponibles à ce lien (en).

Vous avez toujours besoin d’un certificat client pour chiffrer la communication mais vous avez plus besoin de signer ce certificat par le CA.
Vous pouvez donc enlever la ligne « ca /etc/openvpn/keys/ca.crt ».

Pour chaque client/certificat vous allez devoir créer un fichier dans /etc/openvpn/clientstatic.
Voici un exemple de mon user remi-pc (/etc/openvpn/clientstatic/remi-pc) :

# Ces adresses doivent être dans le range définis par server ou server-ipv6
ifconfig-push 10.8.0.10 255.255.255.0 # IPv4
ifconfig-ipv6-push fd42:feed:feed:feed::10/64 # IPv6

Configurer syslog

Par défaut tout les logs sont envoyés vers syslogs, mais on peut souhaiter de rassembler les logs d’OpenVPN.

mkdir /var/log/openvpn
vim /etc/rsyslog.d/openvpn.conf
if $programname startswith 'ovpn-' then /var/log/openvpn/openvpn.log
service rsyslog restart

Configurer logrotate

Le fichier risque de grossir vite, il faut donc mettre en place un logrotate.
Créez le fichier /etc/logrotate.d/openvpn :

/var/log/openvpn/openvpn.log
{
    # On change de fichier toutes les semaines
    weekly
    # On garde 1 an de log
    rotate 48
    # Permet au processus de ne pas s'arrêter à chaque erreur et de poursuivre avec le fichier de log suivant.
    missingok
    # Empêche la rotation de s'effectuer si le fichier de log est vide.
    notifempty
    # Ne compresse pas les fichiers les plus récents
    delaycompress
    compress
}

Démarrer OpenVPN au boot

La commande va dépendre du nom de votre fichier de configuration. Moi j’ai garder le nom par défaut, soit server.conf. La commande est donc :

systemctl enable openvpn@server.service

Et si vous voulez démarrer le serveur c’est :

systemctl start openvpn@server.service

Configuration du client

Déjà il faudra transférer les fichiers /etc/openvpn/easy-rsa/keys/remi-pc.crt et /etc/openvpn/easy-rsa/keys/remi-pc.key vers le client. Utilisez un protocole de transfert sécurisé tel que SSH, ou FTPS. Il ne faut pas que le fichier remi-pc.key soit divulgué. Il contient votre clée privée, si quelqu’un récupère ce fichier, cette personne pourra se faire passer pour vous.
Vous aurez aussi besoin de copier le fichier /etc/openvpn/easy-rsa/keys/ca.crt

Je vous conseille de partir de la configuration d’OpenVPN fournie en exemple.
Cette configuration se situe a l’emplacement : /usr/share/doc/openvpn/examples/sample-config-files/client.conf

Sur Windows il faudra changer l’extension en .ovpn

Limitez l’accès au fichier remi-pc.key. Si vous êtes sur un PC partagé ne mettez pas ce fichier dans le dossier de configuration général mais dans le dossier de votre utilisateur.
Réduisez les droits de lecture sur ce fichier au strict minimum, c’est à dire « vous ».

Voici mes modifications du fichier client.conf :

client
# Vu qu'on a choisi TUN su le serveur
dev tun
# Vu qu'on a choisi UDP sur le serveur, sinon changez
# Si vous voulez vous connecter en IPv6 a votre serveur changer udp en upd6 ou en tcp6
proto udp
# Changer la valeur par l'adresse IPv4 ou IPv6 de votre serveur
remote 8.8.8.8
persist-key
persist-tun
# Indique à TLS que vous êtes du côté client
tls-client
# Chemin vers le fichier ca.cert que vous venez de télécharger (non requis en cas d'authentification par mot de passe)
ca ca.crt
# Chemin vers le fichier remi-pc.cert que vous venez de télécharger
cert remi-pc.crt
# Chemin vers le fichier remi-pc.key que vous venez de télécharger
key remi-pc.key
# Pour augmenter la sécurité on peut vérifier que le certificat du serveur est bien un certificat de type serveur.
# Permet de réduire les risques de "man in the middle".
remote-cert-tls server
# Pour éviter l'usurpation de votre serveur il est possible de vérifier des informations
# du certificat du serveur.
# Pour vérifier le CN (CommonName) du certificat du serveur utilisez la commande :
;verify-x509-name CNDuServeur name
# Dans notre cas ça sera "server"
# Si vous voulez vérifier tout les champs du certificat vous pouvez utiliser :
; verify-x509-name 'C=FR, ST=Nord-Pas-De-Calais, L=Roubaix, O=RMFB, CN=server, name=OpenVPN, emailAddress=openvpn@angenieux.info'

Routage

On a un serveur OpenVPN fonctionnel qui fournis des adresse locales en IPv6 et IPv4 et pousse aussi des DNS. Mais nos paquets ne sont pas router vers internet. On va donc changer ça !

Activer les fonctions de routage dans le kernel :

sysctl -w net.ipv4.ip_forward=1
sysctl -w net.ipv6.conf.all.forwarding=1

Pour que ces options soient permanentes, pas supprimées après un reboot, modifiez le fichier /etc/sysctl.d/10-routing.conf

net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1

Masquerade/NAT

Nous allons maintenant mettre en place le NAT

iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
ip6tables -t nat -A POSTROUTING -s fd42:feed:feed:feed::/64 -o eth0 -j MASQUERADE

Il faudra modifier les adresses pour que cela corresponde aux adresses de réseau privé que vous avez configuré sur le serveur.
Je pars du principe que votre serveur est connecté à internet via eth0.

Si vous voulez garder ces règles en cas de reboot de votre serveur, je vous redirige vers cet article.

Si vous utilisez des Dirty protocols tel que Bittorent, vous aurez besoin de faire de la translation de port. Je vous redirige vers cet article.

Quitter la version mobile