Pour en savoir plus voir la page de Wikipdia : https://fr.wikipedia.org/wiki/Port_(logiciel)
Pour visualiser les ports ouverts d'un hôte et donc connaître les services actifs (en écoute) :
root@debian:~# netstat -tanpu Connexions Internet actives (serveurs et établies) Proto Recv-Q Send-Q Adresse locale Adresse distante Etat PID/Program name tcp 0 0 127.0.0.1:3306 0.0.0.0:* LISTEN 645/mysqld tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 478/sshd tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 1087/exim4 tcp 0 464 192.168.1.159:22 192.168.1.196:50264 ESTABLISHED 1119/sshd: root@pts tcp6 0 0 :::80 :::* LISTEN 680/apache2 tcp6 0 0 :::22 :::* LISTEN 478/sshd tcp6 0 0 ::1:25 :::* LISTEN 1087/exim4 udp 0 0 0.0.0.0:68 0.0.0.0:* 692/dhclient root@debian:~#
Exemple du service SSH (port 22) :
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 478/sshd tcp 0 464 192.168.1.159:22 192.168.1.196:50264 ESTABLISHED 1119/sshd: root@pts
Le port 50264 est choisi aléatoirement par le client lors de l'initialisation de la connexion, pour communiquer avec le serveur.
udp 0 0 0.0.0.0:68 0.0.0.0:* 692/dhclient
===== Scan de port TCP=====
Source Wikipedia : https://fr.wikipedia.org/wiki/Transmission_Control_Protocol#.C3.89tablissement_d.27une_connexion
Schéma d'établissement d'une connexion TCP :
- Le client envoie un segment avec le flag SYN au serveur,
- Le serveur lui répond par un segment avec le flag SYN/ACK,
- Le client confirme par un segment avec le flag ACK.
Durant cet échange initial, les numéros de séquence des deux parties sont synchronisés :
- Le client utilise son numéro de séquence initial dans le champ “Numéro de séquence” du segment SYN (x par exemple),
- Le serveur utilise son numéro de séquence initial dans le champ “Numéro de séquence” du segment SYN/ACK (y par exemple) et ajoute le numéro de séquence du client plus un (x+1) dans le champ “Numéro d'acquittement” du segment,
- Le client confirme en envoyant un ACK avec un numéro de séquence augmenté de un (x+1) et un numéro d'acquittement correspondant au numéro de séquence du serveur plus un (y+1).
Si le serveur rejette la connexion, il répond avec un segment dont le flag est RESET.
==== Attributs disponible et valeur par défaut pour le protocole TCP ====
<code python>
»> ls(TCP)
sport : ShortEnumField = (20)
dport : ShortEnumField = (80)
seq : IntField = (0)
ack : IntField = (0)
dataofs : BitField = (None)
reserved : BitField = (0)
flags : FlagsField = (2)
window : ShortField = (8192)
chksum : XShortField = (None)
urgptr : ShortField = (0)
options : TCPOptionsField = ({})
»>
</code>)
==== Envoi d'un paquet TCP sur le service Web d'un serveur (port 80) avec le flag SYN ====
* valeurs du segment TCP à préciser :
* * port de destination 80 pour le service Web
* * port source client 55 555 (choisi au dessus de 49 151)
* * flag positionné à SYN (valeur S)
* création du segment encapsulé dans un paquet IP destiné à l'hôte 192.168.1.1 (Box Internet) :
<code python>
»> paquet = IP(dst='192.168.1.1') / TCP(sport=55555, dport=80, flags='S')
»>
</code>
* envoi du paquet
<code python>
»> rep, non_rep = sr(paquet)
Begin emission:
..Finished to send 1 packets.
..
Received 5 packets, got 1 answers, remaining 0 packets
»> rep.show()
0000 IP / TCP 192.168.1.159:55555 > 192.168.1.1:http S =⇒ IP / TCP 192.168.1.1:http > 192.168.1.159:55555 SA / Padding
»>
</code>
* Le résultat est toujours composé des deux couples paquet émis / paquet reçu.
* Le paquet envoyé sur le port 80 (Scapy affiche http à la place du numéro de port 80) avec le flag positionné à SYN (Scapy affiche un S pour l'attribut flags ce qui correspond à la valeur numérique 2)
<code python>
»> rep[0][0][TCP].show()
###[ TCP ]###
sport= 55555
dport= http
seq= 0
ack= 0
dataofs= None
reserved= 0
flags= S
window= 8192
chksum= None
urgptr= 0
options= {}
»>
</code>
* le paquet reçu correspond a les flags positionnés à SYN et ACK (Scapy affiche SA ce qui correspond à la valeur numérique 18) ⇒ le port 80 est ouvert.
<code python>
rep[0][1][TCP].show()
###[ TCP ]###
sport= http
dport= 55555
seq= 3631598158
ack= 1
dataofs= 6
reserved= 0
flags= SA
window= 14600
chksum= 0x5f04
urgptr= 0
options= [('MSS', 1460)]
###[ Padding ]###
load= 'I5'
»>
</code>
==== Envoi d'un paquet TCP sur le port 22 d'un serveur alors que le service SSH n'est pas actif ====
* valeurs du segment TCP à préciser :
* * port de destination 22 pour le service SSH
* * port source client 55 555 (choisi au dessus de 49 151)
* * flag positionné à SYN (valeur S)
* création du segment encapsulé dans un paquet IP destiné à l'hôte 192.168.1.100 (Imprimante réseau) :
<code python>
»> paquet = IP(dst='192.168.1.100') / TCP(sport=55555, dport=22, flags='S')
»> rep, non_rep = sr(paquet)
Begin emission:
..Finished to send 1 packets.
..
Received 5 packets, got 1 answers, remaining 0 packets
»> rep.show()
0000 IP / TCP 192.168.1.159:55555 > 192.168.1.100:ssh S =⇒ IP / TCP 192.168.1.100:ssh > 192.168.1.159:55555 RA / Padding
»> rep[0][1][TCP].show()
###[ TCP ]###
sport= ssh
dport= 55555
seq= 0
ack= 1
dataofs= 5
reserved= 0
flags= RA
window= 0
chksum= 0x5262
urgptr= 0
options= {}
###[ Padding ]###
load= '\x00\x00\x00\x00\x00\x00'
»>
</code>
* Le résultat est toujours composé des deux couples paquet émis / paquet reçu.
* Le paquet envoyé sur le port 22 (Scapy affiche ssh à la place du numéro de port 80) avec le flag positionné à SYN (Scapy affiche un S pour l'attribut flags ce qui correspond à la valeur numérique 2)
* le paquet reçu correspond a les flags positionnés à RESET et ACK (Scapy affiche RA ce qui correspond à la valeur numérique 20) ⇒ le port 22 n'est pas ouvert.
<code python>
»> rep[0][1][TCP].flags
20
»>
</code>
==== Préciser plusieurs ports ====
Il est possible d'utiliser une liste de valeurs pour les attributs des protocoles sous la forme :
* dport=[80,443] pour indiquer une liste de ports : ici uniquement les ports 80 et 446 ;
* dport=(80,443) pour indiquer une plage de valeurs : ici les ports allant de 82 à 443.
===== Scan de port UDP=====
Rappel : Un port UDP est simplement en écoute car UDP ne gère pas l'établissement de connexions.
==== Exemple de scan UDP pour déterminer si le service DNS est actif sur un hôte (en écoute) ==== Les paramètres à utiliser * le nom/adresse IP du serveur DNS dans le paquet IP, * Le port UDP a utilisé et qui est 53 dans le segment UDP. * il faut encapsuler les informations DNS sans préciser la requête de résolution de nom car il s'agit d'un simple scan. Deux réponses sont possibles : * Si le port est ouvert et donc le service DNS est actif, l'application répond en UDP, * Si le port est fermé, l'application répond avec un message d'erreur ICMP port-unreachable. <code python> »> paquet = IP(dst='192.168.1.1') / UDP(dport=53) / DNS() »> rep, nonrep = sr(paquet) Begin emission: ..Finished to send 1 packets. .. Received 5 packets, got 1 answers, remaining 0 packets »> rep.show() 0000 IP / UDP / DNS Qry =⇒ IP / UDP / DNS Ans / Padding »> paquet = IP(dst='192.168.1.100') / UDP(dport=53) / DNS() »> rep, non_rep = sr(paquet) Begin emission: ..Finished to send 1 packets. . Received 4 packets, got 1 answers, remaining 0 packets »> rep.show() 0000 IP / UDP / DNS Qry =⇒ IP / ICMP 192.168.1.100 > 192.168.1.159 dest-unreach port-unreachable / IPerror / UDPerror »> </code> ==== Retour à Python : la bibliothèque Scapy … ====