Introduction


J'avais pris pour habitude de faire mes tunnels avec SSH -D mais on ne peut pas tunneliser tout le traffic d'un coup. Le tunnel SSH est vu comme un proxy SOCKS et il faut que les logiciels soient compatibles avec ce type de proxy. De plus, SSH n'est pas très pratique pour les clients M$. OpenVPN permet de monter des tunnels à la manières des VPN Concentrator Cisco mais ne nécessitant qu'une simple VM Linux ;-)

Je vais le mettre en œuvre dans deux optiques différentes :
  • Accéder à son réseau local depuis l'extérieur.
  • Accéder à l'extérieur (internet) depuis un réseau inconnu.

Le premier cas de figure est celui qu'on obtient avec la configuration par défaut. Voici un schéma pour fixer les différentes variables utilisées par la suite :
openvpn_cas1.png


Le deuxième cas de figure est traité dans un chapitre spécifique.

Installation d'OpenVPN


Il peut être nécessaire d'activer le dépôt EPEL :
wget http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
yum install epel-release-6-8.noarch.rpm

OU
yum install epel-release

Puis, on installe OpenVPN :
yum install openvpn
chkconfig openvpn on
mkdir -p /etc/openvpn/easy-rsa/keys


Depuis openVPN 2.3.0, les scripts easy-rsa ne sont plus fournis. Il faut aller les chercher sur github :
https://github.com/OpenVPN/easy-rsa

