78
Rapport de projet de deuxième année Thème : Communication sous linux avec des sockets utilisant le protocole de transport SCTP Réalisé par OUNIS Lotfi TALBI Mohamed Encadrant : M. TABBANE Nabil Année universitaire : 2008/2009

P2A_Ounis Lotfi

  • Upload
    lotfi

  • View
    236

  • Download
    1

Embed Size (px)

DESCRIPTION

Cet travail a été réalisé dans le cadre de mon projet de deuxième année sous le thème de protocole de transport SCTP.

Citation preview

Page 1: P2A_Ounis Lotfi

Rapport de projet de deuxième année

Thème :

Communication sous linux avec des sockets

utilisant le protocole de transport SCTP

Réalisé par

OUNIS Lotfi TALBI Mohamed

Encadrant :

M. TABBANE Nabil

Année universitaire : 2008/2009

Page 2: P2A_Ounis Lotfi

- 2 -

TABLE DES MATIERES

Table des matières

Liste des acronymes

Liste des figures

Liste des tableaux

Introduction générale………………………………………………………………………………………………………01

I. Les protocoles de transports………………………………………………………………………………………02

I.1. Historique…………………………………………………………………………………………………………..02

I.2. Les caractéristiques de TCP/IP……………………………………………………………………………03

I.3. Le protocole TCP…………………………………………………………………………………………………04

I.4. Le protocole UDP…………………………………………………………………………………………………13

I.5. Limitations des protocoles usuels…………………………………………………………………………16

II. Le protocole SCTP……………………………………………………………………………………………………….17

II.1. Introduction ………………………………………………………………………………………………..………17

II.2. Spécifications du protocole SCTP………………………………………………………………………….18

II.2.1. Les caractéristiques du SCTP………………………………………………………………………18

II.2.1.1. Le multi streaming………………………………………………………………………….18

II.2.1.2. Le multi homing………………………………………………………………………………21

II.2.1.3. Autres caractéristiques……………………………………………………………………22

II.2.2. L’établissement de la connexion et le transfert des données…………………..……22

II.2.3. Format de l’unité de protocole SCTP……………………………………………………………24

III. L’implémentation du protocole SCTP sous linux……………………………………………………………25

III.1. Le module SCTP dans le noyau linux………………………………………………………………………25

III.2. L’interface de programmation ………………………………………………………………………………26

III.2.1. Présentation……………………………………………………………………………………………….26

III.2.2. Le style one-to-one: ……………………………………………………………………………………27

III.2.3. Le style one-to-many: …………………………………………………………………………………28

III.3. Manipulation des sockets utilisant SCTP sous linux……………………………………………..…30

III.3.1. Un simple client/serveur………………………………..……………………………………………36

III.3.2. Un serveur multi-flux …………………………………………………………………………..…......37

III.3.3. Test INIT/COOKIE_ECHO flooding ……………………………………………………………….39

III.3.4. HTTP over SCTP ……………..……………………………………….…………………………………36

III.4. Conclusion……………………………………………………………………………………………..…………….38

Conclusion générale…………………………………………………………………………………………………..…39

Bibliographie……………………………………………………………………………………………………………….40

Annexe…………………………………………………………………………………………………………………..…….41

Page 3: P2A_Ounis Lotfi

- 3 -

Liste des acronymes

ARPANET: Advanced Research Projects Agency Network

ATM: Asynchronous transfer mode

DARPA: Defense Advanced Research Projects Agency

DNS Domain Name System

DoS: Denial of Service

ECN: Explicit Congestion Notification

FDDI: Fiber Distributed Data Interface

IANA: Internet Assigned Numbers Authority

IETF: Internet Engineering Task Force

IPv4: Internet Protocol version 4

ISN: Numéro de séquence initial

MSS: Stands for Maximum Segment Size

MTU: maximum transmission unit

NFS: Network File System

OS: Operating System

PSTN: Public Switched Telephone Network

RFC: Request For Comment

RTT: Realtime Technology

SSH: Secure Shell

TSN: Transmit Sequence Number

VoIP: (Voice over Internet Protocol)

VRML: Virtual Reality Modeling Language

xDSL: x Digital Subscriber Line

Page 4: P2A_Ounis Lotfi

- 4 -

Listes des figures

Figure 1 : le modèle TCP/IP vs le modèle OSI

Figure 2 : TCP encapsulé dans IP

Figure 3 : Structure de l'en-tête TCP

Figure 4 : Établissement d'une connexion

Figure 5 : Clôture d'une connexion

Figure 6 : Émission d'un rst

Figure 7 : Mécanisme de l'acquittement

Figure 8 : Principe de la fenêtre glissante

Figure 9 : Détail de la fenêtre glissante

Figure 10 : Numéro de port comme numéro de service

Figure 11 : UDP encapsulé dans IP

Figure 12 : Structure de l'en-tête UDP

Figure 13 : Cas du checksum non nul

Figure 14 : SCTP dans OSI.

Figure 15 : connexion en TCP

Figure 16 : Exemples de deux hôtes multi-homed.

Figure 17 : Une association SCTP avec deux chemins

Figure 18 : Une association SCTP avec un seul chemin

Figure 19 : Exemple d’une association avec quatre flux.

Figure 20 : initialisation d’une association

Figure 21 : la fermeture d’association

Figure 22: Analyse de trafic SCTP avec wireshark

Page 5: P2A_Ounis Lotfi

- 5 -

Figure 23 : les fonctions d’une association SCTP one-to-one

Figure 24 : les fonctions d’une association SCTP one-to-many

Figure 25: Client et serveur de streaming des messages SCTP.

Figure 26: diagramme d’état du l’association entre le client et le serveur.

Figure 27: Schéma du SYN flood

Figure 28 : l’analyse de SYN flooding sur un serveur en TCP

Figure 29 : ressources alloué au serveur TCP (tcpS) au moment du flooding

Figure 30. Architecture Client/serveur pour le transfert de HTTP sur TCP/SCTP.

Page 6: P2A_Ounis Lotfi

- 6 -

Liste des tableaux

Tableau 1. Les types des portions de SCTP

Tableau 2. Comparaison entre UDP, TCP et SCTP

Page 7: P2A_Ounis Lotfi

- 7 -

Introduction générale Aujourd’hui nous pouvons observer une évolution très importante des réseaux. Cette évolution prend deux formes : le nombre et la diversité de technologies et le débit offert par les nouvelles technologies. Les ordinateurs personnels commercialisés actuellement sont équipés d’office de plusieurs interfaces réseau. Il s’agit, par exemple, de cartes Ethernet 1Gb, de cartes sans fils 802.11g ou de modems ADSL.

Le débit antérieurement mesuré en Kb/s se mesure maintenant en Gb/s et le progrès n’a pas l’air de pouvoir s’arrêter à ce point. Ce progrès peut continuer et le débit peut plus que doubler chaque année.

D’un autre côté, l’Internet d’aujourd’hui est toujours principalement basé sur le protocole IPv4 (Internet Protocol, version 4) dans la couche réseau et sur les protocoles TCP (Transmission Control Protocol) et UDP (User Datagram Protocol) dans la couche transport. Ces protocoles ont été proposés et développés dans les années 70 pour des technologies qui peuvent être aujourd’hui considérées comme des technologies anciennes.

A cette époque, qui est considéré comme l’époque de la naissance de l’Internet dans sa forme moderne, le réseau était une innovation et a vite évolué vers un réseau global comprenant une centaine de machines. Sa bande passante était fortement limitée et très chère.

Les interfaces réseau n’étaient pas aussi populaires qu’elles le sont aujourd’hui. Tout cela a provoqué la naissance de protocoles adaptés au contexte existant. Tel que le protocole SCTP (Stream control Transmission Protocol) qui a été élaboré par l’IETF (Internet Engineering Task Force) Pour répondre aux nouveaux besoins des applications de télécommunications. Bien que développé pour le transfert de la signalisation dans les environnements VoIP (Voice over Internet Protocol), ce protocole est appelé, dans un avenir proche, à couvrir un spectre beaucoup plus large de besoins. Pour cela on a décidé d’étudier le protocole SCTP dans ce modeste travail.

Ce rapport est organisé de la manière suivante :

Dans le premier chapitre, on dresse un état de l’art sur les protocoles de transport usuels. On présente les caractéristiques des protocoles TCP et UDP.

Dans le deuxième chapitre, on décrit le protocole SCTP en tenant compte des ses principaux caractéristiques.

Dans le troisième et dernier chapitre, on exploite des implémentations libres en langage C sous linux de protocole SCTP pour mettre en évidence ses caractéristiques et ses avantages par rapport aux autres protocoles.

Page 8: P2A_Ounis Lotfi

- 8 -

I. Les protocoles de transports I.1. Historique En 1969 aux États Unis, l'agence gouvernementale DARPA lance un projet de réseau expérimental, basé sur la commutation de paquets. Ce réseau, nommé ARPANET, fut construit dans le but d'étudier les technologies de communications, indépendamment de toute contrainte commerciale Un grand nombre de techniques de communication par modems datent de cette époque. L'expérience d'ARPANET est alors si concluante que toutes les organisations qui lui sont rattachées l'utilisent quotidiennement pour leurs messages de service. En 1975, le réseau passe officiellement du stade expérimental au stade opérationnel. Le développement d'ARPANET ne s'arrête pas pour autant, les bases des protocoles TCP/IP sont développées à ce moment, donc après que ARPANET soit opérationnel. En Juin 1978 Jon Postel définit IPv4 et en 1981 IP est standardisé dans la RFC 791. En 1983 les protocoles TCP/IP sont adoptés comme un standard militaire et toutes les machines sur le réseau commencent à l'utiliser. Pour faciliter cette reconversion, la DARPA demande à l'université de Berkeley d'implémenter ces protocoles dans leur version (BSD) d'Unix. Ainsi commence le mariage entre ce système d'exploitation et les protocoles TCP/IP. L'apport de l'Université de Berkeley est majeur, tant au niveau théorique (concept des sockets) qu'au niveau de l'utilisateur, avec des utilitaires très homogènes qui s'intègrent parfaitement au paradigme d'usage existant (rcp, rsh, rlogin...). Depuis cette époque, un nouveau terme est apparu pour désigner cette interconnexion de réseaux, l'Internet. Le succès de cette technologie est alors très important et suscite un intérêt croissant de la part d'acteurs très divers, et en particulier La « National Science Foundation » qui y voit un intérêt majeur pour la recherche scientifique et soutient donc ce nouveau moyen de mettre en communication tous les chercheurs. Depuis 1990, ARPANET n'est plus, pourtant le terme Internet demeure il désigne maintenant un espace de communication qui englobe la planète tout entière. Des millions de sites partout sur la surface du globe y sont connectés. Depuis 1994, l'Internet s'est ouvert au commerce, surtout avec l'apparition en 1991 d'un nouvel outil de consultation, le « World Wide Web » ou « Web » et ses interfaces populaires : Mosaic, Netscape, Mozilla, Firefox, Konqueror... Depuis 1995, pour faire face à sa popularité fortement croissante et aux demandes de transactions sécurisées, le protocole évolue et une nouvelle version, la version 6 (IPng puis tout simplement IPv6), est définie et en cours de déploiement expérimental. Les protocoles désignés par TCP/IP ont également envahi les réseaux locaux eux-mêmes, car il est plus facile d'utiliser les mêmes protocoles en interne et en externe. Pour les utilisateurs, l'accès à l'Internet est possible à l'aide d'une collection de programmes spécialisés si faciles à utiliser que l'on peut ignorer tout (ou presque) de leur fonctionnement interne. Seuls les programmeurs d'applications réseaux et les administrateurs de systèmes ont besoin d'en connaître les arcanes. Les services réseaux les plus populaires sont principalement :

• Le courrier électronique qui permet l'échange de messages entres usagers.

Page 9: P2A_Ounis Lotfi

- 9 -

• Les innombrables forums de discussion. • Le transfert de fichiers entre machines • Le « remote login », ou ses équivalents cryptés • Les serveurs inter-actifs. Les « anciens » se nommaient archie, gopher, veronica,

wais,etc. Désormais ils sont rendus obsolètes par le « web » (protocole http ). • Puis maintenant la radio, la vidéoconférence, la réalité virtuelle avec le VRML, le

« chat », les bourses d’échange point à point, les '' blogs '' forme évoluée des pages personnelles, etc.

En conclusion, on peut dire que l'Internet est une collection apparemment anarchique (il n'y a pas de structure hiérarchique et centralisée) de réseaux interconnectés et appartenant à divers propriétaires. I.2. Les caractéristiques de TCP/IP

Le succès de TCP/IP, s'il vient d'abord d'un choix du gouvernement américain, s'appui ensuite sur des caractéristiques intéressantes :

• C'est un protocole ouvert, les sources en sont disponibles gratuitement et ont été développées indépendamment d'une architecture particulière, d'un système d'exploitation particulier, d'une structure commerciale propriétaire. Ils sont donc théoriquement transportables sur n'importe quel type de plate-forme, ce qui est prouvé de nos jours.

• Ce protocole est indépendant du support physique du réseau. Cela permet à TCP/IP d'être véhiculé par des supports et des technologies aussi différents qu'une ligne série, un câble coaxial Ethernet, une liaison louée, un réseau token-ring, une liaison radio (satellites, « wireless » 802.11a/b/g), une liaison FDDI 600Mbits, une liaison par rayon laser, infrarouge, xDSL, ATM, fibre optique.

• Le mode d'adressage est commun à tous les utilisateurs de TCP/IP quelle que soit la plate-forme qui l'utilise. Si l'unicité de l'adresse est respectée, les communications aboutissent même si les hôtes sont aux antipodes.

• Les protocoles de hauts niveaux sont standardisés ce qui permet des développements largement répandus et inter-opérables sur tous types de machines.

Les majeures parties des informations relatives à ces protocoles sont publiées dans les RFCs (Requests For Comments). Les RFCs contiennent les dernières versions des spécifications de tous les protocoles TCP/IP, ainsi que bien d'autres informations comme des propositions d'améliorations des outils actuels, la description de nouveaux protocoles, des commentaires sur la gestion des réseaux...etc.

Page 10: P2A_Ounis Lotfi

- 10 -

Figure 1 : le modèle TCP/IP vs modèle OSI

I.3. Le protocole TCP

TCP est l'acronyme de « Transmission Control Protocol », il est défini dans la RFC 793 .Les données encapsulées dans un en-tête TCP sont des « paquets TCP ».

Figure 2 : TCP encapsulé dans IP

a) Caractéristiques de TCP TCP est bien plus compliqué qu'UDP examiné au chapitre suivant, il apporte en contrepartie des services beaucoup plus élaborés.

Cinq points principaux caractérisent ce protocole :

Page 11: P2A_Ounis Lotfi

- 11 -

TCP contient un mécanisme pour assurer le bon acheminement des données. Cette possibilité est absolument indispensable dès lors que les applications doivent transmettre de gros volumes de données et de façon fiable.

Il faut préciser que les paquets de données sont acquittés de bout en bout et non de point en point. D'une manière générale le réseau assure l'acheminement et les extrémités le contrôle.

