52 votes

Comment prendre en charge les connexions IPv4 et IPv6 ?

Je travaille actuellement sur une application de socket UDP et je dois intégrer un support pour que les connexions IPV4 et IPV6 puissent envoyer des paquets à un serveur.

J'espérais que quelqu'un pourrait m'aider et m'indiquer la bonne direction ; la majorité de la documentation que j'ai trouvée n'était pas complète. Il serait également utile que vous puissiez m'indiquer les différences entre les sockets Winsock et BSD.

Merci d'avance !

80voto

Martin v. Löwis Points 61768

La meilleure approche consiste à créer un socket de serveur IPv6 qui peut également accepter des connexions IPv4. Pour ce faire, créez un socket IPv6 ordinaire, tournez le bouton off l'option de prise de courant IPV6_V6ONLY le lier à l'adresse "any", et commencer à recevoir. Les adresses IPv4 seront présentées comme des adresses IPv6, dans l'ordre suivant mappé IPv4 format.

La principale différence entre les systèmes est de savoir si IPV6_V6ONLY est a) disponible, et b) activé ou désactivé par défaut. Il est désactivé par défaut sous Linux (c'est-à-dire qu'il autorise les sockets à double pile sans setsockopt), et est activé sur la plupart des autres systèmes.

En outre, la pile IPv6 de Windows XP ne prend pas en charge cette option. Dans ces cas, vous devrez créer deux sockets de serveur distincts, et les placer dans des threads sélectionnés ou multiples.

7voto

Einstein Points 2935

L'API des sockets est régie par les RFC de l'IETF et devrait être la même sur toutes les plateformes, y compris Windows WRT IPv6.

Pour les applications IPv4/IPv6, il s'agit de TOUTES à propos de getaddrinfo() y getnameinfo() . getaddrinfo est un génie - il examine le DNS, les noms de port et les capacités du client pour résoudre l'éternelle question "puis-je utiliser IPv4, IPv6 ou les deux pour atteindre une destination particulière ?". Ou si vous optez pour la voie dual-stack et souhaitez qu'il renvoie des adresses IPv4 mappées en IPv6, il le fera également.

Il fournit une sockaddr * structure qui peut être branchée sur bind() , recvfrom() , sendto() et la famille d'adresses pour socket() Dans de nombreux cas, cela signifie qu'il n'y a pas de désordre. sockaddr_in(6) des structures à remplir et à traiter.

Pour les implémentations UDP, je serais prudent quant à la mise en place de sockets à double pile ou, plus généralement, à la liaison à toutes les interfaces ( INADDR_ANY ). Le problème classique est que, lorsque les adresses ne sont pas verrouillées (cf. bind() ) à des interfaces spécifiques et que le système dispose de plusieurs demandes d'interfaces, les réponses peuvent transiter par des adresses différentes pour les ordinateurs disposant de plusieurs adresses en fonction des caprices de la table de routage du système d'exploitation, ce qui perturbe les protocoles d'application, en particulier les systèmes ayant des exigences d'authentification.

Pour les implémentations UDP où cela ne pose pas de problème, ou TCP, les sockets à double pile peuvent faire gagner beaucoup de temps lors de l'activation IPv* de votre système. Il faut faire attention à ne pas se reposer entièrement sur la double pile lorsque ce n'est pas absolument nécessaire, car il ne manque pas de plateformes raisonnables (Old Linux, BSD, Windows 2003) déployées avec des piles IPv6 qui ne sont pas capables de prendre en charge les sockets à double pile.

4voto

Dave Points 11

J'ai joué avec sous Windows et il semble bien qu'il y ait un problème de sécurité, si vous vous liez à l'adresse loopback, la socket IPv6 est correctement liée à [::1] mais la socket IPv4 mappée est liée à INADDR_ANY, donc votre application (supposée) sécurisée et uniquement locale est en fait exposée au monde entier.

3voto

Owen DeLong Points 11

Les RFC ne précisent pas vraiment l'existence de l'option de socket IPV6_V6ONLY, mais, si elle est absente, les RFC sont assez claires sur le fait que l'implémentation doit se faire comme si cette option était FAUX.

Lorsque l'option est présente, je dirais qu'elle devrait être par défaut FALSE, mais, pour des raisons de compréhension, les implémentations BSD et Windows sont par défaut TRUE. Il existe une revendication bizarre selon laquelle il s'agit d'un problème de sécurité parce qu'un programmeur IPv6 non averti pourrait se lier en pensant qu'il se lie uniquement à IN6ADDR_ANY pour IPv6 seulement et accepter accidentellement une connexion IPv4, causant un problème de sécurité. Je pense que c'est à la fois tiré par les cheveux et absurde, en plus d'être une surprise pour quiconque s'attend à une mise en œuvre conforme à la RFC.

Dans le cas de Windows, la non-compatibilité ne sera généralement pas une surprise. Dans le cas de BSD, c'est au mieux malheureux.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X