Journal pppoesk : programme pour clore les 'sessions fantômes' PPPoE

Posté par .
Tags : aucun
0
13
nov.
2006
Bonjour,

Il y a quelques mois sur une ligne ADSL non-dégroupée j'ai eu beaucoup de soucis avec ce qui est souvent appelé une "session fantôme", c'est-à-dire qu'après une déconnexion sauvage, plus moyen de se reconnecter avant un délai aléatoire.

La seule solution que j'avais alors était de patienter (plusieurs heures), ou de téléphoner au FAI qui fait une manip et me permet de me reconnecter rapidement.

Après quelques recherches/sniffage le problème semble venir du protocole PPPoE, qui encapsule le traffic PPP entre le concentrateur d'accès du FAI et l'équipement client. La session PPPoE semble être perdue côté client, mais reste active chez le FAI, interdisant l'établissement d'une nouvelle session.

La solution consiste à envoyer un paquet PPPoE PADT (terminate), qui force la fermeture de la session côté FAI.
La commande pppoe permet d'y arriver, au prix de quelques manipulations, comme détaillé sur le blog de Lucas Nussbaum :

http://www.lucas-nussbaum.net/blog/?p=198

Cette solution fonctionne, mais nécessite trop de manipulations, c'est pourquoi j'ai écrit pppoesk (PPPoE session killer), qui forge et envoi ce fameux paquet PADT.

Techniquement j'ai utilisé libpcap pour sniffer les paquets sur l'interface reliée au modem, récupérer ainsi l'identifiant de session et les adresses MAC, ensuite je forge le paquet PADT à l'aide de la bibliothèque libnet.
Il est possible de spécifier une adresse MAC source, comme si par exemple le modem était relié à un routeur et que pppoesk est utilisé autre part.

Pour le moment je n'ai testé que sur Linux x86, dans un proche avenir cela fonctionnera également sur FreeBSD et architectures big-endian.

J'espère que ce programme (license GPL) sera utile pour au moins quelqu'un d'autre que moi ;)