Le protocole TCP permet l'établissement d'un circuit virtuel entre les deux points qui échangent de l'information. On dit aussi que TCP fonctionne en mode connecté (par opposition à UDP qui est en mode non connecté ou encore mode datagramme).

Avant le transfert les 2 applications se mettent en relation avec leurs OS respectifs, les informent de leurs désirs d'établir ou de recevoir une communication. Pratiquement, l'une des deux applications doit effectuer un appel que l'autre doit accepter. Les protocoles des deux OS communiquent alors en s'envoyant des messages au travers du réseau pour vérifier que le transfert est possible (autorisé) et que les deux applications sont prêtes pour leurs rôles. Une fois ces préliminaires établis, les modules de protocole informent les applications respectives que la connexion est établie et que le transfert peut débuter. Durant le transfert, le dialogue entre les protocoles continue, pour vérifier le bon acheminement des données.

Conceptuellement, pour établir une connexion (un circuit virtuel) il faut avoir réuni les éléments du quintuplet :

• Le protocole : C'est TCP mais il y pourrait y avoir d'autres transports qui assurent le même service.

• adresse IP locale : Adresse de la machine qui émet. • Port local : Le numéro de port associé au processus. Il est imposé ou est déterminé

automatiquement. • adresse IP distante : Adresse de la machine distante. • Port distant : Le numéro de port associé au service à atteindre. Il est obligatoire de le

connaître précisément.

TCP a la capacité de mémoriser des données : Aux deux extrémités du circuit virtuel, les applications s'envoient des volumes de données absolument quelconques, allant de 0 octet à des centaines (ou plus) de Mo.

À la réception, le protocole délivre les octets exactement comme ils ont été envoyés. Le protocole est libre de fragmenter le flux de données en paquets de tailles adaptées aux réseaux traversés. Il lui incombe cependant d'effectuer le réassemblage et donc de stocker temporairement les fragments avant de les présenter dans le bon ordre à l'application.

TCP est indépendant vis à vis des données transportées, c'est un flux d'octets non structuré sur lequel il n'agit pas. TCP simule une connexion en « full duplex ». Pour chacune des deux applications en connexion par un circuit virtuel, l'opération qui consiste à lire des données peut s'effectuer indépendamment de celle qui consiste à en écrire. Le protocole autorise la clôture du flot dans une direction tandis que l'autre continue à être active. Le circuit virtuel est rompu quand les deux parties ont clos le flux.

Page 12: P2A_Ounis Lotfi

- 12 -

b) Description de l'en-tête La figure suivante montre la structure d'un en-tête TCP. Sa taille normale est de 20 octets, à moins que des options soient présentes.

Figure 3 : Structure de l'en-tête TCP

• PORT SOURCE : Le numéro de port de l'application locale. • PORT DESTINATION : Le numéro de port de l'application distante. • NUMERO DE SEQUENCE : C'est un nombre qui identifie la position des données à

transmettre par rapport au segment original. Au démarrage de chaque connexion, ce champ contient une valeur non nulle et non facilement prévisible, c'est la séquence initiale ou ISN.TCP numérote chaque octet transmis en incrémentant ce nombre 32 bits non signé. Il repasse à 0 après avoir atteint 232 - 1 (4 294 967 295). Pour le premier octet des données transmis ce nombre est incrémenté de un, et ainsi de suite...

• NUMERO D’ACQUITTEMENT : C'est un numéro qui identifie la position du dernier octet reçu dans le flux entrant. Il doit s'accompagner du drapeau ACK (voir plus loin).

• TAILLE DE L’EN-TÊTE : (OFFSET), il s'agit d'un déplacement qui permet d'atteindre les données quand il y a des options. Codé sur 4 bits, il s'agit du nombre de mots de 4 octets qui composent l'en-tête. Le déplacement maximum est donc de 60 octets ( 24-1 x 4 octets). Dans le cas d'un en-tête sans option, ce champ porte la valeur 5. 10 mots de 4 octets sont donc possibles pour les options.

• RESERVE : Six bits réservés pour un usage futur. • CODE : Six bits pour influer sur le comportement de TCP en caractérisant l'usage du

segment (URG, ACK, PSH, RST, SYN, FIN).

c) Début et clôture d'une connexion

Établissement d'une connexion

L'établissement d'une connexion TCP s'effectue en trois temps, comme le schéma de la figure 4 l'explicite.

Page 13: P2A_Ounis Lotfi

- 13 -

Figure 4 : Établissement d'une connexion

On suppose que l'émetteur du premier paquet avec le bit SYN a connaissance du couple (adresse IP du récepteur, numéro de port du service souhaité).

L'émetteur du premier paquet est à l'origine de l'établissement du circuit virtuel, c'est une attitude généralement qualifiée de « client ». On dit aussi que le client effectue une « ouverture active » (active open).

Le récepteur du premier paquet accepte l'établissement de la connexion, ce qui suppose qu'il était prêt à le faire avant que la partie cliente en prenne l'initiative. C'est une attitude de « serveur ». On dit aussi que le serveur effectue une « ouverture passive » (passive open).

1. Le client envoie un segment comportant le drapeau SYN, avec sa séquence initiale (ISN = x).

2. Le serveur répond avec sa propre séquence (ISN = y), mais il doit également acquitter le paquet précédent, ce qu'il fait avec ACK (seq = x + 1).

3. Le client doit acquitter le deuxième segment avec ACK (seq = y + 1).

Une fois achevée cette phase nommée « three-way handshake », les deux applications sont en mesure d'échanger les octets qui justifient l'établissement de la connexion.

Clôture d'une connexion

Clôture canonique

Un échange de trois segments est nécessaire pour l'établissement de la connexion ; il en faut quatre pour qu'elle s'achève de manière canonique (orderly release).

Page 14: P2A_Ounis Lotfi

- 14 -

Figure 5 : Clôture d'une connexion

La raison est qu'une connexion TCP est « full-duplex », ce qui implique que les données circulent indépendamment dans un sens et dans l'autre. Les deux directions doivent donc pouvoir être interrompues indépendamment l'une de l'autre.

L'application qui envoie un paquet avec le drapeau FIN indique à la couche TCP de la machine distante qu'elle n'enverra plus de donnée. La machine distante doit acquitter ce segment, comme il est indiqué sur la figure 5, en incrémentant d'une unité le « sequence number ».

La connexion est véritablement terminée quand les deux applications ont effectué ce travail. Il y a donc échange de 4 paquets pour terminer la connexion.

Au total, sans compter les échanges propres au transfert des données, les deux couches TCP doivent gérer 7 paquets, il faut en tenir compte lors de la conception des applications !

Sur la figure on constate que le serveur continue d'envoyer des données bien que le client ait terminé ses envois. Le serveur a détecté cette attitude par la réception d'un caractère d’EOF (en C sous Unix).

Cette possibilité a son utilité, notamment dans le cas des traitements distants qui doivent s'accomplir une fois toutes les données transmises, comme par exemple pour un tri.

Clôture abrupte

Au lieu d'un échange de quatre paquets comme précédemment, un mécanisme de reset est prévu pour terminer une connexion au plus vite (abortive release).

Page 15: P2A_Ounis Lotfi

- 15 -

Ce type d'arrêt est typiquement géré par la couche TCP elle-même quand l'application est brutalement interrompue sans avoir effectué un appel à la primitive close, comme par exemple lors d'un appel au primitif abort (), ou après avoir rencontré une exception non prise en compte.

L'extrémité qui arrête brutalement la connexion émet un paquet assorti du bit RST, après avoir (ou non) envoyé les derniers octets en attente. Ce paquet clôt l'échange. Il ne reçoit aucun acquittement.

L'extrémité qui reçoit le paquet de reset (bit RST), transmet les éventuelles dernières données à l'application et provoque une sortie d'erreur du type « Connection reset par peer » pour la primitive de lecture réseau. Comme c'est le dernier échange, si des données restaient à transmettre à l'application qui a envoyé le RST elles peuvent être détruites.

Figure 6 : Émission d'un rst

d) Contrôle du transport

Le bon acheminement des données applicatives est assuré par un mécanisme d'acquittement des paquets, comme nous avons déjà pu l'examiner partiellement au paragraphe précédent.

Le mécanisme de l'acquittement

Figure 7 : Mécanisme de l'acquittement

Page 16: P2A_Ounis Lotfi

- 16 -

• Au départ du Paquet i une horloge se déclenche. Si cette horloge dépasse une valeur limite avant réception de l'ACK le Paquet i est retransmis.

• Cette valeur limite est basée sur la constante MSL qui est un choix d'implémentation, généralement de 30 secondes à 2 minutes. Le temps maximum d'attente est donc de 2 x MSL.

• Le temps qui s'écoule entre l'émission d'un paquet et la réception de son acquittement est le RTT, il doit donc être inférieur à 2 x MSL. Il est courant sur l'Internet actuel d'avoir un RTT de l'ordre de la seconde.

Il faut noter que le RTT (Realtime Technology) est la somme des temps de transit entre routeur et du temps passé dans les diverses files d'attente sur les routeurs.

• L'émetteur conserve la trace du Paquet i pour éventuellement le renvoyer.

Si on considère des délais de transmission de l'ordre de 500 ms (voire plus), un tel mécanisme est totalement inadapté au transfert de flux de données. On peut aussi remarquer qu'il sous-emploie la bande passante du réseau.

Fenêtres glissantes

Cette attente de l'acquittement est pénalisante, sauf si on utilise un mécanisme de « fenêtres glissantes », comme le suggère la figure 8 :

Figure 8 : Principe de la fenêtre glissante

Avec ce principe, la bande passante du réseau est beaucoup mieux employée.

Si l'un des paquets doit être réémis, la couche TCP du destinataire aura toute l'information pour le replacer dans le bon ordre.

Page 17: P2A_Ounis Lotfi

- 17 -

À chaque paquet est associée une horloge comme sur la figure 7.

Le nombre de paquets à envoyer avant d'attendre le premier acquittement est fonction de deux paramètres :

• La largeur de la fenêtre précisée dans le champ WINDOW de l'en-tête. Des valeurs courantes sont de l'ordre de 4096, 8192 ou 16384.

• Elle change dynamiquement pour deux raisons :

� L'application change la taille du « buffer du socket » qui correspond à la taille de cette fenêtre.

� Chaque acquittement ACK envoyé est assorti d'une nouvelle valeur de taille de la fenêtre, permettant ainsi à l'émetteur d'ajuster à tout instant le nombre de segment qu'il peut envoyer simultanément. Cette valeur peut être nulle, comme par exemple lorsque l'application cesse de lire les données reçues. C'est ce mécanisme qui assure le contrôle de flux de TCP.

• La taille maximale des données, ou MSS vaut 512 octets par défaut. C'est la plus grande taille du segment de données que TCP enverra au cours de la session.

• Le datagramme IP a donc une taille égale au MSS augmentée de 40 octets (20 + 20), en l'absence d'option de TCP.

Cette option apparait uniquement dans un paquet assorti du drapeau SYN, donc à l'établissement de la connexion.

Figure 9 : Détail de la fenêtre glissante

Le débit obtenu dépend de la taille de la fenêtre et bien sûr de la bande passante disponible. On conçoit aisément qu'entre la situation de la figure 7 et celle de la figure 8 l'usage de la bande passante s'améliore. Par contre l'agrandissement de la taille de la fenêtre ne se conçoit que jusqu'à une limite optimale au delà de laquelle des paquets sont perdus parce que envoyés trop rapidement pour être reçus par le destinataire. Or, pour fonctionner de manière optimale, TCP se doit de limiter au maximum la perte de paquets et donc leur réémission.

Page 18: P2A_Ounis Lotfi

- 18 -

Cette taille limite optimale de la largeur de la fenêtre est, comme on peut le deviner, fonction de la bande passante théorique du réseau et surtout de son taux d'occupation instantané. Cette dernière donnée est fluctuante, aussi TCP doit-il asservir continument les tailles de fenêtre pour en tenir compte.

Évitement de congestion

Le contrôle du flux, pour éviter la congestion des routeurs, est implémenté à l'aide d'une variable (cwnd) nommée « congestion window » que l'on traduit par fenêtre de congestion.

Concrètement, le nombre maximum de segments de données ( x MSS en octets) que l'émetteur peut envoyer avant d'en recevoir le premier acquittement est le minimum entre cette variable (cwnd) et la taille de la fenêtre annoncée par le récepteur à chaque acquittement de paquet.

Le contenu de cette variable est piloté par les algorithmes de départ lent « slow start », et d'évitement de congestion « congestion avoidance » examiné ici.

La limite de croissance de la variable cwnd est la taille de la fenêtre annoncée par le récepteur. Une fois la capacité de débit maximale atteinte, si un paquet est perdu l'algorithme d'évitement de congestion en diminue linéairement la valeur (contrairement au « slow start » qui l'augmente exponentiellement).

I.4. Le protocole UDP

UDP est l'acronyme de « User Datagram Protocol », il est défini dans la RFC 768. Les données encapsulées dans un en-tête UDP sont des « paquets UDP ».

a) Identification de la destination Au niveau de la couche Internet les datagrammes sont routés d'une machine à une autre en fonction des bits de l'adresse IP qui identifient le numéro de réseau. Lors de cette opération aucune distinction n'est faite entre les services ou les utilisateurs qui émettent ou reçoivent des datagrammes, i.e. tous les datagrammes sont mélangés.

La couche UDP ajoute un mécanisme qui permet l'identification du service (niveau Application). En effet, il est indispensable de faire un tri entre les diverses applications (services) : plusieurs programmes de plusieurs utilisateurs peuvent utiliser simultanément la même couche de transport et il ne doit pas y avoir de confusion entre eux.

Pour le système Unix les programmes sont identifiés de manière unique par un numéro de processus, mais ce numéro est éphémère, non prévisible à distance, il ne peut servir à cette fonction.

Page 19: P2A_Ounis Lotfi

- 19 -

L'idée est d'associer la destination à la fonction qu'elle remplit. Cette identification se fait à l'aide d'un entier positif que l'on baptise port.

• Le système d'exploitation local a à sa charge de définir le mécanisme qui permet à un processus d'accéder à un port.

• La plupart des systèmes d'exploitation fournissent le moyen d'un accès synchrone à un port. Ce logiciel doit alors assurer la possibilité de gérer la file d'attente des paquets qui arrivent, jusqu'à ce qu'un processus (Application) les lise. A l'inverse, l'OS, bloque un processus qui tente de lire une donnée non encore disponible.

Pour communiquer avec un service distant il faut donc avoir connaissance de son numéro de port, en plus de l'adresse IP de la machine elle-même.

La figure 10 explicite la notion de port. La couche IP sépare les datagrammes TCP et UDP grâce au champ PROTOVI1 de son en-tête, l'association du protocole de transport et du numéro de port identifie un service sans ambiguïté.

Conceptuellement on s'aperçoit alors que rien ne s'oppose à ce qu'un même service (Numéro de port) soit attribué conjointement aux trois protocoles (en pointillés sur la figure). Cette situation est d'ailleurs courante dans la réalité des serveurs.

Figure 10 : Numéro de port comme numéro de service

b) Description de l'en-tête

Un paquet UDP est conçu pour être encapsulé dans un datagramme IP et permettre un échange de données entre deux applications, sans échange préliminaire. Ainsi, si les données à transmettre n'obligent pas IP à fragmenter, un paquet UDP génère un datagramme IP et c'est tout.

