简介

在Socket编程的时候,我们需要实时获取我们所需要的IP地址。例如在编写后门的时候,我们可能需要获得有效的外网IP或内网IP;有时候我们可能需要判断我们获取的是否是虚拟机网卡,这时候就需要对每一张网卡上的特征进行识别。以下笔者总结了一些常用的处理方法供大家参考。

参考资料:1.
提取网卡信息方法
              2.
虚拟与物理网卡区分方法

一、什么是物理网卡和虚拟网卡?

图示如下:红色部分包含VMWare的为虚拟网卡。 
图片 1 
通常,我们部署VMWare虚拟机、VMSphere虚拟集群、XenCenter虚拟集群是都会涉及虚拟网卡。 
图片 2

Linux下双物理网卡设置成虚拟网卡

为了提供网络的高可用我们需要将多块网卡绑定设置成一块虚拟的网卡对外提供服务,这样可以防止一块网卡损坏或者防止网线连接故障造成的连接中断。

下面在Linux下我们使用eth0与eth1来虚拟成为bond0为例:——绑定的前提条件:芯片组型号相同,而且网卡应该具备自己独立的BIOS芯片。

操作平台:OLE Linux 6.6

1、创建虚拟网络接口配置文件ifcfg-bond0,并指定网卡IP:vi /etc/sysconfig/
network-scripts/ifcfg-bond0

cat /etc/sysconfig/network-scripts/ifcfg-bond0

DEVICE=bond0

BOOTPROTO=static

IPADDR=10.0.11.10

NETMASK=255.255.252.0

GATWAY=10.0.11.1

ONBOOT=yes

USERCTL=no

TYPE=Ethernet

2、分别修改ifcfg-eth0和ifcfg-eth1—–不能设置有关IP,网关,子网掩码等信息。

cat /etc/sysconfig/network-scripts/ifcfg-eth0

DEVICE=eth0

BOOTPROTO=dhcp

ONBOOT=yes

USERCTL=no

MASTER=bond0

SLAVE=yes

TYPE=Ethernet

cat /etc/sysconfig/network-scripts/ifcfg-eth1

DEVICE=eth1

BOOTPROTO=dhcp

ONBOOT=yes

USERCTL=no

MASTER=bond0

SLAVE=yes

TYPE=Ethernet

3、因为虚拟网卡实在内核模块中实现的,所以需要安装有module,在/etc/modules.conf中添加如下内容,以使系统在启动时加载bonding模块,对外虚拟网络接口设备为
bond0。
加入下列两行
alias bond0 bonding
options bond0 miimon=100 mode=0 —
0表示两块物理网卡是以负载均衡的方式运行。

注:miimon是用来进行链路监测的。比如:miimon=100,那么系统每100ms监测一次链路连接状态,如果有一条线路不通就转入另一条线路;mode的值表示工作模式,他共有0,1,2,3四种模式,常用的为0,1两种。

mode=0表示load balancing
(round-robin)为负载均衡方式,两块网卡都处于active状态。

mode=1表示fault-tolerance
(active-backup)提供冗余功能,就是说默认情况下只有一块网卡处于active,另一块做备份.

如果采用此模式则:options bond0 miimon=100 mode=1
primary=eth0—表示eth0为active状态,eth1为备用状态。

bonding只能提供链路监测,即从主机到交换机的链路是否接通。如果只是交换机对外的链路down掉了,而交换机本身并没有故障,那么bonding会认为链路没有问题而继续使用

4、在/etc/rc.local中添加如下命令。
cat /etc/rc.local

modprobe bonding miimon=100 mode=0

配置完成重启主机. 
Bringing up interface bond0 OK
Bringing up interface eth0 OK
Bringing up interface eth1 OK

本文永久更新链接地址:

为了提供网络的高可用我们需要将多块网卡绑定设置成一块虚拟的网卡对外提供服务,这样可以防止一块…

Linux下双物理网卡设置成虚拟网卡

为了提供网络的高可用我们需要将多块网卡绑定设置成一块虚拟的网卡对外提供服务,这样可以防止一块网卡损坏或者防止网线连接故障造成的连接中断。

下面我们使用eth0与eth1来虚拟成为bond0为例:——绑定的前提条件:芯片组型号相同,而且网卡应该具备自己独立的BIOS芯片.

