2009-07-09 2 views
1

Можно создать дубликат:
Getting the MAC address of the remote hostПоиск MAC-адрес из IP-адреса

Я работаю над модулем, который имеет архитектуру клиент-сервер. И я должен аутентифицировать подключаемую одноранговую машину на основе MAC address.

Во время установки я хранил зашифрованный список допустимых MAC-адресов.

Обратите внимание: я не контролирую эту одноранговую машину, и на ней будет работать какое-либо стороннее приложение, и я не могу установить какое-либо приложение на эту одноранговую машину.

Во время работы, когда происходит соединение сокета, мне нужно знать MAC-адрес для IP-адреса, используемого в соединении, чтобы я мог проверить его на ранее сохраненном MAC-адресе.

Существуют ли какие-либо доступные API C/C++, которые могут помочь мне получить MAC-адрес с IP-адреса. Этот аппарат обычно подключается в локальной сети, но он может быть в разных подсетях.

Мой модуль является мультиплатформенным и работает в Windows, Solaris и Linux, а аналогичная машина может работать на любой ОС.

+4

Если вы потратили две минуты на поиск «MAC-адреса», вы бы нашли http://stackoverflow.com/questions/1092463/getting-the-mac-address-of-the-remote-host и несколько других сообщая вам, что это принципиально невозможно, если две машины не находятся в одной локальной сети. –

+0

Моя ошибка, я пропустил этот вопрос. В большинстве случаев сверстники находятся в одной подсети, но есть возможность разной подсети. Я рассмотрю упомянутый вопрос. – nurxb01

+0

На самом деле, я предлагаю вам попробовать http://stackoverflow.com/search?q=mac%20address&tab=newest. –

ответ

1

Не аутентифицировать по MAC-адресу. Их легко обмануть. Используйте библиотеку проверки подлинности HTTP, такую ​​как Chilkat.

+0

Одноранговые приложения - это простое приложение для сокетов tcp/ip, на котором у меня нет никакого контроля. Я не могу установить какое-либо из моих приложений на этом peer m/c. – nurxb01

8

К сожалению, простой ответ действительно «не делай этого».

Если ваши одноранговые машины находятся в другой подсети (и, следовательно, трафик между вами и партнером проходит через маршрутизатор), тогда нет способа сделать то, что вы хотите - MAC-адрес пакетов, которые вы получаете, будет MAC-адрес маршрутизатора, который перенаправил их вам, поскольку это устройство уровня канала, с которым вы общаетесь. Только маршрутизатор, ближайший к одноранговой машине, будет знать, что такое MAC-адрес партнера, и эта информация не передается.

Если одноранговые компьютеры находятся в одной подсети, тогда входящие пакеты будут содержать MAC-адрес однорангового узла в заголовке Ethernet ... но это будет удалено до того, как пакет будет доставлен в ваше приложение. Ваши параметры в значительной степени ограничены захватом пакетов в сетевом интерфейсе, который вы слушаете, чтобы получить весь пакет, или используя любые инструменты, которые ваша система предоставляет для проверки локальной таблицы ARP. Оба эти параметра очень зависят от платформы!

Кроме того, ни один из вариантов, скорее всего, не будет работать без изменений, если интерфейсы, с которыми вы имеете дело, не являются интерфейсами Ethernet (возможно, это PPP-ссылки или Wi-Fi или фанки-виртуализированный интерфейс какого-то типа, .. .), и они не будут работать с IPv6.

Если после всего этого вы все еще определились, просмотрите libpcap/WinPCap для захвата пакетов, что является самым переносимым вариантом, который приходит на ум. Чтобы проверить локальные таблицы ARP, Linux, OS X, Solaris и Windows предоставляют утилиту командной строки arp, но синтаксис, вероятно, будет отличаться. Если API доступен, я бы не ожидал никакой общности между платформами - для такого типа нет стандарта, потому что вы действительно не должны этого делать!

+0

Стивен, я думаю, теперь изменит мою стратегию. :) и спасибо за упоминание ссылки libpcap. – nurxb01

1

Как mcandre упоминалось, это невероятно легко подделать MAC-адреса, но все-таки ответить на ваш вопрос, я думаю, что вы можете сделать это на всех ОС через сокеты BSD-стиля, если вы находитесь на той же локальной сети:

Вот пример кода от this forum post

#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; 
} 
+0

SIOCGIFADDR получает адрес локального интерфейса, OP был после адреса удаленного партнера. – caf

+0

oops - не слишком внимательно смотрел на то, что я копировал, потому что я был на работе. Отредактировано, чтобы удалить этот раздел, поскольку он посторонний. благодаря – Marc

2

Это невозможно сделать. Нет гарантии, что ваш партнерский узел даже имеет MAC-адрес. Вполне возможно, что одноранговый узел подключается к сети через dial-up (PPP) или какой-либо другой не-Ethernet-интерфейс.