Page 20: P2A_Ounis Lotfi

- 20 -

Figure 11 : UDP encapsulé dans IP

• UDP apporte un mécanisme de gestion des ports, au dessus de la couche Internet. • UDP est simplement une interface au dessus d'IP, ainsi l'émission des messages se

fait-elle sans garantie de bon acheminement. Plus généralement, tous les défauts d'IP sont applicables à UDP. Plus particulièrement, les paquets à destination d'une application UDP sont conservés dans une pile de type FIFO. Si l'application destinatrice ne les « consomme » pas assez rapidement, les plus anciens paquets risquent d'être écrasés par les plus récents. Un risque supplémentaire (par rapport aux propriétés d'IP déjà connues) de perte de données.

• Il n'y a aucun retour d'information au niveau du protocole pour apporter un quelconque moyen de contrôle sur le bon acheminement des données.

• C'est au niveau applicatif qu'il convient de prendre en compte cette lacune. • Par opposition à TCP, UDP est désigné comme un mode de transport « non

connecté », ou encore mode datagramme.

Parmi les utilisations les plus courantes d'UDP on peut signaler le serveur de noms (DNS), base de données répartie au niveau mondial, et qui s'accommode très bien de ce mode de transport.

En local d'autres applications très utiles comme tftp ou nfs sont également susceptibles d'employer UDP.

La figure 12 décrit la structure de l'en-tête.

Figure 12 : Structure de l'en-tête UDP

• UDP SOURCE PORT : Le numéro de port de l'émetteur du paquet. Ce champ est optionnel, quand il est spécifié il indique le numéro de port que le destinataire doit employer pour sa réponse. La valeur zéro (0) indique qu'il est inutilisé, le port 0 n'est donc pas celui d'un service valide.

• UDP DESTINATION PORT : Le numéro de port du destinataire du paquet. • MESSAGE LENGTH : C'est la longueur du paquet, donc comprenant l'en-tête et le

message. La longueur minimale est 8 et la longueur maximale est 65 535 - H(IP). Dans le cas courant (IP sans option) cette taille maximale est donc de 65 515.

Page 21: P2A_Ounis Lotfi

- 21 -

• CHECKSUM : Le checksum est optionnel et toutes les implémentations ne l'utilisent pas. S'il est employé, il porte sur un pseudo en-tête constitué de la manière suivante :

Figure 13 : Cas du checksum non nul

Ce pseudo en-tête est prévu initialement pour apporter une protection en cas de datagrammes mal routés.

c) Attribution des ports :

Devant l'explosion du nombre des services enregistrés, l'IANA a modifié la segmentation qui précède. Désormais les numéros de ports sont classés selon les trois catégories suivantes :

1. Le segment [1,1023] est toujours réservé aux services bien connus. Les services bien connus sont désignés par l'IANA et sont mis en œuvre par des applications qui s'exécutent avec des droits privilégiés (root sur une machine Unix)

2. Le segment [1024,49151] est celui des services enregistrés. Ils sont énumérés par l'IANA et peuvent être employés par des processus ayant des droits ordinaires.

I.5. Limitations des protocoles usuels

Les protocoles TCP et UDP ont été conçu à une époque où l'usage de la commande ligne était universel, et les applications graphiques utilisant le réseau très rares.

Une trentaine d'années plus tard, on peut faire le constat pratiquement inverse : les applications textes interactives (beaucoup de petits messages applicatifs) disparaissent au profit d'applications moins interactives et qui sont plus orientées flux de données (vidéo, audio, téléphonie...) avec des échanges plus volumineux et des besoins en transport qui ont évolué.

Page 22: P2A_Ounis Lotfi

- 22 -

Le principe de la fenêtre glissante, si performant qu'il soit pour assurer le bon acheminement des données. En effet, si le paquet de données de tête n'est pas acquitté, les suivants, même reçus, sont en attente avant d'être délivrés à l'application.

En termes de sécurité des applications et des services sous TCP, ce protocole est vulnérable aux attaques déni de service (DoS), telles que TCP/SYN flooding. Un TCP/SYN flooding se produit quand un hôte malveillant forge un paquet IP avec une fausse adresse IP et envoie un grand nombre de messages SYN à la victime (généralement un serveur). Chaque fois que la pile TCP de la victime, reçoit un nouveau message SYN, le serveur alloue des ressources pour le nouveau message SYN. Lorsque la pile TCP est inondé de messages multiples SYN, la victime ne peut accueillir plus de ressources et ne parviennent pas à assurer le service des nouvelles messages SYN légitimes.

L'indépendance de TCP vis à vis de la structure des données est également un inconvénient dans certaines applications comme la téléphonie pour laquelle la notion de messages successifs est bien plus intéressante.

Depuis le début des années 2000 l'IETF met au point le protocole SCTP qui fournit des services similaires à ceux de TCP, en abandonne certains et apporte les nouvelles fonctionnalités adaptées aux nouveaux besoins.

Page 23: P2A_Ounis Lotfi

- 23 -

II. Le protocole SCTP II.1. Introduction Stream Control Transmission Protocol [3] est un protocole relativement nouveau, mais qui se développe beaucoup et vient en complément des protocoles TCP et UDP. Il possède aussi un haut niveau de fiabilité que TCP, mais utilise moins de temps système. Ce protocole fut à l'origine développé pour la téléphonie sur IP, ou voix sur IP (VoIP), et possède certains attributs intéressants qui en proviennent. Le niveau de l'industrie VoIP requiert une très haute fiabilité, ce qui veut dire une grande faculté de récupération pour gérer les différentes sortes de problèmes.

Figure 14 : SCTP dans le modèle OSI.

Page 24: P2A_Ounis Lotfi

- 24 -

II.2. Spécifications du protocole SCTP II.2.1. Caractéristiques du SCTP II.2.1.1. Le multi-homing Une connexion en TCP est définie par 4 paramètres : une adresse IP d’émetteur, un port source, une adresse IP du récepteur et un port destination. Cette façon de définir une connexion détermine deux adresses stables et inchangeables pendant la connexion. Une fois les adresses définies au début d’une connexion, elles sont gardées jusqu’à sa terminaison.

Figure 15 : connexion en TCP

Dans cette logique, une connexion TCP est établie entre deux adresses IP. Le protocole SCTP propose une logique différente : une association est établie entre deux structures appelées extrémités (endpoint). Une extrémité est un ensemble d’adresses de destination auxquelles on peut également envoyer des paquets ou un ensemble d’adresses source desquelles on peut également accepter des paquets. Une extrémité comprend aussi un numéro du port, qui doit être unique et ne peut pas être utilisé par une autre extrémité. Pour ce qui est des adresses, une extrémité SCTP peut utiliser une liste d’adresses IPv4, IPv6 ou des noms de machine. D’un point de vue réseau, un point terminal est l’extrémité logique du protocole de transport SCTP. Dans le cas d’une connexion simple (single-homed), l’identification du point terminal sera décrite de la manière suivante: point extrémité = [adresse IP: port SCTP]. Dans le cas d’une connexion multiple (multi-homed), les différentes adresses IP utilisées partagent un port SCTP unique : Point extrémité = [adresse IP1, adresse

IP2, ... adresse IPn: port SCTP].

Page 25: P2A_Ounis Lotfi

- 25 -

Figure 16 : Exemples de deux hôtes multi-homed.

La notion de chemin est introduite pour gérer des extrémités SCTP. Elle fait appel à une structure de données créée dans une association SCTP. Un chemin est créé pour chaque adresse IP annoncée par le destinataire pendant la phase d’initialisation. Il contient une adresse IP destination et une adresse IP source qui est déterminée par les règles du routage local pour l’adresse IP de la destination donnée. Le chemin contient également des paramètres additionnels (des paramètres de contrôle de congestion, des compteurs de retransmission, le MTU, etc.). Quant à l’envoi d’un message, SCTP ne choisit pas d’adresse destination, mais un chemin. Une fois le chemin choisi, le protocole met les adresses destination et source de ce chemin dans le message et l’envoie. A ce stade, le protocole n’a aucune influence ni sur l’adresse source ni sur l’adresse destination du message. Les deux adresses sont celles du chemin choisi. Le multi-homing dans SCTP a été proposé dans le but d’augmenter la fiabilité du protocole. En cas de panne impliquant une adresse (interface, câble, réseau etc.), SCTP permet d’utiliser un autre chemin. De cette façon, la communication dans une association peut être maintenue même en cas de problèmes avec la connectivité impliquant une adresse. Pour l’instant SCTP ne permet pas d’appliquer la répartition de charge ni le choix dynamique d’adresses pendant une association.

Page 26: P2A_Ounis Lotfi

- 26 -

Figure 17 : Une association SCTP avec deux chemins

Figure 18 : Une association SCTP avec un seul chemin Dans les figures 17 et 18 nous présentons deux scénarios différents. Dans la figure 18 nous avons un client équipé d’une carte réseau et un serveur avec deux cartes réseau. Quand le client établit une association, il crée deux chemins : un pour l’adresse server_1 et le deuxième pour l’adresse server_2. Dans les deux chemins il met son adresse locale client_1 comme l’adresse source. La deuxième figure 11 montre la situation inverse. Le client possède deux cartes réseau et le serveur n’en possède qu’une. Dans ce cas, le client ne crée qu’un chemin pour l’adresse server_1. Selon sa table du routage, il met dans ce chemin son adresse client_1 comme l’adresse source. La deuxième adresse du client n’est pas utilisée dans ce cas. Ainsi, le client ne possède qu’un seul chemin.

Page 27: P2A_Ounis Lotfi

- 27 -

II.2.1.2. Le multi-streaming Le protocole SCTP permet le multi-flux simultané dans une même association, d'où le nom Stream Control Transmission Protocol (Protocole de Contrôle de Transmission de Flux). Un flux unique peut, par exemple, être ouvert pour télécharger une simple page web, et ainsi les images et documents html seront chargés dans le même flux simultanément. Ou pourquoi pas un protocole de bases de données qui créera un contrôle de flux séparé et ensuite utilisera plusieurs flux pour recevoir les sorties des différentes requêtes simultanément. Il permet d’envoyer plusieurs flux de données indépendants sur une connexion au niveau transport. La fiabilité et le contrôle de congestion sont gérés indépendamment pour chaque flux. S’il y a des problèmes qui apparaissent dans un flux donné, ils ne dérangent pas les autres. La possibilité d’avoir plusieurs flux indépendants dans une association est une caractéristique qui rend SCTP différent des protocoles de transport existants. Contrairement à TCP où les données sont transmises en flux d’octets, dans SCTP les données sont envoyées en flux de messages. En plus, SCTP permet d’avoir plusieurs flux de données dans une association. Cela est possible grâce à l’utilisation d’un drapeau (flag Stream Identifier S) présent dans chaque bloc de données (les messages de contrôle ne sont attribués à aucun flux), indiquant le numéro de flux approprié. D’après ce drapeau, l’émetteur décide dans quel flux le message est transmis et le récepteur peut reconnaître de quel flux le message vient. L’identificateur de flux est de 16 bits ce qui permet d’avoir 65536 flux séparés dans une association. Comme la gestion d’acquittement est basée sur des flux, la transmission de chaque flux est indépendante. En cas de blocage ou de perte d’un message d’un flux, les autres flux peuvent toujours être délivrés sans contrainte. Des problèmes de transmission sont résolus au niveau du flux considéré.

Figure 19 : Exemple d’une association avec quatre flux.

Parmi des applications qui peuvent bénéficier du multi-streaming, on peut mentionner des protocoles de signalisation dans des réseaux téléphoniques PSTN (Public Switched Telephone Network) ou des navigateurs web. Dans le premier cas, ce qui est essentiel, c’est l’indépendance des flux dans une association et la possibilité de livraison de messages en dehors de séquence. Si un message est bloqué ou retardé, les autres peuvent être délivrés au

Page 28: P2A_Ounis Lotfi

- 28 -

destinataire. Dans le deuxième cas, le navigateur peut télécharger une page entière dans une association. Tous les objets de la page (fichiers html, images, sons, styles, etc.) peuvent être téléchargés en même temps dans des flots indépendants. Cela permet d’économiser des ressources, du côté du client aussi bien que du côté du serveur.

II.2.1.3. Autres caractéristiques i. La fiabilité Le protocole SCTP utilise les sommes de contrôle et SACK pour détecter les données corrompues, endommagées, dupliquées ou réordonnées. Il peut ensuite retransmettre les données si nécessaire. C'est à peu près comme TCP, mais SCTP est plus tolérant pour le réordonnancement des données et permet un captage plus rapide.

ii. Orienté message Chaque message peut être mis en trames et donc vous pouvez garder la structure et ordonner le flux de données. TCP est orienté octet et tout ce que vous obtenez est un flux d'octets sans aucun ordre entre les différentes données. Vous avez donc besoin d'une couche d'abstraction dans TCP.

iii. Adaptatif au débit Il est développé pour collaborer et coexister avec TCP au niveau de la bande passante. Il l'augmente ou la réduit en fonction des conditions de charge du réseau comme TCP. Il a aussi le même algorithme pour les démarrages lents quand les paquets sont perdus. ECN est également supporté. II.2.2. L’établissement la connexion et le transfert des données II.2.2.1. Initialisation et association Chaque connexion est initialisée en créant une association entre les deux hôtes qui désirent entrer en contact. Cette association est initialisée quand un utilisateur en a besoin. Cette initialisation est réalisée par 4 paquets. Le premier, un bloc INIT, est envoyé, en réponse il reçoit un INIT ACK contenant un témoin (cookie), ensuite la connexion peut démarrer en envoyant les données. Cependant, deux paquets supplémentaires sont envoyés. Le témoin reçoit en réponse un bloc COOKIE ECHO, lequel reçoit enfin un bloc COOKIE ACK.

Page 29: P2A_Ounis Lotfi

- 29 -

Figure 20 : initialisation d’une association

II.2.2.2. Envoi de données et contrôle de session

SCTP, à ce niveau, on peut envoyer des données. Dans SCTP il existe des blocs de contrôle et des blocs de données, comme vu précédemment. Les blocs de données sont envoyés en utilisant le bloc DATA, auquel il est répondu par un bloc SACK. Ça fonctionne pratiquement de la même façon que TCP SACK. Les blocs SACK sont des blocs de contrôle. Au dessus de tout ça, il existe d'autres blocs de contrôle. Les blocs HEARTBEAT et HEARTBEAT ACK d'un côté, et les blocs ERROR de l'autre. Les blocs HEARTBEAT sont utilisés pour conserver la connexion active, et les blocs ERROR sont utilisés pour informer des divers problèmes ou erreurs de connexion, comme un id de flux invalide ou des paramètres de données obligatoires absents, etc.

II.2.2.3. Arrêt et abandon