操作平台:OLE Linux 6.6

1、创建虚拟网络接口配置文件ifcfg-bond0,并指定网卡IP:vi /etc/sysconfig/
network-scripts/ifcfg-bond0

cat /etc/sysconfig/network-scripts/ifcfg-bond0

DEVICE=bond0

BOOTPROTO=static

IPADDR=10.0.11.10

NETMASK=255.255.252.0

GATWAY=10.0.11.1

ONBOOT=yes

USERCTL=no

TYPE=Ethernet

2、分别修改ifcfg-eth0和ifcfg-eth1—–不能设置有关IP,网关,子网掩码等信息。

cat /etc/sysconfig/network-scripts/ifcfg-eth0

DEVICE=eth0

BOOTPROTO=dhcp

ONBOOT=yes

USERCTL=no

MASTER=bond0

SLAVE=yes

TYPE=Ethernet

cat /etc/sysconfig/network-scripts/ifcfg-eth1

DEVICE=eth1

BOOTPROTO=dhcp

ONBOOT=yes

USERCTL=no

MASTER=bond0

SLAVE=yes

TYPE=Ethernet

3、因为虚拟网卡实在内核模块中实现的,所以需要安装有module,在/etc/modules.conf中添加如下内容,以使系统在启动时加载bonding模块,对外虚拟网络接口设备为
bond0。

加入下列两行
alias bond0 bonding
options bond0 miimon=100 mode=0 —
0表示两块物理网卡是以负载均衡的方式运行。

注:miimon是用来进行链路监测的。比如:miimon=100,那么系统每100ms监测一次链路连接状态,如果有一条线路不通就转入另一条线路;mode的值表示工作模式,他共有0,1,2,3四种模式,常用的为0,1两种。

mode=0表示load balancing
(round-robin)为负载均衡方式,两块网卡都处于active状态。

mode=1表示fault-tolerance
(active-backup)提供冗余功能,就是说默认情况下只有一块网卡处于active,另一块做备份.

如果采用此模式则:options bond0 miimon=100 mode=1
primary=eth0—表示eth0为active状态,eth1为备用状态。

bonding只能提供链路监测,即从主机到交换机的链路是否接通。如果只是交换机对外的链路down掉了,而交换机本身并没有故障,那么bonding会认为链路没有问题而继续使用

4、在/etc/rc.local中添加如下命令。

cat /etc/rc.local

modprobe bonding miimon=100 mode=0

配置完成重启主机.
Bringing up interface bond0 OK
Bringing up interface eth0 OK
Bringing up interface eth1 OK

图片 3

为了提供网络的高可用我们需要将多块网卡绑定设置成一块虚拟的网卡对外提供服务,这样可以防止一块…

为了提供网络的高可用我们需要将多块网卡绑定设置成一块虚拟的网卡对外提供服务,这样可以防止一块网卡损坏或者防止网线连接故障造成的连接中断。

C++代码样例

二、辨别物理网卡和虚拟网卡的应用场景

场景一:一般部署虚拟集群的时候会用到。 
场景二:通过抓包分析数据请求来源是物理网卡发出的数据包,还是虚拟网卡地址发出的包时候会用到。辨识都是通过mac地址区分的。 
场景三:其他需要区分网卡的场景。

下面在Linux下我们使用eth0与eth1来虚拟成为bond0为例:——绑定的前提条件:芯片组型号相同,而且网卡应该具备自己独立的BIOS芯片。

1. 头文件(包含特征处理函数)

/////////////////////////////////////////
//
// FileName : NetInfoProc.h
// Creator : PeterZ
// Date : 2018-6-21 23:50
// Comment : 网卡信息筛选
// Editor : Visual Studio 2017
//
/////////////////////////////////////////

#pragma once

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <strsafe.h>
#include <WinSock2.h>
#include <Iphlpapi.h>
#include <cstring>

#pragma comment(lib,"Iphlpapi.lib")

using namespace std;

#define REG_ERROR -2
#define NO_PCI -1
#define IS_PCI 0


/**
 * @brief 查看字符串中是否有指定特征串
 * @param source 指向源字符串的指针
 * @param target 指向目标字符串的指针
 */
