Comment mettre en place un vpn redondant sur site distant dont les clients doivent avoir une adresse IP VPN fixe ?
Voila un challenge qu'il m'a été demandé de réaliser et le tout évidemment à moindre coût.
Ce genre de demande est assez singulier, mais peut-être utile lorsqu'il faut récupérer des données sur des appareils connectés en 3G ou adsl (IP dynamique).
1) Introduction - Le réseau actuel :
Une petit image valant mieux qu'un grand discours :
Résumé :
Réseau 1 : 192.168.1.0/24
Réseau 2 : 192.168.100.0/24
Réseau de liaison réseau 1 - réseau 2 : 192.168.2.0/24
Serveur de VPN dans le réseau 1 : 192.168.1.50
Serveur de VPN dans le réseau 2 : 192.168.100.50
Clients VPN dans le réseau 10.10.0.0/24
2) Présentation des outils utilisés et de la conception théorique du projet :
Outils :
- Deux serveur debian 7 ( passé en instable / jessie ). Depuis je suis passé sur Ubuntu car celui-ci fournit des versions plus récentes des programmes utilisés ( corosync et pacemaker )
- Openvpn : Je ne vous le présente plus. Il sera utilisé ici pour créer un vpn en mode routé.
- Quagga : Derrière ce nom bizarre se cache l'implémentation sous Linux des protocoles de routing tels que rip,ospf,bgp.
- Pacemaker/corosync : Il s'agit d'une suite qui implémente le clustering et la HA sous Linux.
- Une bonne base en administration Linux et réseau.
Méthodologie :
Comment tout ça va fonctionner ensemble ?
"Facile", Openvpn sera démarré sur un des serveurs.
Quagga s'occupera du routage en OSPF entre les routeurs et les deux serveur VPN.
Et finalement, Pacemaker/Corosync s'occupera de gérer le lancement d'openvpn sur les serveurs et de démarrer le vpn sur le deuxième serveur en cas de problème au niveau du premier serveur (rupture de connexion, plantage du serveur, etc.)
Ça parait simple comme-ça. Passons donc à la pratique.
3) Openvpn
A) Installation et génération des clés
Connectez vous en root sur votre premier serveur :
apt-get install openvpncd
/usr/share/doc/openvpn/examples/easy-rsa/2.0/
Editez le fichier vars pour le personnaliser selon votre organisation et appliquez-le :
nano varssource
./vars
Générer les clés :
./build-ca
./build-dh
./build-key-server srv1
./build-key client1
./build-key client2
Adaptez les nom srv1 et client1 pour refléter votre organisation et générez une clé par client VPN.
Copiez les clés générées dans le dossier d'openvpn :
mkdir /etc/openvpn/keys
cp keys/* /etc/openvpn/keys/
B) Fichier de configuration :
Serveurs :
port 1194
proto udp
dev tun
ca keys/ca.crt
cert keys/srv1.crt
key keys/srv1.key # This file should be kept secret
dh keys/dh1024.pem
server 10.10.0.0 255.255.255.0
topology subnet
push "route 192.168.0.0 255.255.0.0"
client-config-dir ccd
client-to-client
keepalive 10 120
comp-lzo
persist-key
persist-tun
status openvpn-status.log
verb 3
Clients :
client
dev tun
proto udp
remote adresse-externe-srv1 1194
remote adresse-externe-srv2 1194
resolv-retry infinite
nobind
persist-key
persist-tun
ca keys/ca.crt
cert keys/Client1.crt
key keys/Client1.key
comp-lzo
verb 3
keepalive 10 120
Il s'agit d'une configuration assez classique.
Créez le dossier ccd avec un fichier par clients pour leur assigner leur adresse IP :
cd /etc/openvpn/
mkdir ccd
nano ccd/Client1
Le nom du fichier doit être le nom donné au certificat.
Contenu du fichier :
ifconfig-push 10.10.0.11 255.255.255.0
Voila donc notre VPN configuré sur un serveur.
Copiez la configuration à l'identique sur le deuxième serveur ( Faites une archive du dossier /etc/openvpn et transférer la sur le deuxième serveur par scp ).
4) Quagga
1) Installation :
Installez quagga à l'aide d'apt :
apt-get install quagga
Quagga est un paquet qui regroupe plusieurs petits daemons qui permettent d'émuler un routeur.
Ils se configurent avec un syntaxe semblable aux routeurs cisco. Mais chaque daemon se configure séparément !
Ils sont accessible en telnet sur le localhost !
2) Configuration :
La première chose a faire est d'activer les daemons utiles :
nano /etc/quagga/daemons
Mettre yes à zebbra et ospfd
Ici deux solutions s'adressent à vous : configurer en mode console, ou adapter les config ci-dessous et relancer quagga.
Le mode console s'accède en telnet ex : telnet localhost zebra pour zebra et telnet localhost ospfd pour ospf
Config Zebra : zebra.conf
! -*- zebra -*-
!
! zebra sample configuration file
!
! $Id: zebra.conf.sample,v 1.1 2002/12/13 20:15:30 paul Exp $
!
hostname SRV1
password unmotsdepasse
enable password unmotsdepasse
!
! Interface's description.
!
!interface lo
! description test of desc.
!
!interface sit0
! multicast
!
! Static default route sample.
!
!ip route 0.0.0.0/0 203.181.89.241
!
!log file /var/log/quagga/zebra.log
Zebra doit être configuré un minimum car c'est lui qui dirige les autres daemons.
Config Ospfd : ospfd.conf
!
! Zebra configuration saved from vty
! 2013/09/30 15:32:06
!
hostname SRV1
password unmotsdepasse
enable password unmotsdepasse
log stdout
!
!
!
interface eth0
ip ospf authentication message-digest
ip ospf message-digest-key 1 md5 clé-md5-en-clair
!
interface eth1
!
interface lo
!
interface tun0
!
router ospf
redistribute connected
network 10.10.0.0/24 area 0.0.0.0
network 192.168.1.0/24 area 0.0.0.0
area 0.0.0.0 authentication message-digest
neighbor ip-router1
!
line vty
!
Le but de cet article n'étant pas d'expliquer le fonctionnement d'ospf et sa configuration dans les divers équipement réseaux existant, je vous laisse chercher sur le net pour de plus amples informations.
La même configuration doit être faite sur le deuxième serveur en adaptant le commande "network".
Vous devez également configurer les différents routeurs de vos réseaux pour correspondre à cette configuration.
En effet ospf doit être configuré au minimum sur les routeurs entre les deux serveurs.
Redémarrer le service quagga pour être sur que vos changement aient été pris en considération :
/etc/init.d/quagga restart
3) Les test :
Comme premier test, lancez le VPN sur le srv1.
Vous devez voir en quelques secondes une route vers ce serveur pour le réseau 10.10.0.0/24 apparaitre dans les différent routeurs où vous avez configuré l'ospf.
Maintenant coupez openvpn sur ce serveur et démarrez le sur l'autre. La route devrait se mettre à jour et rediriger vers l'autre serveur maintenant.
Si tout est bon, refaites le même test mais avec un client connecté.
Si vous rencontrez des problème de communication au niveau du client malgré qu'il soit bien connecté, vérifiez que vos router ne fasse pas du filtrage de session tcp.
En effet, comme le schéma ci dessous le montre, un paquet tcp partant du réseau interne va passer par la gateway sans retourner par celle-ci au retour. Du coup, si la gateway filtre les session, elle va trouver la situation anormale et couper la session.
Schéma :
5) Pacemaker/Corosync :
1) Introduction :
Pacemaker et Corosync permettent de contrôler et coordonner des ressources sur différents serveurs.
Corosync se charge de la communication entre les serveurs.
Pacemaker se charge de décider sur quel serveur est démarré une ressource configurée.
2) Notes techniques :
J'ai du passer mes serveurs Debian en Jessie suite a des problèmes de désynchronisations inexpliquées entre mes serveurs qui aboutissait à un démarrage d'openvpn sur les deux serveurs en simultanés.
Depuis je n'ai plus de problème, mais c'est à confirmer.
Il faut noter également que la suite Pacemaker/Corosync permet de monter un vrai cluster qui switch en une seconde une ressource d'un serveur à l'autre, de couper une serveur qui cause problème avec un système d'élection, etc.
Dans notre projet, nous allons simplifier cette utilisation à vérifier l'état d'openvpn et l'état de la connexion.
Je pense que ça couvre 99% de cas rencontré lors de l'utilisation d'openvpn.
3) Installation :
Installation des paquets :
apt-get install corosync pacemaker
4) Configuration de corosync :
Corosync a été conçu à la base pour fonctionner en multicast. Hors en site distant dans deux réseaux différents, cette configuration serait impossible sans artifice.
Heureusement pour nous, une version en udp a été implémentée.
Il est aussi important d'assigner en dur dans le fichier hosts les nom des machines sur les deux serveurs car Corosync et Pacemaker utilisent ces noms pour reconnaitre les serveurs (résultat de la commande uname -n) :
Fichier /etc/hosts :
Adresse-Ip-Srv1 Srv1
Adresse-Ip-Srv2 Srv2
La configuration est assez simple : Il faut déclarer les serveurs et le fait que nous allons utiliser Pacemaker.
Fichier /etc/corosync/corosync.conf
compatibility: whitetank
totem {
version: 2
# How long before declaring a token lost (ms)
token: 3000
# How many token retransmits before forming a new configuration
token_retransmits_before_loss_const: 10
# How long to wait for join messages in the membership protocol (ms)
join: 240
# How long to wait for consensus to be achieved before starting a new round of membership configuration (ms)
consensus: 3600
# Turn off the virtual synchrony filter
vsftype: none
# Number of messages that may be sent by one processor on receipt of the token
max_messages: 20
# Limit generated nodeids to 31-bits (positive signed integers)
clear_node_high_bit: yes
# Disable encryption
secauth: off
# How many threads to use for encryption/decryption
threads: 0
# Optionally assign a fixed node id (integer)
nodeid: 1111
# This specifies the mode of redundant ring, which may be none, active, or passive.
rrp_mode: none
interface {
member {
memberaddr: Adresse Ip Serveur 1
}
member {
memberaddr: Adresse Ip Serveur 2
}
# The following values need to be set based on your environment
ringnumber: 0
bindnetaddr: Adresse Ip Serveur 1
mcastport: 5405
}
transport: udpu
}
amf {
mode: disabled
}
service {
# Load the Pacemaker Cluster Resource Manager
ver: 0
name: pacemaker
}
aisexec {
user: root
group: root
}
logging {
fileline: off
to_stderr: yes
to_logfile: yes
logfile: /var/log/corosync/corosync.log
to_syslog: yes
syslog_facility: daemon
debug: off
timestamp: on
logger_subsys {
subsys: AMF
debug: off
tags: enter|leave|trace1|trace2|trace3|trace4|trace6
}
}
Pour le deuxième serveur, il suffit de changer les adresses et le nodeid (en rouge).
Une fois le fichier de configuration prêt, relancer le service sur les deux serveurs :
/etc/init.d/corosync restart
5) Configuration de Pacemaker :
Il faut commencer par démarrer le service car la configuration s'effectue avec l'outil crm.
Pacemaker se charge de répliquer la configuration sur les serveurs.
/etc/init.d/pacemaker start
Il faut commencer par désactiver les options de clustering :
crm configure property stonith-enabled=false
crm configure property no-quorum-policy=ignore
Il faut ensuite configurer les ressources que nous allons utiliser :
Openvpn et un ping vers des serveur distant, ce qui va permettre de tester l'état de la connexion :
Définition de la ressource openvpn :
crm configure primitive openvpn lsb:openvpn op monitor interval="30s"
Définition de la ressource ping :
crm configure primitive p_ping ocf:pacemaker:ping \
params host_list="8.8.8.8 4.2.2.2" multiplier="100" dampen="5s" \
op monitor interval="60" timeout="60" \
op start interval="0" timeout="60" \
op stop interval="0" timeout="60"
crm configure clone c_ping p_ping
Vous pouvez évidement adaptez les cible du ping.
Le multiplier est utilisé pour donner un poids décisionnel à la ressource.
La commande clone permet de répliquer cette ressource sur les serveurs. En effet, le ping doit tourner en simultané sur les deux serveur pour éviter que le ressource migre vers un serveur hors connexion.
Nous allons ensuite obliger Pacemaker a démarrer openvpn sur un serveur ou le ping est bon.
crm configure location OpenVpnCluster openvpn \
rule $id="OpenVpnCluster-rule" -inf: not_defined pingd or pingd lte 0
Si vous voulez fixer openvpn sur un serveur préféré :
crm configure location PrefVpnAir openvpn \
rule $id="PrefVpnAir-rule" 50: #uname eq Srv1
Avec cette commande openvpn sera démarré sur le Srv1 si le ping est bon sur celui-ci. Si le ping tombe, openvpn est démarré sur Srv2. Une fois la situation rentrée dans l'ordre openvpn revient sur Srv1.
Pour éviter les cas de "split brain", il faut mettre en place un système de stonith. Ici j'utilise le système par ssh qui n'est pas recommandé mais suffit pour 99% des cas ou le split brain intervient lors d'une coupure de connexion.
primitive st-ssh stonith:external/ssh \
params hostlist="vpn-air col-air-vpn"
Il faut avoir echangé les clés ssh entre les deux serveurs pour que ça fonctionne.
Voici notre configuration simplifiée terminée. Pour de plus amples information sur Pacemaker et sa configuration, je vous renvoie vers la doc officielle.
6) Vérification :
La commande crm_mon permet de contrôler l'état des ressources et de Pacemaker. ex:
============
Last updated: Tue Nov 26 18:31:39 2013
Last change: Thu Nov 21 09:58:59 2013 via crmd on Srv1
Stack: openais
Current DC: Srv1 - partition with quorum
Version: 1.1.7-ee0730e13d124c3d58f00016c3376a1de5323cff
2 Nodes configured, 2 expected votes
3 Resources configured.
============
Online: [ Srv1 Srv2 ]
Clone Set: c_ping [p_ping]
Started: [ Srv1 Srv2 ]
openvpn (lsb:openvpn): Started Srv1
Redémarrer le Srv1 et regarder celui-ci passer offline et openvpn démarrer sur Srv2.
7) Conclusion
Voici la fin du tutoriel.
En théorie votre VPN redondant devrait être pleinement fonctionnel.
J'espère avoir été assez clair et concis.
Je suis évidemment ouvert à toutes vos remarques, suggestions, questions.