La connexion est finalement fermée soit par un bloc ABORT soit plus "poliment" par un bloc SHUTDOWN. SCTP ne possède pas d'état semi-fermé comme TCP, un côté ne peut pas continuer à envoyer des données tandis que l'autre a fermé. Quand un utilisateur/application désire fermer le socket SCTP de façon courtoise, il appelle le protocole SHUTDOWN. SCTP envoie alors toutes les données encore dans ses mémoires tampon, et ensuite envoie un bloc SHUTDOWN. Quand le destinataire reçoit le SHUTDOWN, il stoppera l'acceptation des données provenant de l'application et cessera d'envoyer des données. Une fois obtenu tous les SACK pour les données, il enverra un bloc SHUTDOWN ACK, et une fois que le côté qui ferme la connexion a reçu ce bloc, il répondra par un bloc SHUTDOWN COMPLETE. La session est maintenant complètement fermée. Une autre façon de fermer une connexion est d'utiliser ABORT. Mais c'est un moyen pas très poli de supprimer une association SCTP. Quand une des deux parties désire arrêter une association SCTP instantanément, elle envoie un bloc ABORT avec toutes les valeurs

Page 30: P2A_Ounis Lotfi

- 30 -

correctes signées. Toutes les données dans les tampons seront déchargées et l'association terminée. Le destinataire fera de même après vérification du bloc ABORT.

Figure 21 : la fermeture d’association

II.3. Format de l’unité de protocole SCTP

La structure d’une unité de protocole SCTP est modulaire. Il contient un en-tête de format commun pour tous les types possibles. Il comprend aussi une ou plusieurs portions. Deux types de portions existent : la portion de données et les portions de contrôle. Il y a un seul type de portion pour contenir des données. Pour transporter les différents messages de contrôle utilisés pendant de différentes étapes d’une association, il y a plusieurs types de portions de contrôle. La spécification initiale [3] définit 14 types des portions de contrôle, mais avec des extensions, il y en a actuellement 17. Le tableau 1 présente tous les types de portions. Tableau 1 : Les types des portions de SCTP VALEUR NOM DESCRIPTION 0 DATA Les données d’utilisateur 1 INIT Initiation d’une association 2 INIT ACK Acquittement de la portion

INIT 3 SACK Acquittement de la réception

de données

4 HEARTBEAT Vérification d’accessibilité d’une adresse IP de l’autre extrémité

5 HEARTBEAT ACK Acquittement de la portion HEARTBEAT

6 ABORT Fermeture immédiate d’une association

Page 31: P2A_Ounis Lotfi

- 31 -

7 SHUTDOWN Début de la fermeture normale d’une association

8 SHUTDOWN ACK Acquittement de la portion SHUTDOWN

9 ERROR Notification d’une erreur 10 COOKIE ECHO Porte le COOKIE pendant

l’initialisation d’une association

11 COOKIE ACK Acquittement de la portion COOKIE ECHO

12 ECNE Réservé pour utilisation dans Explicit Congestion Notification

13 CWR Réservé pour utilisation dans Explicit Congestion Notification

14 SHUTDOWN COMPLETE

Acquittement de la portion SHUTDOWN ACK

Les portions de données peuvent être mises dans un message avec des portions de contrôle. Il y a pourtant certaines contraintes : – les portions du type INIT, INIT ACK et SHUTDOWN COMPLETE doivent être seules dans un paquet. – la portion ABORT ne peut pas être mise dans le même message que les portions des données (du type DATA). – la taille totale du message ne peut pas excéder le MTU (Maximal Transmission Unit). II.4. Conclusion Le protocole SCTP présente des caractéristiques intéressantes ce qui a encouragé certains à entrer dans la phase d’implémentation, même si ces implémentations sont assez jeunes elles servent à mettre en œuvre ce protocole dans des applications internet telles que le http, le ftp…

Page 32: P2A_Ounis Lotfi

- 32 -

III. L’implémentation du protocole SCTP

sous linux Parmi toutes les implémentations existantes nous avons choisi de travailler avec un module de SCTP pour le noyau de linux (LKSCTP) et une interface de programmation pour le langage C (libsctp) car elles sont les plus utilisées au niveau universitaire comme au niveau industriel. III.1. Le module SCTP dans le noyau linux LKSCTP [14] est un projet développé par l’IETF SIGTRAN [15] et qui est un projet de mise en œuvre de la Stream Control Transmission Protocol (SCTP) dans le noyau Linux. Ce projet vise à diffuser des informations sur SCTP et à encourager le déploiement de SCTP dans des environnements réels des usagers. Pour installer ce noyau dans un environnement Debian (Ubuntu 8), on peut suivre l’un de deux méthodes : Installation à l’aide du gestionnaire des paquets (apt-get) : #apt-get install lksctp Installation à partir des sources : A partir des sources du projet : (à partir http://sourceforge.net/projects/lksctp). L'implémentation de SCTP est fournie avec un outil de test (sctp_test ou sctp_darn), permettant d'effectuer une simple transmission. L'émetteur doit taper la commande suivante : sctp_test -H local-addr -P local-port -h remote-addr -p remote-port -s Quant au récepteur, sa commande est : sctp_test -H local-addr -P local-port –l

Page 33: P2A_Ounis Lotfi

Figure 22

III.2. L’interface de programmationIII.2.1. Présentation La bibliothèque sctplib(Munich, Allemagne) et de la l'Université d'Essen(Allemagne) Elle a été développée ende mise en œuvre du protocole SCTP. La bibliothèque de fonctions 10 de la RFC 2960, et la plupart des paramètres des fonctions sont autoprogrammeur. En plus de l'interface des fonctions entre un protocole de couche supérieure (ULP) et le SCTP, la bibliothèque offre également un peut être utilisé pour gérer l’appel de fonction pour les faire exécuter à un certain point du temps ou ouvre et lier les sockets SCTPutilisé pour un système de comutilisées par la simple liaison statique de la bibliothèque libsctp avec l’applicationlsctp libsctp lors du édition du lien)Il existe deux types d’interface de programmation dans SCTP :• UDP-style : ce style est similaire au style sans connexion de UDP. Il offre l’accès à

les options spécifiques de SCTP.

• TCP-style : ce style offre une sémantique de type mode connecté de TCP. Il ne donne pas l’accès à toutes les options spécifiques de SCTP. Il est proposé pour faciliter le portage d’applications utilisant TCP à SCTP. Dans le cas le plus simple, cela se traduit par une seule modification du type de socket dans le code d’une application.

Toutes les fonctions et leurs options dans les deux interfaces de programmation sontcompatibles avec l’interface de programmation classique des sockets, sauf pour les optionsspécifiques à SCTP.

- 33 -

22 : Analyse de trafic SCTP avec wireshark

’interface de programmationPrésentation

La bibliothèque sctplib-1,0 [10] est le fruit d'une coopération entre Siemens AG et de la Computer Networking Technology Group de l

(Allemagne). e en 1999 et a été conçue pour devenir un prototype assez complet

en œuvre du protocole SCTP. La bibliothèque de fonctions a été inspirée de l'article 10 de la RFC 2960, et la plupart des paramètres des fonctions sont autoprogrammeur. En plus de l'interface des fonctions entre un protocole de couche supérieure (ULP) et le SCTP, la bibliothèque offre également un certain nombre de fonctions d'aide qui peut être utilisé pour gérer l’appel de fonction pour les faire exécuter à un certain point du

vre et lier les sockets SCTP par un port configurable qui peut être ensuite être utilisé pour un système de communication asynchrone. Toutes ces fonctions peuvent être utilisées par la simple liaison statique de la bibliothèque libsctp avec l’applicationlsctp libsctp lors du édition du lien), et y inclure le fichier « sctp.h ».

terface de programmation dans SCTP : : ce style est similaire au style sans connexion de UDP. Il offre l’accès à

cifiques de SCTP.

: ce style offre une sémantique de type mode connecté de TCP. Il ne donne pas ès à toutes les options spécifiques de SCTP. Il est proposé pour faciliter le portage

d’applications utilisant TCP à SCTP. Dans le cas le plus simple, cela se traduit par une seule modification du type de socket dans le code d’une application.

onctions et leurs options dans les deux interfaces de programmation sontcompatibles avec l’interface de programmation classique des sockets, sauf pour les options

’interface de programmation

est le fruit d'une coopération entre Siemens AG Computer Networking Technology Group de l'IEM de

1999 et a été conçue pour devenir un prototype assez complet été inspirée de l'article

10 de la RFC 2960, et la plupart des paramètres des fonctions sont auto-explicatif au programmeur. En plus de l'interface des fonctions entre un protocole de couche supérieure

certain nombre de fonctions d'aide qui peut être utilisé pour gérer l’appel de fonction pour les faire exécuter à un certain point du

par un port configurable qui peut être ensuite être munication asynchrone. Toutes ces fonctions peuvent être