BOOL IsInString(LPCSTR source, LPCSTR target)
{
    if (source == NULL && target == NULL)
    {
        return false;
    }
    const size_t targetLength = strlen(target);
    const size_t sourceLength = strlen(source);

    if (sourceLength >= targetLength)
    {
        for (int i = 0; i < strlen(source); i++)
        {
            if (i + targetLength > sourceLength)
            {
                return false;
            }
            for (int j = 0; j < targetLength; j++)
            {
                if (*(source + i + j) != *(target + j))
                {
                    break;
                }
                if (j == targetLength - 1)
                {
                    return true;
                }
            }
        }
    }
    return false;
}

/**
 * @brief 获取注册表数据
 * @param hRoot 根键
 * @param szSubKey 子键
 * @param szValueName 数据项名
 * @param szRegInfo 数据
 */
BOOL GetRegInfo(HKEY hRoot, LPCTSTR szSubKey, LPCTSTR szValueName, LPSTR szRegInfo)
{
    HKEY hKey;
    DWORD dwType = REG_SZ;
    DWORD dwLenData = strlen(szRegInfo);
    LONG lRes = RegCreateKeyEx(hRoot, szSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL);
    if (lRes != ERROR_SUCCESS)
    {
        if (lRes == 5)
        {
            printf("Please use Administrator Privilege !\n");
        }
        else
        {
            printf("Get Register Info Error! Error Code is ");
            printf("%ld\n", lRes);
        }
        RegCloseKey(hKey);
        RegCloseKey(hRoot);
        return false;
    }
    RegQueryValueEx(hKey, szValueName, 0, &dwType, NULL, &dwLenData);
    lRes = RegQueryValueEx(hKey, szValueName, 0, &dwType, (LPBYTE)szRegInfo, &dwLenData);
    if (lRes != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        RegCloseKey(hRoot);
        return false;
    }
    RegCloseKey(hKey);
    RegCloseKey(hRoot);
    return true;
}

/**
 * @brief 验证注册信息是否是PCI物理网卡(需要以管理员权限运行程序)
 * @param pIpAdapterInfo 指向网卡数据的指针
 */
int IsPCINetCard(const PIP_ADAPTER_INFO pIpAdapterInfo)
{
    //通过注册表特征去除非物理网卡
    CHAR szRegSubKey[255] = "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\";
    CHAR szNetCardRegInfo[255] = "\0";
    StringCchCat(szRegSubKey, sizeof(szRegSubKey), pIpAdapterInfo->AdapterName);
    StringCchCat(szRegSubKey, sizeof(szRegSubKey), "\\Connection");
    if (!GetRegInfo(HKEY_LOCAL_MACHINE, szRegSubKey, "PnPInstanceId", szNetCardRegInfo))
    {
        return REG_ERROR;
    }
    if (strncmp(szNetCardRegInfo, "PCI", 3) == 0) return IS_PCI;
    else return NO_PCI;

}


/**
 * @brief 验证是否是虚拟网卡
 * @param pIpAdapterInfo 指向网卡数据的指针
 */
