mardi 21 mai 2013, 22:17:06 (UTC+0200)
NIS, NFSv4, autofs5 & dual stack IPv4 + IPv6
Pour employer une formule marketing à 2€cts, la collection des acronymes donnés dans le titre constitue un «savoureux mélange» entre anachronisme et modernité. Ceci-dit, je me doute bien qu'à la lecture du même titre, d'aucuns auront déjà trouvé que la mixture est on ne peut plus indigeste ! Enfin, n'ayant plus du peur du ridicule, voici une petite introduction sur ce faux-nouveau support : Association NIS, NFSv4 et autofs.
Après avoir adapté les supports de la rubrique développement à IPv6, je me suis posé la question de faire le même travail sur les autres supports de travaux pratiques. Écrire une version IPv6 séparée pour chaque séance de travaux pratiques obligerait à maintenir deux versions pour un même document. Au delà de la quantité de travail, il y a fort à parier qu'une version IPv6 isolée ne serait jamais utilisée vu ce que l'on sait de l'engouement général pour adopter rapidement ce protocole. Il restait donc l'option du document unique double pile ou dual stack dans le jargon. À titre d'entraînement, j'ai repris un vieux support abandonné qui associe trois services.
- Network Information Service (NIS) permet le partage des paramètres de compte utilisateur. C'est un service démodé qui ne fonctionne qu'avec la pile IPv4 ; ce qui le rend intéressant dans le contexte présent.
- Network File System (NFS) est le système de fichiers réseau de prédilection dans le monde Unix. Sa version 4 fonctionne très bien avec la pile IPv6.
- Automounter (autofs) permet l'accès transparent au système de fichiers réseau. On l'utilise lors de la connexion d'un utilisateur pour accéder simplement à son répertoire. Normalement, ce service fonctionne avec IPv6. J'ai découvert avec surprise que son utilisation d'IPv6 est assez singulière puisqu'il semble s'appuyer exclusivement sur les enregistrements DNS.
Même si le but recherché était de «croiser» les usages des deux piles de protocole de couche réseau, le résultat a dépassé mes attentes puisqu'en trois services on dispose de trois modes opératoires distincts.
Pour être complet, il faut ajouter les appels de procédures distants (RPC) sur lesquels sont basés NIS et NFS. C'est justement ce mécanisme qui autorise le mixage entre les deux piles IPv4 et IPv6.
# rpcinfo -s ip6-srvr.fake.domain
program version(s) netid(s) service owner
100000 2,3,4 local,udp,tcp,udp6,tcp6 portmapper superuser
100004 1,2 tcp,udp ypserv superuser
100009 1 udp yppasswdd superuser
100003 4,3,2 udp6,tcp6,udp,tcp nfs superuser
100227 3,2 udp6,tcp6,udp,tcp - superuser
100021 4,3,1 tcp6,udp6,tcp,udp nlockmgr superuser
600100069 1 tcp,udp fypxfrd superuser
100007 1,2 tcp,udp ypbind superuser
100005 3,2,1 tcp6,udp6,tcp,udp mountd superuser
autofs troubleshooting
Comme je l'ai dit plus haut la version du paquet autofs fourni dans la branche testing semble se baser uniquement sur les enregistrements DNS. Voyons comment je suis parvenu à cette conclusion.
- On commence par un montage statique de l'arborescence depuis le poste
client.
# mount -t nfs4 [2a01:240:feb2:10::12]:/home /ahome root@clnt:/home/etu# ls -lAh /ahome/etu-nis/ total 16K -rw------- 1 etu-nis etu-nis 385 mai 21 2013 .bash_history <snip/> # mount | grep nfs4 [2a01:240:feb2:10::12]://home on /ahome type nfs4 \ (rw,relatime,vers=4,rsize=65536,wsize=65536,namlen=255,hard,proto=tcp6, \ timeo=600,retrans=2,sec=sys,clientaddr=2a01:240:feb2:10::11,minorversion=0, \ local_lock=none,addr=2a01:240:feb2:10::12)
Le montage statique utilisant les adresses IPv6 fonctionne. Rien d'original. - On passe à l'utilisation du démon automount avec des fichiers de
configuration complétés directement sur le poste client, toujours avec une
adresse IPv6 numérique.
# cat /etc/auto.master /ahome /etc/auto.home # cat /etc/auto.home * -port=2049,-fstype=nfs4 [2a01:240:feb2:10::12]:/home/& # service autofs start [ ok ] Starting automount.... # automount -m autofs dump map information =========================== global options: none configured Mount point: /ahome source(s): instance type(s): file map: /etc/auto.home * | -port=2049,-fstype=nfs4 [2a01:240:feb2:10::12]:/home/&
La configuration a bien été prise en compte par le démon ...# ls -lAh /ahome/etu-nis ls: impossible d'accéder à /ahome/etu-nis: Aucun fichier ou dossier de ce type # tail -3 /var/log/syslog clnt automount[3652]: attempting to mount entry /ahome/etu-nis clnt automount[3652]: mount(nfs): no hosts available clnt automount[3652]: failed to mount /ahome/etu-nisCatastrophe ! Le montage automatique échoue. - On reprend la même expérience avec un nom d'hôte DNS dont les
enregistrements AAAA et PTR sont valides.
# service autofs start [ ok ] Starting automount.... # automount -m autofs dump map information =========================== global options: none configured Mount point: /ahome source(s): instance type(s): file map: /etc/auto.home * | -port=2049,-fstype=nfs4 vm2.fake.domain:/home/& # dig +short aaaa vm2.fake.domain 2a01:240:feb2:10::12 root@clnt:/home/etu# dig +short -x 2a01:240:feb2:10::12 vm2.fake.domain.
L'adresse IPv6 utilisée est bien identique à celle du test précédent.# ls -lAh /ahome/etu-nis total 16K -rw------- 1 etu-nis etu-nis 385 mai 21 23:44 .bash_history <snip/> # tail -3 /var/log/syslog clnt automount[3759]: mounted indirect on /ahome with timeout 300, freq 75 seconds clnt automount[3759]: attempting to mount entry /ahome/etu-nis clnt automount[3759]: mounted /ahome/etu-nisBingo ! Cette fois-ci le montage se fait correctement. Enfin, si les paramètres de configuration sont publiés via NIS, ça fonctionne aussi.
Voilà. On peut considérer que le choix consistant à associer les trois services est pertinent puisqu'il illustre des usages distincts de la pile IPv6. À mon niveau de connaissances, je ne sais pas si le fait d'imposer l'utilisation des enregsitrements DNS par le démon automount est volontaire.
Dans tous les cours sur IPv6, il est courant de dire que comme le format numérique des adresses IPv6 est très difficile à retenir, l'usage des enregistrements DNS est impératif. Pour généraliser l'utilisation de la double pile réseau, il semble qu'il faille revoir la séquence des travaux pratiques. Je vais devoir aborder le service DNS au tout début de façon à en bénéficier pour le cycle sur le stockage et les systèmes de fichiers réseau. En conclusion, le support de travaux pratiques DNS est le prochain sur la liste !
Posté par Philippe Latu | permalien et commentaires | dans : nfs, travaux_pratiques, système | Read it in english with Google
mardi 5 mars 2013, 21:54:58 (UTC+0100)
Initiation au développement IPv4 + IPv6
La rubrique dev vient d'être enrichie d'un nouveau support sur l'Initiation au développement C sur les sockets IPv4 & IPv6.
Ce qui, au départ, ne devait être qu'un complément au précédent document utilisant seulement IPv4 a finalement abouti à une progression en quatre étapes ou programmes. J'ai conservé l'idée initiale d'échange de chaîne de caractères entre un client et un serveur. Cette forme rudimentaire de chat est très bien accueillie par les étudiants.
La première étape est un plagiat éhonté du programme showip du livre Beej's Guide to Network Programming. La technique de parcours des enregistrements addrinfo issus de l'appel à getaddrinfo() est ensuite reprise dans tous les autres programmes du document. À la deuxième étape, le programme client se contente d'ouvrir la première prise réseau ou socket disponible. Jusque là, tout va bien ! C'est avec le programme serveur que les choses se compliquent. Faut-il utiliser une ou deux prises réseau ?
Franchement, je n'ai pas le recul nécessaire pour prendre parti sur cette question. Ce qui est sûr, c'est que la solution «académique» est plus séduisante pour un prof. Le code de la couche application est indépendant des protocoles de la couche réseau et la quantité de code est plus réduite. Ça n'empêche pas de souffrir un peu sur l'utilisation de l'option bindv6only et sur l'interprétation des codes d'erreurs associés. J'ai fini par aboutir au tableau de tests suivant. Les deux étapes restantes proposent les programmes serveurs avec une puis deux prises réseau.
|
client ou talker |
Serveur ou listener socket unique
|
Serveur ou listener socket double
|
|---|---|---|
|
Client dual stack
|
IPv6 |
IPv6 |
|
Client single stack
|
IPv6 IPv4-mapped IPv6 addresses |
IPv4 |
Une fois la difficulté de gestion des options sur les sockets franchie, la dernière étape avec le codage d'un serveur dual stack à deux prises réseau permet de se familiariser avec l'utilisation de la fonction select() et des macros associées.
Pour conclure, l'utilisation conjointe des deux protocoles IPv4 et IPv6 entraîne un niveau de difficulté plus important dans la manipulation des enregistrements d'adresses IP. Ce pas supplémentaire peut être délicat à franchir pour un public débutant. C'est certainement la raison pour laquelle les enseignants préfèrent s'en remettre à des bibliothèques de plus haut niveau pour aborder les sockets. En Génie Électrique, les développements sont très proches de l'espace noyau et le langage C reste incontournable, ce qui rend le compromis délicat à négocier.
Comme d'habitude, si quelqu'un à le courage de s'attaquer à la lecture du document, je serais très content de lire toutes les remarques ou critiques !
Posté par Philippe Latu | permalien et commentaires | dans : dev, formations | Read it in english with Google
jeudi 7 février 2013, 17:45:15 (UTC+0100)
Architecture système et initiation au développement réseau
Avant les séances de travaux pratiques sur l'initiation au développement sur les sockets avec les étudiants de seconde année de DUT GE2I, j'ai voulu passer à une version dual stack IPv4 et IPv6 des programmes étudiés. L'évolution relativement récente consiste à remplacer les appels à 'gethostbyname' par l'utilisation de 'getaddrinfo' qui renvoie les adresses des deux versions du protocole IP via des pointeurs sur des enregistrements 'addrinfo' chaînés. Tout ceci fonctionne très bien et la façon dont les données sont structurées est très intéressante à étudier ... à mes yeux.
On constate une fois de plus que le niveau requis pour accéder à la compréhension d'une technique ou d'une technologie augmente sans cesse. Pour un débutant complet, il devient de plus en plus difficile de se hisser à un niveau permettant de s'accrocher au train en marche. L'argument qui vient immédiatement consiste à dire que les étudiants actuels sont nés avec l'intégration système et qu'ils utilisent très bien leur smartphone sans se soucier de l'encapsulation des paquets IP dans les réseaux radio numériques. Mon point de vue repose sur le fait que le niveau correspondant à «l'utilisation» des systèmes n'est pas suffisant pour accéder à un emploi et un niveau de revenus décent. Je tente donc à nouveau ma chance en présentant quelques éléments sur l'architecture système. L'idée est de montrer que les systèmes d'exploitation des «dispositifs mobiles» dont les étudiants sont friands ont une longue histoire chaotique mais continue. Suivant cette idée, les «petits programmes pour débuter» viennent bien s'intégrer dans les technologies utilisées au quotidien.
La présentation est disponible aux formats ODP et PDF. Si vous avez envie d'apporter des corrections, n'hésitez pas !
Posté par Philippe Latu | permalien et commentaires | dans : dev, réseau, formations | Read it in english with Google
jeudi 22 novembre 2012, 17:51:40 (UTC+0100)
Aire OSPF et passerelles multiples (2ème)
Suite à l'article Aire OSPF et passerelles multiples et au cycle de travaux pratiques des M1 STRI sur l'interconnexion des réseaux locaux et étendus, voici une variante d'utilisation du marquage de paquets avec des tables de routage multiples. L'idée est toujours d'implanter un mécanisme de tolérance aux pannes entre les passerelles d'une aire OSPF et un routeur de niveau «supérieur».
Ici, les trois routeurs protagonistes ont chacun une interface dans le même domaine de diffusion et on utilise un octet d'adresse MAC pour identifier et distinguer les passerelles.
Pour un nouveau flux sortant de l'aire OSPF, il y a ...
- Marquage du premier paquet en fonction de l'adresse MAC source dans la chaîne PREROUTING de la table mangle.
- Mémorisation du marquage de paquet dans le mécanisme de suivi d'état du système de filtrage (connmark)
- Entrée dans la table de routage dédiée au routeur de bordure à l'origine du flux.
Pour un flux retour dans l'aire OSPF, il y a ...
- Restauration du marquage de paquet en fonction des enregistrements effectués via le mécanisme de suivi d'état
- Entrée dans la table de routage dédiée au routeur de bordure vers lequel le flux doit être dirigé.
La configuration correspondante est alors obtenue avec ...
- Une table de routage par routeur de bordure :
# cat /etc/iproute2/rt_tables # # reserved values # 255 local 254 main 253 default 0 unspec # # local # #1 inr.ruhep 72 centares 79 naboo
# ip route add 10.0.16.0/20 via 172.16.1.1 table centares # ip route add 10.0.32.0/20 via 172.16.1.1 table centares # ip route add default dev bond0 table centares
# ip route add 10.0.16.0/20 via 172.16.4.1 table naboo # ip route add 10.0.32.0/20 via 172.16.4.1 table naboo # ip route add default dev bond0 table naboo
- Des règles de marquages utilisant la table mangle :
# iptables -t mangle -A PREROUTING -i bond0.1 -m mac --mac-source 00:1f:c6:01:26:72 -j MARK --set-mark 72 # iptables -t mangle -A PREROUTING -i bond0.1 -m mac --mac-source 00:1f:c6:01:26:79 -j MARK --set-mark 79 # iptables -t mangle -A PREROUTING -i bond0.1 -j CONNMARK --save-mark # iptables -t mangle -A PREROUTING -i bond0 -j CONNMARK --restore-mark
- Des règles d'entrée dans les tables de routage en fonction des marques :
# ip rule add fwmark 72 table centares # ip rule add fwmark 79 table naboo
Le plan d'adressage est donné dans le support Étude de cas sur l'interconnexion LAN/WAN.
Ici, l'interface bond0 correspond au lien vers l'Internet et l'interface bond0.1 appartient au même réseau local que les deux routeurs de bordure.
Voilà ! Cette configuration n'est qu'un exemple supplémentaire d'utilisation des tables de routage multiples sur les systèmes GNU/linux. Cette technique est trop souvent considérée à tort comme «effrayante». Dès lors que l'on accepte de traiter le problème pas à pas, la «représentation intellectuelle» de la gestion des flux se met plus facilement en place ;).
Une fois de plus, le «copié-collé de la mort» si cher aux étudiants ne rend pas service et ne permet pas de visualiser les mécanismes en jeu.
Posté par Philippe Latu | permalien et commentaires | dans : ospf, rpdb, failover, réseau, formations, travaux_pratiques | Read it in english with Google
dimanche 23 septembre 2012, 17:24:57 (UTC+0200)
Comment résoudre un problème d'accès à la configuration du service LDAP
En révisant le support de travaux pratiques sur l'introduction aux annuaires LDAP avec OpenLDAP, j'ai perdu un certain temps avant de pouvoir traiter la partie sur l'analyse de la configuration du service LDAP. Relativement à l'édition précédente, les versions du paquet source openldap ont évolué et un petit détail sur la résolution des noms m'avait échappé. Bien sûr, me direz-vous, dans la vraie vie tout le monde installe son service LDAP en ayant préalablement validé que le serveur est connu du service DNS. Eh bien, pas moi ! Dans un contexte de travaux pratiques, on cherche à isoler les services les uns des autres de façon à ne traiter qu'un seul problème bien identifié à la fois. Voyons donc comment on peut se fourvoyer facilement et quelle démarche aurait pu être suivie d'entrée de jeu.
Au début, il était question d'authentification ...
Pour valider les questions et les réponses du TP, on configure de façon très classique deux instances de machines virtuelles avec le système de base et le service SSH en Debian/testing : un serveur et un client. On effectue les mises à jour et on renomme les machines. On obtient avec la topologie suivante :
|eth0
_|____
(_______) noyau
|Routeur| <-- système hôte
(_______)
|br0 @IP: 198.51.100.1
___|______
| | <-- openvswitch
`-.------.-'
|tap0 |tap1
| --'.
| |' |hostname : vm-ldap-client
| |. |@IP : 198.51.100.3
--'. `--'
|' |hostname : vm-ldap-server
|. |@IP : 198.51.100.2
`--'
Après installation des deux paquets slapd et ldap-utils sur le serveur, on teste l'accès à la configuration.
Traitement des actions différées (« triggers ») pour « man-db »... Paramétrage de libltdl7:amd64 (2.4.2-1.1) ... Paramétrage de libodbc1:amd64 (2.2.14p2-5) ... Paramétrage de libperl5.14 (5.14.2-13) ... Paramétrage de libslp1 (1.2.1-9) ... Paramétrage de slapd (2.4.31-1) ... Creating new user openldap... done. Creating initial configuration... done. Creating LDAP directory... done. [ ok ] Starting OpenLDAP: slapd. Paramétrage de ldap-utils (2.4.31-1) ... localepurge: Disk space freed in /usr/share/locale: 0 KiB localepurge: Disk space freed in /usr/share/man: 0 KiB Total disk space freed by localepurge: 0 KiB # ldapsearch -Y EXTERNAL -H ldapi:/// -b "cn=config" dn ldap_sasl_interactive_bind_s: Local error (-2)
Eh paf ! C'est à partir de là que les choses ont mal tourné. Je me suis focalisé sur l'authentification SASL et non sur la partie interactive_bind_s du message. Pourtant, cette instruction est bien celle préconisée dans le fichier de documentation du paquet slapd : /usr/share/doc/slapd/README.Debian.gz
Je me suis lancé dans la configuration de l'authentification SASL avec le paquet sasl2-bin et le mécanisme PAM pour authentifier les utilisateurs locaux dont le super-utilisateur qui doit avoir accès sans restriction à la configuration du ou des annuaires LDAP configurés sur le serveur. Bien que cette authentification soit fonctionnelle, j'obtenais toujours le même message d'erreur. La situation était bloquée. Pas moyen de modifier le DIT.
À la fin, il n'était plus question que de résolution des noms
Au lieu de m'enfermer dans cette voie sans issue, j'aurais dû commencer par faire appel à strace.
# strace ldapsearch -Y EXTERNAL -H ldapi:/// -b "cn=config" dn
<snipped>
recvfrom(4, "h4\201\203\0\1\0\0\0\1\0\0\16vm-ldap-server\0\0\34\0\1"..., 2048, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("198.51.100.1")}, [16]) = 107
gettimeofday({1348409171, 770189}, NULL) = 0
poll([{fd=4, events=POLLIN}], 1, 4998) = 1 ([{fd=4, revents=POLLIN}])
ioctl(4, FIONREAD, [107]) = 0
recvfrom(4, "6\361\201\203\0\1\0\0\0\1\0\0\16vm-ldap-server\0\0\1\0\1"..., 1941, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("198.51.100.1")}, [16]) = 107
close(4) = 0
write(2, "ldap_sasl_interactive_bind_s: Lo"..., 47ldap_sasl_interactive_bind_s: Local error (-2)
) = 47
write(3, "0\5\2\1\1B\0", 7) = 7
close(3)
Voici à nouveau le message d'erreur consécutivement à une transaction réseau avec des sockets. Mais que diable vient faire cette requête réseau dans une manipulation locale au système ? On passe donc à l'analyse réseau sur le système hôte ; celui avec l'adresse IP 198.51.100.1.
# tshark -i br0 ! port 22 tshark: Lua: Error during loading: [string "/usr/share/wireshark/init.lua"]:45: dofile has been disabled Running as user "root" and group "root". This could be dangerous. Capturing on br0 0.000000 198.51.100.2 -> 198.51.100.1 DNS 74 Standard query 0x6213 A vm-ldap-server 0.000266 198.51.100.1 -> 198.51.100.2 DNS 149 Standard query response 0x6213 No such name 0.016816 198.51.100.2 -> 198.51.100.1 DNS 74 Standard query 0x2cd4 A vm-ldap-server 0.016885 198.51.100.2 -> 198.51.100.1 DNS 74 Standard query 0x28a4 AAAA vm-ldap-server 0.017050 198.51.100.1 -> 198.51.100.2 DNS 149 Standard query response 0x28a4 No such name 0.017110 198.51.100.1 -> 198.51.100.2 DNS 149 Standard query response 0x2cd4 No such name
Bingo ! la requête locale sur le DIT de l'annuaire à besoin de connaître la correspondance entre nom et adresse IP. On se jette sur l'édition du fichier /etc/hosts dans lequel on donne l'information manquante.
# head -4 /etc/hosts 127.0.0.1 localhost 127.0.1.1 vm-ldap-server 198.51.100.2 vm-ldap-server
Ouf ! Une nouvelle exécution de la commande ldapsearch ne produit plus d'erreur et on peut enfin modifier le DIT de l'annuaire.
# ldapsearch -Y EXTERNAL -H ldapi:/// -b "cn=config" dn SASL/EXTERNAL authentication started SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth SASL SSF: 0 # extended LDIF # # LDAPv3 # base <cn=config> with scope subtree # filter: (objectclass=*) # requesting: dn # <snipped> # search result search: 2 result: 0 Success # numResponses: 12 # numEntries: 11
En guise de conclusion
C'est une nouvelle petite leçon d'humilité. On s'imagine être expérimenté et on se fait attraper comme un débutant sur un détail insignifiant en apparence.
Maintenant, pour rebondir sur le billet intitulé 7 astuces pour rapporter les bogues Debian efficacement et voir vos problèmes résolus, est-ce que le problème que je viens de rencontrer mérite un rapport de bug ? Il m'est déjà arrivé dans le passé d'émettre des rapports qui ont fait flop. Ils étaient soit hors sujet (#616487), soit sans aucun intérêt.
Posté par Philippe Latu | permalien et commentaires | dans : travaux_pratiques, système | Read it in english with Google