Product SiteDocumentation Site

10.2. Réseau privé virtuel

Un réseau privé virtuel (Virtual Private Network, ou VPN) est un moyen de relier par Internet deux réseaux locaux distants via un tunnel (généralement chiffré pour des raisons de confidentialité). Souvent, cette technique sert simplement à intégrer une machine distante au sein du réseau local de l'entreprise.
Il y a plusieurs manières d'obtenir ce résultat. OpenVPN est une solution efficace et facile à déployer et maintenir, s'appuyant sur SSL/TLS. On peut également employer IPsec qui permet de chiffrer les communications IP entre deux hôtes, de manière transparente — c'est-à-dire que les applications fonctionnant sur ces hôtes n'ont pas besoin d'être modifiées pour tenir compte de l'existence du réseau privé virtuel. SSH offre également une fonctionnalité de VPN bien que cela ne soit pas son rôle premier. Enfin, il est possible de recourir au protocole PPTP de Microsoft. Ce livre négligera les autres solutions.

10.2.1. OpenVPN

Logiciel dédié à la création de réseaux privés virtuels, sa mise en œuvre implique la création d'interfaces réseau virtuelles à la fois sur le serveur VPN et sur le (ou les) client(s). Il gère aussi bien les interfaces tun (tunnel de niveau IP) que tap (tunnel de niveau Ethernet). Concrètement, on emploiera des interfaces tun sauf lorsque l'on souhaite intégrer les clients VPN dans le réseau local du serveur par le biais d'un pont Ethernet (bridge).
OpenVPN s'appuie sur OpenSSL pour gérer toute la cryptographie SSL/TLS et assurer les fonctions associées (confidentialité, authentification, intégrité, non-répudiation). Il peut être configuré pour employer une clé secrète partagée ou pour exploiter des certificats X509 d'une infrastructure de clés publiques. Cette dernière configuration sera toujours privilégiée car plus souple pour gérer une population croissante d'utilisateurs nomades disposant d'un accès au VPN.

10.2.1.1. Infrastructure de clés publiques easy-rsa