BOOL IsVirtualNetCard(const PIP_ADAPTER_INFO pIpAdapterInfo)
{
    //去除有特征名的虚拟网卡
    if (IsInString(strlwr(pIpAdapterInfo->Description), "virtual")) return true;
    //去除有MAC的虚拟网卡 vmware
    if (pIpAdapterInfo->Address[0] == 0x00 && pIpAdapterInfo->Address[1] == 0x05 && pIpAdapterInfo->Address[2] == 0x69) return true;
    //去除有MAC的虚拟网卡 vmware
    if (pIpAdapterInfo->Address[0] == 0x00 && pIpAdapterInfo->Address[1] == 0x0C && pIpAdapterInfo->Address[2] == 0x29) return true;
    //去除有MAC的虚拟网卡 vmware
    if (pIpAdapterInfo->Address[0] == 0x00 && pIpAdapterInfo->Address[1] == 0x50 && pIpAdapterInfo->Address[2] == 0x56) return true;
    //去除有MAC的虚拟网卡 vmware
    if (pIpAdapterInfo->Address[0] == 0x00 && pIpAdapterInfo->Address[1] == 0x1C && pIpAdapterInfo->Address[2] == 0x14) return true;
    //去除有MAC的虚拟网卡 parallels
    if (pIpAdapterInfo->Address[0] == 0x00 && pIpAdapterInfo->Address[1] == 0x1C && pIpAdapterInfo->Address[2] == 0x42) return true;
    //去除有MAC的虚拟网卡 microsoft virtual pc
    if (pIpAdapterInfo->Address[0] == 0x00 && pIpAdapterInfo->Address[1] == 0x03 && pIpAdapterInfo->Address[2] == 0xFF) return true;
    //去除有MAC的虚拟网卡 virtual iron
    if (pIpAdapterInfo->Address[0] == 0x00 && pIpAdapterInfo->Address[1] == 0x0F && pIpAdapterInfo->Address[2] == 0x4B) return true;
    //去除有MAC的虚拟网卡 red hat xen , oracle vm , xen source, novell xen
    if (pIpAdapterInfo->Address[0] == 0x00 && pIpAdapterInfo->Address[1] == 0x16 && pIpAdapterInfo->Address[2] == 0x3E) return true;
    //去除有MAC的虚拟网卡 virtualbox
    if (pIpAdapterInfo->Address[0] == 0x08 && pIpAdapterInfo->Address[1] == 0x00 && pIpAdapterInfo->Address[2] == 0x27) return true;
    return false;
}


/**
 * @brief 验证是否是0.0.0.0不可用IP
 * @param pIpAdapterInfo 指向网卡数据的指针
 */
BOOL IsInvalidIp(const PIP_ADAPTER_INFO pIpAdapterInfo)
{
    IP_ADDR_STRING *pIpAddrString = &(pIpAdapterInfo->IpAddressList);
    do
    {
        if (!strcmp(pIpAddrString->IpAddress.String, "0.0.0.0"))
        {
            return false;
        }
        if ((pIpAddrString = pIpAddrString->Next) == NULL)
        {
            return true;
        }
    } while (pIpAddrString);
    return true;
}

/**
* @brief 验证是否是内网IP
* @param pIpAdapterInfo 指向网卡数据的指针
*/
BOOL IsIntranetIP(const PIP_ADAPTER_INFO pIpAdapterInfo)
{
    IP_ADDR_STRING *pIpAddrString = &(pIpAdapterInfo->IpAddressList);
    do
    {
        if (strncmp(pIpAddrString->IpAddress.String, "10", 2) == 0 || (strncmp(pIpAddrString->IpAddress.String, "172.16", 6) > 0 && strncmp(pIpAddrString->IpAddress.String, "172.31", 6) < 0) || strncmp(pIpAddrString->IpAddress.String, "192.168", 7) == 0)
        {
            return true;
        }
        if ((pIpAddrString = pIpAddrString->Next) == NULL)
        {
            return false;
        }
    } while (pIpAddrString);
    return true;
}

三、 如何区分物理网卡和虚拟网卡呢?

操作平台:OLE Linux 6.6

2. CPP文件(代码应用演示)

/////////////////////////////////////////
//
// FileName : NetCardVer.cpp
// Creator : PeterZ
// Date : 2018-6-21 23:50
// Comment : 网卡信息筛选
// Editor : Visual Studio 2017
//
/////////////////////////////////////////

#include "NetInfoProc.h"

void Output1(PIP_ADAPTER_INFO pIpAdapterInfo); //结果输出1(正常结果)
void Output2(PIP_ADAPTER_INFO pIpAdapterInfo); //结果输出2(删除虚拟网卡的结果)
void Output3(PIP_ADAPTER_INFO pIpAdapterInfo); //结果输出3(去除非PCI物理网卡) >>需要以管理员权限运行程序<<
void Output4(PIP_ADAPTER_INFO pIpAdapterInfo); //结果输出4(筛选内网网卡)