utilisées par la simple liaison statique de la bibliothèque libsctp avec l’application ( option –

: ce style est similaire au style sans connexion de UDP. Il offre l’accès à toutes

: ce style offre une sémantique de type mode connecté de TCP. Il ne donne pas ès à toutes les options spécifiques de SCTP. Il est proposé pour faciliter le portage

d’applications utilisant TCP à SCTP. Dans le cas le plus simple, cela se traduit par une

onctions et leurs options dans les deux interfaces de programmation sont compatibles avec l’interface de programmation classique des sockets, sauf pour les options

Page 34: P2A_Ounis Lotfi

- 34 -

Pour décider quel style de l'interface à utiliser, l'application doit tenir compte de plusieurs facteurs :

• Quel type de serveur est en cours de rédaction, itératif (sans connexion) ou concurrent (avec connexion)?

• Combien de sockets souhaitez que le serveur gérer? • Combien des états de connexion que l'application souhaite maintenir?

Lorsque l’API de SCTP est en cours de développement, une terminologie différente a été utilisée pour les deux types de sockets, et les lecteurs doivent parfois rencontrer ces vieux termes dans la documentation ou le code source. Le terme initial de socket one-to-one est « TCP-style », et le terme initial de socket one-to-many est « DP-style ». Ces termes de style sont abandonnés, car ils ont tendance à causer de la confusion en créant des attentes où SCTP ne se comportent plus comme TCP ou UDP. La terminologie actuelle («one-to-one » et « one-to-many ») attire notre attention sur la différence essentielle entre les deux styles de socket. Enfin, notons que certains auteurs utilisent le terme «many-to-one » au lieu de « one-to-many», les termes sont interchangeables.

III.2.2. Le style one-to-one:

Un utilisateur typique de style one-to-one suivre la chronologie représentée dans la figure 23. Lorsque le serveur est lancé, il ouvre un socket, se lie à une adresse, et attend une connexion client à accepter l'appel système. Quelque temps plus tard, le client est lancé, il ouvre un socket, et lance une association avec le serveur. Nous supposons que le client envoie une requête au serveur, le serveur traite la demande, puis il renvoie une réponse au client. Ce cycle continue jusqu'à ce que le client initie un arrêt de l'association. Cette action ferme l'association.

Page 35: P2A_Ounis Lotfi

- 35 -

Figure 23 : les fonctions d’une association SCTP one-to-one La primitive qui crée un socket SCTP de style one-to-one est la suivante :

III.2.3. Le style one-to-many: Le style one-to-many permet au programmeur d’écrire un serveur sans besoin de créer un grand nombre de descripteurs de socket. Un descripteur représentera plusieurs associations, de la même manière qu'un socket UDP peut recevoir des messages provenant de plusieurs clients. Un identifiant d’association est utilisé pour identifier une association unique d'un socket de type one-to-many. Cet identifiant est une valeur de type sctp_assoc_t, il est un entier.

Les utilisateurs de ce style doit prendre les points suivants en considération :

#include <sys/socket.h>

int socket (int AF_INET, int SOCK_SREAM, int IPPROTO_SCTP) ;

Retourne: descripteur non nul si OK, -1 si erreur.

Page 36: P2A_Ounis Lotfi

- 36 -

• Lorsque le client ferme l'association, le serveur se ferme automatiquement, éliminant ainsi tout état de l'association à l'intérieur du noyau.

• Tout usage de primitives sendto, sendmsg, sctp_sendmsg à une adresse, pour une association qui n'existe pas encore, provoque une ouverture à la tentative, ce qui crée (en cas de succès), une nouvelle association avec cette adresse.

• L'utilisateur doit utiliser les fonctions : sendto, sendmsg, ou sctp_sendmsg, et ne pas utiliser les fonctions send ou write (des primitives propres à chaque style).

• Les événements d’une association doivent être activés, et si une application ne souhaite pas recevoir ces événements, il convient de les désactiver explicitement à l'aide des options de sctp_events. Par défaut, le seul événement activé est le sctp_data_io_event, qui fournit des données auxiliaires de la recvmsg et sctp_recvmsg. Ce paramètre par défaut s'applique à la fois pour le style one-to-one et le one-to-many.

Le montage de ce style est décrit dans la figure 24. Tout d'abord, le serveur est démarré, crée un socket, se lie à une adresse, afin de permettre d'écouter les appels des clients des associations, et appelle sctp_recvmsg, qui bloque toutes les opérations en attente du premier message. Le client ouvre un socket et demande sctp_sendto, qui établit implicitement l'association et greffe une demande de données au serveur sur le troisième paquet d’initiation. Le serveur reçoit la demande et renvoie une réponse. Le client reçoit la réponse et ferme le socket, donc la fermeture de l'association.

Figure 24 : les fonctions d’une association SCTP one-to-one

Page 37: P2A_Ounis Lotfi

Cet exemple montre que des messages de plusieurs associations (c'estclients) peuvent être traités par un seul fil de contrôle. Avec SCTP, un socket onepeut également être utilisé en conjonction avec la fonction serveurs d'être combinés.

La primitive qui crée un socket SCTP

III.3. Manipulation des sockets SCTP Avant d’entamer le développement des applications internet qui utilisent le protocole SCTP comme protocole de transport, nous avons choisiélémentaires, ce qui nous permet de bien manipulede programmation SCTP. Dans ce chapitre, nous avons suivil’application SCTP à coder, en première phase nous avons décidé d’écrire des applications minimalistes qui illustrent l’utilisation de deux (étudiées précédemment), le mode one

� Note : tous les exemples sont

III.3.1. Un simple serveur/client Un serveur de streaming des messages messages de types chaines des caractères.

Figure 25: Client et serveur de streaming des messages SCTP. Nous avons créé deux versions de ce serveur/client

• Une version one-to-one (ou style TCP)La démarche suivie par le serv

#include <sys/socket.h>

int socket (int AF_INET

- 37 -

Cet exemple montre que des messages de plusieurs associations (c'estclients) peuvent être traités par un seul fil de contrôle. Avec SCTP, un socket onepeut également être utilisé en conjonction avec la fonction sctp_peeloff pour permettre

primitive qui crée un socket SCTP de style one-to-many est la suivante :

Manipulation des sockets SCTPd’entamer le développement des applications internet qui utilisent le protocole

de transport, nous avons choisi de débuter par des applications élémentaires, ce qui nous permet de bien manipuler les fonctions et primitives de

s ce chapitre, nous avons suivi une démarche progressive au niveau de la complexité du l’application SCTP à coder, en première phase nous avons décidé d’écrire des applications minimalistes qui illustrent l’utilisation de deux type de l’interfaces de programmation SCTP (étudiées précédemment), le mode one-to-one et le mode one-to-many.

es exemples sont écrits avec le langage C.

Un simple serveur/client Un serveur de streaming des messages sert à recevoir et à envoyer des simples

messages de types chaines des caractères.

: Client et serveur de streaming des messages SCTP.

Nous avons créé deux versions de ce serveur/client : one (ou style TCP) : par le serveur est la suivante :

#include <sys/socket.h>

AF_INET, int SOCK_SEQPACKET, int IPPROTO_SCTP

Retourne: descripteur non nul

Cet exemple montre que des messages de plusieurs associations (c'est-à-dire, plusieurs clients) peuvent être traités par un seul fil de contrôle. Avec SCTP, un socket one-to-many

pour permettre à des

:

Manipulation des sockets SCTP d’entamer le développement des applications internet qui utilisent le protocole

de débuter par des applications r les fonctions et primitives de l’interface

démarche progressive au niveau de la complexité du l’application SCTP à coder, en première phase nous avons décidé d’écrire des applications

type de l’interfaces de programmation SCTP

sert à recevoir et à envoyer des simples

: Client et serveur de streaming des messages SCTP.

IPPROTO_SCTP) ;

descripteur non nul si OK, -1 si erreur.

Page 38: P2A_Ounis Lotfi

- 38 -

� Créer un socket avec les paramètres suivants : famille=AF_INET, type=SOCK_STREAM, protocole=IPPROTO_SCTP à l’aide du primitive socket ().

� Lier ce socket avec un port bien défini et son adresse en utilisant la primitive sctp_bindx ().

� On se met à l’écoute par la primitive listen (). � A chaque nouvelle demande de connexion, le serveur crée un nouveau socket

(new_fd) avec la primitive accept (). � Si toutes ces instructions se terminent par succès, le serveur entre dans le

boucle de service (écriture, lecture) � Enfin, chaque socket doit se terminer par la primitive close ()

Le client doit suivre cette démarche : � Créer un socket comme celui de serveur � Sans le lier, le client demande une connexion (sctp_connectx ()), en cas

d’absence des erreurs, il entre dans la boucle de lecture/écriture. � Il termine par la fermeture de l’association.

Dans cet exemple, on introduit un mécanisme de notification pour bien suivre les états des associations (la procédure handle_event ()).

• Une version one-to-many (ou style UDP) Dans ce modèle on n’a pas besoin des primitives connect () et accept ().

Le serveur crée le socket (avec les paramètres AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP) le lie et se met a l’écoute des connections des clients puis il entre dans le boucle de service.

� On note ici qu’un seul socket sert à servir tous les clients, d’où le terme one-

to-many.

III.3.2. Un serveur multi-flux : Dans cet exemple nous avons démontré le caractère multi-streaming du protocole SCTP.

C’est un serveur de temps, il envoie le temps pour un client qui se connecte, le temps local sur un flux numéro 0 et le temps globale (GMT) sur un autre flux numéro 1.

Nous avons aussi introdui un mécanisme des informations concernant l’association sous forme de deux structures sctp_sndrcvinfo et sctp_event_subscribe pour mieux exploiter la variété du l’API SCTP.

La figure présente le déroulement des processus entre le client et le serveur.

Page 39: P2A_Ounis Lotfi

Figure 26: diagramme d’état de

III.3.3. Test INIT/COOKIE_ECHO Dans ce test, nous avons démontré la non(qui a été développé et appliqué sur TCP

Lors de l'initialisation d'une connexion TCP entre un messages a lieu. Le principe est celui du threeconnexion normale sans volonté de nuire, se déroule comme suit

- 39 -

: diagramme d’état de l’association entre le client et le serveur

Test INIT/COOKIE_ECHO floodingDans ce test, nous avons démontré la non-validité du concept du TCP SYNé développé et appliqué sur TCP) sur le protocole SCTP.

Lors de l'initialisation d'une connexion TCP entre un client et un serveur, un échange de messages a lieu. Le principe est celui du three-way handshake, qui, dans le cas d'une connexion normale sans volonté de nuire, se déroule comme suit :

le serveur temps.

flooding : validité du concept du TCP SYN-flooding

client et un serveur, un échange de way handshake, qui, dans le cas d'une

Page 40: P2A_Ounis Lotfi

- 40 -

1. le client demande une connexion en envoyant un message SYN (pour synchronize) au serveur

2. Le serveur répond et accepte en envoyant SYN-ACK (synchronize-acknowledgment) vers le client

3. Le client répond à son tour avec un message ACK (acknowledgment). La connexion est alors établie.

Un client malveillant peut supprimer la dernière étape et ne pas répondre avec le ACK. Le serveur attend un certain temps car ce délai pourrait avoir été causé par la latence du réseau. Cette période d'attente par le serveur était d'environ 75 secondes lors des premières attaques SYN.

À ce stade, la connexion est semi-ouverte et consomme un certain nombre de ressources du côté du serveur (mémoire, temps processeur, etc.). En générant suffisamment de connexions de ce type, il est possible de monopoliser les ressources du serveur. Comme le nombre de connexions est la plupart du temps limité, le serveur n'accepte plus de nouveaux clients avec pour résultat un déni de service. Dans certains cas, le serveur peut même planter par manque de ressources.

Figure 27: Schéma du SYN flood

• Contremesure assurée par SCTP

Lors de l’établissement d’une association, l’INIT-ACK chunk transporte un paramètre spécial : un state cookie, plus couramment appelé cookie. Ce paramètre permet aux associations SCTP de s’affranchir des attaques de type SYN attack possibles avec TCP.

Page 41: P2A_Ounis Lotfi

- 41 -

Comme l’utilisateur principal du cookie est l’émetteur du INIT-ACK chunk, la structure de celui-ci peut, en théorie, contenir n’importe quel type d’informations.

Le cookie n’a pas vraiment de structure interne, et doit être retransmis de manière transparente par le récepteur du INIT-ACK chunk, pour qui le cookie n’a aucune signification. Comme l’intention est de déplacer vers le client et le réseau la tâche de sauvegarde des informations d’établissement d’association, il est nécessaire d’avoir une méthode qui valide que celui-ci n’a pas été modifié durant le chemin de retour vers la station émettrice, ceci au moyen d’une signature électronique. Le choix de l’algorithme de hashing pour la signature du cookie est important. En effet, la complexité du calcul de ces algorithmes diffère et pourrait déboucher sur une attaque des ressources CPU.

Environnement du test :

L’environnement du test consiste en en deux pc portable connectés en un LAN via un point d’accès wifi du Sup’Com

Hôte 1 : serveur http (sous TCP puis sous SCTP)

Hôte 2 : client illégitime

Scénario TCP (respectivement STCP):

� L’hôte 1 lance le processus tcp_server (resp. sctp_server) en attendant une connexion (association) de la part du client.

� L’hôte 2 émet une infinité des requêtes SYN (resp. INIT) vers l’hôte 1 en utilisant l’outil netcat (disponible sur Ubuntu 8.04).

� Pour suivre les ressources que les processus utilisent (quantité de RAM, pourcentage de CPU, la durée de ce processus depuis son démarrage) nous avons utiliser la commande « top ».

Page 42: P2A_Ounis Lotfi

Résultats :

Figure 28 : l’analyse de SYN flooding sur un serveur en TCP

Figure 29 : ressources alloué au serveur TCP (tcpS) au moment du flooding

- 42 -

: l’analyse de SYN flooding sur un serveur en TCP

: ressources alloué au serveur TCP (tcpS) au moment du flooding

: l’analyse de SYN flooding sur un serveur en TCP

: ressources alloué au serveur TCP (tcpS) au moment du flooding

Page 43: P2A_Ounis Lotfi

On a remarqué que les ressources allouées lors d’une attaque SYN sur un serveur sous TCP augmentent rapidement, alors que dans le cas du SCTP sauf les ressources initiales restent allouées pour le processus du serveur, c'estpour servir la série des paquets INIT.

III.3.4. HTTP over SCTP Le protocole HTTP (HyperText Transfeutilisés sur le WEB. Typiquement, les clients demandent des documents du serveur web et les affichent à l’utilisateur une fois que les documents ont été cherchés. HTTP est un protocole orienté message, où chaque message est conformeplusieurs fichiers incorporés (gifs/jpgs…) sont transférés en utilisant HTTP, on désire quechaque fichier soit transféré correctement. Cependant, la livraison en séquence de ces fichiers n’est pas exigée. En fait, les fichiers incorporés doivent être affichés au bout du temps le plus court possible. La plupart desplusieurs connexions TCP au niveau dufichiers incorporés sur ces connexions. Celafichiers incorporés qui peuvent être cherchés sur ltemps. Comme nous l’avons, SCTP sépare la notion de transmission decelle d’une association. Ce qui permet d’avoir plusieurs transfert de données sur ces fluxdifférents flux sont partiellement ordonnées au sein d’une association etretard causé par les problèmes de

Figure 30 : Architecture Client/serveur pour

- 43 -

On a remarqué que les ressources allouées lors d’une attaque SYN sur un serveur sous TCP augmentent rapidement, alors que dans le cas du SCTP sauf les ressources initiales restent allouées pour le processus du serveur, c'est-à-dire qu’aucune considérationpour servir la série des paquets INIT.

HTTP over SCTP : Le protocole HTTP (HyperText Transfert Protocol) est l’un des protocoles les plus

WEB. Typiquement, les clients demandent des documents du serveur web et les l’utilisateur une fois que les documents ont été cherchés. HTTP est un protocole

chaque message est conforme aux spécifications RFC1945incorporés (gifs/jpgs…) sont transférés en utilisant HTTP, on désire quetransféré correctement. Cependant, la livraison en séquence de ces fichiers

les fichiers incorporés doivent être affichés au bout du temps le plus court possible. La plupart des utilisateurs web essaye d’atteindre cet objectif en ouvrant plusieurs connexions TCP au niveau du serveur et en divisant les demandes GET pour ces fichiers incorporés sur ces connexions. Cela permet aux navigateurs de rendre autant de fichiers incorporés qui peuvent être cherchés sur les connexions TCP multiples, en même

, SCTP sépare la notion de transmission de fluxcelle d’une association. Ce qui permet d’avoir plusieurs flux au sein d’une association, le

flux est totalement ordonné, alors que les données appartenant à sont partiellement ordonnées au sein d’une association et ceci peut réduire le

retard causé par les problèmes de head-of-line blocking.

Architecture Client/serveur pour le transfert de HTTP sur TCP/SCTP.

On a remarqué que les ressources allouées lors d’une attaque SYN sur un serveur sous TCP augmentent rapidement, alors que dans le cas du SCTP sauf les ressources initiales

considération n’est prise

t Protocol) est l’un des protocoles les plus WEB. Typiquement, les clients demandent des documents du serveur web et les

l’utilisateur une fois que les documents ont été cherchés. HTTP est un protocole aux spécifications RFC1945. Lorsque

incorporés (gifs/jpgs…) sont transférés en utilisant HTTP, on désire que transféré correctement. Cependant, la livraison en séquence de ces fichiers

les fichiers incorporés doivent être affichés au bout du temps le plus indre cet objectif en ouvrant

serveur et en divisant les demandes GET pour ces permet aux navigateurs de rendre autant de

connexions TCP multiples, en même

flux de données de d’une association, le

données appartenant à ceci peut réduire le

le transfert de HTTP sur TCP/SCTP.

Page 44: P2A_Ounis Lotfi

- 44 -

Et pour cela nous avons choisit le serveur web THTTPD 2.25 [13] qui à l’origine tourne sous TCP et de l’adopter pour fonctionner sous SCTP tout en exploitant le caractère multi-streaming. THTTPD est très adapté à la délivrance de contenu statique tel que des pages HTML ou des images. D'ailleurs, de nombreux site utilisent Apache pour les pages dynamiques et THPPTD pour les images ou les contenus statiques. En effet, les pages dynamiques avec HTTPD ne sont disponibles qu'en CGI, bien qu'il existe la possibilité d'avoir un module PHP pour les versions antérieures (avec un plus ou moins de "bidouillage"). Une des caractéristiques intéressantes de THTTPD est la possibilité de contrôler de manière simple et efficace le partage de la bande passante et son utilisation maximale. Une autre fonctionnalité (controversée) que de nombreuses personnes trouvent tout aussi intéressante, est le contrôle d'accès par référer local, pour éviter par exemple qu'une image de votre cru soit diffusée sur une page distante sans héberger l'image, mais en utilisant celle qui est sur votre machine et consommant ainsi votre bande passante, tout en dénaturant le contexte de diffusion de votre travail. Enfin, la version du THTTPD incorporé SCTP est rigide contre les attaques du type INIT flooding, de plus dans un environnement ou les sites hébergés sont de types multimédias l’effet head-of-line blocking est presque négligeables ce qui est considéré comme un avantages pour ce type d’application internet.

III.4. Conclusion : Après l’exécution de la pile des tests précédents, nous avons arrivé à établir tableau récapitulatif qui illustre une comparaison entre le protocole SCTP et les protocoles usuels TCP et UDP, cette comparaison prend en considération plusieurs critères aide à prendre la décision sur le choix du protocole de transport associés à une application internet quelconque. Tableau 2 : Comparaison entre UDP, TCP et SCTP Protocole UDP TCP

SCTP

Démarrage Aucun établissement de connexion

établissement de connexion sur 3 temps

établissement de connexion sur 4 temps, avec échange de cookie,

Fiabilité Pas d’acquittement de msg �pas d’assurance de livraison

Mécanisme d’acquittement �fiable

Acquittement sélectif�fiable

Ordre de livraison Pas d’ordre Numérotation des msg

Messages ordrés ou non ordrés

Contrôle de congestion

Aucun mécanisme mis en œuvre

Mis en œuvre Mis en œuvre

Procédure de fermeture

Aucune Fermeture spécifié Le mode « half closed » est possible

Fermeture spécifié Le mode « half closed » n’est pas

Page 45: P2A_Ounis Lotfi

- 45 -

possible SYN attack Insensible Une faille de TCP Résolu avec les

cookies Head-of-Line blocking

Insensible Partiellement résolu (plusieurs connexion)

Résolu (les flux non bloquants entre eux)

Multi-homing Pas supporté Pas supporté Supporté

Page 46: P2A_Ounis Lotfi

- 46 -

Conclusion générale: Les nouvelles caractéristiques apportées par ce protocole permettront de faire face aux limitations imposées par les protocoles actuels et de laisser la voie libre aux nouvelles applications temps réel. Le protocole SCTP présente des caractéristiques très intéressantes en tant que moyen de transport pour la signalisation SS7, aussi comme alternative aux protocoles TCP ou UDP dans des applications standards. L’avantage d’un nouveau protocole tel que SCTP est que tous les aspects novateurs ou optionnels des protocoles comme TCP ou UDP ont été pensés dans leur globalité pour n’en retirer que le meilleur afin de définir le SCTP. Le multi-homing et l’augmentation de la sécurité (SYN ATTACK, Cookies) sont des caractéristiques essentielles pour les serveurs, où la fiabilité est très importante. Le concept de streams est, quant à lui, très intéressant pour la création d’applications utilisées quotidiennement, comme par exemple un browser Web, un client FTP ou une application de vidéoconférence. Actuellement, plusieurs connexions sont nécessaires, souvent de types différents (UDP, TCP), ce qui implique l’utilisation de plusieurs ports et des difficultés de gestion du réseau. Prenons l’exemple d’une transmission VoIP : les ports ouverts pour la transmission des données ne sont pas connus à l’avance, ce qui rend difficile la configuration du firewall qui protège le réseau local (LAN), de la part de l’administrateur. De la même manière, lorsqu’une connexion est ouverte vers un serveur FTP, si un des deux points terminaux (le client ou le serveur) se trouve derrière un firewall, le mode passif est nécessaire, car le port utilisé pour la réception des données n’est pas connu à l’avance. Enfin, l’acquittement sélectif est une caractéristique très importante lors de transmissions à longue distance, car il permet une augmentation des performances en évitant la retransmission complète du dernier bloc de données transmis. Comme nous l’ont montré les tests concernant les fonctionnalités et les performances du protocole, même s’il est encore assez jeune, SCTP possède déjà des implémentations libres et fonctionnelles. Le nombre important d’entreprises qui participent au développement de SCTP, et la position de celles-ci sur le marché international de l’informatique et des télécommunications, sont des indices qui portent à croire que SCTP va prendre beaucoup d’importance dans le futur.

Page 47: P2A_Ounis Lotfi

- 47 -

Bibliographie

1. http://www.laissus.fr/cours

2. www.linux-france.org

3. IETF: Stream Control Transmission Protocol, October 2000, RFC2960 et RFC 4960

4. IETF draft: Stream Control Transmission Protocol (SCTP) Dynamic Address

Reconfiguration, February 2003

5. IETF draft: Architecture of Mobile SCTP for IP Mobility Support, June 2003

6. IETF: IP Mobility Support for IPv4, August 2002,RFC3309

7. IETF draft: Stream Control Transmission Protocol (SCTP) Dynamic Address

Reconfiguration, August 2002,

8. IETF: TCP Selective Acknowledgment Options, October 1996, RFC2018

9. UNIX® Network Programming Volume 1, Third Edition: The Sockets Networking API, R.

Stevens

10. Documentation of the SCTP-Implementation (Siemens.de)

11. www.pastel.paristech.org

12. www.ibm.com

13. www.acme.com

14. www.lksctp.sourceforge.net/

15. www.sigtran.ss7box.com

16. Linux : programmation système et réseau 2eme édition, Joëlle Delacroix.

Page 48: P2A_Ounis Lotfi

Annexe A : les blocs SCTP

Format d'en-têtes génériques SCTP

En-tête communs et génériques SCTP

Tableau 1. Les valeurs de champs type dans l’entête générique

Numéro de bloc Nom de bloc

0 Données utiles (DATA)

1 Initialisation (INIT)

2 Accusé-réception d'initialisation (INIT ACK)

3 Accusé-réception sélectif (SACK)

4 Requête de détection de collision (HEARTBEAT)

5 Accusé-réception sur requête de détection de collision (HEARTBEAT ACK)

6 Abandon (ABORT)

7 Fermeture (SHUTDOWN)

8 Accusé-réception de fermeture (SHUTDOWN ACK)

9 Erreur d'opération (ERROR)

10 Témoin d'état (COOKIE ECHO)

- 48 -

: les blocs SCTP

têtes génériques SCTP

tête communs et génériques SCTP

Les valeurs de champs type dans l’entête générique

Nom de bloc

Données utiles (DATA)

Initialisation (INIT)

réception d'initialisation (INIT ACK)

réception sélectif (SACK)

Requête de détection de collision (HEARTBEAT)

réception sur requête de détection de collision (HEARTBEAT

Abandon (ABORT)

Fermeture (SHUTDOWN)

réception de fermeture (SHUTDOWN ACK)

Erreur d'opération (ERROR)

Témoin d'état (COOKIE ECHO)

réception sur requête de détection de collision (HEARTBEAT

Page 49: P2A_Ounis Lotfi

Numéro de bloc Nom de bloc

11 Accusé-réception de témoin (COOKIE ACK)

12 Réservé pour écho de notification de congestion explicite (ECNE)

13 Réservé pour fenêtre de

14 Arrêt complet (SHUTDOWN COMPLETE)

15-62 Réservé pour l'IETF

63 IETF-Blocs d'extension définis

64-126 Réservé pour l'IETF

127 IETF - Blocs d'extension définis

128-190 Réservé pour l'IETF

191 IETF - Blocs d'extension

192-254 Réservé pour l'IETF

255 IETF - Blocs d'extension définis

Bloc SCTP ABORT

Bloc SCTP COOKIE ACK

Bloc SCTP COOKIE ECHO

Bloc SCTP DATA

- 49 -

Nom de bloc

réception de témoin (COOKIE ACK)

Réservé pour écho de notification de congestion explicite (ECNE)

Réservé pour fenêtre de congestion réduite (CWR)

Arrêt complet (SHUTDOWN COMPLETE)

Réservé pour l'IETF

Blocs d'extension définis

Réservé pour l'IETF

Blocs d'extension définis

Réservé pour l'IETF

Blocs d'extension définis

Réservé pour l'IETF

Blocs d'extension définis

Bloc SCTP ABORT

Bloc SCTP COOKIE ACK

Bloc SCTP COOKIE ECHO

Bloc SCTP DATA

Réservé pour écho de notification de congestion explicite (ECNE)

Page 50: P2A_Ounis Lotfi

Bloc SCTP ERROR

Bloc SCTP HEARTBEAT

Bloc SCTP HEARTBEAT ACK

Bloc SCTP INIT

Tableau 2.3. Paramètres variables INIT

Nom du paramètre

- 50 -

Bloc SCTP ERROR

Bloc SCTP HEARTBEAT

Bloc SCTP HEARTBEAT ACK

Paramètres variables INIT

Statuts Valeur type

Page 51: P2A_Ounis Lotfi

Nom du paramètre Adresse IPv4

Adresse IPv6

Protection témoin

Adresse de nom d'hôte

Types d'adresses supportées

Réservé pour possibilité ECN Ci-dessous nous décrivons les trois paramètres les plus communs utilisés dans le bloc INIT.

Bloc SCTP INIT ACK

Tableau 3. Variables des paramètres INIT ACK

Nom de paramètre StatusAdresse IPv4 Optionnel

Adresse IPv6 Optionnel

État Cookie Obligatoire

Paramètre inconnu Optionnel

Conservateur de cookie Optionnel

Nom adresse de l'hôte Optionnel

Reservé pour ECN Optionnel

- 51 -

Statuts Valeur type Optionnelle 5

Optionnelle 6

Optionnelle 9

Optionnelle 11

Optionnelle 12

Optionnelle 32768

dessous nous décrivons les trois paramètres les plus communs utilisés dans le bloc INIT.

Bloc SCTP INIT ACK

Variables des paramètres INIT ACK

Status Type de valeur Optionnel 5

Optionnel 6

Obligatoire 7

Optionnel 8

Optionnel 9

Optionnel 11

Optionnel 32768

dessous nous décrivons les trois paramètres les plus communs utilisés dans le bloc INIT.

Page 52: P2A_Ounis Lotfi

Bloc SCTP SACK

Bloc SCTP SHUTDOWN

Bloc SCTP SHUTDOWN ACK

Bloc SCTP SHUTDOWN COMPLETE

- 52 -

SHUTDOWN

Bloc SCTP SHUTDOWN ACK

Bloc SCTP SHUTDOWN COMPLETE

Page 53: P2A_Ounis Lotfi

- 53 -

Annexe B: les codes sources

B.1 : Serveur one-to-one :

/* serveroo.c : implementation d'un serveur echo sur une association SCTP one-to-one.ce serveur est similaire a celui d'un TCP */ #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <stdlib.h> #include <unistd.h> #include <netinet/sctp.h>//la librairie SCTP #include <sys/uio.h> #include <errno.h> #define BUFLEN 100 int debug=0; static void handle_event(void *buf) { struct sctp_assoc_change *sac; struct sctp_send_failed *ssf; struct sctp_paddr_change *spc; struct sctp_remote_error *sre; union sctp_notification *snp; char addrbuf[INET6_ADDRSTRLEN]; const char *ap; struct sockaddr_in *sin; struct sockaddr_in6 *sin6; snp = buf; switch (snp->sn_header.sn_type) { case SCTP_ASSOC_CHANGE: sac = &snp->sn_assoc_change; printf("^^^ assoc_change: state=%hu, error=%hu, instr=%hu " "outstr=%hu\n", sac->sac_state, sac->sac_error, sac->sac_inbound_streams, sac->sac_outbound_strea ms); break; case SCTP_SEND_FAILED: ssf = &snp->sn_send_failed;

Page 54: P2A_Ounis Lotfi

- 54 -

printf("^^^ sendfailed: len=%hu err=%d\n", ssf->ssf_length, ssf->ssf_error); break; case SCTP_PEER_ADDR_CHANGE: spc = &snp->sn_paddr_change; if (spc->spc_aaddr.ss_family == AF_INET) { sin = (struct sockaddr_in *)&spc->spc_aaddr; ap = inet_ntop(AF_INET, &sin->sin_addr, addrbuf, INET6_ADDRSTRLEN); } else { sin6 = (struct sockaddr_in6 *)&spc->spc_aaddr; ap = inet_ntop(AF_INET6, &sin6->sin6_addr, addrbuf, INET6_ADDRSTRLEN); } printf("^^^ intf_change: %s state=%d, error=%d\n" , ap, spc->spc_state, spc->spc_error); break; case SCTP_REMOTE_ERROR: sre = &snp->sn_remote_error; printf("^^^ remote_error: err=%hu len=%hu\n", ntohs(sre->sre_error), ntohs(sre->sre_length)); break; case SCTP_SHUTDOWN_EVENT: printf("^^^ shutdown event\n"); break; default: printf("unknown type: %hu\n", snp->sn_header.sn_type); break; } } /** * * * * * * la fonction main() * * * * * * **/ /************************************************/ int main(int argc, char **argv) { int fd, new_fd, sz, len, msg_flags; int idleTime = 20; struct sockaddr_in sin[1], cli_addr;/* l'addresse serveur et l'addresse client*/ struct sctp_event_subscribe event; char readbuf[BUFLEN]; struct sctp_sndrcvinfo sri; fd_set fdset; /* controle des arguments de serveur (le numero du port)*/

Page 55: P2A_Ounis Lotfi

- 55 -

if (argc < 2) /*argc=1 si la commande est sans arg uments */ { printf ("\nUsage: <%s> <num_port>\n\n", argv[0]); return -1;/* SORTIE */ } /* Creation de la socket d'ecoute */ if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_SCT P)) == -1) { perror("socket"); exit(1); } /* */ sin->sin_family = AF_INET; sin->sin_port = htons(atoi(argv[1])); sin->sin_addr.s_addr = INADDR_ANY;/* @ du machine locale*/ if (bind(fd, (struct sockaddr *)sin, sizeof (*sin) ) == -1) /*on peut utiliser sctp_bindx()*/ { perror("bind"); exit(1); } /* Permet a une seule ass. d'etre accepté (one-to- one) */ if (listen(fd, 1) < 0) { perror("listen"); exit(1); } /* Preparation du zone mem pour sri*/ memset (&sri, 0, sizeof(sri)); printf ("[one-to-one]: Serveur demarre...Attendant des associations ...\n"); FD_ZERO(&fdset);/* Inisialisation du l'ensemble fd set*/ FD_SET(fd, &fdset);/* Ajout de fd au fdset */ /* Le boucle du serveur (l'attente) */ while(1) { /* int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeo ut); */ if (select (fd+1, &fdset, 0, 0, 0) <= 0) continue; /* Acceptation d'une association */ new_fd = accept (fd, (struct sockaddr *) &cli_add r, (socklen_t *) &len); if (new_fd >=0 ) printf ("\n Connection provenant de : %s\n", inet_ntoa(cli_addr.sin_addr));

Page 56: P2A_Ounis Lotfi

- 56 -

/* Configuration des params du socket du connexio n (new_fd) */ memset (&event, 0, sizeof(event)); if (setsockopt(new_fd, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(event)) != 0) { perror("setevent failed"); exit(1); } while (1) { /* Imprimer sur serveur tous données */ memset (readbuf, 0, sizeof(readbuf)); len = sizeof (struct sockaddr_in); #if 0 sz = recv(new_fd, readbuf, sizeof(readbuf), 0); if (debug) printf ("recv:[%d,e:%d]: ", sz, errno); #endif sz = sctp_recvmsg (new_fd, readbuf, sizeof(readbuf), 0, 0, &sri, 0); if (debug) printf ("sctp_recvmsg:[%d,e:%d,fl:%X]: ", sz, errno, msg_f lags); if (sz <= 0) break; printf ("msg: %s sur flux : %d\n", readbuf, sri.sinfo_stream); sz = sctp_sendmsg (new_fd, readbuf, sz, 0, len, 0, 0, sri.sinfo_stream, 0, 0); if (debug) printf ("sctp_sendmsg:[%d,e:%d]\n", sz, errno); } close(new_fd); } /* unreachable */ close(fd); }

B.2: Client one-to-one:

/* clientoo.c : implementation d'un client echo sur u ne association SCTP one-to-one. ce client est similaire a celui d'un TCP autheurs: OL & TM /dimanche mai 03

Page 57: P2A_Ounis Lotfi

- 57 -

*/ #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <stdlib.h> #include <unistd.h> #include <netinet/sctp.h>//la librairie SCTP #include <sys/uio.h> #include <errno.h> int debug=0; int main(argc, argv) int argc; char **argv; { int sock_fd, sz, len, msg_flags; int idleTime = 2; struct sockaddr_in sin[1], serv_addr; struct sctp_event_subscribe event; char buf[256]; struct sctp_sndrcvinfo sri; if (argc < 3) { printf ("\nUsage: <%s> <ip-serveur> <port> \n\n" , argv[0]); return -1; } serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons (atoi(argv[2])); serv_addr.sin_addr.s_addr = inet_addr(argv[1]); sock_fd = socket (AF_INET, SOCK_STREAM, IPPROTO_SC TP); if (sock_fd == -1) { printf ("\nEchec de Creation du socket \n"); return -1; } if (connect (sock_fd, (struct sockaddr *) &serv_ad dr, sizeof(serv_addr)) < 0) { printf ("\nEchec de Connection au serveur [%s] !! \n\n", inet_ntoa(serv_addr.sin_addr)); return -1; } else { printf ("\nConnecte au [%s]\n", inet_ntoa(serv_addr.sin_addr)); }

Page 58: P2A_Ounis Lotfi

- 58 -

memset (&event, 0, sizeof(event)); if (setsockopt(sock_fd, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(event)) != 0) { perror("Echec de configuration des evenements"); exit(1); } memset (buf, 0, sizeof(buf)); len = sizeof(serv_addr); printf("Pour envoyer un msg taper : [num_flux] vot re msg \n"); printf ("<S>: "); while (fgets(buf, 256, stdin)) { if (buf[0] != '[') { if (!strncmp(buf, "exit", 4)) break; printf ("Erreur, suivez la forme'[num_flux] msg'\n"); continue; } sri.sinfo_stream = strtol(buf+1, NULL, 0); sz = strlen(buf); len = sizeof(serv_addr); sz = sctp_sendmsg (sock_fd, buf, sz, 0, len, 0, 0 , sri.sinfo_stream, 0, 0); if (debug) printf ("sctp_sendmsg:[%d,e:%d]\n", sz , errno); if (sz <= 0) break; sz = sctp_recvmsg (sock_fd, buf, sizeof(buf), 0, 0, &sri, &msg_flags); if (debug) printf ("sctp_recvmsg:[%d,e:%d] ", sz, errno); if (sz <= 0) break; printf ("<-- %s on str %d\n", buf, sri.sinfo_stre am); memset (buf, 0, sizeof(buf)); printf ("<S>: "); } printf ("\nOver !!\n"); close (sock_fd); return 0; }

Page 59: P2A_Ounis Lotfi

- 59 -

B.3: Serveur one-to-many:

#include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <stdlib.h> #include <unistd.h> #include <netinet/sctp.h> #include <sys/uio.h> #include <errno.h> #define BUFLEN 100 int debug=0; static void handle_event(void *buf) { /* les notifications sctp */ struct sctp_assoc_change *sac; struct sctp_send_failed *ssf; struct sctp_paddr_change *spc; struct sctp_remote_error *sre; union sctp_notification *snp; /**/ char addrbuf[INET6_ADDRSTRLEN]; const char *ap; struct sockaddr_in *sin; struct sockaddr_in6 *sin6; snp = buf; switch (snp->sn_header.sn_type) { case SCTP_ASSOC_CHANGE: sac = &snp->sn_assoc_change; printf("NOTIF :assoc_change: etat=%hu, erreur=%hu , flux_in=%hu " "flux_out=%hu\n", sac->sac_state, sac->sac_error, sac->sac_inbound_streams, sac->sac_outbound_strea ms); break; case SCTP_SEND_FAILED: ssf = &snp->sn_send_failed; printf("NOTIF :sendfailed: longeur=%hu erreur=%d\ n", ssf->ssf_length, ssf->ssf_error); break;

Page 60: P2A_Ounis Lotfi

- 60 -

case SCTP_PEER_ADDR_CHANGE: spc = &snp->sn_paddr_change; if (spc->spc_aaddr.ss_family == AF_INET) { sin = (struct sockaddr_in *)&spc->spc_aaddr; ap = inet_ntop(AF_INET, &sin->sin_addr, addrbuf, INET6_ADDRSTRLEN); } else { sin6 = (struct sockaddr_in6 *)&spc->spc_aaddr; ap = inet_ntop(AF_INET6, &sin6->sin6_addr, addrbuf, INET6_ADDRSTRLEN); } printf("NOTIF intf_change: %s etat=%d, erreur=%d\ n", ap, spc->spc_state, spc->spc_error); break; case SCTP_REMOTE_ERROR: sre = &snp->sn_remote_error; printf("NOTIF remote_error: erreur=%hu longeur=%hu\n", ntohs(sre->sre_error), ntohs(sre->sre_length)); break; case SCTP_SHUTDOWN_EVENT: printf("NOTIF shutdown event\n"); break; default: printf("NOTIF unknown type: %hu\n", snp->sn_header.sn_type); break; } } int main(int argc, char **argv) { int fd, sz, len, msg_flags; int idleTime = 20; struct sockaddr_in sin[1], cli_addr; struct sctp_event_subscribe event; char readbuf[100]; struct sctp_sndrcvinfo sri; if (argc < 2) { printf ("\nUsage: <%s> <port>\n\n", argv[0]); return -1; } if ((fd = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_ SCTP)) == -1) {

Page 61: P2A_Ounis Lotfi

- 61 -

perror("socket"); exit(1); } sin->sin_family = AF_INET; sin->sin_port = htons(atoi(argv[1])); sin->sin_addr.s_addr = INADDR_ANY; if (bind(fd, (struct sockaddr *)sin, sizeof (*sin) ) == -1) { perror("bind"); exit(1); } #if 0 memset (&event, 0, sizeof(event)); #else event.sctp_data_io_event = 1; event.sctp_association_event = 1; event.sctp_address_event = 1; event.sctp_send_failure_event = 1; event.sctp_peer_error_event = 1; event.sctp_shutdown_event = 1; event.sctp_partial_delivery_event = 1; #endif if (setsockopt(fd, IPPROTO_SCTP, SCTP_EVENTS, &eve nt, sizeof(event)) != 0) { perror("setevent failed"); exit(1); } /* Configurer l'assoc a se fermer dans un delain d e 20 sec */ if (setsockopt(fd, IPPROTO_SCTP, SCTP_AUTOCLOSE, &idleTime, 4) < 0) { perror("setsockopt SCTP_AUTOCLOSE"); exit(1); } /* le Serveur se mets a l'ecoute (one-to-many) */ if (listen(fd, 1) < 0) { perror("listen"); exit(1); } memset (&sri, 0, sizeof(sri)); printf ("Serveur <one-to-many>: Demmarge terminé.. .attente des associations ...\n"); /* boucle serveur */ while(1) {

Page 62: P2A_Ounis Lotfi

- 62 -

memset (readbuf, 0, sizeof(readbuf)); len = sizeof (struct sockaddr_in); sz = sctp_recvmsg (fd, readbuf, sizeof(readbuf), &cli_addr, &len, &sri, &msg_flags); if (debug) printf ("sctp_recvmsg:[%d,e:%d,fl:%X]: ", sz, errno, msg_flags); if (sz <= 0) break; if (msg_flags & MSG_NOTIFICATION) { handle_event(readbuf); continue; } printf (">>>msg %s sur flux: %d\n", readbuf, sri.sinfo_stream); sz = sctp_sendmsg (fd, readbuf, sz, &cli_addr, le n, sri.sinfo_ppid, sri.sinfo_flags, sri.sinfo_stream, 0, 0); if (debug) printf ("sctp_sendmsg:[%d,e:%d]\n", sz, errno); } close(fd); }

