1 votes

Trouver l'adresse MAC à partir de l'IP

Duplicata possible :
Obtenir l'adresse MAC de l'hôte distant

Je travaille sur un module qui a une architecture client-serveur. Et je dois authentifier la machine de l'homologue qui se connecte sur la base de l'adresse Mac.

Au moment de l'installation, je stocke une liste cryptée d'adresses Mac valides.

Veuillez noter que je n'ai aucun contrôle sur cette machine et qu'une application tierce sera exécutée sur celle-ci. Je ne peux pas installer d'application sur cette machine.

Au moment de l'exécution, lorsque la connexion par socket se produit, j'ai besoin de connaître le Mac Id de l'IP utilisé dans la connexion, afin de pouvoir le valider par rapport à l'adresse Mac précédemment stockée.

Existe-t-il une API C/C++ qui puisse m'aider à obtenir l'adresse MAC à partir de l'adresse IP ? Cette machine est généralement connectée à un réseau local mais peut se trouver sur différents sous-réseaux.

Mon module est multiplateforme et fonctionne sous Windows, Solaris et Linux. De la même manière, le module pair peut fonctionner sur n'importe quel système d'exploitation.

8voto

Daniel Beck Points 196

Malheureusement, la réponse simple est vraiment "ne faites pas ça".

Si les machines de votre homologue se trouvent sur un sous-réseau différent (et donc que le trafic entre vous et l'homologue passe par un routeur), il n'y a aucun moyen de faire ce que vous voulez -- l'adresse MAC des paquets que vous recevez sera l'adresse MAC du routeur qui vous les a transmis, car c'est le périphérique de la couche de liaison avec lequel vous communiquez. Seul le routeur le plus proche de la machine homologue connaîtra l'adresse MAC de cette dernière - et cette information n'est pas transmise.

Si les machines homologues se trouvent sur le même sous-réseau, les paquets entrants contiendront l'adresse MAC de l'homologue dans l'en-tête Ethernet... mais celle-ci sera supprimée avant que le paquet ne soit livré à votre application. Vos options sont pratiquement limitées à la capture de paquets sur l'interface réseau que vous écoutez pour obtenir le paquet entier, ou à l'utilisation des outils fournis par votre système pour vérifier la table ARP locale. Ces deux options sont très dépendantes de la plate-forme !

De plus, aucune des deux options n'est susceptible de continuer à fonctionner sans modification si les interfaces avec lesquelles vous travaillez ne sont pas des interfaces Ethernet (il peut s'agir de liaisons PPP, ou de WiFi, ou d'une interface virtuelle quelconque, ...), et elles ne fonctionneront pas non plus avec IPv6.

Si après tout cela, vous êtes toujours déterminé, regardez dans libpcap / WinPCap pour la capture de paquets, qui est l'option la plus portable qui vient à l'esprit. Pour vérifier les tables ARP locales, Linux, OS X, Solaris et Windows fournissent tous une fonction de vérification de l'adresse IP. arp l'utilitaire de ligne de commande, mais la syntaxe est susceptible de varier. Si une API est disponible, je ne m'attends pas à ce qu'elle soit commune aux différentes plates-formes - il n'y a pas de norme pour ce genre de choses, parce que vous ne devriez vraiment pas le faire !

2voto

sigjuice Points 9166

C'est impossible à faire. Il n'y a aucune garantie que votre partenaire de connexion ait une adresse MAC. Il est tout à fait possible que l'homologue se connecte au réseau via un accès commuté (PPP) ou une autre interface non Ethernet.

1voto

mcandre Points 6965

Ne pas authentifier par l'adresse MAC. Il est facile de les usurper. Utilisez une bibliothèque d'authentification HTTP comme Chilkat .

1voto

Marc Points 2019

Comme mcandre l'a mentionné, il est incroyablement facile d'usurper des adresses mac, mais pour répondre à votre question, je pense que vous pouvez le faire sur tous les OS par le biais de sockets de type BSD si vous êtes sur le même LAN :

Voici un exemple de code tiré de ce message du forum

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <arpa/inet.h>

int main(int argc, char *argv[]) {
    struct ifreq ifr;
    int sock, j, k;
    char *p, addr[32], mask[32], mac[32];

    if (argc<2) {
        fprintf(stderr,"missing argument, example: eth0\n");
        return 1;
    }

    sock=socket(PF_INET, SOCK_STREAM, 0);
    if (-1==sock) {
        perror("socket() ");
        return 1;
    }

    strncpy(ifr.ifr_name,argv[1],sizeof(ifr.ifr_name)-1);
    ifr.ifr_name[sizeof(ifr.ifr_name)-1]='\0';

    if (-1==ioctl(sock, SIOCGIFADDR, &ifr)) {
        perror("ioctl(SIOCGIFADDR) ");
        return 1;
    }
    p=inet_ntoa(((struct sockaddr_in *)(&ifr.ifr_addr))->sin_addr);
    strncpy(addr,p,sizeof(addr)-1);
    addr[sizeof(addr)-1]='\0';

    if (-1==ioctl(sock, SIOCGIFNETMASK, &ifr)) {
        perror("ioctl(SIOCGIFNETMASK) ");
            return 1;
        }
        p=inet_ntoa(((struct sockaddr_in *)(&ifr.ifr_netmask))->sin_addr);
        strncpy(mask,p,sizeof(mask)-1);
        mask[sizeof(mask)-1]='\0';

        if (-1==ioctl(sock, SIOCGIFHWADDR, &ifr)) {
        perror("ioctl(SIOCGIFHWADDR) ");
        return 1;
    }
    for (j=0, k=0; j<6; j++) {
        k+=snprintf(mac+k, sizeof(mac)-k-1, j ? ":%02X" : "%02X",
            (int)(unsigned int)(unsigned char)ifr.ifr_hwaddr.sa_data[j]);
    }
    mac[sizeof(mac)-1]='\0';

    printf("\n");
    printf("name:    %s\n",ifr.ifr_name);
    printf("address: %s\n",addr);
    printf("netmask: %s\n",mask);
    printf("macaddr: %s\n",mac);
    printf("\n");

    close(sock);
    return 0;
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X