On ajoute ces scripts :
wget https://github.com/OpenVPN/easy-rsa/archive/master.zip
unzip master
mv easy-rsa-master/easy-rsa/2.0/* .
rm master
rm -r easy-rsa-master


On ouvre le parefeu :
vim /etc/sysconfig/iptables
-A INPUT -m state --state NEW -m udp -p udp --dport 1194 -j ACCEPT
service iptables restart


Configuration autorité de certification


L'authentification d'openVPN s'appuie sur des certificats. Pour une configuration par défaut, il suffit de lancer des scripts :
cd /etc/openvpn/easy-rsa
. ./vars
./clean-all
./build-ca

Vous pouvez modifier les valeurs par défaut en éditant le fichier vars. Cela peut être utile si vous comptez générer beaucoup de certifs/clés. Bref, on crée ensuite le certificat pour le serveur VPN :
./build-key-server <mon_vpn>.<mon_domaine>

Ne pas mettre de passphrase, signer le certif et on commit sur l'autorité.

Enfin, on crée un truc appelé protocole Diffie-Hellman qui va servir a crypter les échanges dans notre tunnel (parait il). Bref, on lance la commande suivante :
./build-dh

Création d'un certif pour un client


Avec les outils easy-rsa, il est très simple de créer une clé et un certif pour un utilisateur :
cd /etc/openvpn/easy-rsa/
./build-key <mon_pseudo>


On retrouve ensuite dans le dossier easy-rsa/keys, la paire clé/certif pour notre utilisateur.

Configuration du service openVPN


On copie le modèle de fichier de conf et on l'édite :
cp /usr/share/doc/openvpn-2.3.1/sample/sample-config-files/server.conf /etc/openvpn/
vim /etc/openvpn/server.conf


Il faut modifier les lignes suivantes, choisir un sous réseau pour le tunnel VPN, par exemple 192.168.1.0/24 :
ca /etc/openvpn/easy-rsa/keys/ca.crt
cert /etc/openvpn/easy-rsa/keys/<mon_vpn>.<mon_domaine>.crt
key /etc/openvpn/easy-rsa/keys/<mon_vpn>.<mon_domaine>.key  # This file should be kept secret
dh /etc/openvpn/easy-rsa/keys/dh2048.pem
server <vpn_subnet> 255.255.255.0


Puis on démarre le service :
service openvpn start
ifconfig tun0


Accéder à son réseau local


Avec la première conf, on accède à son serveur VPN mais on a sûrement envi d'accéder au reste de notre LAN. Pour se faire, il faut modifier le fichier de conf server.conf et ajouter cette instruction qui va définir une route sur le client :
push "route <lan_subnet> 255.255.255.0"

Puis on autorise notre serveur VPN a forwarder les paquets (eth1 est la patte sur le sous réseau <lan_subnet>/24) :
vim /etc/sysctl.conf
net.ipv4.ip_forward = 1
/sbin/sysctl -w net.ipv4.ip_forward=1
vim /etc/sysconfig/iptables
-A FORWARD -i eth1 -j ACCEPT
-A FORWARD -o eth1 -j ACCEPT
service iptables restart


Si votre passerelle par défaut et le VPN sont sur le même serveur, il n'y a rien de plus à configurer. Sinon notre client sait qu'il doit router les paquets vers ce LAN en passant par le tunnel mais les serveurs du LAN ne savent pas comment répondre à notre client. Il faut donc ajouter, sur notre passerelle, une route vers le sous réseau <vpn_subnet> ayant pour passerelle la patte privée (eth1) du serveur VPN :
route add -net <vpn_subnet> netmask 255.255.255.0 gw <ip-lan_vpn>

Pour déclarer une route statique sur RedHat :
vim /etc/sysconfig/network-scripts/route-eth1
<vpn_subnet>/24 via <ip-lan_vpn>
service network restart


Configuration d'un client


On commence par installer openvpn, la partie serveur et la partie cliente utilisent le même paquet mais on va dire que le client ici est un debian like :
apt-get install openvpn

Pour un client basé sur Red Hat : yum install epel-release -y, yum install openvpn -y

Ensuite, on crée quelques répertoires :
cd /etc/openvpn
mkdir -p easy-rsa/keys


Il faut récupérer sur le serveur le couple clé/certificat pour notre utilisateur ainsi que la chaîne de certification (la CA). Un pti coup de SCP par exemple et on met le fichier <mon_pseudo>.key, <mon_pseudo>.crt et ca.crt dans le dossier /etc/openvpn/easy-rsa/keys/.

On crée un fichier de config :
cp /usr/share/doc/openvpn-<version>/sample/sample-config-files/client.conf /etc/openvpn/
vim /etc/openvpn/client.conf


On modifie la ligne "remote" en indiquant l'adresse de notre serveur :
remote <ip-public_vpn> 1194

Puis les lignes concernant les credentials :
ca /etc/openvpn/easy-rsa/keys/ca.crt
cert /etc/openvpn/easy-rsa/keys/<mon_pseudo>.crt
key /etc/openvpn/easy-rsa/keys/<mon_pseudo>.key


Ensuite, on démarre le service et on fonce voir les logs :-)
service openvpn start
ifconfig tun0
tail -f /var/log/messages | /var/log/syslog


Scénario 2 : Accéder à l'internet depuis un réseau inconnu


Le premier scénario est le plus classique, je veux accéder chez moi depuis l'extérieur sans ouvrir toutes les fenêtres, portes, chatières. Ici, je vais aborder un deuxième scénario, le cas des accès depuis un réseau qui n'est pas de confiance : ça peut être un hotspot wifi, une prise réseau dans un hôtel ou encore une petite parano envers votre FAI. L'objectif ici est de créer un tunnel sécurisé jusqu'à un point du réseau qui soit de confiance puis accéder à l'internet normalement.

openvpn_cas2.png

Premièrement, on va configurer notre OpenVPN pour utiliser TCP plutôt qu'UDP. Car certains pare-feu ne permettent pas aux paquets UDP de rentrer (c'est à dire les réponses de votre serveur VPN). De plus, TCP est plus stable (et lent certes) quand les réseaux ont de petites perturbations, cela nous intéresse ici car on va se connecter depuis des réseaux totalement hétérogènes. Enfin, on peut masquer son flux VPN en faisant croire qu'il s'agit d'un autre flux sur TCP, par exemple du HTTPS (port 443).

Pour utiliser TCP, premièrement on modifie la conf d'iptables :
vim /etc/sysconfig/iptables
-A INPUT -m state --state NEW -m tcp -p tcp --dport 443 -j ACCEPT
-A FORWARD -i tun0 -J ACCEPT
-A FORWARD -o tun0 -J ACCEPT
service iptables restart
vim /etc/sysctl.conf
net.ipv4.ip_forward = 1
/sbin/sysctl -w net.ipv4.ip_forward=1


Mais il va falloir ajouter de quoi faire du NAT depuis le tunnel vers la patte publique de votre serveur VPN :
iptables -t nat -A POSTROUTING -s <vpn_subnet>/24 -o eth0 -j SNAT --to-source <ip-public_vpn>
service iptables save


Ensuite, il faut modifier la conf du VPN :
vim /etc/openvpn/server.conf
port 443
proto tcp
service openvpn restart



Pour la configuration du client, il faut faire la même chose que vu plus haut mais adapter le protocole et le serveur à contacter :
vim /etc/openvpn/client.conf
proto tcp
remote <ip-public_vpn> 443
service openvpn start
ifconfig tun0
tail -f /var/log/messages | /var/log/syslog


Si vous regardez la configuration du routage de votre poste client, vous constaterez qu'une nouvelle gateway par défaut vient surcharger l'existante. On a besoin de la première pour pouvoir contacter le serveur OpenVPN puis après il faut router tout le trafic vers ce dernier.

Concernant les DNS, on récupère les IP des DNS via le DHCP de son réseau local, sauf qu'une fois le tunnel up, il faut taper sur les mêmes DNS que son OpenVPN. C'est problématique sous Linux, il faut scripter (coté client) la mise à jour de resolv.conf. J'ai "triché" en tapant sur des DNS accessibles à tous, de toute façon, je ne fais aucune requête DNS avant d'établir le tunnel.

OpenVPN et OpenVZ


J'ai installé OpenVPN sur un VPS qui tournait sur un OpenVZ, j'ai rencontré deux petits problèmes :
  • Le module tun/tap n'était pas disponible pour mon VPS, j'ai une erreur "ERROR: Cannot open TUN/TAP dev /dev/net/tun: Operation not permitted (errno=1)". On l'ajoute avec une commande dans le genre vzctl mais comme je n'avais pas la main dessus, on peut aussi l'activer via la panneau de gestion de son VPS.
  • La commande iptables -j MASQUERADE échoue avec l'erreur " iptables: No chain/target/match by that name.". Alors que les versions -j SNAT ou -j DNAT fonctionnent, je ne sais pas du tout pourquoi...

Références


Pour l'installation, je me suis basé sur cette doc principalement : http://mathieu-androz.developpez.com/articles/linux/vpn/

Pour la configuration du scénario 2, j'ai pioché dans la FAQ : http://openvpn.net/index.php/open-source/documentation/howto.html#scope

Le tux "Incognitux" est basé sur le TuxG2 de http://tux.crystalxp.net que je me suis permis de modifier avec Gimp :-)