http://www.frozenbox.com/pppoesk
  • # Ouah

    Posté par (page perso) . Évalué à 4.

    Il y a quelques années (genre 3) quand le problème se posait j'avais juste fait un script de quelques lignes avec tcpdump, grep et pppoe -k. Je suis impressionné que tu aies pris le temps de faire un truc propre avec même une page de doc !
      J'en ai retrouvé une version d'ailleurs, je ne sais pas si c'est celle qui marchait, je récupérais l'interface de mon modem avec adictrl donc ce morceau est assez spécifique :
      eval `tcpdump -e -i \`adictrl -i\` -t -c 1 2>/dev/null | grep PPPoE | sed -e 's/^\([^ ]*\) .*\[ses 0x\([^]]*\)\].*$/MAC=\1 ; SESS=$((16#\2))/'`
      MAC=`echo $MAC|tr -d ':'`
      echo "pppoe -e $SESS:$MAC -k"
      • [^] # Re: Ouah

        Posté par . Évalué à 10.

        Pour être honnête, je suis certain d'avoir passé plus de temps à documenter ce programme (commentaires dans le code, page wiki, page de manuel) qu'à écrire du code.

        C'est vrai que c'est limite ennuyeux d'écrire de la doc, mais étant déjà tombé sur quelques projets abandonnés sans doc, je me suis dit que je ne ferai ce coup à personne.

        C'est tellement bête d'écrire quelque chose qui sera peut-être inutile dans l'avenir faute de documentation.
    • # Ouah aussi

      Posté par (page perso) . Évalué à 3.

      Ouah, je suis cité sur LinuxFR sans qu'on me le dise ;)

      Je recommande la lecture du billet sur mon blog, pas parce que c'est mon blog, mais juste parce que ca montre un bon exemple de la nullité absolue de Tele2.

      Liens vers le soft et ce journal ajoutés sur mon blog.
      • [^] # Re: Ouah aussi

        Posté par . Évalué à 1.

        J'allais t'écrire ce soir ;)

        C'est peut-être moi qui cherche mal, mais autant le problème est assez connu sous Windows par son numéro d'erreur, autant il est quasi-confidentiel pour les autres OS !

        C'est grâce à ton blog que j'ai pu constater que je n'avais pas un problème rare et isolé, et que mon bout de code pourait certainement servir à d'autres personnes.
    • # Erf

      Posté par (page perso) . Évalué à 2.

      Alors moi j'ai le probleme inverse, ppp persuadé d'être encore connecté alors que y'a plus rien. Donc il semblerait que le connexion soit morte coté FAI mais pas du coté de mon serveur...

      Actuellement, ma solution qui me permet de ne plus avoir ce probleme est la suivante, forcer la déconnexion adsl tous les jours:

      # crontab -l|grep adsl
      0 6 * * * /usr/local/bin/adsl
      # cat /usr/local/bin/adsl
      #!/bin/ksh

      ps ax|grep ppp| while read pid other
      do
      kill $pid 2>/dev/null
      done
      sleep 60
      ppp -ddial pppoe
      #

      Pour le moment, j'ai eu le probleme une fois en 6 mois.
    • # Problème de compilation

      Posté par . Évalué à 2.

      Peut être que je m'y suis pris comme un pieds : j'ai essayé de compiler sous Ubuntu Dapper histoire de voir, mais il y a une erreur :

      pppoesk.c:24:19: erreur: pppoe.h : Aucun fichier ou répertoire de ce type
      pppoesk.c: Dans la fonction «extract_pppoe_data» :
      pppoesk.c:100: erreur: déréférencement d'un pointeur de type incomplet
      pppoesk.c: Dans la fonction «forge_packet» :
      pppoesk.c:141: attention : assignment makes pointer from integer without a cast
      pppoesk.c:147: attention : passing argument 2 of «libnet_adv_cull_packet» from incompatible pointer type

      Je ne sais pas ou trouver pppoe.h

      libnet1(version 1.1.2.1-2), et libpcap0.8 (version 0.9.4-1) sont installées

      Au final j'aimerais installer pppoesk sur une debian stable (le pc qui me sert de routeur pour une connexion à Tele2 justement).

      Question annexe : comment déclancher ce programme automatiquement lorsque le problème arrive ? Par une annalyse des log ?

      En tout cas, un grand merci pour avoir mis en lumière et résolu ce problème.
      • [^] # Re: Problème de compilation

        Posté par . Évalué à 1.

        Je m'en occupe ce soir, ca vient de moi et je viens encore d'apprendre quelque chose sur les autotools.

        Merci de me l'avoir signalé ;)
      • [^] # Re: Problème de compilation

        Posté par . Évalué à 3.

        Ca y est, modification effectuée. J'avais oublié d'ajouter pppoe.h dans la liste des fichiers sources (tout comme la page de man !), ce qui fait que make dist me générait un tarball sans les précieux pppoe.h et pppoesk.1

        Concernant la 'surveillance', j'utilise un bête script qui ping le premier routeur disponible, si pas de réponse, couic et pon adsl.

        Il doit être possible de faire plus propre en relancant d'abord la connexion ppp, et si ca ne marche pas, lancer pppoesk. Mais dans mon cas c'est toujours un problème de session fantôme, je n'ai donc pas pris la peine de faire ce test supplémentaire.
        • [^] # Re: Problème de compilation

          Posté par . Évalué à 3.

          Merci ça compile, par contre, j'ai patché quelques petites choses :
          - les messages d'erreurs utilise pcap_geterror et libnet_geterror au lieu de errbuf qui n'est pas initialisé.
          - si pcap_next renvoie une erreur, elle est affichée
          - la variable ip est initialisée à 0

          ce qui permet de voir le message d'erreur avec libpcap 0.8 (pas 0.9) lors de l'appel de la fonction pcap_compile :
          pcap_compile() failed: syntax error

          ma version patchée est là :
          http://a.flament.free.fr/data/pppoesk/pppoesk.c

          Après je ne peux pas tester plus : je n'ai pas eu le problème de session fantome, et lorsque je lance le programme alors que la session est encore active, elle n'est pas coupée.
          • [^] # Re: Problème de compilation

            Posté par . Évalué à 2.

            Merci pour tes modifications, je les incorpore dès que possible.

            Concernant le problème, pourrais-tu sniffer l'interface reliée à ton modem, et vérifier que le paquet PADT est bien envoyé avec le bon identifiant de session PPPoE ?

            Tu peux connaitre ton identifiant de session en regardant dans les paquets pppoe.
            • [^] # Re: Problème de compilation

              Posté par . Évalué à 1.

              J'ai refait des tests : la connexion est bien coupée à chaque fois. La fois précédente, je n'ai pas du supprimer le "-p" dans la ligne de commande.

              Pour voir si le paquet part réellement j'ai essayé d'installer tcpdump mais la problème avec ma debian stable :
              - tcpdump demande la version 0.8
              - pppoesk demande la version 0.9 (version actuellement installée)

              j'ai pas voulu forcer dpkg.

              Mais si la connexion est bien coupée à chaque fois que je lance pppoesk, je pense que c'est bon.
              • [^] # Re: Problème de compilation

                Posté par . Évalué à 1.

                Ouf, tu m'a fait peur ;)

                Si la connexion est bien coupée, c'est que ca marche comme voulu.

                Quand au problème de version avec libpcap, la version 0.9 dispose des mots-clés "pppoes" et "pppoed" pour filtrer le traffic adéquat, ce que ne propose pas la version 0.8, d'où le "pcap_setfilter() failed" si compilation avec la version 0.8.

                Il doit y avoir moyen de connaitre le type des paquets en testant certains bits, pour n'importe quelle version de libpcap, je planche dessus.

                Merci pour ton retour d'expérience en tout cas.

    Suivre le flux des commentaires

    Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.