B.4: Client one-to-many:

#include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <stdlib.h> #include <unistd.h> #include <netinet/sctp.h> #include <sys/uio.h> #include <errno.h> int debug=0; int main(argc, argv) int argc; char **argv; { int sock_fd, sz, len, msg_flags; int idleTime = 2; struct sockaddr_in sin[1], serv_addr; struct sctp_event_subscribe event; char buf[256]; struct sctp_sndrcvinfo sri;

Page 63: P2A_Ounis Lotfi

- 63 -

if (argc < 3) { printf ("\nUsage: <%s> <ip_serveur> <port> \n\n", argv[0]); return -1; } serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons (atoi(argv[2])); serv_addr.sin_addr.s_addr = inet_addr(argv[1]); sock_fd = socket (AF_INET, SOCK_SEQPACKET, IPPROTO _SCTP); if (sock_fd == -1) { printf ("\nImpossible de creer le socket \n"); return -1; } if (connect (sock_fd, (struct sockaddr *) &serv_ad dr, sizeof(serv_addr)) < 0) { printf ("\nTmpossible de se connecter au serveur [%s] !! \n\n", inet_ntoa(serv_addr.sin_addr)); return -1; } else { printf ("\nConnecté au [%s]\n", inet_ntoa(serv_addr.sin_addr)); } memset (&event, 0, sizeof(event)); if (setsockopt(sock_fd, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(event)) != 0) { perror("setevent failed"); exit(1); } memset (buf, 0, sizeof(buf)); len = sizeof(serv_addr); printf ("<S>: "); while (fgets(buf, 256, stdin)) { if (buf[0] != '[') { if (!strncmp(buf, "exit", 4)) break; printf ("Erreur, Respectez la forme '[num_flux]msg'\n<msg>:"); continue; } sri.sinfo_stream = strtol(buf+1, NULL, 0); sz = strlen(buf); len = sizeof(serv_addr);

Page 64: P2A_Ounis Lotfi

- 64 -

sz = sctp_sendmsg (sock_fd, buf, sz, &serv_addr, len, 0, 0, sri.sinfo_stream, 0, 0); if (debug) printf ("sctp_sendmsg:[%d,e:%d]\n", sz , errno); sz = sctp_recvmsg (sock_fd, buf, sizeof(buf), &serv_addr, &len, &sri, &msg_flags); if (debug) printf ("sctp_recvmsg:[%d,e:%d] ", sz, errno); if (sz <= 0) break; printf ("<-- %s on str %d\n", buf, sri.sinfo_stre am); memset (buf, 0, sizeof(buf)); printf ("<msg>: "); } printf ("\nOver !!\n"); close (sock_fd); return 0; }

