Fping à la découverte d’hôtes

Quoi de mieux que la bonne commande “ping” pour découvrir si des hôtes répondent présents ou non dans un réseau. Mais si nous avons plusieurs centaines de machines à vérifier, et/ou si un Firewall détecte les comportements de ping d’une adresse IP les unes après les autres, la mission de reconnaissance devient longue et fastidieuse.

Afin de palier au manque de la commande “ping” classique, l’outil fping permet de fournir en entrée une liste de plusieurs hôtes, ou réseaux, à analyser. Et à la place d’attendre la réponse d’un hôte pour commencer le test suivant, fping passera à un hôte suivant sélectionné dans la liste fournie en entrée et cela de façon aléatoire.

Installation fping

sudo apt install fping # debian
sudo pacman -S fping # archlinux

Ping sur un hôte

sudo fping xxx.xxx.xxx.xxx
xxx.xxx.xxx.xxx is unreachable

Ping sur plusieurs hôtes

sudo fping xxx.xxx.xxxx.xxx yyy.yyy.yyy.yyy
yyy.yyy.yyy.yyy is alive
xxx.xxx.xxx.xxx is unreachable

Ping sur plusieurs hôtes fournis dans un fichier

cat hosts.txt
xxx.xxx.xxx.xxx
yyy.yyy.yyy.yyy

sudo fping -f hosts.txt
yyy.yyy.yyy.yyy is alive
xxx.xxx.xxx.xxx is unreachable

Ping sur un réseau ou un nombre déterminé de hôtes

sudo fping -g xxx.xxx.xxx.0/24
sudo fping -g xxx.xxx.xxx.8 xxx.xxx.xxx.15

Il n’est pas possible de spécifier plusieurs réseaux les uns à la suite des autres, ni même de les appeler par l’option -f

Afficher le temps de réponse au ping

sudo fping -e yyy.yyy.yyy.yyy
yyy.yyy.yyy.yyy is alive (128 ms)

Afficher la résolution de l’adresse IP

sudo fping -n yyy.yyy.yyy.yyy
toto.toto.com is alive

Afficher l’IP et la résolution de l’adresse IP

sudo fping -n -A yyy.yyy.yyy.yyy
toto.toto.com (yyy.yyy.yyy.yyy) is alive

Afficher les statistiques finale

sudo fping -s xxx.xxx.xxx.xxx yyy.yyy.yyy.yyy
yyy.yyy.yyy.yyy is alive
xxx.xxx.xxx.xxx is unreachable

2 targets
1 alive
1 unreachable
0 unknown addresses

4 timeouts (waiting for response)
5 ICMP Echos sent
1 ICMP Echo Replies received
0 other ICMP received

23.3 ms (min round trip time)
23.3 ms (avg round trip time)
23.3 ms (max round trip time)
4.087 sec (elapsed real time)

N’afficher que les hôtes qui répondent

sudo fping -a xxx.xxx.xxx.xxx yyy.yyy.yyy.yyy
yyy.yyy.yyy.yyy

N’afficher que les hôtes qui ne répondent pas

sudo fping -u xxx.xxx.xxx.xxx yyy.yyy.yyy.yyy
xxx.xxx.xxx.xxx

Ping fping versus ping nmap