//主函数
int main(void)
{
    PIP_ADAPTER_INFO pIpAdapterInfo = (PIP_ADAPTER_INFO)malloc(sizeof(IP_ADAPTER_INFO));
    unsigned long stSize = sizeof(IP_ADAPTER_INFO);
    int nRel = GetAdaptersInfo(pIpAdapterInfo, &stSize);
    if (ERROR_BUFFER_OVERFLOW == nRel/*GetAdaptersInfo参数传递的内存空间不足*/)
    {
        //free(pIpAdapterInfo);
        pIpAdapterInfo = (PIP_ADAPTER_INFO)realloc(pIpAdapterInfo, stSize);
        nRel = GetAdaptersInfo(pIpAdapterInfo, &stSize);
    }
    if (ERROR_SUCCESS == nRel)
    {
        printf(">>>>>>>>> 正常结果 <<<<<<<<<<<\n\n");
        Output1(pIpAdapterInfo);
        printf("\n\n>>>>>>>>> 删除虚拟网卡的结果 <<<<<<<<<\n\n");
        Output2(pIpAdapterInfo);
        printf("\n\n>>>>>>>>> 去除非PCI物理网卡的结果 <<<<<<<<<\n\n");
        Output3(pIpAdapterInfo);
        printf("\n\n>>>>>>>>> 筛选内网网卡的结果 <<<<<<<<<\n\n");
        Output4(pIpAdapterInfo);
    }
    if (pIpAdapterInfo)
    {
        free(pIpAdapterInfo);
    }
    system("pause");
    return 0;
}

//结果输出1(正常结果)
void Output1(PIP_ADAPTER_INFO pIpAdapterInfo)
{
    //可能有多网卡,因此通过循环去判断
    while (pIpAdapterInfo)
    {
        //输出信息
        cout << "网卡名称:" << pIpAdapterInfo->AdapterName << endl;
        cout << "网卡描述:" << pIpAdapterInfo->Description << endl;
        cout << "网卡MAC地址:" << pIpAdapterInfo->Address;
        for (UINT i = 0; i < pIpAdapterInfo->AddressLength; i++)
        {
            if (i == pIpAdapterInfo->AddressLength - 1)
            {
                printf("%02x\n", pIpAdapterInfo->Address[i]);
            }
            else
            {
                printf("%02x-", pIpAdapterInfo->Address[i]);
            }
        }
        cout << "网卡IP地址如下:" << endl;
        IP_ADDR_STRING *pIpAddrString = &(pIpAdapterInfo->IpAddressList);
        //可能网卡有多IP,因此通过循环去判断
        do
        {
            cout << pIpAddrString->IpAddress.String << endl;
            pIpAddrString = pIpAddrString->Next;
        } while (pIpAddrString);
        pIpAdapterInfo = pIpAdapterInfo->Next;
        cout << "*****************************************************" << endl;
    }
    return;
}

//结果输出2(删除虚拟网卡的结果)
void Output2(PIP_ADAPTER_INFO pIpAdapterInfo)
{
    //可能有多网卡,因此通过循环去判断
    while (pIpAdapterInfo)
    {
        //去除虚拟网卡IP
        if (IsVirtualNetCard(pIpAdapterInfo))
        {
            pIpAdapterInfo = pIpAdapterInfo->Next;
            continue;
        }
        //输出信息
        cout << "网卡名称:" << pIpAdapterInfo->AdapterName << endl;
        cout << "网卡描述:" << pIpAdapterInfo->Description << endl;
        cout << "网卡MAC地址:" << pIpAdapterInfo->Address;
        for (UINT i = 0; i < pIpAdapterInfo->AddressLength; i++)
        {
            if (i == pIpAdapterInfo->AddressLength - 1)
            {
                printf("%02x\n", pIpAdapterInfo->Address[i]);
            }
            else
            {
                printf("%02x-", pIpAdapterInfo->Address[i]);
            }
        }
        cout << "网卡IP地址如下:" << endl;
        IP_ADDR_STRING *pIpAddrString = &(pIpAdapterInfo->IpAddressList);
        //可能网卡有多IP,因此通过循环去判断
        do
        {
            cout << pIpAddrString->IpAddress.String << endl;
            pIpAddrString = pIpAddrString->Next;
        } while (pIpAddrString);
        pIpAdapterInfo = pIpAdapterInfo->Next;
        cout << "*****************************************************" << endl;
    }
    return;
}

