Blog - Latest News

2012/11/24
24 Nov 2012

Installer un serveur VPN L2TP via IPSec

1. Prérequis

Pour faire une bonne soupe :

  • il faut un ordi sous linux quelque part sur internet mais avec autre chose qu'une connexion Free (évidemment)
  • Il faut que cette machine ait une bonne connexion (1kb/s en upload, c'est moyen)
  • Il faut que cette machine soit en direct sur internet ou si elle est derrière un routeur, il faut avoir accès au routeur pour rediriger des ports (SAT)

Dans mon cas, j'utilise une Centos 6.3 avec le dernier repository EPEL.

2. Installation

2.1. Installation des paquets

Première chose à faire, installer le repo de Nikoforge dans lequel IPSec est patché pour pouvoir autoriser les wildcards dans la config des PSK de racoon (nécessaire pour pouvoir connecter un device iOS mais pas Android) :

rpm -ivH http://repo.nikoforge.org/redhat/el6/nikoforge-release-latest

On installe ensuite IPSec et L2TP :

yum -y install ipsec-tools xl2tpd

2.2. IPSec

On initialise racoon (la partie IKE de IPSec) :

cat > /etc/racoon/init.sh <<EOF
#!/bin/sh
# set security policies
echo -e "flush;\n\
        spdflush;\n\
        spdadd 0.0.0.0/0[0] 0.0.0.0/0[1701] udp -P in  ipsec esp/transport//require;\n\
        spdadd 0.0.0.0/0[1701] 0.0.0.0/0[0] udp -P out ipsec esp/transport//require;\n"\
        | setkey -c
# enable IP forwarding
echo 1 > /proc/sys/net/ipv4/ip_forward
EOF

chmod 750 /etc/racoon/init.sh

sed --in-place '/\/etc\/racoon\/init.sh/d'  /etc/rc.d/rc.local
echo /etc/racoon/init.sh >> /etc/rc.d/rc.local

On configure :

cat > /etc/racoon/racoon.conf <<EOF
path include "/etc/racoon";
path pre_shared_key "/etc/racoon/psk.txt";
path certificate "/etc/racoon/certs";
path script "/etc/racoon/scripts";
remote anonymous
{
        exchange_mode    aggressive,main;
        passive          on;
        proposal_check   obey;
        support_proxy    on;
        nat_traversal    on;
        ike_frag         on;
        dpd_delay        20;
        proposal
        {
                encryption_algorithm  aes;
                hash_algorithm        sha1;
                authentication_method pre_shared_key;
                dh_group              modp1024;
        }
        proposal
        {
                encryption_algorithm  3des;
                hash_algorithm        sha1;
                authentication_method pre_shared_key;
                dh_group              modp1024;
        }
}
sainfo anonymous
{
        encryption_algorithm     aes,3des;
        authentication_algorithm hmac_sha1;
        compression_algorithm    deflate;
        pfs_group                modp1024;
}
EOF

chmod 600 /etc/racoon/racoon.conf

On crée sa PSK, c'est le secret qu'on renseignera tout à l'heure sur l'iPhone (ici thisis_my_psk_the_longer_is_the_better123) :

cat > /etc/racoon/psk.txt <<EOF
* thisis_my_psk_the_longer_is_the_better123
EOF

chmod 600 /etc/racoon/psk.txt

2.3. L2TP

On crée la config de L2TP dans laquelle on règle l'adresse IP du serveur vue depuis les clients (ici 10.27.27.254) ainsi que la plage d'adresse que L2TP va attribuer automatiquement aux clients (ici, de 10.27.27.1 à 10.27.27.253). Pas besoin donc de serveur DHCP ou de Pool IP mappé sur un serveur DHCP comme dans certaines appliances Cisco ou Clavister :

cat > /etc/xl2tpd/xl2tpd.conf <<EOF
[global]
ipsec saref = yes
force userspace = yes
[lns default]
local ip = 10.27.27.254
ip range = 10.27.27.1-10.27.27.253
refuse pap = yes
require authentication = yes
ppp debug = yes
length bit = yes
pppoptfile = /etc/ppp/options.xl2tpd
EOF

Deux choses à prendre en compte :

  • on met évidemment local ip et ip range dans un même réseau
  • on n'utilise pas les mêmes adresses qu'un réseau local déjà joignable depuis le serveur sinon L2TP ne va pas pouvoir router correctement.

On crée maintenant la configuration PPP dans laquelle on va renseigner les DNS. J'ai mis ici des serveurs DNS public (OpenDNS et Google) mais c'est évidemment mieux de mettre les vôtres :

cat > /etc/ppp/options.xl2tp <<EOF
ms-dns 208.67.222.222
ms-dns 8.8.8.8
require-mschap-v2
asyncmap 0
auth
crtscts
lock
hide-password
modem
debug
name l2tpd
proxyarp
lcp-echo-interval 10
lcp-echo-failure 100
EOF

On crée enfin les comptes utilisateurs qu'on utilisera dans la configuration du client tout à l'heure (login potsky et mot de passe thisis_my_passW0RDZZ) :

cat > /etc/ppp/chap-secrets <<EOF
# client       server    secret       IP addresses
potsky      *         thisis_my_passW0RDZZ     *
EOF

chmod 600 /etc/ppp/chap-secrets

2.4. Startup

On démarre tout ça et on dit à notre Centos de démarrer tout ça au boot :

chkconfig racoon on
chkconfig xl2tpd on
service racoon start
service xl2tpd start
/etc/racoon/init.sh

A ce stade, on peut déjà tester depuis son client (paragraphe 4) mais la seule chose qu'on pourra faire une fois le VPN activé, c'est pinger le serveur 10.27.27.254. En effet, quand la Centos reçoit un paquet de 10.27.27.1 à destination d'un serveur sur internet, elle le met à la poubelle parce que ce n'est ni un message destiné à la Centos, ni un message de la Centos. Il va falloir natter le paquet, c'est à dire changer l'adresse d'origine et garder ce changement en mémoire pour que quand la réponse reviendra, on puisse faire l'opération inverse. C'est de l'ip masquerading.

3. Configuration du mode routeur et d'iptables

3.1. SAT

Si le serveur est derrière un routeur, il faut satter les ports suivants vers le serveur VPN :

Port Type Description
500 UDP IPSec IKE
4500 UDP IPSec NAT-T
1701 UDP L2TP Traffic

3.2. Serveur en mode routeur

Par défaut, le noyau linux ne gère pas les paquets "qui passent". Il faut donc mettre le noyau en mode routeur :

echo "net.ipv4.ip_forward = 1" |  tee -a /etc/sysctl.conf
echo "net.ipv4.conf.all.accept_redirects = 0" |  tee -a /etc/sysctl.conf
echo "net.ipv4.conf.all.send_redirects = 0" |  tee -a /etc/sysctl.conf
for vpn in /proc/sys/net/ipv4/conf/*; do echo 0 > $vpn/accept_redirects; echo 0 > $vpn/send_redirects; done
sysctl -p

3.3. IPTables

Si vous n'aviez pas de règles de type *nat auparavant, il suffit de rajouter cela à votre config :

cat >> /etc/sysconfig/iptables <<EOF
*nat
:PREROUTING ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A POSTROUTING -o eth0 -s 10.27.27.0/24 -j MASQUERADE
COMMIT
EOF

La règle dit que tout ce qui passe dans iptables avec comme adresse source 10.27.27.*doit être envoyé vers l'interface eth0 qui est mon WAN. Il faut faire un IP Masquerading pour partager l'IP WAN du serveur.

Dans la partie *filter de iptables, il faut donc autoriser les forwards dans les deux sens (que si la connexion a été initiée par le client pour le retour par contre --state ESTABLISHED,RELATED) :

*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
...
-A FORWARD -i eth0 -d 10.27.27.0/24 -m state --state ESTABLISHED,RELATED -j ACCEPT
-A FORWARD -s 10.27.27.0/24 -o eth0 -j ACCEPT
-A FORWARD -j DROP
...

Et quand vous relançez iptables via un service iptables restart, si vous avez un message d'erreur qui dit que le module n'est pas activé, vous pouvez forcer l'utilisation du module NAT de iptables :

cat >> /etc/sysconfig/iptables-config <<EOF
IPTABLES_MODULES="iptable_nat ip_nat_ftp"
EOF

4. Test sur le device

Sur iOS 6 par exemple, dans Général > VPN > Ajouter une configuration VPN :

Compte et Mot de passe sont renseignés dans le fichier  /etc/ppp/chap-secrets
Secret est la PSK renseignée dans le fichier  /etc/racoon/psk.txt

Ensuite, on met sur On le VPN et le device se connecte en quelques secondes.
On peut alors voir les détails succincts de la connexion :

Enfin, il suffit d'aller sur un site comme www.whatismyip.com pour vérifier que l'IP du device vue depuis internet n'est plus celle du domicile mais celle du serveur.

5. Test sur le serveur

Quand la connexion est établie, sur le serveur, on voit une nouvelle interface ppp0.
Lorsqu'un second client se connecte, une nouvelle interface ppp1 se crée et ainsi de suite.

$ ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UNKNOWN qlen 1000
    link/ether 00:50:56:96:75:e6 brd ff:ff:ff:ff:ff:ff
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UNKNOWN qlen 1000
    link/ether 00:50:56:96:75:e7 brd ff:ff:ff:ff:ff:ff
15: ppp0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 3
    link/ppp

6. Problèmes

Pour l'instant, je n'ai pas résolu le problème suivant : j'active le VPN sur mon iPhone, ça marche. J'active le VPN sur mon iPad, ça marche mais celui de mon iPhone ne fonctionne alors plus. Ce seulement si les 2 devices sont sur le même réseau local. Le serveur VPN ne doit pas être capable de gérer deux connexions entrantes provenant de la même IP mais de 2 ports source différents. En même temps IPSec n'est pas fait à la base pour gérer des clients itinérants...

Tags: , , , , , , , , ,
10 replies
  1. dalouuu says:

    merci, ça marche au poil et j’ai appris pas mal de choses intéressantes
    juste quelques coquilles dans les commandes avec < EOF qui devraient être <> /etc/sysctl.conf
    ?

    Reply
  2. dalouuu says:

    tous tes cat sont mal écrits…
    soit tu as oublié de doubler le signe inférieur (presque tous les cat ont ce pb)
    soit tu as pas collé le EOF double inférieur (presque tous les cat ont ce pb)
    soit tu as mis le signe inférieur au lieu de supérieur (racoon.conf)

    et dans ta config iptables les “: P” de postrouting et prerouting sont convertis en url de smileys

    Reply
  3. dalouuu says:

    double inférieur —-> au double inférieur

    Reply
  4. dalouuu says:

    de rien il ne te reste plus qu’à coller tes EOF aux <<

    Reply
  5. potsky says:

    C’est fait !!! Merci The Lou !

    Reply
  6. dalouuu says:

    et il reste celui là qui a son < dans le mauvais sens
    cat < /etc/racoon/racoon.conf <<EOF

    Reply

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply

Your email address will not be published. Required fields are marked *

*