L'algorithme RSA est très employé en cryptographie à clé publique. Il permet de générer deux clés (une privée et une publique) étroitement liées dont les propriétés mathématiques sont telles qu'un message chiffré avec la clé publique ne peut être déchiffré que par le détenteur de la clé privée (on assure ainsi la confidentialité). Inversement, un message chiffré avec la clé privée peut être déchiffré par tout possesseur de la clé publique. Cela permet d'authentifier la provenance d'un message, on sait alors que ce dernier a été expédié par le propriétaire de la clé privée. Associé à une empreinte (MD5, SHA1 ou une variante plus récente), on obtient un mécanisme de signature d'un message quelconque. Une paire de clés (une privée et la publique correspondante) est appelée « biclé ».
Toutefois, n'importe qui peut créer une biclé et s'attribuer l'identité de son choix. Pour régler ce problème, le concept d'autorité de certification (CA, Certificate Authority) a été créé par le standard X.509. Il s'agit d'une entité disposant d'une biclé de confiance que l'on nomme « certificat racine ». Ce certificat va seulement être employé pour signer d'autres certificats après avoir vérifié l'identité qui y est inscrite. Toute application exploitant des certificats X.509 doit disposer d'un ou plusieurs certificats racines de confiance pour valider l'authenticité des certificats qui lui sont présentés.
OpenVPN ne fait pas exception à la règle. Pour éviter de payer (cher) les services d'une autorité de certification, il est possible de créer sa propre autorité de certification, interne à l'entreprise. Le paquet easy-rsa peut être employé comme infrastructure de gestion de certificats X.509, il s'appuie sur un ensemble de scripts utilisant la commande openssl.
Les administrateurs de Falcot décident de l'employer pour créer les certificats nécessaires, à la fois pour le serveur et pour les clients. La configuration de tous les clients sera ainsi a priori identique puisqu'il suffira de préciser à chacun qu'il ne doit faire confiance qu'aux certificats signés par l'autorité de certification locale, celle de Falcot. Ils commencent par créer cette dernière ; pour cela, ils mettent en place un répertoire contenant les fichiers nécessaires à l'autorité de certification à un emplacement qu'ils contrôlent, et de préférence sur une machine non connectée au réseau afin de limiter les risques de vol de la clé privée de l'autorité de certification.
$ make-cadir pki-falcot
$ cd pki-falcot
Ils placent les paramètres nécessaires dans le fichier vars et notamment ceux débutant par KEY_, puis ils les intègrent dans l'environnement :
$ vim vars
$ grep KEY_ vars
export KEY_CONFIG=`$EASY_RSA/whichopensslcnf $EASY_RSA`
export KEY_DIR="$EASY_RSA/keys"
echo NOTE: If you run ./clean-all, I will be doing a rm -rf on $KEY_DIR
export KEY_SIZE=2048
export KEY_EXPIRE=3650
export KEY_COUNTRY="FR"
export KEY_PROVINCE="Loire"
export KEY_CITY="Saint-Étienne"
export KEY_ORG="Falcot Corp"
export KEY_EMAIL="admin@falcot.com"
export KEY_OU="Certificate authority"
export KEY_NAME="Certificate authority for Falcot Corp"
# If you'd like to sign all keys with the same Common Name, uncomment the KEY_CN export below
# export KEY_CN="CommonName"
$ . ./vars
NOTE: If you run ./clean-all, I will be doing a rm -rf on /home/roland/pki-falcot/keys
$ ./clean-all
Ils créent alors la biclé de l'autorité de certification (les fichiers keys/ca.crt et keys/ca.key sont créés au cours de cette opération) :
$ ./build-ca
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) [Loire]:
Locality Name (eg, city) [Saint-Étienne]:
Organization Name (eg, company) [Falcot Corp]:
Organizational Unit Name (eg, section) [Certificate authority]:
Common Name (eg, your name or your server's hostname) [Falcot Corp CA]:
Name [Certificate authority for Falcot Corp]:
Email Address [admin@falcot.com]:
On peut alors créer un certificat pour le serveur VPN ainsi que les paramètres Diffie-Hellman nécessaires pour le côté serveur d'une connexion SSL/TLS. Le serveur VPN est identifié par son nom DNS vpn.falcot.com ; ce nom est employé dans les fichiers de clés générés (keys/vpn.falcot.com.crt pour le certificat public et keys/vpn.falcot.com.key pour la clé privée) :
$ ./build-key-server vpn.falcot.com
Generating a 2048 bit RSA private key
.....................................................................................................................+++
...........+++
writing new private key to 'vpn.falcot.com.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) [Loire]:
Locality Name (eg, city) [Saint-Étienne]:
Organization Name (eg, company) [Falcot Corp]:
Organizational Unit Name (eg, section) [Certificate authority]:
Common Name (eg, your name or your server's hostname) [vpn.falcot.com]:
Name [Certificate authority for Falcot Corp]:
Email Address [admin@falcot.com]:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
Using configuration from /home/roland/pki-falcot/openssl-1.0.0.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName           :PRINTABLE:'FR'
stateOrProvinceName   :PRINTABLE:'Loire'
localityName          :T61STRING:'Saint-\0xFFFFFFC3\0xFFFFFF89tienne'
organizationName      :PRINTABLE:'Falcot Corp'
organizationalUnitName:PRINTABLE:'Certificate authority'
commonName            :PRINTABLE:'vpn.falcot.com'
name                  :PRINTABLE:'Certificate authority for Falcot Corp'
emailAddress          :IA5STRING:'admin@falcot.com'
Certificate is to be certified until Mar  6 14:54:56 2025 GMT (3650 days)
Sign the certificate? [y/n]:y


1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
$ ./build-dh
Generating DH parameters, 2048 bit long safe prime, generator 2
This is going to take a long time
[…]
Il ne reste plus qu'à créer les certificats pour les clients du VPN, un par ordinateur ou personne autorisée à s'y connecter :
$ ./build-key PierreDurand
Generating a 2048 bit RSA private key
................................+++
..............................................+++
writing new private key to 'PierreDurand.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) [Loire]:
Locality Name (eg, city) [Saint-Étienne]:
Organization Name (eg, company) [Falcot SA]:
Organizational Unit Name (eg, section) [Certificate authority]:Development unit
Common Name (eg, your name or your server's hostname) [PierreDurand]:Pierre Durand
[…]
Maintenant que tous les certificats ont été créés, il reste à les copier là où ils sont nécessaires : la clé publique du certificat racine (keys/ca.crt) se trouvera sur toutes les machines (serveur et clients), en /etc/ssl/certs/Falcot_CA.crt. Le certificat serveur s'installe uniquement sur le serveur (keys/vpn.falcot.com.crt en /etc/ssl/vpn.falcot.com.crt et keys/vpn.falcot.com.key en /etc/ssl/private/vpn.falcot.com.key avec des droits restreints pour que seul l'administrateur puisse le lire) accompagné des paramètres Diffie-Hellman (keys/dh2048.pem) que l'on peut installer en /etc/openvpn/dh2048.pem. Chaque certificat client s'installe de manière similaire sur le client VPN correspondant.

10.2.1.2. Configuration du serveur OpenVPN

Par défaut, le script d'initialisation d'OpenVPN tente de démarrer tous les réseaux privés virtuels définis dans /etc/openvpn/*.conf. Pour mettre en place un serveur VPN, il suffit donc de déposer le fichier de configuration correspondant dans ce répertoire. On peut s'inspirer de /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz, une configuration serveur relativement standard. Il faut évidemment éditer les paramètres ca, cert, key et dh pour indiquer les emplacements retenus (/etc/ssl/certs/Falcot_CA.crt, /etc/ssl/vpn.falcot.com.crt, /etc/ssl/private/vpn.falcot.com.key et /etc/openvpn/dh2048.pem respectivement). La directive server 10.8.0.0 255.255.255.0 indique le sous-réseau employé par le VPN : le serveur dispose de la première IP (10.8.0.1) et les clients se voient attribuer le reste des adresses.
Dans cette configuration, l'interface réseau virtuelle n'est créée que lorsque OpenVPN est démarré et sera généralement nommée tun0. Comme le pare-feu est généralement configuré en même temps que les interfaces réseau réelles, et que cela se déroule avant le démarrage d'OpenVPN, il est souhaitable de créer une interface réseau virtuelle persistente à ce moment-là et de configurer OpenVPN pour faire usage de cette interface pré-existante. Cela permet en outre de choisir le nom donné à l'interface réseau. La commande openvpn --mktun --dev vpn --dev-type tun crée une interface réseau virtuelle nommée vpn et de type tun ; elle peut facilement s'intégrer au début du script de configuration du pare-feu ou dans une directive up de /etc/network/interfaces. Le fichier de configuration d'OpenVPN doit être mis à jour en conséquence avec les directives dev vpn et dev-type tun.
Sans mesures supplémentaires, les clients VPN n'ont accès qu'au serveur VPN, par l'intermédiaire de l'adresse IP 10.8.0.1. Pour donner accès au réseau local (192.168.0.0/24), il faut ajouter une directive push route 192.168.0.0 255.255.255.0 à la configuration d'OpenVPN afin que les clients VPN obtiennent automatiquement une route indiquant que le réseau en question est joignable par l'intermédiaire du VPN. En outre, il faut s'assurer que toutes les machines du réseau local aient une route indiquant que le réseau privé virtuel est accessible par l'intermédiaire du serveur VPN (c'est automatiquement le cas si le serveur VPN est installé sur la passerelle du réseau local). Alternativement, il faut configurer le masquerading sur le serveur afin que les connexions initiées par les clients apparaissent comme provenant du serveur VPN (voir Section 10.1, « Passerelle »).

10.2.1.3. Configuration du client OpenVPN

Pour mettre en place un client OpenVPN, il faut également déposer un fichier de configuration dans /etc/openvpn/. On pourra s'inspirer de /usr/share/doc/openvpn/examples/sample-config-files/client.conf pour une configuration standard. La directive remote vpn.falcot.com 1194 indique l'adresse et le port du serveur OpenVPN. Les directives ca, cert et key doivent aussi être modifiées pour indiquer l'emplacement des différentes clés.
Si l'on ne veut pas que la connexion au VPN soit automatiquement mise en place au démarrage, on peut positionner AUTOSTART à none dans /etc/default/openvpn. On peut toujours démarrer/stopper une connexion VPN spécifique avec service openvpn@nom start et service openvpn@nom stop (la connexion nom correspond à celle définie dans /etc/openvpn/nom.conf).
Le paquet network-manager-openvpn-gnome est une extension de Network Manager (voir Section 8.2.4, « Configuration réseau itinérante ») lui permettant de gérer des réseaux privés virtuels OpenVPN. Chaque utilisateur peut ainsi configurer graphiquement une connexion à un VPN OpenVPN et la contrôler depuis l'icône de gestion du réseau.

10.2.2. Réseau privé virtuel avec SSH

Il existe en réalité deux méthodes pour établir un réseau privé virtuel à l'aide de SSH. La première, historique, consiste à établir une couche PPP au-dessus du lien SSH. Elle est documentée dans un HOWTO :
La seconde méthode est plus récente. OpenSSH permet en effet, depuis sa version 4.3, d'établir des interfaces réseau virtuelles (tun*) de part et d'autre d'une connexion SSH. Ces interfaces réseau peuvent alors être configurées exactement comme s'il s'agissait d'interfaces réseau locales. Il faut autoriser la création de tunnels en positionnant PermitTunnel à « yes » dans la configuration du serveur SSH (/etc/ssh/sshd_config). Lors de l'établissement de la connexion, il faut explicitement demander la création d'un tunnel en passant l'option -w any:any (on peut remplacer any par le numéro de périphérique tun désiré). Des deux côtés, l'utilisateur doit avoir les droits administrateur pour créer le périphérique réseau nécessaire (autrement dit, il faut se connecter en tant que root).
Quelle que soit la méthode choisie, l'établissement d'un réseau privé virtuel sur SSH est très simple à mettre en œuvre. En revanche, ce n'est pas le fonctionnement le plus efficace : il n'est pas adapté aux gros débits sur le réseau privé virtuel.
Concrètement, en encapsulant une pile de protocole TCP/IP dans une connexion TCP/IP (SSH), on emploie deux fois le protocole TCP (une fois pour le SSH proprement dit et une fois à l'intérieur du tunnel). Cela pose quelques problèmes, notamment à cause de la capacité de TCP à s'adapter aux conditions du réseau en variant les délais de timeout (délai maximal d'attente). Le site suivant détaille ces problèmes : On réservera donc l'utilisation de cette méthode aux tunnels établis ponctuellement et qui n'ont pas de fortes contraintes de performance.

10.2.3. IPsec

IPsec, le standard en matière de réseau privé virtuel IP, est nettement plus difficile à mettre en œuvre. Il est intégré au noyau Linux et, pour l'employer sous Debian, il suffit d'installer le paquet ipsec-tools recelant des outils complémentaires et de paramétrage. Sur le plan pratique, le fichier /etc/ipsec-tools.conf de chaque hôte abrite les paramètres de « tunnels IPsec » (ou Security Association dans le vocabulaire IPsec) le concernant et le script /etc/init.d/setkey offre le moyen d'établir (paramètre start) ou de stopper (stop) un tunnel. Chaque tunnel est une liaison sûre avec un autre hôte connecté au réseau privé virtuel. On peut constituer ce fichier manuellement en s'aidant de la page de manuel setkey(8). Mais administrer un parc étoffé ainsi, en paramétrant explicitement, devient difficile car le nombre de tunnels augmente vite. L'installation d'un démon IKE (IPsec Key Exchange, échange de clés IPsec) comme racoon ou strongswan simplifie tout cela en centralisant l'administration et améliore la sécurité en organisant une rotation des clés employées.
Malgré son statut de référence, sa complexité de mise en œuvre restreint considérablement l'usage d'IPsec dans la pratique. On préférera généralement une solution à base d'OpenVPN lorsque les tunnels VPN nécessaires sont peu nombreux et n'évoluent pas régulièrement.

10.2.4. PPTP

PPTP (Point-to-Point Tunneling Protocol, ou protocole de tunnel en point à point) emploie deux canaux de communication, pour échanger respectivement des informations de contrôle et des données (ces dernières emploient le protocole GRE — Generic Routing Encapsulation, ou encapsulation de routage générique). Une connexion PPP standard s'établit sur le canal d'échange de données.

10.2.4.1. Configuration du client

Le paquet pptp-linux est facile à configurer. Les instructions suivantes sont inspirées de sa documentation officielle :
Les administrateurs de Falcot ont créé plusieurs fichiers : /etc/ppp/options.pptp, /etc/ppp/peers/falcot, /etc/ppp/ip-up.d/falcot et /etc/ppp/ip-down.d/falcot.

Exemple 10.2. Fichier /etc/ppp/options.pptp

# Options PPP employées pour une connexion PPTP
lock
noauth
nobsdcomp
nodeflate

Exemple 10.3. Fichier /etc/ppp/peers/falcot

# vpn.falcot.com est le serveur PPTP
pty "pptp vpn.falcot.com --nolaunchpppd"
# la connexion s'identifiera comme utilisateur « vpn »
user vpn
remotename pptp
# la prise en charge du chiffrement est nécessaire
require-mppe-128
file /etc/ppp/options.pptp
ipparam falcot

Exemple 10.4. Fichier /etc/ppp/ip-up.d/falcot

# Créer la route vers le réseau local de Falcot
if [ "$6" = "falcot" ]; then
  # 192.168.0.0/24 est le réseau distant chez Falcot
  route add -net 192.168.0.0 netmask 255.255.255.0 dev $1
fi

Exemple 10.5. Fichier /etc/ppp/ip-down.d/falcot

# Supprimer la route vers le réseau local de Falcot
if [ "$6" = "falcot" ]; then
  # 192.168.0.0/24 est le réseau distant chez Falcot
  route del -net 192.168.0.0 netmask 255.255.255.0 dev $1
fi

10.2.4.2. Configuration du serveur

pptpd est le serveur PPTP pour Linux. Son fichier de configuration principal /etc/pptpd.conf n'a presque pas besoin de modifications ; il faut juste y renseigner localip (adresse IP locale) et remoteip (adresse IP distante). Dans le fichier suivant, le serveur PPTP a toujours l'adresse IP 192.168.0.199 et les clients PPTP reçoivent des adresses IP comprises entre 192.168.0.200 et 192.168.0.250.

Exemple 10.6. Fichier /etc/pptpd.conf

# TAG: speed
#
#       Specifies the speed for the PPP daemon to talk at.
#
speed 115200

# TAG: option
#
#       Specifies the location of the PPP options file.
#       By default PPP looks in '/etc/ppp/options'
#
option /etc/ppp/pptpd-options

# TAG: debug
#
#       Turns on (more) debugging to syslog
#
# debug

# TAG: localip
# TAG: remoteip
#
#       Specifies the local and remote IP address ranges.
#
#       You can specify single IP addresses separated by commas or you can
#       specify ranges, or both. For example:
#
#               192.168.0.234,192.168.0.245-249,192.168.0.254
#
#       IMPORTANT RESTRICTIONS:
#
#       1. No spaces are permitted between commas or within addresses.
#
#       2. If you give more IP addresses than MAX_CONNECTIONS, it will
#          start at the beginning of the list and go until it gets
#          MAX_CONNECTIONS IPs. Others will be ignored.
#
#       3. No shortcuts in ranges! ie. 234-8 does not mean 234 to 238,
#          you must type 234-238 if you mean this.
#
#       4. If you give a single localIP, that's ok - all local IPs will
#          be set to the given one. You MUST still give at least one remote
#          IP for each simultaneous client.
#
#localip 192.168.0.234-238,192.168.0.245
#remoteip 192.168.1.234-238,192.168.1.245
#localip 10.0.1.1
#remoteip 10.0.1.2-100
localip 192.168.0.199
remoteip 192.168.0.200-250
Il faut aussi modifier la configuration PPP employée par le serveur PPTP, consignée dans le fichier /etc/ppp/pptpd-options. Les paramètres importants à changer sont les noms du serveur (pptp) et du domaine (falcot.com) ainsi que les adresses IP des serveurs DNS et Wins.

Exemple 10.7. Fichier /etc/ppp/pptpd-options

## turn pppd syslog debugging on
#debug

## change 'servername' to whatever you specify as your server name in chap-secrets
name pptp
## change the domainname to your local domain
domain falcot.com

## these are reasonable defaults for WinXXXX clients
## for the security related settings
# The Debian pppd package now supports both MSCHAP and MPPE, so enable them
# here. Please note that the kernel support for MPPE must also be present!
auth
require-chap
require-mschap
require-mschap-v2
require-mppe-128

## Fill in your addresses
ms-dns 192.168.0.1
ms-wins 192.168.0.1

## Fill in your netmask
netmask 255.255.255.0

## some defaults
nodefaultroute
proxyarp
lock
La dernière étape est d'enregistrer l'utilisateur vpn et le mot de passe associé dans le fichier /etc/ppp/chap-secrets. Le nom du serveur doit y être renseigné explicitement, l'astérisque (*) habituel ne fonctionnant pas. Par ailleurs, il faut savoir que les clients PPTP sous Windows s'identifient sous la forme DOMAINE\\UTILISATEUR au lieu de se contenter du nom d'utilisateur. C'est pourquoi on trouve aussi dans ce fichier l'utilisateur FALCOT\\vpn. On peut encore y spécifier individuellement les adresses IP des utilisateurs, ou indiquer un astérisque dans ce champ si l'on ne souhaite pas d'adresses fixes.

Exemple 10.8. Fichier /etc/ppp/chap-secrets

# Secrets for authentication using CHAP
# client        server  secret      IP addresses
vpn             pptp    f@Lc3au     *
FALCOT\\vpn     pptp    f@Lc3au     *