L2TP

De ClissXXI.

Sommaire

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
  1. 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

Liens

Outils personnels