Vérifier l'ouverture d'un port sous GNU/Linux
Aujourd'hui un article assez basique sur un sujet plutôt simple mais qui concerne tout le monde : vérifier si un port est bien ouvert sur des machines GNU/Linux.
Introduction
Ce sujet est plutôt simple mais je pense qu'il concerne tout le monde, car c'est la base pour vérifier si un service est fonctionnel ou non. Cela permet de tester vos règles de pare-feu ainsi que les différents accès réseaux, ces tâches sont le quotidien de la plupart des admninistrateurs réseau/système. On verra d'abord comment vérifier directement sur la machine si le port est en écoute, s'il existe des connexions établies et pour finir on verra comment tester les flux vers des machines distantes. Nous n'aborderons pas le filtrage des flux sur les pare-feu car ce n'est pas le sujet de l'article.
Dans cet article nous allons utiliser deux machines sous GNU/Linux Red Hat Enterprise Linux 8 pour les tests :
- Machine 1 : 192.168.3.1 - p-awx-01
- Machine 2 : 192.168.3.4 - p-docker-01
Vérification des ports en écoute
Tout d'abord nous allons vérifier les ports en écoute sur la machine 192.168.3.4, il y en a normalement plusieurs. Pour cela nous pouvons utiliser plusieurs commandes, dans mon cas j'utilise ss
ou netstat
. Selon votre distribution vous aurez au moins un des deux outils présent.
netstat / ss
Vérification des ports TCP en écoute avec netstat -lnt
ou ss -lnt
:
1[root@p-docker-01 ~]# netstat -lnt
2Connexions Internet actives (seulement serveurs)
3Proto Recv-Q Send-Q Adresse locale Adresse distante Etat
4tcp 0 0 0.0.0.0:8081 0.0.0.0:* LISTEN
5tcp 0 0 192.168.3.4:8082 0.0.0.0:* LISTEN
6tcp 0 0 0.0.0.0:8083 0.0.0.0:* LISTEN
7tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN
8tcp 0 0 0.0.0.0:8088 0.0.0.0:* LISTEN
9tcp6 0 0 :::22 :::* LISTEN
10
11[root@p-docker-01 ~]# ss -lnt
12State Recv-Q Send-Q Local Address:Port Peer Address:Port
13LISTEN 0 128 127.0.0.1:199 0.0.0.0:*
14LISTEN 0 128 0.0.0.0:8081 0.0.0.0:*
15LISTEN 0 128 192.168.3.4:8082 0.0.0.0:*
16LISTEN 0 128 0.0.0.0:8083 0.0.0.0:*
17LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
18LISTEN 0 128 0.0.0.0:8088 0.0.0.0:*
19LISTEN 0 128 [::]:22 [::]:*
Vous remarquerez que l'on retrouve les connexions IPv4 & IPv6. On ne parlera que de IPv4 dans l'article. Les ports suivants sont en écoute : 8081, 8082, 8083, 22 & 8088.
Au niveau des options nous avons :
-l
pour listen-n
pour ne pas résoudre le nom des ports-t
pour TCP
De mon côté j'ai tendance à utiliser les arguments -lntp
pour afficher le PID et le nom du programme :
1[root@p-docker-01 ~]# netstat -lntp
2Connexions Internet actives (seulement serveurs)
3Proto Recv-Q Send-Q Adresse locale Adresse distante Etat PID/Program name
4tcp 0 0 0.0.0.0:8081 0.0.0.0:* LISTEN 87115/docker-proxy
5tcp 0 0 192.168.3.4:8082 0.0.0.0:* LISTEN 197733/docker-proxy
6tcp 0 0 0.0.0.0:8083 0.0.0.0:* LISTEN 88320/docker-proxy
7tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 854/sshd
8tcp 0 0 0.0.0.0:8088 0.0.0.0:* LISTEN 28833/docker-proxy
9tcp6 0 0 :::22 :::* LISTEN 854/sshd
10
11[root@p-docker-01 ~]# ss -lntp
12State Recv-Q Send-Q Local Address:Port Peer Address:Port
13LISTEN 0 128 127.0.0.1:199 0.0.0.0:* users:(("snmpd",pid=853633,fd=10))
14LISTEN 0 128 0.0.0.0:8081 0.0.0.0:* users:(("docker-proxy",pid=87115,fd=4))
15LISTEN 0 128 192.168.3.4:8082 0.0.0.0:* users:(("docker-proxy",pid=197733,fd=4))
16LISTEN 0 128 0.0.0.0:8083 0.0.0.0:* users:(("docker-proxy",pid=88320,fd=4))
17LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=854,fd=5))
18LISTEN 0 128 0.0.0.0:8088 0.0.0.0:* users:(("docker-proxy",pid=28833,fd=4))
19LISTEN 0 128 [::]:22 [::]:* users:(("sshd",pid=854,fd=7))
Même principe avec UDP en utilisant netstat -lnu
ou ss -lnu
:
1[root@p-docker-01 ~]# netstat -lnu
2Connexions Internet actives (seulement serveurs)
3Proto Recv-Q Send-Q Adresse locale Adresse distante Etat
4udp 0 0 0.0.0.0:53 0.0.0.0:*
5udp 0 0 0.0.0.0:161 0.0.0.0:*
6udp6 0 0 :::53 :::*
7
8[root@p-docker-01 ~]# ss -lnu
9State Recv-Q Send-Q Local Address:Port Peer Address:Port
10UNCONN 0 0 0.0.0.0:53 0.0.0.0:*
11UNCONN 0 0 0.0.0.0:161 0.0.0.0:*
12UNCONN 0 0 [::]:53 [::]:*
On voit bien les ports 161 (snmp) et 53 (DNS, mais ouvert avec nc pour le test). Avec les arguments -lnup
:
1[root@p-docker-01 ~]# netstat -lnup
2Connexions Internet actives (seulement serveurs)
3Proto Recv-Q Send-Q Adresse locale Adresse distante Etat PID/Program name
4udp 0 0 0.0.0.0:53 0.0.0.0:* 826544/nc
5udp 0 0 0.0.0.0:161 0.0.0.0:* 853633/snmpd
6udp6 0 0 :::53 :::* 826544/nc
7
8[root@p-docker-01 ~]# ss -lnup
9State Recv-Q Send-Q Local Address:Port Peer Address:Port
10UNCONN 0 0 0.0.0.0:53 0.0.0.0:* users:(("nc",pid=826544,fd=4))
11UNCONN 0 0 0.0.0.0:161 0.0.0.0:* users:(("snmpd",pid=853633,fd=9))
12UNCONN 0 0 [::]:53 [::]:* users:(("nc",pid=826544,fd=3))
Pour terminer, on peut également regrouper l'ensemble des arguments pour avoir toutes les informations : -lntup
1[root@p-docker-01 ~]# netstat -lntup
2Connexions Internet actives (seulement serveurs)
3Proto Recv-Q Send-Q Adresse locale Adresse distante Etat PID/Program name
4tcp 0 0 127.0.0.1:199 0.0.0.0:* LISTEN 853633/snmpd
5tcp 0 0 0.0.0.0:8081 0.0.0.0:* LISTEN 87115/docker-proxy
6tcp 0 0 192.168.3.4:8082 0.0.0.0:* LISTEN 197733/docker-proxy
7tcp 0 0 0.0.0.0:8083 0.0.0.0:* LISTEN 88320/docker-proxy
8tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 854/sshd
9tcp 0 0 0.0.0.0:8088 0.0.0.0:* LISTEN 28833/docker-proxy
10tcp6 0 0 :::22 :::* LISTEN 854/sshd
11udp 0 0 0.0.0.0:53 0.0.0.0:* 826544/nc
12udp 0 0 0.0.0.0:161 0.0.0.0:* 853633/snmpd
13udp6 0 0 :::53 :::* 826544/nc
14
15[root@p-docker-01 ~]# ss -lntup
16Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port
17udp UNCONN 0 0 0.0.0.0:53 0.0.0.0:* users:(("nc",pid=826544,fd=4))
18udp UNCONN 0 0 0.0.0.0:161 0.0.0.0:* users:(("snmpd",pid=853633,fd=9))
19udp UNCONN 0 0 [::]:53 [::]:* users:(("nc",pid=826544,fd=3))
20tcp LISTEN 0 128 127.0.0.1:199 0.0.0.0:* users:(("snmpd",pid=853633,fd=10))
21tcp LISTEN 0 128 0.0.0.0:8081 0.0.0.0:* users:(("docker-proxy",pid=87115,fd=4))
22tcp LISTEN 0 128 192.168.3.4:8082 0.0.0.0:* users:(("docker-proxy",pid=197733,fd=4))
23tcp LISTEN 0 128 0.0.0.0:8083 0.0.0.0:* users:(("docker-proxy",pid=88320,fd=4))
24tcp LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=854,fd=5))
25tcp LISTEN 0 128 0.0.0.0:8088 0.0.0.0:* users:(("docker-proxy",pid=28833,fd=4))
26tcp LISTEN 0 128 [::]:22 [::]:* users:(("sshd",pid=854,fd=7))
Vérification des sessions établies
Cette section ne va concerner que les sessions TCP.
netstat / ss
Comme tout à l'heure nous allons utiliser les commandes netstat
& ss
.
Tout d'abord avec les arguments -natu
:
1Proto Recv-Q Send-Q Adresse locale Adresse distante Etat
2tcp 0 0 127.0.0.1:199 0.0.0.0:* LISTEN
3tcp 0 0 0.0.0.0:8081 0.0.0.0:* LISTEN
4tcp 0 0 192.168.3.4:8082 0.0.0.0:* LISTEN
5tcp 0 0 0.0.0.0:8083 0.0.0.0:* LISTEN
6tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN
7tcp 0 0 0.0.0.0:8088 0.0.0.0:* LISTEN
8tcp 0 0 192.168.3.4:22 10.2.2.2:1609 ESTABLISHED
9tcp 0 48 192.168.3.4:22 10.2.2.2:1046 ESTABLISHED
10tcp 0 0 192.168.3.4:35646 172.65.251.78:443 ESTABLISHED
11tcp 0 0 192.168.3.4:22 10.2.2.2:1610 ESTABLISHED
12tcp 0 0 192.168.3.4:41542 172.65.251.78:443 ESTABLISHED
13tcp 0 0 192.168.3.4:22 10.2.2.2:1054 ESTABLISHED
14tcp6 0 0 :::22 :::* LISTEN
15udp 0 0 0.0.0.0:53 0.0.0.0:*
16udp 0 0 0.0.0.0:161 0.0.0.0:*
17udp6 0 0 :::53 :::*
18
19[root@p-docker-01 ~]# ss -natu
20Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port
21udp UNCONN 0 0 0.0.0.0:53 0.0.0.0:*
22udp UNCONN 0 0 0.0.0.0:161 0.0.0.0:*
23udp UNCONN 0 0 [::]:53 [::]:*
24tcp LISTEN 0 128 127.0.0.1:199 0.0.0.0:*
25tcp LISTEN 0 128 0.0.0.0:8081 0.0.0.0:*
26tcp LISTEN 0 128 192.168.3.4:8082 0.0.0.0:*
27tcp LISTEN 0 128 0.0.0.0:8083 0.0.0.0:*
28tcp LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
29tcp LISTEN 0 128 0.0.0.0:8088 0.0.0.0:*
30tcp ESTAB 0 0 192.168.3.4:22 10.2.2.2:1609
31tcp ESTAB 0 48 192.168.3.4:22 10.2.2.2:1046
32tcp ESTAB 0 0 192.168.3.4:35646 172.65.251.78:443
33tcp ESTAB 0 0 192.168.3.4:22 10.2.2.2:1610
34tcp ESTAB 0 0 192.168.3.4:41542 172.65.251.78:443
35tcp ESTAB 0 0 192.168.3.4:22 10.2.2.2:1054
36tcp LISTEN 0 128 [::]:22 [::]:*
Cela permet de récupérer les ports en écoute ainsi que les connexions. Pour filtrer sur les connexions seulement il suffit d'utiliser grep
:
1[root@p-docker-01 ~]# ss -natu | grep ESTAB
2tcp ESTAB 0 0 192.168.3.4:22 10.2.2.2:1609
3tcp ESTAB 0 48 192.168.3.4:22 10.2.2.2:1046
4tcp ESTAB 0 0 192.168.3.4:35646 172.65.251.78:443
5tcp ESTAB 0 0 192.168.3.4:22 10.2.2.2:1610
6tcp ESTAB 0 0 192.168.3.4:41542 172.65.251.78:443
7tcp ESTAB 0 0 192.168.3.4:22 10.2.2.2:1054
8
9[root@p-docker-01 ~]# netstat -natu | grep ESTAB
10tcp 0 0 192.168.3.4:22 10.2.2.2:1609 ESTABLISHED
11tcp 0 48 192.168.3.4:22 10.2.2.2:1046 ESTABLISHED
12tcp 0 0 192.168.3.4:35646 172.65.251.78:443 ESTABLISHED
13tcp 0 0 192.168.3.4:22 10.2.2.2:1610 ESTABLISHED
14tcp 0 0 192.168.3.4:41542 172.65.251.78:443 ESTABLISHED
15tcp 0 0 192.168.3.4:22 10.2.2.2:1054 ESTABLISHED
Dans ces connexions, nous voyons bien plusieurs choses :
- Des flux https sortants
- Des flux ssh entrants (ma connexion VPN)
Cette partie a été présentée avant car elle permettra de vérifier vos connexions dans les tests à venir. Il est possible d'aller beaucoup plus loin au niveau des sessions TCP afin de voir les différents états mais ce n'est pas le but de cet article.
Vérifier les flux
Une fois que vous avez vérifié que les ports étaient bien en écoute, vous pouvez tester directement une connexion sur l'un d'eux.
Tous les tests sont effectués dans le sens 192.168.3.1 -> 192.168.3.4.
telnet
Attention cette méthode n'est valide que pour un port TCP.
Lorsque l'on parle de telnet
nous pensons tous à un protocole d'administration non sécurisé, mais c'est aussi un excellent outil pour tester simplement si un port est accessible ou non.
Par exemple pour tester si le port 22 est ouvert sur la machine 192.168.3.4 vous pouvez simplement lancer telnet 192.168.3.4 22
:
1[root@p-awx-01 tzkuat]# telnet 192.168.3.4 22
2Trying 192.168.3.4...
3Connected to 192.168.3.4.
4Escape character is '^]'.
5SSH-2.0-OpenSSH_8.0
On voit bien que la connexion est établie, et on la retrouve bien avec notre commande ss
sur le serveur distant :
1[root@p-docker-01 /]# ss -natu | grep ESTAB | grep 192.168.3.1
2tcp ESTAB 0 0 192.168.3.4:22 192.168.3.1:58738
On remarque également que le résultat est différent si la connexion n'aboutit pas :
1[root@p-awx-01 ~]# telnet net-security.fr 2222
2Trying 54.36.91.62...
nc / ncat
Nous pouvons également utiliser l'outil netcat qui va permettre de tester à la fois les flux TCP & UDP.
Connexion en TCP
Comme pour telnet il suffit de lancer une commande suivie d'un port pour vérifier la connectivité. Vous pouvez lancer nc -v <IP> <PORT>
pour tester simplement la connexion ou nc -vz <IP> <PORT>
pour réaliser un scan de port :
1[root@p-awx-01 ~]# nc -v 192.168.3.4 22
2Ncat: Version 7.70 ( https://nmap.org/ncat )
3Ncat: Connected to 192.168.3.4:22.
4SSH-2.0-OpenSSH_8.0
5^C
6
7[root@p-awx-01 ~]# nc -vz 192.168.3.4 22
8Ncat: Version 7.70 ( https://nmap.org/ncat )
9Ncat: Connected to 192.168.3.4:22.
10Ncat: 0 bytes sent, 0 bytes received in 0.01 seconds.
Connexion en UDP
Pour UDP, on pourrait penser qu'il suffit de rajouter l'argument -u
et que le principe restera le même, mais non, car cela ne fonctionne pas et répond toujours que le port est en écoute, un exemple sur un DNS public :
1[root@p-awx-01 ~]# nc -vzu 1.1.1.1 53
2Ncat: Version 7.70 ( https://nmap.org/ncat )
3Ncat: Connected to 1.1.1.1:53.
4Ncat: UDP packet sent successfully
5Ncat: 1 bytes sent, 0 bytes received in 2.01 seconds.
6
7[root@p-awx-01 ~]# nc -vzu 1.1.1.1 55
8Ncat: Version 7.70 ( https://nmap.org/ncat )
9Ncat: Connected to 1.1.1.1:55.
10Ncat: UDP packet sent successfully
11Ncat: 1 bytes sent, 0 bytes received in 2.01 seconds.
12
13[root@p-awx-01 ~]# nc -vzu 1.1.1.1 161
14Ncat: Version 7.70 ( https://nmap.org/ncat )
15Ncat: Connected to 1.1.1.1:161.
16Ncat: UDP packet sent successfully
17Ncat: 1 bytes sent, 0 bytes received in 2.01 seconds.
18
19[root@p-awx-01 ~]# nc -vzu 1.1.1.1 1693
20Ncat: Version 7.70 ( https://nmap.org/ncat )
21Ncat: Connected to 1.1.1.1:1693.
22Ncat: UDP packet sent successfully
23Ncat: 1 bytes sent, 0 bytes received in 2.01 seconds.
Personnellement pour vérifier si un port UDP est ouvert, je stoppe le service en question (snmp par exemple) et j'utilise netcat des deux côtés : côté serveur pour mettre le port en écoute et côté client pour initier la connexion.
Tout d'abord on va mettre le port en écoute sur le serveur (192.168.3.4) avec la commande nc -lu 192.168.3.4 161
ou nc -lu 161
si vous ne spécifiez pas l'IP sur laquelle écouter. Les deux arguments vous permettent de mettre le port en écoute et d'utiliser UDP. Si on vérifie avec netstat
depuis un autre terminal on voit bien le port en écoute :
1[root@p-docker-01 ~]# netstat -lnup
2Connexions Internet actives (seulement serveurs)
3Proto Recv-Q Send-Q Adresse locale Adresse distante Etat PID/Program name
4udp 0 0 192.168.3.4:161 0.0.0.0:* 864800/nc
Pour terminer et vérifier la connexion, il suffit de lancer la connexion côté client et d'envoyer du texte avec la commande nc -u 192.168.3.4 161
:
1[root@p-awx-01 ~]# ncat -u 192.168.3.4 161
2test netcat UDP
3test net-security.fr
Si vous retournez maintenant sur votre terminal ou le netcat
serveur est lancé, vous devriez retrouver le texte envoyé (si la connexion est bonne bien entendu) :
1[root@p-docker-01 ~]# nc -lu 192.168.3.4 161
2test netcat UDP
3test net-security.fr
On voit bien que les échanges fonctionnent dans ce cas. Nous allons nous arrêter ici pour la partie netcat, on reviendra dessus dans un article dédié si cela vous intéresse.
nmap
Il est difficile de parler d'ouverture de flux et de port sans mentionner nmap
. Cette boite à outil permet très rapidement de vérifier si un port est ouvert. Nous n'allons pas aborder les scans de port dans cette section car ce n'est pas le but de l'article.
Connexion TCP
Pour vérifier si un port est ouvert il suffit de lancer la commande suivante nmap -Pn <IP> -p <PORT>
:
1[root@p-awx-01 ~]# nmap -Pn 192.168.3.4 -p 22
2Starting Nmap 7.70 ( https://nmap.org ) at 2021-07-11 01:43 CEST
3Nmap scan report for 192.168.3.4
4Host is up (0.00025s latency).
5
6PORT STATE SERVICE
722/tcp open ssh
8MAC Address: 6A:1B:4C:97:64:C6 (Unknown)
9
10Nmap done: 1 IP address (1 host up) scanned in 0.52 seconds
11[root@p-awx-01 ~]# nmap -Pn 192.168.3.4 -p 2222
12Starting Nmap 7.70 ( https://nmap.org ) at 2021-07-11 01:43 CEST
13Nmap scan report for 192.168.3.4
14Host is up (0.00026s latency).
15
16PORT STATE SERVICE
172222/tcp closed EtherNetIP-1
18MAC Address: 6A:1B:4C:97:64:C6 (Unknown)
19
20Nmap done: 1 IP address (1 host up) scanned in 0.50 seconds
21[root@p-awx-01 ~]# nmap -Pn 192.168.3.4 -p 8081
22Starting Nmap 7.70 ( https://nmap.org ) at 2021-07-11 01:43 CEST
23Nmap scan report for 192.168.3.4
24Host is up (0.00024s latency).
25
26PORT STATE SERVICE
278081/tcp open blackice-icecap
28MAC Address: 6A:1B:4C:97:64:C6 (Unknown)
29
30Nmap done: 1 IP address (1 host up) scanned in 0.50 seconds
Au niveau des arguments, on mentionne seulement de vérifier le port même si le ping ne répond pas (-Pn
) et on spécifie le port avec -p
. On voit bien dans les résultats que les ports 22 et 8081 sont ouverts et que le 2222 est fermé.
Connexion UDP
Pour UDP, le principe reste cette fois le même, on va seulement rajouter l'argument -sU
pour spécifier qu'on cherche un port UDP. Cela donne nmap -Pn <IP> -sU -p <PORT>
:
1[root@p-awx-01 ~]# nmap -Pn 192.168.3.4 -sU -p 161
2Starting Nmap 7.70 ( https://nmap.org ) at 2021-07-11 01:53 CEST
3Nmap scan report for 192.168.3.4
4Host is up (0.00030s latency).
5
6PORT STATE SERVICE
7161/udp open snmp
8MAC Address: 6A:1B:4C:97:64:C6 (Unknown)
9
10Nmap done: 1 IP address (1 host up) scanned in 0.50 seconds
11[root@p-awx-01 ~]# nmap -Pn 192.168.3.4 -sU -p 22
12Starting Nmap 7.70 ( https://nmap.org ) at 2021-07-11 01:53 CEST
13Nmap scan report for 192.168.3.4
14Host is up (0.00029s latency).
15
16PORT STATE SERVICE
1722/udp closed ssh
18MAC Address: 6A:1B:4C:97:64:C6 (Unknown)
19
20Nmap done: 1 IP address (1 host up) scanned in 0.50 seconds
21[root@p-awx-01 ~]# nmap -Pn 192.168.3.4 -sU -p 2221
22Starting Nmap 7.70 ( https://nmap.org ) at 2021-07-11 01:53 CEST
23Nmap scan report for 192.168.3.4
24Host is up (-0.15s latency).
25
26PORT STATE SERVICE
272221/udp closed rockwell-csp1
28MAC Address: 6A:1B:4C:97:64:C6 (Unknown)
29
30Nmap done: 1 IP address (1 host up) scanned in 0.49 seconds
Et voilà ! On voit bien que le port 161 est ouvert et que les deux autres sont fermés.
On va s'arrêter là sur les commandes et les tests, vous pouvez maintenant voir si un port est en écoute et ouvert sur une machine.
J’espère que cet article vous aura plu, si vous avez des questions ou des remarques sur ce que j’ai pu écrire n’hésitez pas à réagir avec moi par mail ou en commentaire ! N’hésitez pas à me dire également si ce genre d’article vous plaît !
Merci pour votre lecture et à bientôt !