B.5: Serveur temps mlti-flux:

/* * sctpsrvr.c * * un serveur SCTP multi-flux. * * */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <time.h> #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <netinet/sctp.h> #include "common.h" int main() { int listenSock, connSock, ret; struct sockaddr_in servaddr; struct sctp_initmsg initmsg;

Page 65: P2A_Ounis Lotfi

- 65 -

char buffer[MAX_BUFFER+1]; time_t currentTime; /* Creation du socket SCTP (style one-to-one) */ listenSock = socket( AF_INET, SOCK_STREAM, IPPROT O_SCTP ); /* Configuration du l'adresse */ bzero( (void *)&servaddr, sizeof(servaddr) ); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl( INADDR_ANY ); servaddr.sin_port = htons(PORT); ret = sctp_bindx( listenSock, (struct sockaddr *) &servaddr, 1, SCTP_BINDX_ADD_ADDR); /* Chaque association contient au maximum 5 flux (streams) */ memset( &initmsg, 0, sizeof(initmsg) ); initmsg.sinit_num_ostreams = 5; initmsg.sinit_max_instreams = 5; initmsg.sinit_max_attempts = 4; ret = setsockopt( listenSock, IPPROTO_SCTP, SCTP_ INITMSG, &initmsg, sizeof(initmsg) ); /* Ecoute avec un FA de taille 5 */ listen( listenSock, 5 ); /* Boucle du Serveur */ while( 1 ) { printf("Serveur demmaré...Addresse : %s \n", inet_ntoa(servaddr.sin_addr.s_addr)); /* un client a connecté */ connSock = accept( listenSock, (struct sockaddr *)NULL, (int *)NULL ); /* la variable temps */ currentTime = time(NULL); /* Envoyer temps locale sur stream 0 (local tim e stream) */ snprintf( buffer, MAX_BUFFER, "%s\n", ctime(&cu rrentTime) ); ret = sctp_sendmsg( connSock, (void *)buffer, (size_t)strlen(buffer), NULL, 0, 0, 0, LOCALTIME_S TREAM, 0, 0 ); /* Envoyer temps locale sur stream 1 (GMT strea m) */

Page 66: P2A_Ounis Lotfi

- 66 -

snprintf( buffer, MAX_BUFFER, "%s\n", asctime( gmtime( &currentTime ) ) ); ret = sctp_sendmsg( connSock, (void *)buffer, (size_t)strlen(buffer), NULL, 0, 0, 0, GMT_STREAM, 0, 0 ); /* Fermer la connection avec le client */ close( connSock ); } return 0; }

B.6: Client temps multi-flux

/* * sctpclnt.c * * client SCTP multiflux. * */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <netinet/sctp.h> #include <arpa/inet.h> #include "common.h" int main(argc, argv) int argc; char **argv; { int connSock, in, i, ret, flags; struct sockaddr_in servaddr; struct sctp_status status; struct sctp_sndrcvinfo sndrcvinfo; struct sctp_event_subscribe events; struct sctp_initmsg initmsg; char buffer[MAX_BUFFER+1];

Page 67: P2A_Ounis Lotfi

- 67 -

/* Creation Socket SCTP (one-to-one style) */ connSock = socket( AF_INET, SOCK_STREAM, IPPROTO_ SCTP ); /* Chaque association contient au maximum 5 flux (streams) */ memset( &initmsg, 0, sizeof(initmsg) ); initmsg.sinit_num_ostreams = 5; initmsg.sinit_max_instreams = 5; initmsg.sinit_max_attempts = 4; ret = setsockopt( connSock, IPPROTO_SCTP, SCTP_IN ITMSG, &initmsg, sizeof(initmsg) ); /* Specify the peer endpoint to which we'll conne ct */ bzero( (void *)&servaddr, sizeof(servaddr) ); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(PORT); servaddr.sin_addr.s_addr = inet_addr( argv[1] ); /* Se connecter au serveur */ ret = connect( connSock, (struct sockaddr *)&serv addr, sizeof(servaddr) ); printf("%s\n",argv[1]); /* Association avec echange des notifications et de s evenements */ memset( (void *)&events, 0, sizeof(events) ); events.sctp_data_io_event = 1; ret = setsockopt( connSock, SOL_SCTP, SCTP_EVENTS , (const void *)&events, sizeof( events) ); in = sizeof(status); ret = getsockopt( connSock, SOL_SCTP, SCTP_STATUS , (void *)&status, (socklen_t *) &in ); printf("assoc id = %d\n", status.sstat_assoc_id ); printf("state = %d\n", status.sstat_state ); printf("instrms = %d\n", status.sstat_instrms ) ; printf("outstrms = %d\n", status.sstat_outstrms ); /* Client recoit seulement un msg */ for (i = 0 ; i < 2 ; i++) { in = sctp_recvmsg( connSock, (void *)buffer, sizeof(buffer), (struct sockaddr *)NULL, 0, &sndrcvinfo, &flags ); if (in > 0) { buffer[in] = 0; if (sndrcvinfo.sinfo_stream == LOCALTIME_STRE AM) {

Page 68: P2A_Ounis Lotfi

- 68 -

printf("(Local) %s\n", buffer); } else if (sndrcvinfo.sinfo_stream == GMT_STR EAM) { printf("(GMT ) %s\n", buffer); } } } /* Close our socket and exit */ close(connSock); return 0; } B.7: thttpd 2.5 over SCTP

/* Create socket. */ listen_fd = socket( saP->sa.sa_family, SOCK_STR EAM, IPPROTO_SCTP );//creation du socket SCTP if ( listen_fd < 0 ) { syslog( LOG_CRIT, "socket %.80s - %m", httpd_ntoa( saP ) ); return -1; } (void) fcntl( listen_fd, F_SETFD, 1 ); /* Allow reuse of local addresses. */ on = 1; if ( setsockopt( listen_fd, SOL_SOCKET, SO_REUSEADDR, (char*) &on, sizeof(on) ) < 0 ) syslog( LOG_CRIT, "setsockopt SO_REUSEADDR - %m" ) ; /* Bind to it. */ if ( bind( listen_fd, &saP->sa, sockaddr_len( s aP ) ) < 0 ) { syslog( LOG_CRIT, "bind %.80s - %m", httpd_ntoa( saP ) ); (void) close( listen_fd ); return -1; } /* Set the listen file descriptor to no-delay / non-blocking mode. */ flags = fcntl( listen_fd, F_GETFL, 0 ); if ( flags == -1 ) { syslog( LOG_CRIT, "fcntl F_GETFL - %m" ); (void) close( listen_fd );

Page 69: P2A_Ounis Lotfi

- 69 -