//结果输出3(去除非PCI物理网卡)
void Output3(PIP_ADAPTER_INFO pIpAdapterInfo)
{
    //可能有多网卡,因此通过循环去判断
    while (pIpAdapterInfo)
    {
        //去除非PCI物理网卡
        if (IsPCINetCard(pIpAdapterInfo) != IS_PCI)
        {
            if (IsPCINetCard(pIpAdapterInfo) == REG_ERROR)
            {
                printf("1\n");
                return;
            }
            pIpAdapterInfo = pIpAdapterInfo->Next;
            continue;
        }
        //输出信息
        cout << "网卡名称:" << pIpAdapterInfo->AdapterName << endl;
        cout << "网卡描述:" << pIpAdapterInfo->Description << endl;
        cout << "网卡MAC地址:" << pIpAdapterInfo->Address;
        for (UINT i = 0; i < pIpAdapterInfo->AddressLength; i++)
        {
            if (i == pIpAdapterInfo->AddressLength - 1)
            {
                printf("%02x\n", pIpAdapterInfo->Address[i]);
            }
            else
            {
                printf("%02x-", pIpAdapterInfo->Address[i]);
            }
        }
        cout << "网卡IP地址如下:" << endl;
        IP_ADDR_STRING *pIpAddrString = &(pIpAdapterInfo->IpAddressList);
        //可能网卡有多IP,因此通过循环去判断
        do
        {
            cout << pIpAddrString->IpAddress.String << endl;
            pIpAddrString = pIpAddrString->Next;
        } while (pIpAddrString);
        pIpAdapterInfo = pIpAdapterInfo->Next;
        cout << "*****************************************************" << endl;
    }
    return;
}

//结果输出4(筛选内网网卡)
void Output4(PIP_ADAPTER_INFO pIpAdapterInfo)
{
    //可能有多网卡,因此通过循环去判断
    while (pIpAdapterInfo)
    {
        //筛选内网网卡
        if (!IsIntranetIP(pIpAdapterInfo))
        {
            pIpAdapterInfo = pIpAdapterInfo->Next;
            continue;
        }
        //输出信息
        cout << "网卡名称:" << pIpAdapterInfo->AdapterName << endl;
        cout << "网卡描述:" << pIpAdapterInfo->Description << endl;
        cout << "网卡MAC地址:" << pIpAdapterInfo->Address;
        for (UINT i = 0; i < pIpAdapterInfo->AddressLength; i++)
        {
            if (i == pIpAdapterInfo->AddressLength - 1)
            {
                printf("%02x\n", pIpAdapterInfo->Address[i]);
            }
            else
            {
                printf("%02x-", pIpAdapterInfo->Address[i]);
            }
        }
        cout << "网卡IP地址如下:" << endl;
        IP_ADDR_STRING *pIpAddrString = &(pIpAdapterInfo->IpAddressList);
        //可能网卡有多IP,因此通过循环去判断
        do
        {
            cout << pIpAddrString->IpAddress.String << endl;
            pIpAddrString = pIpAddrString->Next;
        } while (pIpAddrString);
        pIpAdapterInfo = pIpAdapterInfo->Next;
        cout << "*****************************************************" << endl;
    }
    return;
}

方法一:老套且仅适用于windows操作系统。

原理大致如: 
先由 GetAdaptersInfo
获取所有网卡的基本信息。然后利用网卡名去注册表中查找对应的硬件信息。若是物理网卡,其硬件信息中通常会包含
PCI 。 
例如,某个网卡的名为 {ACA306D0-1D69-4116-BC2B-919B428AD084}。 
他在注册表中的信息所在位置为: 
HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Network/{4D36E972-E325-11CE-BFC1-08002BE10318}/{ACA306D0-1D69-4116-BC2B-919B428AD084}/Connection 
若PnpInstanceID的值以PCI开头,说明是物理网卡,MediaSubType为01则是常见网卡,02为无线网卡。 
图片 4

常见08年早期博客实现: 

该方法仅适用于windows操作系统,不具备普遍通用性。

1、创建虚拟网络接口配置文件ifcfg-bond0,并指定网卡IP:vi /etc/sysconfig/
network-scripts/ifcfg-bond0

方法二:综合stackoverflow和github得出(2016年10月8日)。

cat /etc/sysconfig/network-scripts/ifcfg-bond0

1、包含以下MAC地址的前8个字节(前3段)是虚拟网卡:

"00:05:69"; //vmware1
"00:0C:29"; //vmware2
"00:50:56"; //vmware3
"00:1c:14"; //vmware4
"00:1C:42"; //parallels1
"00:03:FF"; //microsoft virtual pc
"00:0F:4B"; //virtual iron 4
"00:16:3E"; //red hat xen , oracle vm , xen source, novell xen
"08:00:27"; //virtualbox

举例以下的网卡地址中:

Line 34: PhysicalAddress: 00:FF:C4:73:16:0D
Line 110: PhysicalAddress: 8C:89:A5:BD:1A:6A
Line 215: PhysicalAddress: 00:50:56:C0:00:01
Line 316: PhysicalAddress: 00:50:56:C0:00:08

 

后两个以00:50:56 开头的都是VMWare虚拟网卡地址。

基于此:实现也就非常简单,思路如下: 
获取网卡地址后,判定前8个字节,循环变量上面的列表,如果前8个字节相同,终止程序,即为虚拟网卡地址;否则为物理网卡地址。

DEVICE=bond0

2、以下链接进行了虚拟网卡类别区分探讨:

BOOTPROTO=static

3、以下链接给出了虚拟网卡全分类的接口实现:

IPADDR=10.0.11.10

4、可能疑问?

1)如果包含的不全是不是会不准确。 
是的,需要集思广益,多搜集资料,使得尽量全面。

NETMASK=255.255.252.0

四:小结

刚入职的时候分析数据包,架构师一眼就能区分出哪些是VMWare机器发送的,现在才知道是基于Mac地址的前几位得出的结论。 
而我知道这个原理比架构师足足晚了2年,这,或许就是差距和值得努力的地方!

2016年10月8日 23:59 思于家中床前

作者:铭毅天下 
转载请标明出处,原文地址: 
 
如果感觉本文对您有帮助,请点击‘顶’支持一下,您的支持是我坚持写作最大的动力,谢谢!

GATWAY=10.0.11.1

ONBOOT=yes

USERCTL=no

TYPE=Ethernet

2、分别修改ifcfg-eth0和ifcfg-eth1—–不能设置有关IP,网关,子网掩码等信息。

cat /etc/sysconfig/network-scripts/ifcfg-eth0

DEVICE=eth0

BOOTPROTO=dhcp

ONBOOT=yes

USERCTL=no

MASTER=bond0

SLAVE=yes

TYPE=Ethernet

cat /etc/sysconfig/network-scripts/ifcfg-eth1

DEVICE=eth1

BOOTPROTO=dhcp

ONBOOT=yes

USERCTL=no

MASTER=bond0

SLAVE=yes

TYPE=Ethernet

3、因为虚拟网卡实在内核模块中实现的,所以需要安装有module,在/etc/modules.conf中添加如下内容,以使系统在启动时加载bonding模块,对外虚拟网络接口设备为
bond0。
加入下列两行
alias bond0 bonding
options bond0 miimon=100 mode=0 —
0表示两块物理网卡是以负载均衡的方式运行。

注:miimon是用来进行链路监测的。比如:miimon=100,那么系统每100ms监测一次链路连接状态,如果有一条线路不通就转入另一条线路;mode的值表示工作模式,他共有0,1,2,3四种模式,常用的为0,1两种。

mode=0表示load balancing
(round-robin)为负载均衡方式,两块网卡都处于active状态。

mode=1表示fault-tolerance
(active-backup)提供冗余功能,就是说默认情况下只有一块网卡处于active,另一块做备份.

如果采用此模式则:options bond0 miimon=100 mode=1
primary=eth0—表示eth0为active状态,eth1为备用状态。

bonding只能提供链路监测,即从主机到交换机的链路是否接通。如果只是交换机对外的链路down掉了,而交换机本身并没有故障,那么bonding会认为链路没有问题而继续使用

4、在/etc/rc.local中添加如下命令。
cat /etc/rc.local

modprobe bonding miimon=100 mode=0

配置完成重启主机. 
Bringing up interface bond0 OK
Bringing up interface eth0 OK
Bringing up interface eth1 OK

本文永久更新链接地址:http://www.linuxidc.com/Linux/2015-06/119287.htm

图片 5

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图