L2TP
Layer 2 Transport Protocol
Principe
Le PPP (Point to Point Protocol) est pratique pour les opérateur: il permet d'authentifier l'usager (présentation d'un indentifiant/mot de passe en PAP ou CHAP) et d'attribuer en retour une adresse IP, une passerelle et un DNS. PPP transport de l'IP, pas d'ethernet.
La limite c'est que ce protocole est fait pour fonctionner sur une ligne série (RS232). Donc avec un modem RTC (ceux qui font un bruit de fax) qui émule une ligne série longue distance, c'est tout à fait adapté.
Avec un modem ADSL, ça ne marche plus. Comme les opérateurs ne sont pas moins paresseux que les autres informaticiens, ils ont adapté des anciennes méthodes pour qu'elles fonctionnent avec les nouveaux systèmes. Et voila qu'apparaissent:
- le PPTP (Point to Point Transport Protocol)
- le L2TP (PPP over UDP)
- le PPPoE (PPP over Ethernet)
- le DHCP
Dans le cas du DHCP, il n'y a pas d'authentification, cependant, comme un modem cable ou ADSL tranporte la couche ethernet, l'opérateur peut faire une authentification implicite sur l'adresse MAC (la première vue par l'opérateur -> numéricable en mode bridge, ou l'adresse MAC du modem/routeur dans le cas de la plupart des Box).
Du côté opérateur internet, les 2 gagnants de la liste précedentes sont
- PPPoE/PPPoA (modem/routeur ADSL)
- DHCP (numéricable et free -entre autres-)
Le L2TP est traditionnellement utilisé au dessus d'IPSec pour faire des VPN permettant de transporter de l'ethernet (L2TP sait aussi transporter de l'ethernet).
Sous Linux
Comme on aime bien réutiliser ce qui fonctionne déjà, L2TP et PPPoE s'appuie sur le démon PPP existant:
- L2TP = xl2tpd + pppd
- PPPoE = rp-pppoe.so + pppd
Il y a donc 2 points différent à configurer: la partie PPP et la partie L2TP / PPPoE
Application: IP fixe numericable
Numéricable distribue ses IP public par DHCP, ces IPs sont dynamiques. Pour avoir une IP fixe, il faut monter un tunnel L2TP. Le trafic passant par le tunnel L2TP aura toujours la même IP fixe en sortie. Dans ce cas IPSec n'est pas nécessaire.
Donc l'idée c'est:
- obtenir une adresse par DHCP (et une route par defaut qu'on va appeler "A")
- monter le tunnel L2TP
- ajouter une route statique qui dit: pour atteindre le serveur L2TP on passe par "A".
- remplacer la route par defaut, ça n'est plus "A", c'est l'entrée du tunnel L2TP
Ajouter la route statique est primordial, il faut d'abord que le tunnel L2TP existe avant qu'on puisse l'utiliser.
Installation sous Debian
Les paquets dont on a besoin
- ppp
- xl2tpd
- udhcpc (un client dhcp)
Le démon xl2tpd permet d'initier (LAC) ou de recevoir (LNS) des connexion L2TP, dans notre cas on ne va s'intéresser qu'a l'établissement d'une connexion.
Config L2TP de base
- /etc/xl2tpd/l2tp-secrets (peut être vide, on ne s'en sert pas)
- /etc/xl2tpd/xl2tpd.conf: ( les commentaires commencent par ";")
[global] port = 1701 auth file = /etc/xl2tpd/l2tp-secrets
[lac numericable] lns = a.b.c.d require authentication = yes ; Le "name" doit être le même que le "username" dans la configuration PPP name = <identifiant-NC> ppp debug = yes ; pratique pour suivre ce qui se passe dans les logs pppoptfile = /etc/ppp/options.l2tpd.numericable ; la conf PPP se trouve la
- /etc/ppp/options.l2tpd.numericable: (les commentaires commencent par "#")
remotename numericable linkname numericable lock ## On présente un login/pass au serveur L2TP, on n'attend pas que celui-ci ## en présente en retour: noauth persist ## on désactive la compression nodeflate nopcomp noaccomp ## on remplace la route par défault par l'entrée du tunnel ## en faisant cela on se tire dans le pied si la route statique ## n'a pas été établie au préalable !!!! on décommentera ces lignes plus tard # replacedefaultroute # defaultroute maxfail 10 noproxyarp ## for the system name (*ap-secrets) name <identifiant-NC> ## unit N -> pppN, histoire d'avoir un ppp1 au lieu d'un ppp0 unit 1
- /etc/ppp/pap-secrets /etc/ppp/chap-secrets, Ajouter la ligne
"<identifiant-NC>" * "<mot-de-passe-NC>"
Vérifiez que les 2 fichiers ne soit lisible que pour les démons concernés (usuellement rw pour root, rien pour les autres)
premier test
Dans une console lancez:
tail -f /var/log/syslog
Puis dans une autre:
echo "c numericable" > /var/run/xl2tpd/l2tp-control
Le fichier syslog devrait s'animer un peu. Si tout s'est bien passé vous devriez avoir une nouvelle interface ppp1
ifconfig ppp1
ppp1 Link encap:Protocole Point-à-Point inet adr: <IP-fixe> P-t-P: w.x.y.z Masque:255.255.255.255 UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1500 Metric:1 ...
routage
Il existe des schéma de routage plus ou moins complexe et plus ou moins adapté à vos besoins. Celui que je présente est relativement simple: tout le trafic passe par le tunnel L2TP à l'exception du trafic de contrôle qui maintient le tunnel L2TP lui même.
- On récupère la route par défaut (donnée pour le moment par le serveur DHCP)
# ip r default via <IP-passerelle-par-defaut-DHCP> dev eth0 proto static
- On ajoute une route statique qui dit: pour toucher le serveur L2TP on passe par cette IP (IP du champs lns dans le fichier xl2tpd.conf)
# route add -host <a.b.c.d> gateway <IP-passerelle-par-defaut-DHCP>
- Maintenant que c'est fait on supprime la route par défaut pour pouvoir la remplacer par l'entrée du tunnel:
# route delete default # route add route add -net 0.0.0.0 dev ppp1
Vérifiez que vous êtes vu avec l'IP fixe par l'exterieur:
# wget -qO - http://checkip.dyndns.com
<html><head><title>Current IP Check</title></head><body>Current IP Address: IP-fixe-operateur </body></html>
ce wget test en une fois:
- la route par défaut
- le DNS pour résoudre checkip.dyndns.org
- l'IP tel qu'elle est vue de l'extérieur
Automatisation
Tout ça c'est bien, mais
- si la machine redémarre on perd toute la conf
- à chaque renouvellement DHCP, on perd la liaison L2TP...
L'idée est de modifier les scripts du client DHCP (udhcpc pour l'occasion) de manière à ce qu'il mette à jour la route statique évoquée plus haut plutôt que la route par défaut. Et comme on peut avoir besoin d'un client DHCP normal pour une autre interface, on va mettre nos script modifiés de côté.
- /etc/network/interfaces
- on met juste l'interface eth0 "up"
auto eth0 iface eth0 inet manual
auto ppp1 iface ppp1 inet manual pre-up udhcpc -n -p /var/run/udhcpc.eth0_ppp1.pid -i eth0 -s /etc/udhcpc/l2tp-nc/script down /bin/echo 'd numericable' > /var/run/xl2tpd/l2tp-control down kill `cat /var/run/udhcpc.eth0_ppp1.pid`
Les script udhcpc, d'abord on recopie ce qui existe:
cp -ar /etc/udhcpc/default.* /etc/udhcpc/l2tp-nc cp /etc/udhcpc/script /etc/udhcpc/l2tp-nc
Ensuite dans /etc/udhcpc/l2tp-nc on modifie 2 scripts
* default.bound (lorsqu'une nouvelle adresse IP est attribuée) * default.renew (lorsque l'adresse IP est renouvellée sans changement)
N'oubliez pas de décommenter les lignes suivantes dans /etc/ppp/options.l2tpd.numericable
replacedefaultroute defaultroute
Les modifications suivantes sont de simples propositions, vous pouvez les améliorer ou les adapter à votre cas de figure
default.bound
#!/bin/sh # Sample udhcpc bound/renew script # Uncomment this to allow dhcpcd to set hostname of the host to the # hostname option supplied by DHCP server. #SET_HOSTNAME='yes' ## ## ClissXXI modification: add static route to the LNS server (L2TP) ## in order to allow pppd to reset the default gateway to the l2tp ## tunnel (ppp1) ## L2TPCONF_FILE=/etc/xl2tpd/xl2tpd.conf L2TP_LAC="numericable" ## ## End ClissXXI header (see footer below) ## RESOLV_CONF="/etc/resolv.conf" [ -n "$broadcast" ] && BROADCAST="broadcast $broadcast" [ -n "$subnet" ] && NETMASK="netmask $subnet" /sbin/ifconfig $interface $ip $BROADCAST $NETMASK if [ -n "$hostname" -a -n "$SET_HOSTNAME" ] then local current_hostname=$(hostname) if [ -z "$current_hostname" -o "$current_hostname" = "(none)" ]; then hostname "$hostname" fi fi if [ -n "$router" ] then echo "Resetting default routes" for i in `/sbin/route -n | grep ^default.*$interface` do route del default gw 0.0.0.0 dev $interface done for i in $router do /sbin/route add default gw $i dev $interface done fi # Update resolver configuration file R="" [ -n "$domain" ] && R="domain $domain " for i in $dns do echo adding dns $i R="${R}nameserver $i " done if [ -x /sbin/resolvconf ] ; then echo -n "$R" | resolvconf -a "${interface}.udhcpc" else echo -n "$R" > "$RESOLV_CONF" fi ## ## ClissXXI footer ## # the very first time, xl2tpd is not launched. # once launched, the init script is smart enought to not reload it /etc/init.d/xl2tpd start LNS_IP=`sed -n -e '/^[[:blank:]]*\[lac[[:blank:]]*'"$L2TP_LAC"'/,/^[[:blank:]]*lns/ s/^[[:blank:]]*lns[[:blank:]]*=[[:blank:]]*\([[:digit:]\.]*\).*/\1/1p' $L2TPCONF_FILE` # LNS_IP=`grep -Eve '^[[:blank:]]*(#.*|)$' $L2TPCONF_FILE | grep -i lns | head -1 | cut -d= -f 2` [ -n "$LNS_IP" ] || exit # consider only the first router GW_ADDR=`echo $router | awk '{print $1}'` # quietly delete route to LNS if any route delete -host $LNS_IP 2>&1 > /dev/null # add static route to LNS route add -host $LNS_IP gateway $GW_ADDR echo "d numericable" > /var/run/xl2tpd/l2tp-control sleep 3 echo "c numericable" > /var/run/xl2tpd/l2tp-control ## ## ClissXXI end footer ##
default.renew
#!/bin/sh # Sample udhcpc bound/renew script # Uncomment this to allow dhcpcd to set hostname of the host to the # hostname option supplied by DHCP server. #SET_HOSTNAME='yes' ## ## ClissXXI modification: add static route to the LNS server (L2TP) ## in order to allow pppd to reset the default gateway to the l2tp ## tunnel (ppp1) ## L2TPCONF_FILE=/etc/xl2tpd/xl2tpd.conf L2TP_LAC="numericable" ## ## End ClissXXI header (see footer below) ## RESOLV_CONF="/etc/resolv.conf" [ -n "$broadcast" ] && BROADCAST="broadcast $broadcast" [ -n "$subnet" ] && NETMASK="netmask $subnet" /sbin/ifconfig $interface $ip $BROADCAST $NETMASK if [ -n "$hostname" -a -n "$SET_HOSTNAME" ] then local current_hostname=$(hostname) if [ -z "$current_hostname" -o "$current_hostname" = "(none)" ]; then hostname "$hostname" fi fi ## ## ClissXXI disabled renew of the default gateway ## # if [ -n "$router" ] # then # echo "deleting routers" # while /sbin/route del default gw 0.0.0.0 dev $interface # do : # done # # for i in $router # do # /sbin/route add default gw $i dev $interface # done # fi ## but change the route to the lns server if needed LNS_IP=`sed -n -e '/^[[:blank:]]*\[lac[[:blank:]]*'"$L2TP_LAC"'/,/^[[:blank:]]*lns/ s/^[[:blank:]]*lns[[:blank:]]*=[[:blank:]]*\([[:digit:]\.]*\).*/\1/1p' $L2TPCONF_FILE` # LNS_IP=`grep -Eve '^[[:blank:]]*(#.*|)$' $L2TPCONF_FILE | grep -i lns | head -1 | cut -d= -f 2` [ -n "$LNS_IP" ] || exit # consider only the first router GW_ADDR=`echo $router | awk '{print $1}'` # quietly delete route to LNS if any route delete -host $LNS_IP 2>&1 > /dev/null # add static route to LNS route add -host $LNS_IP gateway $GW_ADDR ## ## End ClissXXI ## # # Update resolver configuration file R="" [ -n "$domain" ] && R="domain $domain " for i in $dns do echo adding dns $i R="${R}nameserver $i " done if [ -x /sbin/resolvconf ] ; then echo -n "$R" | resolvconf -a "${interface}.udhcpc" else echo -n "$R" > "$RESOLV_CONF" fi