return -1; } if ( fcntl( listen_fd, F_SETFL, flags | O_NDELA Y ) < 0 ) { syslog( LOG_CRIT, "fcntl O_NDELAY - %m" ); (void) close( listen_fd ); return -1; } /* Start a listen going. */ if ( listen( listen_fd, LISTEN_BACKLOG ) < 0 ) { syslog( LOG_CRIT, "listen - %m" ); (void) close( listen_fd ); return -1; } /* Use accept filtering, if available. */ #ifdef SO_ACCEPTFILTER { #if ( __FreeBSD_version >= 411000 ) #define ACCEPT_FILTER_NAME "httpready" #else #define ACCEPT_FILTER_NAME "dataready" #endif struct accept_filter_arg af; (void) bzero( &af, sizeof(af) ); (void) strcpy( af.af_name, ACCEPT_FILTER_NAME ) ; (void) setsockopt( listen_fd, SOL_SOCKET, SO_ACCEPTFILTER, (char*) &a f, sizeof(af) ); } #endif /* SO_ACCEPTFILTER */ return listen_fd; }

B.8 : Client http over SCTP

#include <stdio.h> #include <sys/socket.h> #include <arpa/inet.h> #include <stdlib.h> #include <netdb.h> #include <string.h> #include <netinet/sctp.h> int create_sctp_socket(); char *get_ip(char *host);

Page 70: P2A_Ounis Lotfi

- 70 -

char *build_get_query(char *host, char *page); void usage(); #define HOST "coding.debuntu.org" #define PAGE "/" #define PORT 8080 #define USERAGENT "HTMLGET 1.0" int main(int argc, char **argv) { struct sockaddr_in *remote; int sock; int tmpres; char *ip; char *get; char buf[BUFSIZ+1]; char *host; char *page; if(argc == 1){ usage(); exit(2); } host = argv[1]; if(argc > 2){ page = argv[2]; }else{ page = PAGE; } sock = create_sctp_socket(); ip = get_ip(host); fprintf(stderr, "IP is %s\n", ip); remote = (struct sockaddr_in *)malloc(sizeof(stru ct sockaddr_in *)); remote->sin_family = AF_INET; tmpres = inet_pton(AF_INET, ip, (void *)(&(remote ->sin_addr.s_addr))); if( tmpres < 0) { perror("Can't set remote->sin_addr.s_addr"); exit(1); }else if(tmpres == 0) { fprintf(stderr, "%s is not a valid IP address\n ", ip); exit(1); } remote->sin_port = htons(PORT); if(connect(sock, (struct sockaddr *)remote, sizeo f(struct sockaddr)) < 0){ perror("Could not connect");

Page 71: P2A_Ounis Lotfi

- 71 -

exit(1); } get = build_get_query(host, page); fprintf(stderr, "Query is:\n<<START>>\n%s<<END>>\ n", get); //Send the query to the server int sent = 0; while(sent < strlen(get)) { tmpres = send(sock, get+sent, strlen(get)-sent, 0); if(tmpres == -1){ perror("Can't send query"); exit(1); } sent += tmpres; } //now it is time to receive the page memset(buf, 0, sizeof(buf)); int htmlstart = 0; char * htmlcontent; while((tmpres = recv(sock, buf, BUFSIZ, 0)) > 0){ if(htmlstart == 0) { /* Under certain conditions this will not wor k. * If the \r\n\r\n part is splitted into two m essages * it will fail to detect the beginning of HTM L content */ htmlcontent = strstr(buf, "\r\n\r\n"); if(htmlcontent != NULL){ htmlstart = 1; htmlcontent += 4; } }else{ htmlcontent = buf; } if(htmlstart){ fprintf(stdout, htmlcontent); } memset(buf, 0, tmpres); } if(tmpres < 0) { perror("Error receiving data"); } free(get); free(remote); free(ip); close(sock); return 0; }

Page 72: P2A_Ounis Lotfi

- 72 -

void usage() { fprintf(stderr, "USAGE: htmlget host [page]\n\ \thost: the website hostname. ex: coding.debuntu.or g\n\ \tpage: the page to retrieve. ex: index.html, defau lt: /\n"); } int create_sctp_socket() { int sock; if((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_S CTP)) < 0){ perror("Can't create SCTP socket"); exit(1); } return sock; printf("ouniscape create connection socket with success\n"); } char *get_ip(char *host) { struct hostent *hent; int iplen = 15; //XXX.XXX.XXX.XXX char *ip = (char *)malloc(iplen+1); memset(ip, 0, iplen+1); if((hent = gethostbyname(host)) == NULL) { herror("Can't get IP"); exit(1); } if(inet_ntop(AF_INET, (void *)hent->h_addr_list[0 ], ip, iplen) == NULL) { perror("Can't resolve host"); exit(1); } return ip; } char *build_get_query(char *host, char *page) { char *query; char *getpage = page; char *tpl = "GET /%s HTTP/1.0\r\nHost: %s\r\nUser -Agent: %s\r\n\r\n"; if(getpage[0] == '/'){ getpage = getpage + 1;

Page 73: P2A_Ounis Lotfi

- 73 -

fprintf(stderr,"Removing leading \"/\", convert ing %s to %s\n", page, getpage); } // -5 is to consider the %s %s %s in tpl and the ending \0 query = (char *)malloc(strlen(host)+strlen(getpage)+strlen(USERAG ENT)+strlen(tpl)-5); sprintf(query, tpl, getpage, host, USERAGENT); return query; }

B.9: Codes de SYN flooding

#floodtcp.sh #attaque SYN sur un serveur en TCP while true do nc -z -v 172.16.96.12 4000 done

#floodsctp.sh #attaque SYN sur un serveur en SCTP while true do withsctp nc -z -v 172.16.96.12 4000 done

Annexe C : Les fonctions élémentaires du socket

SCTP

• Fonction sctp_bindx Un serveur de SCTP peut lier un sous-ensemble d'adresses IP associées aux hôtes. Traditionnellement, un serveur TCP ou UDP peut engager une ou toutes les adresses d’un hôte, mais ils ne peuvent pas engager un sous-ensemble d'adresses. La fonction sctp_bindx offre une plus grande souplesse en permettant au socket SCTP de lier un sous-ensemble d'adresses à un hôte. # include <netinet/sctp.h> int sctp_bindx (int sockfd, const struct sockaddr * addrs, addrcnt int, int flags);

Page 74: P2A_Ounis Lotfi

- 74 -

Retour: 0 si OK, -1 en cas d'erreur Le sockfd est un descripteur du socket renvoyé par la fonction socket. Le deuxième argument, addrs, est un pointeur vers une liste d'adresses. Le nombre d'adresses étant passé à sctp_bindx est spécifié par le paramètre addrcnt. Les drapeaux dirigent l’appel de sctp_bindx à l'une des deux mesures dans le tableau 4.

Tableau 1. Les drapeaux utilisés avec la fonction sctp_bindx

L’appel de sctp_bindx peut être introduit sur un socket lié ou non lié. Pour une prise de courant non lié, un appel de sctp_bindx lie la série d'adresses au descripteur. Si sctp_bindx est utilisé sur un socket lié, l'appel peut être utilisé avec SCTP_BINDX_ADD_ADDR pour associer d'autres adresses au descripteur ou avec SCTP_BINDX_REM_ADDR pour supprimer une liste d'adresses associées au descripteur. Si sctp_bindx est effectué sur un socket d'écoute, le changement n'a aucune incidence sur les associations existantes. Les deux drapeaux passés à sctp_bindx sont mutuellement exclusives; si les deux sont donnés, sctp_bindx va échouer, en retournant le code d'erreur EINVAL. Le numéro du port dans tous les sockets doit être le même et il doit correspondre à n'importe quel numéro de port qui est déjà lié, si elle ne le fait pas, alors sctp_bindx va échouer, en retournant le code d'erreur EINVAL.

• Fonction sctp_connectx # include <netinet/sctp.h> int sctp_connectx (int sockfd, const struct sockaddr * addrs, int addrcnt); Retour: 0 pour le succès, -1 en cas d'erreur La fonction sctp_connectx est utilisée pour la connexion à un hôte qui possède plusieurs adresses. Le paramètre addrs est une liste d'adresses. SCTP utilise une ou plusieurs adresses pour l'établissement de l'association. Toutes les adresses figurant dans addrs sont considérées comme valide, des adresses confirmées.

• Fonction sctp_getpaddrs La fonction getpeername n'a pas été conçue avec la notion de multihoming, lors de l'utilisation de SCTP, il ne retourne que la première adresse. Lorsque toutes les adresses sont nécessaires, le sctp_getpaddrs fournit un mécanisme pour l'application pour récupérer toutes les adresses d'un pair.

Page 75: P2A_Ounis Lotfi

- 75 -

# include <netinet/sctp.h> int sctp_getpaddrs (int sockfd, sctp_assoc_t id, struct sockaddr **addrs); Retour: le nombre d'adresses de pairs enregistrées dans addrs, -1 en cas d'erreur Le paramètre sockfd est le descripteur du socket retourné par la fonction socket. L'id est l'identifiant d'une association de style one-to-many. Si le socket utilise le style one-to-one, le champ id est ignoré. addrs est l'adresse d'un pointeur qui est rempli par sctp_getpaddrs. L'appelant doit utiliser sctp_freepaddrs pour libérer des ressources allouées par sctp_getpaddrs lorsqu’ils ne sont plus valables.

• Fonction sctp_freepaddrs

La fonction sctp_freepaddrs libère les ressources allouées par la fonction sctp_getpaddrs. Elle est appelée comme suit: # include <netinet/sctp.h> void sctp_freepaddrs (struct sockaddr * addrs); addrs est le pointeur sur l'ensemble des adresses retournées par sctp_getpaddrs.

• Fonction sctp_getladdrs La fonction sctp_getladdrs peut être utilisée pour récupérer les adresses locales qui font partie d'une association. Cette fonction est souvent nécessaire quand un terminal cherche à savoir exactement quels sont les adresses locales en cours d'utilisation. # include <netinet/sctp.h> int sctp_getladdrs (int sockfd, sctp_assoc_t id, struct sockaddr **addrs); Retour: le nombre d'adresses stockées dans le local addrs, -1 en cas d'erreur

• Fonction sctp_freeladdrs

Cette fonction permet de liberer les ressources allouées par la fonction sctp_getladdrs.

#include <netinet/sctp.h>

void sctp_freeladdrs(struct sockaddr *addrs);

•••• Function sctp_sendmsg

Page 76: P2A_Ounis Lotfi

- 76 -

Le sendmsg peut être utilisé par des applications pour contrôler différentes fonctions du protocole SCTP. L'appel prend la forme suivante: ssize_t sctp_sendmsg (int sockfd, const void * msg, size_t msgsz, const struct sockaddr * to, socklen_t Tolen, PPID uint32_t, uint32_t drapeaux, uint16_t stream, uint32_t timetolive, uint32_t contexte); Retour: le nombre d'octets écrits, -1 en cas d'erreur L'utilisateur du sctp_sendmsg a grandement simplifié la méthode d'envoi mais avec plus d'arguments. Le domaine sockfd contient le descripteur du socket retourné par l'appel-système socket. Le domaine msg pointe vers un tampon d’octets msgsz à envoyer à l'autre pair. Le domaine Tolen contient la longueur de l'adresse stockée dans to. Le domaine PPID détient la charge d'identification du protocole, l’identifiant sera transmis avec les données. Un utilisateur SCTP précise un certain nombre de flux en remplissant le champ stream. L'appelant doit préciser la durée de vie du message en millisecondes dans le domaine de la durée de vie, où 0 représente une durée de vie infinie.

• Fonction sctp_recvmsg Tout comme sctp_sendmsg, la fonction sctp_recvmsg offre aux utilisateurs plus d’options à propos les fonctionnalités avancées de SCTP. Grâce à cette fonction, un utilisateur peut récupérer non seulement l'adresse de ses pairs, mais aussi les domaines msg_flags qui devrait normalement accompagner l’appel de recvmsg (par exemple : MSG_NOTIFICATION, MSG_EOR, etc). La fonction permet également à l'utilisateur de récupérer la structure sctp_sndrcvinfo qui accompagne le message qui a été lue dans le tampon de message. La fonction sctp_recvmsg prend la forme suivante: ssize_t sctp_recvmsg (int sockfd, void * msg, size_t msgsz, struct sockaddr * from, socklen_t * fromlen, struct sctp_sndrcvinfo sinfo *, int * msg_flags); Retour: le nombre d'octets lus, -1 en cas d'erreur Le champ msg est rempli jusqu'à msgsz d’octets de données. L'adresse de l’expéditeur des messages est contenue dans from, la taille de l’adresse se trouve dans l’argument fromlen. Tout message drapeaux sera contenu dans l’argument msg_flags. Si la notification sctp_data_io_event a été activée (par défaut), la structure sctp_sndrcvinfo sera remplie avec des informations détaillées sur le message.

• Fonction sctp_peeloff Il est possible d'extraire une association utilisée dans le style one-to-many et la transformer en une association qui utilise un socket de type one-to-one. La sémantique est un peu comme l'appel de la fonction accept avec un argument supplémentaire. L'appelant passe sockfd du socket one-to-many et l’identifiant de l’association id qui est extrait. À la fin de

Page 77: P2A_Ounis Lotfi

- 77 -

l'appel, un nouveau descripteur du socket est retourné. Ce nouveau descripteur sera de type one-to-one. La fonction prend la forme suivante: int sctp_peeloff (int sockfd, sctp_assoc_t id); Retour: un nouveau descripteur du socket en cas de succès, -1 en cas d'erreur

• Fonction shutdown La fonction shutdown utilisée avec le protocole TCP peut être utilisée avec un point final d’une association SCTP à l'aide du style one-to-one. Parce que la conception de SCTP ne prévoit pas une demi-fermeture d’une association, un point final SCTP réagit à un appel shutdown différemment d'un point de terminaison TCP. Quand un hote SCTP initie une séquence d'arrêt, les deux terminaux doivent remplir toute la transmission de données actuellement dans la file d'attente et fermer l'association. SCTP permet aux hôtes de faire un appel shutdown, et après que shutdown termine, le terminal peut réutiliser le socket pour se connecter à un nouveau pair. Notez que la connexion échoue si le terminal n’attendre pas jusqu'à ce que la séquence d'arrêt SCTP est achevée.

• Les notifications SCTP

L’API SCTP met une série de notifications à la disposition du programmeur. L’utilisateur de SCTP peut suivre l'état de son association par l'intermédiaire de ces notifications. Les alertes communiquent des événements au niveau transport, y compris le changement de statut du réseau, l’association, le démarrage, les erreurs de fonctionnement à distance, et l'expéditeur des messages. Pour les deux styles (one-to-one et le one-to-many), tous les événements sont désactivés par défaut, à l'exception de sctp_data_io_event. Lorsque l’API du SCTP a été développée pour la première fois, l’interface de ce style a accordé à chaque association des notifications activées par défaut .ces notifications peuvent être désactivées. les notifications ont la forme suivante: struct (sctp_tlv u_int16_t sn_type; u_int16_t sn_flags; u_int32_t sn_length; ); / * Événement de notification * / sctp_notification union (

Page 78: P2A_Ounis Lotfi

- 78 -

struct sctp_tlv sn_header; struct sctp_assoc_change sn_assoc_change; struct sctp_paddr_change sn_paddr_change; struct sctp_remote_error sn_remote_error; struct sctp_send_failed sn_send_failed; struct sctp_shutdown_event sn_shutdown_event; struct sctp_adaption_event sn_adaption_event; struct sctp_pdapi_event sn_pdapi_event; );