Nmap propose aussi une option ping pour vérifier si un hôte est accessible ou pas (-sP). A la différence de fping (qui effectue uniquement une demande “ICMP echo request“, nmap va lancer une connexion ACK sur le port 80 de l’adresse IP, et demandera aussi un “ICMP echo request“. L’option “-sP” de nmap n’est pas un véritable ping, mais permet éventuellement d’aller un peu plus loin dans l’étude de disponibilité d’un hôte ou pas.

Prenons, par exemple, notre machine xxx.xxx.xxx.xxx qui ne répond pas avec fping, et lançons l’analyse avec nmap.

sudo nmap -v -sP xxx.xxx.xxx.xxx

Starting Nmap 4.76 ( http://nmap.org ) at 2009-06-28 11:09 CEST
Initiating Ping Scan at 11:09
Scanning xxx.xxx.xxx.xxx [2 ports]
Completed Ping Scan at 11:09, 0.08s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 11:09
Completed Parallel DNS resolution of 1 host. at 11:09, 0.00s elapsed
Host toto.titi.com (xxx.xxx.xxx.xxx) appears to be up.
Read data files from: /usr/local/share/nmap
Nmap done: 1 IP address (1 host up) scanned in 0.59 seconds
Raw packets sent: 2 (68B) | Rcvd: 1 (40B)

Un tcpdump nous permet de voir ce qui se passe lorsque nmap -sP est lancé.

10:17:19.259833 IP 192.168.aaa.aaa.50409 > xxx.xxx.xxx.xxx.80: . ack 2315653060 win 3072
10:17:19.260143 IP 192.168.aaa.aaa > xxx.xxx.xxx.xxx: ICMP echo request, id 21709, seq 0, length 8
10:17:19.283920 IP xxx.xxx.xxx.xxx.80 > 192.168.aaa.aaa.50409: R 2315653060:2315653060(0) win 0

Le hôte ne répond pas à la connexion “ICMP echo request”, mais par contre répond sur le port 80. Ce fait peut être vérifié par un simple telnet.

telnet xxx.xxx.xxx.xxx 80

Trying xxx.xxx.xxx.xxx...
telnet: connect to address xxx.xxx.xxx.xxx: Connection refused
telnet: Unable to connect to remote host

L’on peut remarquer que le port 80 est ouvert, mais filtré par des règles quelconques.

Détection de filtrage par le biais de fping, versus nmap

Fping pourra permettre par les réponses données, de voir que certains hôtes sont inaccessible à cause de règles quelconques, petits exemples :

Exemple 1 :

sudo fping zzz.zzz.zzz.zzz
ICMP Unreachable (Communication Administratively Prohibited) from zzz.zzz.zzz.zzz for ICMP Echo sent to zzz.zzz.zzz.zzz
ICMP Unreachable (Communication Administratively Prohibited) from zzz.zzz.zzz.zzz for ICMP Echo sent to zzz.zzz.zzz.zzz
ICMP Unreachable (Communication Administratively Prohibited) from zzz.zzz.zzz.zzz for ICMP Echo sent to zzz.zzz.zzz.zzz
ICMP Unreachable (Communication Administratively Prohibited) from zzz.zzz.zzz.zzz for ICMP Echo sent to zzz.zzz.zzz.zzz
zzz.zzz.zzz.zzz is unreachable

L’hôte sera déclaré comme “unreachable”, par contre les messages de retour montre qu’un élément filtrant empêche la communication.

Comparons maintenant ces résultats avec l’option “-sP” de nmap.

sudo nmap -v -sP zzz.zzz.zzz.zzz

Starting Nmap 4.76 ( http://nmap.org ) at 2009-06-28 11:20 CEST
Initiating Ping Scan at 11:20
Scanning zzz.zzz.zzz.zzz [2 ports]
Completed Ping Scan at 11:20, 0.08s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 11:20
Completed Parallel DNS resolution of 1 host. at 11:20, 0.02s elapsed
Host yaya.gougou.com (zzz.zzz.zzz.zzz) appears to be up.
Read data files from: /usr/local/share/nmap
Nmap done: 1 IP address (1 host up) scanned in 0.74 seconds
Raw packets sent: 2 (68B) | Rcvd: 1 (56B)

Nmap a déclaré que l’hôte était accessible, car le port 80 de cette machine est accessible, mais par contre ne nous a pas donner autant d’information sur fping sur la présence d’un élément filtrant. Il faudra rajouter l’option “-d” ou “–packet-trace” pour avoir le même résultat que fping.

Exemple 2 :

sudo fping rrr.rrr.rrr.rrr

ICMP Host Unreachable from sss.sss.sss.sss for ICMP Echo sent to rrr.rrr.rrr.rrr
ICMP Host Unreachable from sss.sss.sss.sss for ICMP Echo sent to rrr.rrr.rrr.rrr
ICMP Host Unreachable from sss.sss.sss.sss for ICMP Echo sent to rrr.rrr.rrr.rrr
rrr.rrr.rrr.rrr is unreachable

L’on peut voir grâce à fping que l’hôte sss.sss.sss.sss répond lorsque l’on effectue un ping sur l’hôte rrr.rrr.rrr.rrr

Comparons maintenant ces résultats avec l’option “-sP” de nmap.

sudo nmap -v -sP rrr.rrr.rrr.rrr

Starting Nmap 4.76 ( http://nmap.org ) at 2009-06-28 11:29 CEST
Initiating Ping Scan at 11:29
Scanning rrr.rrr.rrr.rrr [2 ports]
Completed Ping Scan at 11:29, 3.03s elapsed (1 total hosts)
Host rrr.rrr.rrr.rrr appears to be down.
Read data files from: /usr/local/share/nmap
Note: Host seems down. If it is really up, but blocking our ping probes, try -PN
Nmap done: 1 IP address (0 hosts up) scanned in 3.57 seconds
Raw packets sent: 4 (136B) | Rcvd: 0 (0B)

L’on peut voir ici que nmap ne nous signifie pas que l’hôte sss.sss.sss.sss répond lorsque l’on effectue un ping sur l’hôte rrr.rrr.rrr.rrr

L’option “-PN” pourra détecter que l’hôte rrr.rrr.rrr.rrr est up, mais sans pour autant nous signifier que sss.sss.sss.sss est un élément intermédiaire de filtrage.

Fping est un outil de base, qui en complément avec d’autres outils, tels que nmap, pourrait permettre d’avoir une vue complète sur un réseau et effectuer une phase d’approche intéressante.

Tri ordre croissant “latence” avec fichier hosts.txt

hosts.txt

fr-mrs-001.mullvad.net
fr-mrs-002.mullvad.net
fr-par-001.mullvad.net
fr-par-002.mullvad.net
fr-par-003.mullvad.net
gb-lon-101.mullvad.net
gb-lon-102.mullvad.net
gb-lon-103.mullvad.net
gb-lon-104.mullvad.net
gb-lon-105.mullvad.net
gb-lon-201.mullvad.net
gb-lon-202.mullvad.net
gb-lon-301.mullvad.net
gb-mnc-001.mullvad.net
gb-mnc-002.mullvad.net
gb-mnc-003.mullvad.net
gb-mnc-004.mullvad.net
gb-mnc-005.mullvad.net
sudo fping -e -f hosts.txt | awk -F" " '{print $4$5,$1,substr($1,1,2)}' |sort
(57.0ms) fr-par-003.mullvad.net fr
(57.8ms) fr-par-001.mullvad.net fr
(59.3ms) fr-par-002.mullvad.net fr
(61.1ms) gb-lon-202.mullvad.net gb
(61.3ms) gb-lon-105.mullvad.net gb
(61.4ms) gb-lon-101.mullvad.net gb
(61.7ms) gb-lon-102.mullvad.net gb
(62.2ms) gb-lon-104.mullvad.net gb
(62.3ms) gb-lon-201.mullvad.net gb
(64.5ms) gb-lon-301.mullvad.net gb
(65.3ms) gb-lon-103.mullvad.net gb
(65.9ms) gb-mnc-003.mullvad.net gb
(67.1ms) gb-mnc-004.mullvad.net gb
(67.9ms) fr-mrs-001.mullvad.net fr
(67.9ms) gb-mnc-005.mullvad.net gb
(71.1ms) gb-mnc-002.mullvad.net gb
(71.7ms) fr-mrs-002.mullvad.net fr

Pour ne pas avoir le pays sur 2 caractères

sudo fping -e -f hosts.txt |awk -F" " '{print $4$5,$1}' |sort

fping et python

Problème
Vous avez une liste de serveurs (par exemple des serveurs proxy) et vous voulez choisir le plus rapide. Comment mesurer les latences ping ?

Solution
Il y a une belle commande Unix pour cela appelée “fping” (sudo apt-get install fping). “Contrairement à ping, fping est destiné à être utilisé dans les scripts, donc sa sortie est conçue pour être facile à analyser.”

Exemple :

$ fping 221.130.199.121 -C 3 -q
    221.130.199.121 : 389.08 411.15 411.82

Il envoie 3 paquets et après le deux-points, il imprime chaque temps de réponse. Si un temps de réponse n’a pas pu être mesuré, vous verrez un “-“ à sa place.

221.130.199.121 : 297.79 299.52 -

En Python, voici la solution: fping.py

import shlex  
from subprocess import Popen, PIPE, STDOUT
 
def get_simple_cmd_output(cmd, stderr=STDOUT):
    """
    Exécutez une simple commande externe et obtenez sa sortie.
    """
    args = shlex.split(cmd)
    return Popen(cmd,stdout=PIPE, stderr=PIPE,encoding='utf8', shell = True).communicate()[0]
 
def get_ping_time(host):
    host = host.split(':')[0]
    cmd = "fping {host} -C 3 -q".format(host=host)
    res = [float(x) for x in process.get_simple_cmd_output(cmd).strip().split(':')[-1].split() if x != '-']
    if len(res) > 0:
        return sum(res) / len(res)
    else:
        return 999999

Il calcule la moyenne des temps de réponse. Si aucun temps de réponse n’a pu être mesuré, il renvoie une grande valeur.

latence

En informatique, la latence (latency , ou délai de transit, ou retard) est le délai de transmission dans les communications informatiques1 (on trouve parfois l’anglicisme lag).
Il désigne le temps nécessaire à un paquet de données pour passer de la source à la destination à travers un réseau.
À n’importe quel paquet transmis par réseau correspond donc une valeur de latence. Le terme est néanmoins utilisé pour désigner les délais plus longs, perceptibles par les utilisateurs.
On parle aussi de latence pour le temps d’accès à une information sur une mémoire ou un système de stockage (disque ou bande magnétique).Latence (info Wikipédia)

Le fichier serveurs-vpn-mullvad.txt contient tous les serveurs VPN Mullvad
Extrait

Serveur 	Pays 	Ville 	IP 	Groupes
au-bne-001 	Australia 	Brisbane 	43.245.160.162 	au-bne
au-mel-002 	Australia 	Melbourne 	116.206.228.202 	au-mel
au-mel-003 	Australia 	Melbourne 	116.206.228.242 	au-mel
au-mel-004 	Australia 	Melbourne 	116.206.230.98 	au-mel
au-per-001 	Australia 	Perth 	103.77.235.66 	au-per
au-syd-001 	Australia 	Sydney 	43.245.162.130 	au-syd
au-syd-002 	Australia 	Sydney 	221.121.149.194 	au-syd
au-syd-003 	Australia 	Sydney 	103.77.232.146 	au-syd
at-vie-001 	Austria 	Wien 	217.64.127.138 	
at-vie-002 	Austria 	Wien 	217.64.127.202 	
at-vie-003 	Austria 	Wien 	37.120.155.250 	
be-bru-001 	Belgium 	Brussels 	185.104.186.202 	
be-bru-002 	Belgium 	Brussels 	91.207.57.50 	
...

Extraction

awk -F'\t' '{print $1}' serveurs-vpn-mullvad.txt  #Extraire la colonne N° 1 de ce fichier, séparateur tabulation \t 
awk -F'\t' '{print $1,$2,$3}' serveurs-vpn-mullvad.txt |sed '1d' |sed 'N;$!P;$!D;$d' # idem précédent avec suppression de la première et 2 dernières lignes
au-bne-001  Australia  Brisbane 
au-mel-002  Australia  Melbourne 
...
...
us-xlx-001  USA  Stamford, CT 
us-was-001  USA  Washington DC 
us-was-002  USA  Washington DC 
ua-iev-001  Ukraine  Kiev 
awk -F'\t' '{print substr($1,1,2)}' serveurs-vpn-mullvad.txt |sed '1d' |sed 'N;$!P;$!D;$d' #Dans champ 1, a la position 1, printer 2 caracteres
 awk -F'\t' '{print substr($1,1,2)}' serveurs-vpn-mullvad.txt |sed '1d' |sed 'N;$!P;$!D;$d' |sort -u  #idem précédent avec sortie triée sans les doublons
...
lu
lv
md
nl
no
nz
pl
pt
ro
rs
se
sg
sk
ua
us
za
...

Liste des serveurs mullvad.net

awk -F' \t' '{print $1".mullvad.net"}' serveurs-vpn-mullvad.txt |sed '1d' |sed 'N;$!P;$!D;$d' |sort  #Extraire la colonne N° 1 de ce fichier, séparateur 1 espace + tabulation (\t)
...
gb-mnc-001.mullvad.net
gb-mnc-002.mullvad.net
gb-mnc-003.mullvad.net
gb-mnc-004.mullvad.net
gb-mnc-005.mullvad.net
us-atl-001.mullvad.net
us-atl-002.mullvad.net
us-atl-003.mullvad.net
us-bos-001.mullvad.net
...
awk -F'\t' '{print substr($1,1,2),$1,$3}' serveurs-vpn-mullvad.txt |sed '1d' |sed 'N;$!P;$!D;$d' |sort  #Dans champ 1, a la position 1, printer 2 caracteres
...
us us-ric-002  Richmond, VA 
us us-sea-001  Seattle, WA 
us us-sea-002  Seattle, WA 
us us-sea-003  Seattle, WA 
us us-sea-004  Seattle, WA 
us us-sea-101  Seattle, WA 
us us-sfo-001  San Francisco, CA 
us us-sfo-002  San Francisco, CA 
us us-sjc-001  San Jose, CA 
us us-sjc-002  San Jose, CA 
us us-slc-001  Salt Lake City, UT 
us us-slc-002  Salt Lake City, UT 
us us-stl-001  St. Louis , MO 
us us-uyk-001  Secaucus, NJ 
us us-uyk-002  Secaucus, NJ 
us us-was-001  Washington DC 
us us-was-002  Washington DC 
us us-xlx-001  Stamford, CT 
za za-jnb-001  Johannesburg 
awk -F' \t' '{print substr($1,1,2)"|"$1"|"$3"|"$4}' serveurs-vpn-mullvad.txt |sed 'N;$!P;$!D;$d' |sort > serveurs.csv 
# Option : modifier les entêtes sur la première ligne du csv
Pays|Serveur|Ville|IP
Pays|Serveur|Ville|IP
at|at-vie-001|Wien|217.64.127.138
at|at-vie-002|Wien|217.64.127.202
at|at-vie-003|Wien|37.120.155.250
au|au-bne-001|Brisbane|43.245.160.162
au|au-mel-002|Melbourne|116.206.228.202
au|au-mel-003|Melbourne|116.206.228.242
au|au-mel-004|Melbourne|116.206.230.98
au|au-per-001|Perth|103.77.235.66
au|au-syd-001|Sydney|43.245.162.130
au|au-syd-002|Sydney|221.121.149.194
au|au-syd-003|Sydney|103.77.232.146
be|be-bru-001|Brussels|185.104.186.202
be|be-bru-002|Brussels|91.207.57.50
be|be-bru-003|Brussels|37.120.143.138
bg|bg-sof-001|Sofia|185.94.192.42
./csv2json.sh serveurs.csv > serveurs.json
cat serveurs.json
[
    {
        "Pays": "at",
        "Serveur": "at-vie-001",
        "Ville": "Wien",
        "IP": "217.64.127.138"
    },
    {
        "Pays": "at",
        "Serveur": "at-vie-002",
        "Ville": "Wien",
        "IP": "217.64.127.202"
    },
...

    {
        "Pays": "us",
        "Serveur": "us-xlx-001",
        "Ville": "Stamford, CT",
        "IP": "165.84.227.90"
    },
    {
        "Pays": "za",
        "Serveur": "za-jnb-001",
        "Ville": "Johannesburg",
        "IP": "192.230.45.146"
    }
]

Sur le site http://country.io/data/
Un fichier JSON qui met en correspondance les codes pays ISO2 et les codes continent ISO2
Un fichier JSON qui associe les codes pays ISO2 aux noms de pays
Conversion en ligne csv –> sql

PC1 mariadb , Dbeaver

Requête serveurs mullvad

SELECT table_continent.continent_lib, country.Pays as 'Pays',country.Code as 'Code', mullvad.Ville, mullvad.Serveur, mullvad.IP  
FROM mullvad
INNER JOIN country ON ucase(mullvad.Code)=country.Code
INNER JOIN country_continent ON country.Code=country_continent.iso_3166_country
INNER JOIN table_continent ON country_continent.continent_code=table_continent.continent_code
ORDER BY table_continent.continent_lib,country.Pays,mullvad.Serveur;

mysql scsv

Exporter une requête au format CSV

mysql -uadmin -p$(cat /etc/yannick/mariadb) gtkvpn -e "
SELECT table_continent.continent_lib, country.Pays as 'Pays',country.Code as 'Code', mullvad.Ville, mullvad.Serveur, mullvad.IP  
FROM mullvad
INNER JOIN country ON ucase(mullvad.Code)=country.Code
INNER JOIN country_continent ON country.Code=country_continent.iso_3166_country
INNER JOIN table_continent ON country_continent.continent_code=table_continent.continent_code
ORDER BY table_continent.continent_lib,country.Pays,mullvad.Serveur;
" | sed 's/\t/","/g;s/^/"/;s/$/"/;s/\n//g' > serveurs-vpn-mullvad.csv

json mysql

https://mysqlserverteam.com/mysql-8-0-labs-json-aggregation-functions/

Base “gtkvpn” sur PC1

Conversion json :convertcountry-new.json → sql:convertcountry-new.sql

mysql -uadmin -p$(cat /etc/yannick/mariadb) gtkvpn < /media/LaCie/gtkvpn/data/convertcountry-new.sql

Création d’un fichier json à partir d’une base mariadb/mysql

mysql -uadmin -p$(cat /etc/yannick/mariadb) gtkvpn -e "
SELECT
    concat('[',
        GROUP_CONCAT(
               JSON_OBJECT(
                'Continent', table_continent.continent_lib
                ,'Pays', country.Pays
                ,'Code', country.Code
                ,'Ville', mullvad.Ville
                ,'Serveur', mullvad.Serveur
                ,'IP', mullvad.IP
              ) 
       SEPARATOR ',')
    ,']') 
FROM mullvad
INNER JOIN country ON ucase(mullvad.Code)=country.Code
INNER JOIN country_continent ON country.Code=country_continent.iso_3166_country
INNER JOIN table_continent ON country_continent.continent_code=table_continent.continent_code
ORDER BY table_continent.continent_lib,country.Pays,mullvad.Serveur;
" > serveurs-vpn-mullvad.json