Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get correct MAC address from TCP connection?

I am trying to get MAC address of the currenly used network interface.

First of all this simple code based on msdn tcp client example. It is a simplified version of my client app part. It prints out IP address which is used to establish TCP connection with the server (server IP and port are passed as command line parameters). In my client application I get MAC from the IP adress, which I get from socket via getsockname fucntion.

int __cdecl main(int argc, char **argv) 
{
    WSADATA wsaData;
    SOCKET ConnectSocket = INVALID_SOCKET;
    struct addrinfo *result = NULL,
        *ptr = NULL,
        hints;
    int iResult;

    // Validate the parameters
    if (argc != 3) {
        printf("usage: %s server-name port\n", argv[0]);
        return 1;
    }

    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
    if (iResult != 0) {
        printf("WSAStartup failed with error: %d\n", iResult);
        return 1;
    }

    ZeroMemory( &hints, sizeof(hints) );
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;

    // Resolve the server address and port
    iResult = getaddrinfo(argv[1], argv[2], &hints, &result);
    if ( iResult != 0 ) {
        printf("getaddrinfo failed with error: %d\n", iResult);
        WSACleanup();
        return 1;
    }

    // Attempt to connect to an address until one succeeds
    for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) {
        static size_t attempt = 0;
        std::cout << "attempt: " << attempt++ << std::endl;

        // Create a SOCKET for connecting to server
        ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, 
            ptr->ai_protocol);
        if (ConnectSocket == INVALID_SOCKET) {
            printf("socket failed with error: %ld\n", WSAGetLastError());
            WSACleanup();
            return 1;
        }

        // Connect to server.
        iResult = connect( ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
        if (iResult == SOCKET_ERROR) {
            closesocket(ConnectSocket);
            ConnectSocket = INVALID_SOCKET;
            continue;
        }
        break;
    }

    freeaddrinfo(result);

    if (ConnectSocket == INVALID_SOCKET) {
        printf("Unable to connect to server!\n");
        WSACleanup();
        return 1;
    }

    {
        char ip_address_info [128] = "";
        SOCKADDR_IN host = {0};
        int host_size = sizeof (SOCKADDR_IN);  
        int res;

        res = getsockname(ConnectSocket, (SOCKADDR*) &host, &host_size);    
        if (res == 0) {
            sprintf (ip_address_info, "%s:%d", inet_ntoa (host.sin_addr), htons (host.sin_port));
            std::cout << "ip_address_info: " << ip_address_info << std::endl;
        }
        else {
            std::cout << "res == 0 after getsockname" << std::endl;
        }

        host_size = sizeof (SOCKADDR_IN);  
        res = getpeername (ConnectSocket, (SOCKADDR*) &host, &host_size);    
        if (res == 0) {
            sprintf (ip_address_info, "%s:%d", inet_ntoa (host.sin_addr), htons (host.sin_port));   
            std::cout << "ip_address_info: " << ip_address_info << std::endl;
        }
        else {
            std::cout << "res == 0 after getpeername" << std::endl;
        }
    }

    // shutdown the connection since no more data will be sent
    iResult = shutdown(ConnectSocket, SD_SEND);
    if (iResult == SOCKET_ERROR) {
        printf("shutdown failed with error: %d\n", WSAGetLastError());
        closesocket(ConnectSocket);
        WSACleanup();
        return 1;
    }
    std::cout << "shutdown run" << std::endl;

    // cleanup
    closesocket(ConnectSocket);
    WSACleanup();

    return 0;
}

Now the problem and question! When I try using this utility though server port 3128 in my LAN, Kaspersky antivirus (and I assume other antiviruses/farewalls) starts checking it's content (web port or something like that). And I get proxy connection: my app -> Kaspersky -> my server. The IP I get from getsockname function becomes 127.0.0.1. I used to get my currently used MAC from IP in my app, but I can't do so when IP is 127.0.0.1. When I change my server port to something like 2370 all is OK: I get good IP, get MAC. The problem however is that users, who install my program sometimes use proxy servers and port 3128 is common for them, the same goes for antivirus.

  1. Is there a way to get the real IP (outer) which Kaspersky uses to tunnel TCP connection?
  2. Is there other way to find which network adapter is used (it's MAC).

P.S.: I tested this on windows only (and currently interested also), but I assume something like this is possible on other platforms.

like image 557
user3414895 Avatar asked Dec 15 '25 19:12

user3414895


1 Answers

Call GetBestInterfaceEx with your destination socket address.

I believe you use the resulting index value returned from this function to match to the MIB_IFROW array returned from GetIfTable. the MIB_IFROW struct has a member value called bPhysAddr, which is the MAC address.

like image 113
selbie Avatar answered Dec 17 '25 08:12

selbie



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!