From deny@monaco.net Tue Mar 3 11:43:20 2009 From: deny To: traduc@traduc.org Subject: Re: [Traduc] =?utf-8?q?probl=C3=A8me?= Date: Tue, 03 Mar 2009 11:43:00 +0100 Message-ID: <49AD09B4.2000507@monaco.net> In-Reply-To: <49AD06C2.9060809@dodin.org> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============7059349505509788350==" --===============7059349505509788350== Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Le 03/03/2009 11:30 AM, en cette journ=C3=A9e d'hiver *jdd* a =C3=A9crit for= t =C3=A0=20 propos : > deny a =C3=A9crit : >> Le 03/03/2009 10:52 AM, en cette journ=C3=A9e d'hiver *jdd* a =C3=A9crit = fort =C3=A0 >> propos : >>> deny a =C3=A9crit : >>> >>>> Le code docbook g=C3=A9n=C3=A9r=C3=A9 par les fichiers wikis est parfait= ement illisible >>>> et je ne saurais accepter =C3=A0 l'avenir de tels fichiers >>> pourquoi ne pas faire le travail sur le wiki? >>> >>> jdd >>> >=20 > un wiki, on peut y =C3=A9crire, non? oui , on va m=C3=AAme dire que c'est un peu fait pour cela >=20 > Apriori, le docbook cr=C3=A9=C3=A9 par MoinMoin passe bien les scripts (ceu= x du > LDP, en tout cas pour l'instant) >=20 Il passe bien les scripts mais il g=C3=A9n=C3=A9re du code degueulasse, qu'il= va=20 me falloir deux heures pour d=C3=A9boguer -rajouter les en-t=C3=AAtes -rajouter les tags docbook omis -faire une mise en page clarifi=C3=A9e voici d'ailleurs le code g=C3=A9n=C3=A9r=C3=A9 pour que chacun (mais il y a p= as=20 vraiment pas grand monde, donc ca devrait =C3=AAtre rapide) puisse se faire=20 une id=C3=A9e du travail =C3=A0 effectuer je vais sur le wiki je trouve la page envoy=C3=A9 par le traducteur je fais afficher en docbook et ensuite je r=C3=A9cup=C3=A8re le fichier g=C3= =A9n=C3=A9r=C3=A9 et attention les yeux,le voici le voila (et j'envoie ci-joint un exemple de fichier "propre", que je dois tirer=20 de ce torchon ) Il n'y a pas un probl=C3=A8me, la ?
Ga= zette=20 Linux/Brouillons/lg149-C VPN=20 Networking192009-0= 3-02=20 18:51:33KamalSawalToure182009-03-02=20 10:53:00KamalSawalToureRel= ecture=20 faite. Traduction finie. Merci pour votre=20 patience172009-= 03-02=20 01:08:45KamalSawalToure162009-03-02=20 01:07:57KamalSawalTourej'a= i=20 fini. Il reste la=20 relecture152009= -02-23=20 15:28:50KamalSawalToure142009-02-23=20 13:35:28KamalSawalToure132009-02-23=20 11:26:29KamalSawalToure122009-02-10=20 18:51:54KamalSawalToure112009-02-10=20 14:57:25KamalSawalToure102009-02-10=20 13:33:23KamalSawalToure92009-02-10=20 12:41:40KamalSawalToure82008-12-07=20 08:27:06KamalSawalToure72008-10-17=20 17:02:24KamalSawalToure62008-10-17=20 17:00:13KamalSawalToure52008-10-17=20 16:28:34KamalSawalToure42008-10-14=20 12:58:08KamalSawalToure32008-10-14=20 11:47:13KamalSawalToure22008-10-01=20 08:50:27KamalSawalToure12008-09-30=20 15:51:29KamalSawalToure
Configuration=20 d'un R=C3=A9seau Priv=C3=A9 Virtuel (VPN)Cr=C3=A9er son propre = R=C3=A9seau=20 Virtuel Priv=C3=A9 (VPN) est assez facile sur des plateformes qui sont=20 livr=C3=A9es avec un pilote tun: cela permet de traiter le flux des paquets=20 r=C3=A9seaux au niveau de l'espace utilisateur. Bien que cela soit=20 consid=C3=A9rablement plus facile que de faire de la programmation r=C3=A9sea= u=20 dans le noyau, il reste cependant quelques d=C3=A9tails =C3=A0 prendre en com= pte.=20 Cet article vous guidera =C3=A0 travers mes trouvailles.=20 IFF_TUN Versus IFF_TAP=20 Le Pilote tun est un p=C3=A9riph=C3=A9rique deux-en-un:=20 Un P=C3=A9riph=C3=A9rique point =C3=A0 p= oint=20 (IFF_TUN). Le p=C3=A9riph=C3=A9rique TUN permet le traitement de paquets IP. = Un p=C3=A9riph=C3=A9rique Ethernet (IFF_TAP= ). Le=20 p=C3=A9riph=C3=A9rique TAP traite les trames Ethernet.=20 Cet article parle du code =C3=A0=20 =C3=A9crire pour le p=C3=A9riph=C3=A9rique Ethernet.Si vous choisissez le p= =C3=A9riph=C3=A9rique=20 IP, alors vous g=C3=A9n=C3=A8rerez 18 octets par paquet trait=C3=A9; le trafi= c est=20 certes moins important (l'en-t=C3=AAte et la queue du paquet Ethernet), mais = vous aurez =C3=A0 coder un peu plus pour mettre en place votre r=C3=A9seau.=20 Activation du pilote=20 Premi=C3=A8rement, on doit s'assurer que le pilote tun est=20 actif.Sur mon syst=C3=A8me Debian, je dois tout simplement le charger:=20 # /sbin/modprobe tun # /sbin/lsmod | grep tun tun=20 10208 0 # /bin/ls -l /dev/net/tun crw-rw-rw- 1=20 root root 10, 200 2008-02-10 11:30 /dev/net/tun La Configuration Pour des besoins=20 de d=C3=A9monstration, on mettra en place un r=C3=A9seau virtuel de deux h=C3= =B4tes.=20 Une fois qu'on a mis la main sur les paquets Ethernet, nous utiliserons=20 l'encapsulation UDP pour les faire transiter d'une interface virtuelle=20 sur l'h=C3=B4te A vers une interface virtuelle sur l'h=C3=B4te B et vice-vers= a. Le=20 socket UDP sera utilis=C3=A9 en mode non-connect=C3=A9; cela a l'avantage de = nous=20 permettre d'utiliser le m=C3=AAme socket pour envoyer et recevoir des paquets= =20 depuis n'importe quel autre h=C3=B4te de notre r=C3=A9seau virtuel. Toutefois= , la=20 nature non-connect=C3=A9e de notre socket UDP, complique la r=C3=A9ception du= =20 chemin MTU (plus de d=C3=A9tails dessus dans les prochaines lignes).=20 Chaque h=C3=B4te de notre r=C3=A9seau virtuel ex=C3=A9cutera une= instance=20 du programme de d=C3=A9monstration. Pour l'illustrer, le trafic d'une=20 application (telnet dans le cas pr=C3=A9sent) sur l'h=C3=B4te A vers l'applic= ation=20 correspondante (inetd/telnetd) vers l'h=C3=B4te B, utilisera le chemin=20 suivant: Le m=C3=A9canisme de=20 d=C3=A9couverte En pratique, nous avons besoin d'un=20 m=C3=A9canisme pour faire correspondre les adresses IP virtuelles aux=20 adresses IP r=C3=A9elles. Il nous appartient de bidouiller une m=C3=A9thode d= e=20 d=C3=A9couverte pour r=C3=A9soudre ce probl=C3=A8me de correspondance; cepend= ant comme=20 cela n'est pas en rapport direct avec notre sujet du jour, ni n=C3=A9cessaire= =20 pour les besoins de notre petite d=C3=A9monstration d=C3=A9crite ici, nous al= lons=20 tricher et laisser le programme de tunnelling =C3=A9tablir les=20 correspondances par des lignes de commande:=20 Host A# ./udptun=20 Usage: ./udptun local-tun-ip remote-physical-ip Host A# ./udptun=20 172.16.0.1 192.168.2.103 Host B# ./udptun 172.16.0.111 192.168.2.113=20 Mise en=20 place de l'interface La premi=C3=A8re chose =C3=A0 fa= ire=20 est de cr=C3=A9er l'interface Ethernet virtuelle (tap). Cela se fait avec un = simple appel =C3=A0 la fonction open(): Ici, l'indicateur IFF_NO_PI requiert qu'on=20 manipule de trames brutes. Si on ne fait pas cela, les trames se verront=20 ajouter un en-t=C3=AAte de 4 octets. Interface setup: the IP address=20 L'interface virtuelle doit =C3=AAtre identifi=C3=A9e par une adr= esse=20 IP. On la d=C3=A9finira avec un appel de la fonction ioctl():=20 ifr_addr, &addr, sizeof(struct sockaddr)); if (ioctl(sock, SIOCSIFADDR, ifr_tun) < 0) { /*Erreur de traitement, retour*/ } /*Sera Utilis=C3=A9 plus tard pour d=C3=A9finir le MTU.*/ return sock; }]]>Le PMTU (Path Maximum=20 Transmission Unit) La seul =C3=A9l=C3=A9ment que nous= =20 avons =C3=A0 configurer est le MTU (Maximum Transmit Unit) de l'interface.=20 Pour notre interface pseudo-Ethernet, le MTU est la charge la plus=20 importante que les trames Ethernet peuvent transporter. On d=C3=A9finira le=20 PMTU en fonction du MTU. Pour faire simple, on dira que le=20 PMTU est le paquet le plus large qui peut traverser le chemin allant=20 d'un h=C3=B4te =C3=A0 sa destination sans subir de fragmentation. Le=20 PMTU est un param=C3=A8tre important =C3=A0 prendre en compte pour que tout s= e=20 passe bien. Consid=C3=A9rez ceci: en (r=C3=A9)injectant vos trames dans le no= yau,=20 elles se verront attribuer des en-t=C3=AAtes (IP, UDP et Ethernet)=20 suppl=C3=A9mentaires. Si la taille de la trame que vous avez envoy=C3=A9e au = noyau=20 est trop proche du PMTU, la trame finale qui sera envoy=C3=A9e =C3=A0 partir = de=20 l'interface r=C3=A9elle pourrait =C3=AAtre plus grande que le PMTU. Au pire d= es=20 cas, une telle trame sera perdue quelque part en route. Au meilleur des=20 cas, la trame sera fragment=C3=A9e en deux et la premi=C3=A8re partie sera tr= ait=C3=A9e=20 =C3=A0 100%, ce qui ne sera pas le cas pour la seconde partie.=20 Pour =C3=A9viter cela, on doit d=C3=A9couvrir la valeur du PMTU = et=20 s'assurer que la nouvelle trame Ethernet sera correctement dimensionn=C3=A9e = pour le PMTU. Ensuite, on soustraira du PMTU la taille des nouvelles=20 en-t=C3=AAtes et on donnera cette valeur au MTU de l'interface virtuelle.=20 La t=C3=A2che est facile sous Linux, pour un socket TCP: on doit= =20 juste s'assurer que les m=C3=A9canismes de d=C3=A9couverte du PMTU par le noy= au=20 sont configur=C3=A9s, et c'est tout. Par contre pour les sockets= =20 UDP, nous les utilisateurs, avons la responsabilit=C3=A9 de nous assurer que = les datagrammes UDP sont de taille correcte. Si le socket UDP est=20 connect=C3=A9 =C3=A0 l'h=C3=B4te correspondant, un simple appel appel de la f= onction=20 getsockopt()avec l'indicateur IP_MTU positionn=C3=A9, nous donnera le PMTU=20 En ce qui concerne les sockets non-connect=C3=A9s, on doit=20 analyser le PMTU. Premi=C3=A8rement, le socket doit =C3=AAtre configur=C3=A9 = de fa=C3=A7on =C3=A0=20 ce que les datagrammes ne soient pas fragment=C3=A9s (positionner=20 l'indicateur DF); ensuite, on doit configurer de fa=C3=A7on =C3=A0 =C3=AAtre = averti des=20 erreurs ICMP que cela pourrait g=C3=A9n=C3=A9rer. Si un h=C3=B4te ne peut pas= g=C3=A9rer la=20 taille du datagramme sans le fragmenter, alors il devra nous en informer=20 (enfin, on l'esp=C3=A8re): Ensuite, on envoie des datagrammes analys=C3=A9s de = diverses tailles: Pour=20 finir, on farfouille parmi les erreurs jusqu'=C3=A0 trouver le bon PMTU. Si=20 on a une erreur de PMTU, on ajuste la taille du datagramme et on=20 recommence =C3=A0 envoyer les datagrammes jusqu'=C3=A0 ce que la destination = soit=20 atteinte: 0) { /* R=C3=A9ponse re=C3=A7ue. Fin de la d=C3=A9couverte du PMTU. Retou= r.*/ } msg.msg_name =3D (unsigned char*)&addr; msg.msg_namelen =3D sizeof(addr); msg.msg_iov =3D &iov; msg.msg_iovlen =3D 1; msg.msg_flags =3D 0; msg.msg_control =3D cbuf; msg.msg_controllen =3D sizeof(cbuf); res =3D recvmsg(sock, &msg, MSG_ERRQUEUE); if (res < 0) { if (errno !=3D EAGAIN) perror("recvmsg"); /*Nothing for now, return.*/ } for (cmsg =3D CMSG_FIRSTHDR(&msg); cmsg; cmsg =3D CMSG_NXTHDR(&msg,=20 cmsg)) { if (cmsg->cmsg_level =3D=3D SOL_IP) { if (cmsg->cmsg_type =3D=3D IP_RECVERR) { err =3D (struct sock_extended_err *) CMSG_DATA(cmsg); } } } if (err =3D=3D NULL) { /*D=C3=A9couvrte du PMTU: pas d'info jusque l=C3=A0. Retour, mais=20 continue =C3=A0 analyser.*/ } mtu =3D 0; switch (err->ee_errno) { ... case EMSGSIZE: debug(" EMSGSIZE pmtu %d\n", err->ee_info); mtu =3D err->ee_info; break; ... } /*end switch*/ return mtu; /*Mais continue =C3=A0 analyser jusqu'=C3=A0 ce que l'h=C3= =B4te=20 distant soit atteint!*/]]>Une derni=C3=A8re chose: le PMTU est= =20 tenu de changer dans le temps. On devra donc le tester de temps en temps=20 et ensuite configurer le MTU de l'interface virtuelle en fonction des=20 r=C3=A9sultats du test. Si on veut =C3=A9viter toute cette gymnastique, on pe= ut=20 configurer le MTU de fa=C3=A7on s=C3=A9curis=C3=A9e mais moins optimale : cho= isir la=20 valeur la plus petit entre 576 et le MTU de l'interface physique (moins=20 l'en-t=C3=AAte que nous avons mentionn=C3=A9, bien entendu.)=20 Configuration de l'interface: le=20 MTU Apr=C3=A8s avoir finalement obtenu cette valeur=20 magique qu'est le PMTU, nous pouvons correctement configurer le MTU de=20 notre interface: ifr_mtu =3D mtu; if (ioctl(sock, SIOCSIFMTU, ifr_tun) < 0) { /*Erreur de Traitement*/ }]]>Encapsulation=20 UDP Nous avons maintenant une interface=20 virtuelle bien configur=C3=A9e et qui fonctionne. Tout ce que nous avons =C3= =A0=20 faire est de relayer les trames dans les deux directions. Premi=C3=A8rement, = il faut ouvrir un socket UDP non-connect=C3=A9 (Je vous =C3=A9pargne les d=C3= =A9tails),=20 et ensuite: Lire=20 les paquets du fichier descriptif du tap et les envoyer =C3=A0 l'adresse IP=20 physique distante de notre h=C3=B4te correspondant; ceci enverra les paquets = dans une seule direction.=20 0) sendto(_udp_fd, buf, recvlen, 0, (struct=20 sockaddr*)&cliaddr, clilen); ]]>Avertissement:=20 La lecture du fichier descriptif du tap va provoquer un blocage. Cela=20 veut dire que la fonction read() ne va pas =C3=AAtre interrompue m=C3=AAme si= on=20 ferme le descripteur sous-jacent du fichier. On est donc oblig=C3=A9=20 d'utiliser les fonctions poll()/select() sur ce descripteur de fichier=20 avant d'executer la fonction read() dessus si on veut pouvoir terminer=20 ce thread proprement.=20 lire les=20 datagrammes du socket UDP et les envoyer =C3=A0 travers le descripteur de=20 fichier tap : les donn=C3=A9es circuleront maintenant dans la direction=20 oppos=C3=A9e. 0) write(_tun_fd, buf, recvlen); ]]>Notez=20 qu'en pratique, si on a plus de deux h=C3=B4tes dans son r=C3=A9seau virtuel,= on=20 doit regarder le contenu des trames pour v=C3=A9rifier les adresses IP source= =20 et destination avant de d=C3=A9cider o=C3=B9 envoyer la trame. = On=20 peut t=C3=A9l=C3=A9charger les sources des fichiers udptun.c, ttools.c, ttool= s.h=20 et pathmtu.c avec le Makefile; tout ce dont on parl=C3=A9 ci-dessus est aussi= =20 t=C3=A9l=C3=A9chargeable sous la forme d'une archive tar. P comme Priv=C3=A9 Comme on a le=20 contr=C3=B4le total du trafic de notre r=C3=A9seau virtuel, on peut le crypte= r=20 dans l'espace utilisateur. Pour les besoins de cette d=C3=A9monstration, nous= =20 allons construire un VPN complet, que nous allons crypter avec IPSEC=20 (remarque: IPSEC a aussi une fonctionnalit=C3=A9 int=C3=A9gr=C3=A9e de tunnel= ling).=20 Sous Debian, il faut juste installer le paquetage=20 ipsec-tools et utiliser ces fichiers pour des manipulations manuelles:=20 Pour l'h=C3=B4te A: ## Vider le SAD et SPD flush; spdflush;=20 # A & B add 172.16.0.1 172.16.0.111 ah 15700 -A=20 hmac-md5 "123456789.123456"; add 172.16.0.111 172.16.0.1 ah 24500=20 -A hmac-md5 "123456789.123456"; add 172.16.0.1 172.16.0.111 esp=20 15701 -E 3des-cbc "123456789.123456789.1234"; add 172.16.0.111=20 172.16.0.1 esp 24501 -E 3des-cbc "123456789.123456789.1234"; # A=20 spdadd 172.16.0.1 172.16.0.111 any -P out ipsec=20 esp/transport//require ah/transport//require;=20 spdadd 172.16.0.111 172.16.0.1=20 any -P in ipsec esp/transport//require ah/transport//require;=20 Pour=20 l'h=C3=B4te B: ## Vide= r=20 le SAD et SPD flush; spdflush; # A & B add 172.16.0.1=20 172.16.0.111 ah 15700 -A hmac-md5 "123456789.123456"; add=20 172.16.0.111 172.16.0.1 ah 24500 -A hmac-md5 "123456789.123456";=20 add 172.16.0.1 172.16.0.111 esp 15701 -E 3des-cbc=20 "123456789.123456789.1234";=20 add 172.16.0.111 172.16.0.1=20 esp 24501 -E 3des-cbc "123456789.123456789.1234";=20 #dump ah; #dump esp; # B spdadd=20 172.16.0.111 172.16.0.1 any -P out ipsec esp/transport//require ah/transport//require;=20 spdadd 172.16.0.1 172.16.0.111=20 any -P in ipsec esp/transport//require ah/transport//require;=20 Remarquez=20 comme le m=C3=A9canisme de cryptage tout entier est li=C3=A9 aux adresses=20 virtuelles et comme il vous isole des r=C3=A9seaux physiques sur lesquels vos= =20 h=C3=B4tes se trouvent. Vous pouvez directement t=C3=A9l=C3=A9charger le fich= ier=20 ipsec-tools.conf. Le VPN en=20 marche C'est parti! Faisons un ping de 100=20 octets sur l'interface virtuelle de l'autre h=C3=B4te:=20 Host A$ ping -s 100=20 172.16.0.111 Regardons le trafic=20 avec tcpdump sur l'interface virtuelle:: #tcpdump -i tap0 .. 15:43:27.739218 IP 172.16.0.1 >=20 172.16.0.111: AH(spi=3D0x00003d54,seq=3D0x1d):=20 ESP(spi=3D0x00003d55,seq=3D0x1d), length 128=20 15:43:27.740673 IP 172.16.0.111 >=20 172.16.0.1: AH(spi=3D0x00005fb4,seq=3D0x1d): ESP(spi=3D0x00005fb5,seq=3D0x1d), length 128=20 15:43:28.738741 IP 172.16.0.1 >=20 172.16.0.111: AH(spi=3D0x00003d54,seq=3D0x1e):=20 ESP(spi=3D0x00003d55,seq=3D0x1e), length 128=20 15:43:28.740170 IP 172.16.0.111 >=20 172.16.0.1: AH(spi=3D0x00005fb4,seq=3D0x1e): ESP(spi=3D0x00005fb5,seq=3D0x1e), length 128=20 15:43:39.494298 IP 172.16.0.1 >=20 172.16.0.111: AH(spi=3D0x00003d54,seq=3D0x1f):=20 ESP(spi=3D0x00003d55,seq=3D0x1f), length 64=20 15:43:39.496818 IP 172.16.0.111 >=20 172.16.0.1: AH(spi=3D0x00005fb4,seq=3D0x1f): ESP(spi=3D0x00005fb5,seq=3D0x1f), length 40=20 Sur=20 l'interface physique: # tcpdump -i eth2 .. 15:45:46.878156 IP=20 192.168.40.128.11223 > 192.168.40.129.11223: UDP,=20 length 186=20 15:45:46.879021 IP=20 192.168.40.129.11223 > 192.168.40.128.11223: UDP,=20 length 186=20 15:45:47.879479 IP=20 192.168.40.128.11223 > 192.168.40.129.11223: UDP,=20 length 186=20 15:45:47.887054 IP=20 192.168.40.129.11223 > 192.168.40.128.11223: UDP,=20 length 186=20 15:45:48.880268 IP=20 192.168.40.128.11223 > 192.168.40.129.11223: UDP,=20 length 186=20 15:45:48.882738 IP=20 192.168.40.129.11223 > 192.168.40.128.11223: UDP,=20 length 186=20 Tous=20 les chiffres en gras sont des charges utiles. Quand il sort de=20 l'interface virtuelle, le datagramme crypt=C3=A9 est de 186 octets: 14 octets= =20 pour l'en-t=C3=AAte Ethernet, 20 pour l'en-t=C3=AAte IP, un en-t=C3=AAte AH d= e 24=20 octets et un ESP pour les 128 octets restants. Quand il=20 sort de l'interface physique, le datagramme est de 232 octets: 14 octets=20 pour l'en-t=C3=AAte Ethernet, 20 octets pour l'en-t=C3=AAte IP, 8 pour l'en-t= =C3=AAte=20 UDP, 186 octets de charge physique et 4 octets pour le bloc de fin de la=20 trame Ethernet. Nous avons donc rajout=C3=A9 46 octets par datagramme.=20 Ressources=20 Th= e=20 TUN/TAP kernel documentation=20 The Path MTU Discovery=20 RFC The Linux IPv4 man page=20 The RFC=20 Sourcebook