Date de rendu : 18/07/2011 Promotion : 4PPA SRS Rapport final Mise en place du réseau d'une entreprise de taille moyenne Enseignant : Neveu Mail de l enseignant : nneveu@gmail.com Auteurs : - Yassine Bourzik - Abdou Samoura - Rama Samb - Jessy Patel
Sommaire 1. Architecture générale... 4 2. Configuration réseau... 5 a. Configuration LAN... 5 b. Configuration du Routeur... 5 c. Configuration du commutateur d accès... 6 d. Configuration WLAN... 7 3. Configuration sécurité... 8 a. Configuration sécurité LAN... 8 b. Configuration sécurité WLAN... 8 4. Les services installés... 9 a. Résumé technique du projet :... 9 b. Apache... 9 Définition :... 9 c. DHCP... 9 Définition :... 9 d. DNS... 10 Définition :... 10 e. Firewall... 10 Définition :... 10 f. SAMBA... 10 Définition :... 10 g. SSH... 11 Définition :... 11 5. Le serveur de sauvegarde... 11 Définition :... 11 But :... 12 6. Programme client/serveur de messagerie instantanée en C... 13 2
Position des sockets dans le modèle OSI... 14 a. Partie client :... 15 b. Partie serveur... 17 Annexe 1 : Planning... 21 Annexe 2 : Installation et configuration : Apache... 22 Annexe 3 : Installation et configuration : DHCP... 23 Annexe 4 : Installation et configuration : Serveur DNS (BIND)... 24 Annexe 5 : Installation et configuration : Firewall... 27 Annexe 6 : Installation et configuration : Serveur de fichier SAMBA... 28 Annexe 7 : Installation et configuration : SSH... 29 Annexe 7 : Installation et configuration : Serveur de sauvegarde... 30 Annexe 8 : Source serveur... 31 Annexe 9 : Source client... 33 3
1. Architecture générale Il nous a été demandé de réaliser un réseau local d entreprise de taille moyenne. L architecture du réseau choisie est présentée comme suit : Figure 1 : Architecture réseau Le réseau est composé de : Un routeur Cisco 2801 Un switch Cisco 2960 Un point d accès wifi Cisco Aironet 1130 AG Une machine virtuelle serveur DNS DHCP Une machine virtuelle serveur 4
2. Configuration réseau Toute l architecture repose sur la plateforme Cisco. Ce choix a été fait car l administration de l école a mis à notre disposition du matériel de cette marque, aussi leur configuration nous est le plus familier. En outre les équipements Cisco sont relativement simples à configurer et on dispose d une documentation très détaillée et compréhensible sur le site officiel du constructeur. a. Configuration LAN Le LAN est composé du routeur Cisco 2801, du commutateur d accès Cisco 2960 et de la connectique (câbles réseau). b. Configuration du Routeur Le modèle de routeur choisi est un cisco 2801. Les routeurs à services intégrés Cisco gamme 2800 offrent de nombreuses fonctionnalités, notamment : Sécurité intégrée avec notamment un pare-feu, un système de chiffrement et une protection contre les pirates Connecteur d'alimentation redondante intégré sur la plupart des modèles pour une protection renforcée Intégration avec Cisco Unified Communications Manager Express pour permettre la prise en charge du transfert d'appels pour 96 utilisateurs maximum Intégration avec Cisco Survivable Remote Site Telephony (SRST) pour maintenir les services voix locaux en cas de perte de connexion Fiabilité et flexibilité accrues pour vous permettre de prioriser le trafic voix ou l'échange de données de façon à aligner la distribution des informations sur vos besoins métier Prise en charge des connexions VPN pour établir la connexion avec les partenaires ou bureaux distants Prise en charge d'une couverture LAN sans fil dans tout le bureau avec fonctions de sécurité et accès visiteur avancés, compatibles avec toutes les normes sans fil actuelles (IEEE 802.11a/b/g/n) Grand choix d'options de connectivité réseau et haut débit Options de connexion Ethernet (PoE - Power over Ethernet) pour les périphériques réseau afin de réduire les coûts de câblage Ce type de routeur est très adapté aux petites et moyennes entreprises car pouvant intégrer à la fois plusieurs services ce qui permet de réduire non seulement le nombre d équipements mais aussi le coût des investissements. Dans notre cas on n exploitera pas toutes ses fonctionnalités. L interface fastethernet 0/0 est configurée comme passerelle par défaut du réseau local et a comme adresse 192.168.1.1/24. L interface fastethernet 0/1 est configurée pour l accès à internet et a comme adresse 192.168.0.253/24. Le protocole de routage EIGRP est mis en œuvre pour faire communiquer les deux réseaux entre eux. Le choix de ce protocole est du à sa capacité d adaptation car étant hybride. En outre EIGRP est un protocole de routage propriétaire Cisco avec une optimisation permettant de minimiser 5
l'instabilité de routage due aussi bien au changement de topologie qu'à l'utilisation de la bande passante et la puissance du processeur du routeur. c. Configuration du commutateur d accès Le commutateur d accès comme son nom l indique est configuré pour permettre aux utilisateurs de se connecter au LAN pour ainsi avoir accès aux ressources. On a choisi un commutateur adapté aux petites et moyennes entreprises à savoir le Cisco Catalyst 2960. Les commutateurs Cisco Catalyst gamme 2960 offrent de nombreuses fonctionnalités, notamment : Prise en charge des communications voix, données et sans fil, ce qui vous permet d'installer un seul réseau pour tous vos besoins en communication Fonctionnalité PoE (Power over Ethernet) afin de vous permettre de déployer facilement de nouvelles fonctionnalités (voix et sans fil par exemple) sans avoir à installer de nouveaux câbles Choix des protocoles Fast Ethernet (transfert de données de 100 mégabits par seconde) ou Gigabit Ethernet (transfert de données de 1000 mégabits par seconde), en fonction de vos contraintes budgétaires et de vos besoins en performance Plusieurs configurations de modèles avec possibilité de connecter des ordinateurs de bureau, des serveurs, des téléphones IP, des points d'accès sans fil, des caméras de télévision en circuit fermé ou d'autres périphériques réseau Possibilité de configurer des réseaux locaux virtuels de façon à connecter les employés par fonctions organisationnelles, équipes de projet ou applications et non selon des critères physiques ou géographiques Sécurité intégrée Fonctions de surveillance réseau et meilleure résolution des problèmes de connectivité Mises à jour logicielles sans frais supplémentaire Garantie matérielle à vie limitée Dans cette partie, on ne met pas en œuvre la sécurité d accès. Tous les ports sont mis en mode accès avec un spanning-tree portfast pour permettre un accès rapide au réseau sans attente des différents états des ports dû au spanning tree. Les utilisateurs récupèrent leur configuration réseau à partir du serveur DHCP. 6
Switch >en Switch #configure terminal Switch (config)# interface range fastethernet 1/1 15 Switch (config-if-range)# switchport mode access Switch (config-if-range)# spanning-tree portfast Switch (config-if-range)#no shutdown Switch (config-if-range)# exit Switch (config)#exit Switch #copy running-config startup-config Switch # Figure 2 : Exemple de configuration des interfaces du commutateur d accès d. Configuration WLAN Le réseau sans-fil (WLAN) est constitué d un point d accès Cisco Aironet 1130 AG en mode infrastructure. Le mode infrastructure est un mode de fonctionnement qui permet de connecter les ordinateurs équipés d une carte Wi-Fi entre eux via un ou plusieurs Point d accès (PA) qui agissent comme des concentrateurs (exemple : répéteur ou commutateur en réseau Ethernet). Les points d'accès Cisco Aironet gamme 1130AG offrent de nombreuses fonctionnalités, notamment : Deux radios prennent en charge plusieurs options de réseau sans fil fonctionnant dans les bandes de fréquences 2,4 et 5 GHz pour une plus grande flexibilité, une meilleure couverture et une prise en charge améliorée des périphériques clients. Possibilité d'adapter la couverture même en cas d'obstacles ou d'interférences potentielles Facilité d'installation dans les faux-plafonds Intégration avec les logiciels de gestion et de surveillance sans fil de Cisco Système de fixation à blocage hautement sécurisé avec boîtier en plastique léger Le point d accès est configuré avec l adresse ip 192.168.1.2/24. Le SSID du WLAN est «BPSS» qui n est rien d autre que la première lettre du nom de chaque membre de notre groupe de travail. Le SSID (Service Set Identifier) est le nom d'un réseau sans fil selon la norme IEEE 802.11, il comporte au plus 32 caractères. Le point d accès est configuré d une sorte à ne pas diffuser le SSID pour des raisons de sécurité ainsi les utilisateurs n étant pas à sa connaissance ne pourront pas se connecter, ceci constitue donc une couche faible de sécurité du WLAN. Dans cette partie le réseau sans fil est ouvert, c est-à-dire aucun protocole de sécurisation du réseau n est mis en œuvre. La sécurisation du WLAN est abordée dans la partie sécurité du WLAN. 7
3. Configuration sécurité a. Configuration sécurité LAN L accès au LAN nécessite une authentification sur un serveur radius. RADIUS pour «Remote Authentication Dial-In User Service» est un protocole client-serveur permettant de centraliser des données d'authentification. Pour mettre en œuvre ce protocole on a choisi le serveur FreeRADIUS car Il offre une alternative aux autres serveurs d'entreprise RADIUS, et est un des serveurs RADIUS les plus modulaires et riches en fonctionnalités disponibles aujourd'hui. Il est considéré comme le serveur le plus utilisé dans le monde. Il est relativement complexe à configurer mais demeure gratuit et open source. Il convient autant aux systèmes embarqués avec peu de mémoire qu'aux systèmes avec plusieurs millions d'utilisateurs. Le commutateur d accès est configuré comme un client du serveur radius. En outre, des listes d accès«access lists» ont été définis pour sécuriser l accès à internet et l accès au réseau local de l extérieur. On a aussi définis une liste d accès pour restreindre l accès à certains sites selon les horaires. b. Configuration sécurité WLAN On a choisi d authentifier les utilisateurs sans fils avec le même serveur RADIUS que ceux connectés au réseau filaire. En effet le protocole RADIUS nous permet aussi d authentifier les utilisateurs sans fils. Ainsi on aura une seule base pour authentifier tous les utilisateurs du réseau filaire comme sans fil. Le mode de sécurité choisi pour le WLAN est le WPA-Entreprise qui suppose que tous les clients soient en possession des bons certificats pour l accès au réseau et impose l'utilisation d'une infrastructure d'authentification 802.1x basée sur l'utilisation d'un serveur d'authentification, un serveur RADIUS dans notre cas. Le standard 802.1x est une solution de sécurisation, mise au point par l'ieee en juin 2001, permettant d'authentifier (identifier) un utilisateur souhaitant accéder à un réseau (filaire ou sans-fil) grâce à un serveur d'authentification. Le 802.1x repose sur le protocole EAP (Extensible Authentication Protocol), défini par l'ietf, dont le rôle est de transporter les informations d'identification des utilisateurs. La sécurisation du WLAN se fait en quatre étapes à savoir : La génération des certificats La configuration du serveur Radius (Free-Radius) La configuration du point d accès La configuration des clients 8
4. Les services installés a. Résumé technique du projet : Serveur Adresse Service Description Paris 192.168.1.253 DHCP et DNS Marseille 192.168.1.251 Samba, http et Backup Tokyo 192.168.1.254 Radius Gateway 192.168.1.1 Routage PAW 192.168.1.2 Access Point Nom de domaine : Jary.local Jary est l abréviation des initiaux (Jessy, Abdou, Rama et Yassine) b. Apache Définition : Apache est un fournisseur de services Http. C'est un logiciel libre disponible pour la plupart des systèmes d'exploitation. Il équipe actuellement plus de 60% des serveurs internet mondiaux. (Cf. Annexe 2) c. DHCP Définition : Dynamic Host Configuration Protocol (DHCP) Est un terme anglais désignant un protocole réseau dont le rôle est d assurer la configuration automatique des paramètres IP d une station, notamment en lui affectant automatiquement une adresse IP et un masque de sous-réseau. DHCP peut aussi configurer l adresse de la passerelle par défaut, des serveurs de noms DNS et des serveurs de noms NBNS (connus sous le nom de serveurs WINS sur les réseaux de la société Microsoft). (Cf. Annexe 3) 9
d. DNS Définition : Un nom de domaine (ou NDD en notation abrégée ou DNS en Anglais) est un identifiant unique lié à une entité dont les ordinateurs sont reliés au réseau internet. Le système est hiérarchique, permettant la définition de sous-domaine(s) d'un domaine existant. Ce nom est composé d'au moins un mot, le label. S'il y a plusieurs labels, on doit les séparer par un point. Le suffixe sera choisi dans la liste des entités du plus haut niveau, ou Top Level Domain (TLD). Le mot précédent le suffixe peut être n'importe lequel (à quelques conditions syntaxiques près). Il existe deux types de TLD : 1. les cctld (pour Country Code, code pays, c est-à-dire les domaines nationaux), composés de deux lettres identifiant un pays (fr (France), aq (Antarctique), pl (Pologne), gr (Grèce), de (Allemagne), pm (Saint Pierre et Miquelon), etc.). 2. les TLD génériques, composés de trois lettres ou plus. Les règles de dépôt d'un nom de domaine dans ces TLD ne sont pas les mêmes pour tous. (Cf. Annexe 4) e. Firewall Définition : Le pare-feu est un système permettant de filtrer les paquets de données échangés avec le réseau, il s'agit ainsi d'une passerelle filtrante comportant au minimum les interfaces réseau suivante : une interface pour le réseau à protéger (réseau interne) ; une interface pour le réseau externe. (Cf. Annexe 5) f. SAMBA Définition : Un serveur de fichiers permet de partager des données à travers un réseau. Le terme désigne souvent l'ordinateur (serveur) hébergeant le service applicatif. Il possède généralement une grande quantité d'espace disque où sont déposés des fichiers. Les utilisateurs peuvent ensuite les récupérer au moyen d'un protocole de partage de fichier. On utilise généralement l'un des quatre protocoles suivant: 10
FTP (File Transfer Protocol) CIFS (Common Internet File System) anciennement nommé SMB (Server Message Block) NFS (Network File System) NCP (Netware Core Protocol) (Cf. Annexe 6) g. SSH Définition : SSH permet de garantir : La confidentialité : le cryptage des paquets permet de garantir celle-ci. L'intégrité : ssh permet de garantir que les paquets circulant d'un hôte vers un autre ne sont pas altérés. L'authentification : chaque connexion ssh vérifie l'identité du serveur (par sa clé d'hôte ~/.ssh/known_hosts) puis celle du client (par mot de passe ou clé publique~/.ssh/authorized_keys). L'autorisation : il est possible avec ssh de limiter les actions autorisées à l'utilisateur (~/ssh/.authorization). Tunneling : ssh permet de sécuriser un service dont les informations circulent habituellement en clair (POP,IMAP,VNC,...). D'autres aspects du tuneling sont la sécurisation du protocole X11 (X11forwarding), et l'utilisation de clés privées situées sur un hôte distant (Agent forwarding). (Cf. Annexe 7) 5. Le serveur de sauvegarde Définition : La sauvegarde (backup en anglais) est l'opération qui consiste à dupliquer et à mettre en sécurité les données contenues dans un système informatique. Ce terme est proche de deux notions : l'enregistrement des données, qui est l'opération d'écriture des données sur un item d'enregistrement durable, tel qu'un disque dur, une clé USB, des bandes magnétiques, etc. l'archivage, qui consiste à enregistrer des données sur un support à des fins légales ou historiques. 11
La sauvegarde passe forcément par un enregistrement des données, mais pas nécessairement dans un but d'archivage. But : Mettre en place un script qui permet de sauvegarder les différents fichiers de configurations des services DHCP, DNS, http, RADUIS, chat et Samba, dans un répertoire sur le serveur «marseille:/backup/» 12
6. Programme client/serveur de messagerie instantanée en C Il nous a été demandé dans le cadre de notre projet de programmer un client/serveur en C et notre choix s'est porté sur de la messagerie instantanée (chat). La messagerie instantanée, le dialogue en ligne ou le clavardage (québécisme), également désignée par l anglicisme «chat» («bavardage») francisé en «tchat», permet l échange instantané de messages textuels entre plusieurs ordinateurs connectés au même réseau informatique, et plus communément celui d Internet. Contrairement au courrier électronique, ce moyen de communication est caractérisé par le fait que les messages s affichent en temps quasi-réel et permettent un dialogue interactif. Dans la programmation réseau, pour partager des informations entre deux programmes par le réseau, on distingue 2 entités : le client et le serveur. Le client est le programme qui va envoyer le message, tandis que le serveur est le programme qui va recevoir ces données et les traiter. Il peut arriver qu'un programme fasse office de client et de serveur, par exemple, dans le cas de la messagerie instantanée. Vous pouvez envoyer des informations à votre contact tel un client, mais vous pouvez recevoir des informations de la part du contact tel un serveur, la connexion est donc bidirectionnelle. C'est donc cette infrastructure que nous allons utiliser pour la programmation de notre client/serveur. Nous allons utiliser le protocole IP qui permettra de communiquer entre les applications. Il existe par contre deux autres protocoles de la couche transport, c'est à dire, ceux qui vont permettre aux informations de se transiter sur le réseau et de trouver le chemin vers l'autre application. Nous avons tout d'abord le protocole UDP qui permet un échange simple sans contrôle d'intégrité. Ce protocole n'est pas fiable car une information peut arriver altérée, dupliquée ou ne pas arriver du tout et la couche transport ne le détectera pas et ne renverra pas la donnée. Nous avons, par contre, le protocole TCP (que nous utiliserons) qui va s'assurer que la donnée arrive sans déformation, si une donnée est modifiée, dupliquée ou perdue, la couche transport va s'occuper de la renvoyer convenablement au serveur. Aussi, ces communications entre les programmes sont, en fait, une communication entre divers processus. Ce modèle est appelé "socket" qui permet donc la communication inter processus. Les sockets sont généralement implémentés en langage C, et utilisent des fonctions et des structures disponibles dans la librairie <sys/socket.h>. 13
Position des sockets dans le modèle OSI Les sockets se situent juste au-dessus de la couche transport du modèle OSI (protocoles UDP ou TCP), elle-même utilisant les services de la couche réseau (protocole IP / ARP). Modèle des sockets Modèle OSI Application Application utilisant les sockets Présentation Session UDP/TCP IP/ARP Ethernet, X25,... Transport Réseau Liaison Physique Les sockets ont donc besoin d'un ensemble de primitives assurant le service, de génériques qui s'adaptent aux différents besoins de communication. Ils sont indépendants de protocoles et de réseaux particuliers. Un socket est un point de communication par lequel un processus peut émettre ou recevoir des données. On distingue la création du socket de son initialisation avec les adresses et les numéros de port. Par défaut, c'est toujours le client qui se connectera au serveur et pour ce faire, il aura besoin de l'adresse IP du serveur. Il va également avoir besoin du numéro de port qui est équivalent au code de la maison dans la vie de tous les jours. L'adresse IP va signaler où se trouve le serveur et le port va désigner l'application qui recevra les données, dans notre cas, ce sera notre programme et nous utiliserons le port 6666. Nous allons maintenant passer à la partie pratique. Nous verrons donc ici en quelques mots les principales fonctions permettant d'utiliser les sockets. Nous allons nous occuper de la partie client avant d'attaquer la partie serveur. Le programme que nous avons développé est un petit programme de chat basique. Il permettra à deux programmes (un client et un serveur) de discuter entre eux au en quasi-temps-réel, c'est à dire que le client ne pourra pas envoyer des messages successifs au serveur, ce sera un message chacun l'un après l'autre. 14
a. Partie client : Le client est celui qui demande la connexion alors il utilise le processus appelant le serveur afin d obtenir le service. Il est lancé à la demande à partir de n importe quelle station. Dans un 1er temps, nous avons inclus toutes les bibliothèques utiles à l'utilisation de sockets. #include <sys/socket.h> #include <netinet/in.h> #include <stdio.h> #include <errno.h> #include <stdlib.h> #include <string.h> Grace à ces bibliothèques, nous pourrons utiliser toutes les fonctions. Ensuite, nous allons maintenant introduire le main pour déclarer une variable qui contiendra les messages que le client enverra durant ses échanges avec le serveur. Aussi, nous déclarons une structure de type sockaddr_in qui va permettre de spécifier les informations du serveur, c'est à dire le port de connexion et l'adresse IP sur laquelle il attendra la connexion du client : struct sockaddr_in informations; informations.sin_family = AF_INET; informations.sin_port = htons(6666); informations.sin_addr.s_addr = inet_addr("127.0.0.1"); Nous spécifions donc que nous utiliserons le protocole TCP ou UDP et que nous nous connecterons à l'adresse 127.0.0.1 sur le port 6666. Cette adresse IP est en fait l'adresse locale, donc une adresse qui pointe vers le pc même, autrement dit, le client va essayer de se connecter à un serveur présent sur notre machine. Une fois que nous avons défini cela, nous allons devoir définir une variable entière qui contiendra le point d'entrée de la connexion renvoyé par la fonction socket comme expliqué plus haut : int socketid = socket(af_inet, SOCK_STREAM, 0); if (socketid == -1) { perror("socket"); exit (-1); 15
On passera donc en premier paramètre AF_INET pour spécifier que nous utiliserons le protocole TCP ou UDP et nous précisons en deuxième paramètre que ce sera TCP grâce à la constante SOCK_STREAM. Le dernier paramètre est le protocole particulier, c'est très rare qu'on en utilise, on fixera donc ce paramètre à 0. La fonction renvoie un descripteur de socket si elle réussit, mais elle renvoie -1 dans le cas contraire, nous testons donc si elle a échoué, si c'est le cas, nous affichons un message d'erreur grâce à une fonction spécifique (perror) et nous quittons le programme grâce à la fonction exit. Nous spécifions -1 en paramètre de cette fonction pour signaler que la sortie du programme est anormale, donc qu'elle fait suite à une erreur. Si la création du socket s'est bien passée, nous allons devoir nous connecter au serveur, pour cela, nous allons donc utiliser la fonction connect. Enfin, nous allons implémenter une boucle pour que le client puisse envoyer autant de messages qu'il veut. On arrêtera l'envoi et la réception lorsque le client ou le serveur enverra le mot EXIT. Nous faisons donc le squelette de la boucle : do { while (strcmp(phrase, "EXIT")!= 0); Donc ici, les messages que le client enverra seront stockés dans la variable phrase. Ici, nous faisons donc des opérations tant que la phrase est différente de EXIT (donc tant que strcmp renvoie 0). Dans la boucle, nous demandons à l'utilisateur d'entrer la phrase à envoyer et elle est récupérée grâce à une fonction. Maintenant que nous avons récupéré la phrase, il va falloir l'envoyer, nous utiliserons donc la fonction send pour ce faire. En premier, le descripteur de socket est passé en argument, ensuite la donnée à envoyer, la taille de la donnée puis enfin le dernier argument est fixé à 0 pour ne spécifier aucune modification de l'envoi. 16
Ensuite, nous allons préparer la connexion pour recevoir les données envoyées par le serveur, mais uniquement si l'utilisateur n'a pas tapé EXIT, dans ce cas, nous devrons quitter le programme et fermer les sockets : if (strcmp(phrase, "EXIT")!= 0) { memset(phrase, 0, 255); recv(socketid, phrase, 255, 0); printf ("Phrase reçue : %s\n", phrase); Si la phrase est différente de EXIT, le contenu de la chaine de caractère est vidée. Nous utilisons ensuite une fonction qui va attendre la réception de données. (Cf. Annexe 8) b. Partie serveur Le serveur est celui qui offre le service donc il utilise le processus rendant un service spécifique identifié par un port particulier (n port) et qui sera en attente sur une station (adresse IP). Nous insérons donc en premier les bibliothèques nécessaires à l'exploitation des sockets. Une fois ceci fait, il faut introduire la fonction main par laquelle nous allons déclarer des structures qui serviront à retenir les informations de la connexion du côté serveur, le port sur lequel le serveur va écouter, le protocole qu'il utilisera, les informations du client qui s'y connectera (adresse au format binaire), la provenance du port ainsi que le protocole utilisé. Nous devrons déclarer aussi des variables entières qui serviront à contenir les informations du socket que nous utilisons. Nous passons donc en premier paramètre AF_INET pour désigner que nous utiliserons soit le protocole TCP soit UDP. Nous précisons la nature de ce protocole grâce au deuxième paramètre que nous fixons sur SOCK_STREAM pour signaler que c'est TCP qui sera utilisé. Le protocole supplémentaire sera fixé sur 0. Il faudra ensuite également déclarer une variable qui servira à contenir les messages reçus et que l'on va envoyer. Nous devons ensuite déclarer une variable qui servira à contenir la taille de la structure passée en paramètre à la fonction d'acceptation de connexion, cette variable est indispensable au bon fonctionnement de cette fonction. 17
Nous allons ensuite vérifier si le socket est valide : if (socketid == -1) { perror("socket"); exit(-1); Ensuite, nous allons initialiser les champs de la structure contenant les informations de connexion pour le serveur : memset(&information_server, 0, sizeof(struct sockaddr_in)); information_server.sin_port = htons(6666); information_server.sin_family = AF_INET; Nous commençons par effacer le contenu de cette structure grâce à la fonction memset (vue dans la partie string.h de ce site) pour éviter les erreurs dues aux crasses contenues dans la structure. Nous initialisons ensuite le port grâce à la fonction htons sur 6666 pour dire que le serveur écoutera sur ce port et nous réglons la famille de protocole sur AF_INET pour signaler que nous utiliserons TCP ou UDP. Nous allons maintenant devoir créer la connexion avec un nom valide grâce à la fonction bind : if ((bind(socketid, (struct sockaddr *) &information_server, sizeof(struct sockaddr))) == -1) { perror("bind"); exit(-1); Maintenant que la connexion existe, il va falloir la mettre en écoute pour voir si des clients essayent de se connecter : if ((listen(socketid, 5)) == -1) { perror("listen"); exit (-1); Nous passons donc en premier argument de la fonction listen le descripteur de la connexion renvoyé par la fonction socket et nous définissons la taille de la liste de connexion en attente sur 5. Si cette fonction échoue et qu'elle renvoie -1, nous affichons l'erreur grâce à la fonction perror et nous quittons le programme en renvoyant la valeur -1 grâce à la fonction exit. Nous allons ensuite accepter la connexion entrante. Nous commençons donc par effacer le contenu de la structure information_client pour éviter tous conflits avec les crasses contenues dans la structure. Ensuite, nous utilisons une fonction pour accepter la connexion. Le premier argument est donc le descripteur de la connexion renvoyé par la fonction socket. Le deuxième argument est la structure qui recevra les informations de la connexion du client. Le dernier argument sera l'adresse de la variable de longueur qui réceptionnera la longueur de la structure du client. Nous stockons l'identifiant de la connexion entre ce serveur et le client dans 18
la variable connexion. Nous allons également devoir vérifier le contenu de cette variable pour être sûr que la fonction n'a pas échoué : if (connexion == -1) { perror("accept"); exit(-1); printf ("Connexion acceptée de %s\n", inet_ntoa( information_client.sin_addr.s_addr )); Si la connexion est valide, nous affichons un message pour dire que celle-ci a été acceptée et nous affichons l'adresse IP du client. Nous utilisons donc la fonction inet_ntoa et nous passons en premier argument de cette fonction le champ contenant l'adresse IP au format binaire du client. La fonction renverra donc l'adresse IP sous forme décimale pointée. Nous allons maintenant devoir faire la boucle qui va permettre de recevoir les données et d'en renvoyer, voici donc son squelette : do { while (strcmp(phrase, "EXIT")!= 0); Comme vous le voyez, nous exécuterons la boucle tant que le contenu de ce que l'on reçoit ou de ce qu'on envoie sera différent de EXIT. Nous devons donc commencer par recevoir les données : memset(phrase, 0, 255); recv(connexion, phrase, 255, 0); 19
Nous commençons donc par effacer le contenu de la variable phrase en la remplissant de 0 grâce à la fonction memset. Nous utilisons ensuite la fonction recv qui va attendre de recevoir des données. Nous passons donc en premier paramètre l'identifiant de la connexion et en deuxième paramètre la chaine de caractères qui va recevoir les données. Le troisième paramètre est la longueur maximale de la chaine de caractères et le dernier paramètre est un drapeau que nous laisserons à 0 pour ne pas modifier la réception de données. Nous devons ensuite regarder si la phrase reçue n'est pas EXIT : if (strcmp(phrase, "EXIT") == 0) { printf ("Connexion fermée\n"); shutdown(socketid, SHUT_RDWR); exit (0); Nous regardons donc ici si la phrase reçue est égale à EXIT, si c'est le cas, nous indiquons que la connexion est fermée et nous la fermons grâce à la fonction shutdown. Nous passons en premier argument de cette fonction le descripteur de connexion renvoyé par la fonction socket et nous passons la constante SHUT_RDWR en deuxième argument pour signaler que nous fermons la connexion en émission et en réception. Nous quittons ensuite le programme grâce à la fonction exit. Par contre, si la phrase n'est pas EXIT, nous devrons demander à l'utilisateur la phrase de réponse tout en affichant la phrase reçue : printf ("Phrase reçue : %s\n", phrase); printf ("Réponse : "); fgets(phrase, 255, stdin); phrase[strlen(phrase) - 1] = '\0'; send(connexion, phrase, strlen(phrase), 0); Nous commençons donc par afficher la phrase reçue. Nous affichons ensuite un message demandant à l'utilisateur d'entrer sa réponse que nous récupérons grâce au fgets dans la variable phrase. Une fois ceci fait, il ne nous reste plus qu'à envoyer le contenu de la variable phrase grâce à la fonction send. Le premier argument de cette fonction est l'identifiant de la connexion. Le deuxième paramètre est la donnée à envoyer dont la taille est spécifiée comme troisième argument et enfin, nous laissons le dernier paramètre sur 0 pour ne pas modifier l'envoi. Une fois que nous sortons de la boucle, il suffit de terminer la fonction main : return 0; (Cf. Annexe 9) 20
Annexe 1 : Planning 21
Annexe 2 : Installation et configuration : Apache Apache fait partir des logiciels fournis avec la distribution Fedora. Par contre, il est très important d installer la documentation. yum install httpd-manual Une fois installé il va falloir éditer le fichier /etc/http/conf/httpd.conf. En ajoutant la ligne suivante : Listen 192.168.1.253:80 Et commenter la ligne suivante, en ajoutant un «#» au début de la ligne : Listen 80 Démarrer le service : service httpd start Pour activer le service au démarrage du serveur : chkconfig httpd on 22
Annexe 3 : Installation et configuration : DHCP Cette configuration permet la mise en place d un serveur DHCP simple. Nous créerons un DHCP pour le réseau 192.168.1.0/24, la plage d adresse sera 192.168.1.20 à 192.168.1.100. La passerelle sera 192.168.1.1, le serveur DNS sera 192.168.1.253 et le nom de domaine domaine.local. Vérification du paquetage, s il est installé ou pas via la commande : rpm q dhcp Si la paquetage n est pas installé, on peut l installer en exécutant cette commande : yum install dhcp dhclient Une fois installé il va falloir éditer le fichier /etc/dhcpd.conf. ddns-update-style none; ignore client-updates; authoritative; subnet 192.168.1.0 netmask 255.255.255.0 { option routers 192.168.1.1; # passerelle par défaut option subnet-mask 255.255.255.0; # masque de sous-réseau option domain-name "domaine.local"; # nom de domaine option domain-name-servers 192.168.1.253;# serveurs DNS range 192.168.1.25 192.168.1.100; # plage d adresse default-lease-time 21600; # durée du bail en secondes max-lease-time 43200 ; # durée maxi du bail en sec. La syntaxe pour réserver une adresse à une machine : host nommachine { hardware ethernet 12:34:56:78:AB:CD; fixed-address 192.168.22.100; # adresse MAC de la machine # IP que l on veut lui assigner Lancement du service DHCP service dhcpd restart Pour activer le service au démarrage du serveur : chkconfig dhcpd on En cas de problème, il faut vérifier les logs systèmes 23
Annexe 4 : Installation et configuration : Serveur DNS (BIND) Installation du serveur bind yum install bind-chroot Changement des permissions de ces répertoires : chmod 755 /var/named/ chmod 775 /var/named/chroot/ chmod 775 /var/named/chroot/var/ chmod 775 /var/named/chroot/var/named/ chmod 775 /var/named/chroot/var/run/ chmod 777 /var/named/chroot/var/run/named/ Bind est ici installé en chroot, c'est à dire qu'on a modifié son répertoire racine pour assurer une meilleure sécurité. Créons donc un lien symbolique pour faire pointer le répertoire classique sur le répertoire chrooté : cd /var/named/chroot/var/named/ ln -s../../ chroot Activation du service au démarrage du serveur : chkconfig --levels 235 named on CONFIGURATION Dans un premier temps il faut sauvegarder le fichier de configuration de base : cp /etc/named.conf /etc/named.conf.sample Afin d'assurer la sécurité du serveur Bind, on va cacher son numéro de version et ainsi n'autoriser les requêtes récursives que depuis lui-même. Pour cela on modifie le fichier «/etc/named.conf» comme suit : allow-recursion { localhost; ; version "SECRET"; Configuration du DNS primaire : Ces lignes nous permettrons de déclarer notre nom de domaine, A ajouter dans le fichier «/etc/named.conf» 24
zone "jary.local" IN { type master; file "jary.local.zone"; allow-update { none; ; ; Ajouter l interface d écoute, en ajoutant ces lignes au fichier «/etc/named.conf»: listen-on port 53 { 127.0.0.1; 192.168.1.253; ; allow-query { localhost; 192.168.1.0/24; Configuration de la zone DNS La Zone DNS est l'ensemble des entrées DNS associées à un nom de domaine et présentes sur les serveurs DNS D'AMEN. C'est donc ces paramètres qui permettront d'aiguiller vers le bon serveur physique les requêtes des internautes; La zone sera déclaré, en créant le fichier «/var/named/jary.local.zone» avec les paramètres suivant : $TTL 86400 @ IN SOA paris.jary.local. admin.jary.local. ( 2011071601 ; Numéro unique 28800 ; Refresh 14400 ; Retry 3600000 ; Expire 86400 ) ; Minimum @ IN NS paris.jary.local. paris IN A 192.168.1.253 ns IN CNAME paris gateway IN A 192.168.1.1 marseille IN A 192.168.1.251 tokyo IN A 192.168.1.254 DESCRIPTION DES DIFFERENTES PARTIES : Le @ au début de l enregistrement définit la zone : jary.local. La classe, IN, signifie internet. L enregistrement SOA (Start Of Authority), nécessaire pour un serveur maître. Paris.jary.local. : le nom pleinement qualifié du serveur de nom. admin.jary.local. : il s agit de l adresse électronique de l administrateur du serveur. 25
2011071601 : un numéro de série qu il faut incrémenter à chaque modification du fichier. Ce numéro permet aux serveurs esclaves de savoir s il y a du nouveau. 28800 : refresh, délai d attente avant de demander des informations à un serveur esclave. 14400 : retry, si l esclave ne trouve pas le maître, il réessaiera au bout du délai retry. 3600000 : expire, si au bout du délai expire, il n est pas parvenu à entrer en contact avec le serveur maître, il le considère comme inexistant. 86400 : minimum, détermine la durée de vie minimum du cache. Quant à la deuxième partie, il faut différencier plusieurs type d enregistrements : NS : il s agit simplement du serveur de noms. A : une adresse IP, Paris est la machine avec l IP 192.168.1.253 HINFO : donne des infos sur le serveur. MX : désigne un serveur de messagerie CNAME : nom canonique, pour ajouter des aliases à des machines. Configuration de la zone inverse : Le principe est le même, mais pour faire l inverse, retrouver un nom pleinement qualifié grâce à une IP Pour cela, on a créé le fichier «/var/named/192.168.1.0» $ttl 86400 @ IN SOA paris.jary.local. admin.jary.local. ( 2011071601 ; Numéro unique 28800 ; Refresh 14400 ; Retry 3600000 ; Expire 86400 ) ; Minimum @ IN NS paris.jary.local. 253 IN PTR paris.jary.local. 251 IN PTR marseille.jary.local. 254 IN PTR tokyo.jary.local. 1 IN PTR gateway.mon-domaine.local. On va ajouter le serveur Paris dans la liste des resolver DNS, en ajoutant le ligne suivant au fichier /etc/resolv.conf nameserver 127.0.0.1 On redémarre le service DNS : service named restart On fait un test de résolution de nom du site web www.google.fr 26
Annexe 5 : Installation et configuration : Firewall Afin d assurer une meilleur sécurité au différents serveur, on doit ajouter ces paramètres de firewall dans le fichier «/etc/sysconfig/iptables» de chaque serveur : -A RH-Firewall-1-INPUT -p udp -m udp --dport 137 -j ACCEPT -A RH-Firewall-1-INPUT -p udp -m udp --dport 138 -j ACCEPT -A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 139 -j ACCEPT -A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 445 -j ACCEPT -A RH-Firewall-1-INPUT -p udp -m udp --dport 68 -j ACCEPT -A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 67 -j ACCEPT -A RH-Firewall-1-INPUT -p udp -m udp --dport 53 -j ACCEPT -A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 53 -j ACCEPT -A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT Puis on redémarre le service du Firewall : service iptables restart On active le démarrage automatique : chkconfig iptables on 27
Annexe 6 : Installation et configuration : Serveur de fichier SAMBA Introduction : Samba est le système de partage de fichiers via le réseau utilisé notamment par Windows. La configuration donnée ici est dépourvue de toute sécurité mais permet un échange de fichier à l'intérieur d'un réseau local sûr. Prérequis : system-config-samba samba Samba fait partir des logiciels fournis avec la distribution Fedora yum install samba samba-common samba-client samba-swat Lancement automatique du daemon au démarrage : chkconfig smb on On commence par créer des utiliateurs spécifiques au réseau groupadd smbusers useradd -g smbusers -s /bin/false administrateur smbpasswd a administrateur (123456) Le partage de fichier est accessible à partir de l adresse \\192.168.1.251 On partage le répertoire «/tmp» en ajoutant ces commandes au fichier «/etc/samba/smb.conf» [tmp] comment = Temporary file space path = /tmp read only = no public = yes 28
Annexe 7 : Installation et configuration : SSH SERVEUR PARIS : [root@paris ~]# vi /etc/ssh/sshd_config ListenAddress 192.168.1.253 RSAAuthentication yes PubkeyAuthentication yes AuthorizedKeysFile.ssh/authorized_keys [root@paris ~]# touch ~/.ssh/authorized_keys [root@paris ~]# chmod 600 ~/.ssh/authorized_keys [root@paris.ssh]# ssh-keygen t rsa [root@paris.ssh]# scp ~/.ssh/id_rsa.paris.pub root@192.168.1.251:/tmp [root@paris.ssh]# scp ~/.ssh/id_rsa.paris.pub root@192.168.1.254:/tmp [root@paris ~]# cat /tmp/id_rsa.marseille.pub >> ~/.ssh/authorized_keys [root@paris ~]# cat /tmp/id_rsa.tokyo.pub >> ~/.ssh/authorized_keys [root@paris ~]#service sshd restart SERVEUR MARSEILLE : [root@marseille ~]# vi /etc/ssh/sshd_config ListenAddress 192.168.1.251 RSAAuthentication yes PubkeyAuthentication yes AuthorizedKeysFile.ssh/authorized_keys [root@ Marseille ~]# touch ~/.ssh/authorized_keys [root@ Marseille ~]# chmod 600 ~/.ssh/authorized_keys [root@ Marseille.ssh]# ssh-keygen t rsa [root@ Marseille.ssh]# scp ~/.ssh/id_rsa.marseille.pub root@192.168.1.253:/tmp [root@ Marseille.ssh]# scp ~/.ssh/id_rsa.marseille.pub root@192.168.1.254:/tmp [root@ Marseille ~]# cat /tmp/id_rsa.paris.pub >> ~/.ssh/authorized_keys [root@ Marseille ~]# cat /tmp/id_rsa.tokyo.pub >> ~/.ssh/authorized_keys [root@ Marseille ~]#service sshd restart SERVEUR TOKYO : [root@tokyo ~]# vi /etc/ssh/sshd_config ListenAddress 192.168.1.254 RSAAuthentication yes PubkeyAuthentication yes AuthorizedKeysFile.ssh/authorized_keys [root@ tokyo ~]# touch ~/.ssh/authorized_keys [root@ tokyo ~]# chmod 600 ~/.ssh/authorized_keys [root@ tokyo.ssh]# ssh-keygen t rsa [root@ tokyo ssh]# scp ~/.ssh/id_rsa.tokyo.pub root@192.168.1.251:/tmp [root@ tokyo.ssh]# scp ~/.ssh/id_rsa.tokyo.pub root@192.168.1.253:/tmp [root@ tokyo ~]# cat /tmp/id_rsa.marseille.pub >> ~/.ssh/authorized_keys [root@ tokyo ~]# cat /tmp/id_rsa.paris.pub >> ~/.ssh/authorized_keys [root@ Tokyo ~]#service sshd restart 29
Annexe 7 : Installation et configuration : Serveur de sauvegarde Le script (backup.sh) : DATE=`TZ=MET+24 date +%Y%m%d` mkdir /backup/radios/raddb.$date #Sauvegarde du serveur DNS scp root@192.168.1.253:/etc/named.conf /backup/dns/named.conf.$date scp root@192.168.1.253:/var/named/192.168.1.0 /backup/dns/192.168.1.0.$date scp root@192.168.1.253:/var/named/jary.local.zone /backup/dns/jary.local.zone.$date scp root@192.168.1.253:/var/named/named.ca /backup/dns/named.ca.$date scp root@192.168.1.254:/root/simplyserver.c /backup/chat/simplyserver.c.$date scp root@192.168.1.254:/root/simplyclient.c /backup/chat/simplyserver.c.$date scp root@192.168.1.254:/root/chatsrv.o /backup/chat/chatsrv.o.$date scp root@192.168.1.254:/root/chatcli.o /backup/chat/chatcli.o.$date scp root@192.168.1.254:/etc/raddb/* /backup/radios/raddb.$date/ #Sauvegarde de la configuration du DHCP scp root@192.168.1.253:/etc/dhcp/dhcpd.conf /backup/dhcp/dhcpd.conf.$date Explication : Le script permet de sauvegarder les fichiers de configuration avec la date de sauvegarde, comme cela : Fichier_de_configuration.AAAAMMJJ. (Exemple de sauvegarde du fichier smbusers : smbusers.20110715) Automatisation : Le script est automatisé avec la crontab, de manière qu il sera exécuté tous les jours à 1h. [root@marseille backup]#crontab -l 0 1 * * * /backup/backup.sh 30
Annexe 8 : Source serveur #include <sys/socket.h> #include <netinet/in.h> #include <stdio.h> #include <errno.h> #include <stdlib.h> #include <string.h> int main() { struct sockaddr_in information_server; struct sockaddr_in information_client; int socketid = socket(af_inet, SOCK_STREAM, 0); int connexion = 0; char phrase[255]; socklen_t len = sizeof(struct sockaddr_in); if (socketid == -1) { perror("socket"); exit(-1); memset(&information_server, 0, sizeof(struct sockaddr_in)); information_server.sin_port = htons(6666); information_server.sin_family = AF_INET; if ((bind(socketid, (struct sockaddr *) &information_server, sizeof(struct sockaddr))) == -1) { perror("bind"); exit(-1); if ((listen(socketid, 5)) == -1) { perror("listen"); exit (-1); memset(&information_client, 0, sizeof(struct sockaddr_in)); connexion = accept(socketid, (struct sockaddr *) &information_client, &len); if (connexion == -1) { perror("accept"); exit(-1); 31
printf ("Connexion acceptée de : %s\n", inet_ntoa(information_client.sin_addr.s_addr)); do { memset(phrase, 0, 255); recv(connexion, phrase, 255, 0); if (strcmp(phrase, "EXIT") == 0) { printf ("Connexion fermée\n"); shutdown(socketid, SHUT_RDWR); exit (0); printf ("Phrase reçue : %s\n", phrase); printf ("Réponse : "); fgets(phrase, 255, stdin); phrase[strlen(phrase) - 1] = '\0'; send(connexion, phrase, strlen(phrase), 0); while (strcmp(phrase, "EXIT")!= 0); return 0; 32
Annexe 9 : Source client #include <sys/socket.h> #include <netinet/in.h> #include <stdio.h> #include <errno.h> #include <stdlib.h> #include <string.h> int main() { char phrase[255]; struct sockaddr_in informations; informations.sin_family = AF_INET; informations.sin_port = htons(6666); informations.sin_addr.s_addr = inet_addr("127.0.0.1"); int socketid = socket(af_inet, SOCK_STREAM, 0); if (socketid == -1) { perror("socket"); exit (-1); if ((connect(socketid, (struct sockaddr *) &informations, sizeof(struct sockaddr_in))) == -1) { perror("connect"); exit (-1); do { printf ("Entrez votre phrase : "); fgets(phrase, 255, stdin); phrase[strlen(phrase) - 1] = '\0'; if ((send(socketid, phrase, strlen(phrase), 0)) == -1) perror("send"); if (strcmp(phrase, "EXIT")!= 0) { memset(phrase, 0, 255); recv(socketid, phrase, 255, 0); printf ("Phrase reçue : %s\n", phrase); while (strcmp(phrase, "EXIT")!= 0); 33
shutdown(socketid, SHUT_RDWR); return 0; 34