如何跨网段取MAC地址

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何跨网段取MAC地址相关的知识,希望对你有一定的参考价值。

我想做一款软件,在学院机房实现一个功能,比如通过IP段取得MAC地址,这样我就知道有没有同学乱改IP了,然而我们的机房有好几个,都是学校信息中心分给我们学院的不同段的。我在网上查了一下,基本99%的人都说不同段的不能获取MAC地址,我就很凌乱了,为什么我随便在互联网上下载一款局域网软件都带这个不同段取MAC的功能,比如“LanSee”。这些不软不都是人开发的吗?为什么进几年的帖子知道几乎都统一口径说查不到呢?真奇怪。我想知道这款软件如何实现的,原理,最好能带上详细关键代码,什么语言我都接受,最好是D语言。

跨网段获取MAC地址方法如下:
protected void Page_Load(object sender, EventArgs e)

//ReadMSG();

if (!IsPostBack)

Label1.Text =
"//客户端ip:" +

Request.ServerVariables.Get("Remote_Addr").ToString() + "<br>" +
" //客户端主机名:" +
Request.ServerVariables.Get("Remote_Host").ToString() + "<br>" +
"//客户端浏览器IE:" +
Request.Browser.Browser + "<br>" +
"//客户端浏览器 版本号:" +
Request.Browser.MajorVersion + "<br>" +
"//客户端操作系统:" +
Request.Browser.Platform + "<br>" +
"//服务器ip:" +
Request.ServerVariables.Get("Local_Addr").ToString() + "<br>" +
"//服务器名:" +
Request.ServerVariables.Get("Server_Name").ToString() + "<br>";

string stringMAC = "";
string stringIP = "";
ManagementClass MC = new ManagementClass("Win32_NetworkAdapterConfiguration");
ManagementObjectCollection MOC = MC.GetInstances();

foreach (ManagementObject MO in MOC)

if ((bool)MO["IPEnabled"] == true)

stringMAC += MO["MACAddress"].ToString(); //获取网卡的地址
string[] IPAddresses = (string[])MO["IPAddress"]; //获取本地的IP地址
if (IPAddresses.Length > 0)
stringIP = IPAddresses[0];
Label1.Text += "<br>MAC:" + stringMAC + "/ IP:" + stringIP;
if (stringIP == "192.168.1.45")
Label1.Text += "<br>I get you :192.168.1.45<br>";



//在页面上打印出客户端的网卡物理地址(MAC)
//Response.Write(this.GetMac(Request.UserHostAddress.ToString())+"<br>");
GetInfo();


//获取cpu序列号,硬盘ID,网卡MAC地址
private void GetInfo()

string cpuInfo = "";//cpu序列号
ManagementClass cimobject = new ManagementClass("Win32_Processor");
ManagementObjectCollection moc = cimobject.GetInstances();
foreach (ManagementObject mo in moc)

cpuInfo = mo.Properties["ProcessorId"].Value.ToString();
Label1.Text += "cpu序列号:" + cpuInfo.ToString();


//获取硬盘ID
String HDid;
ManagementClass cimobject1 = new ManagementClass("Win32_DiskDrive");
ManagementObjectCollection moc1 = cimobject1.GetInstances();
foreach (ManagementObject mo in moc1)

HDid = (string)mo.Properties["Model"].Value;
Label1.Text += "硬盘序列号:" + HDid.ToString();




//protected void Button1_Click(object sender, EventArgs e)
//

// try
//
// File.Delete(@"D:\\html.html");
//
// catch (Exception e2)
//
// Response.Write(e2.Message);
//
// Response.Write("Delete Successed!");

//

//获取远程客户端的网卡物理地址(MAC)
public string GetMac(string IP) //para IP is the client\'s IP

string dirResults = "";
ProcessStartInfo psi = new ProcessStartInfo();
Process proc = new Process();
psi.FileName = "nbtstat";
psi.RedirectStandardInput = false;
psi.RedirectStandardOutput = true;
psi.Arguments = "-A " + IP;
psi.UseShellExecute = false;
proc = Process.Start(psi);
dirResults = proc.StandardOutput.ReadToEnd();
proc.WaitForExit();
dirResults = dirResults.Replace("\\r", "").Replace("\\n", "").Replace("\\t", "");

Regex reg = new Regex("Mac[ ]0,Address[ ]0,=[ ]0,(?<key>((.)*?))__MAC", RegexOptions.IgnoreCase | RegexOptions.Compiled);
Match mc = reg.Match(dirResults + "__MAC");

if (mc.Success)

return mc.Groups["key"].Value;

else

reg = new Regex("Host not found", RegexOptions.IgnoreCase | RegexOptions.Compiled);
mc = reg.Match(dirResults);
if (mc.Success)

return "Host not found!";

else

return "";


参考技术A 不同网段是直接获取不到mac的,只有通过与目标在同网段的设备(主机)才能取到mac。追问

为什么网络上的回答会千篇一律呢?请问为什么我下载了大小1M的LanSee软件,然后就做到了呢?我把学校分给我们学院几个段的IP都填进了,点下搜索只需10秒钟所有段的IP,用户名,MAC,计算机名,工作组,共享文件,打印机,全部都出来了。我只要取MAC地址,请问别人为什么能在1M大小的软件里面实现,我想是你们还没掌握的技术吧,那你这样乱下结论是否不负责呢?

追答

我不是说获取不到,是说需要条件。比如你可以通过连接IP(电脑)的某些服务获取到某些信息,如果那个IP的那个服务不开你自然就无法获取到。你可以试试获取运营商网内ip的信息看看能获取到什么。

追问

我在学校环境里,都是局域网,上外网必须登录校园网输入用户名才能访问。我们学院就几个IP段,我只想通过这种方式(因为IP段我肯定知道),做到有人乱改我能第一时间在我的电脑上发现,现在都有保护还原设置,博士生希望能开放方便他们使用,但有不自觉的乱改IP导致教师工作室经过被冲突上不了网。LanSee是可以实现我的需求,但缺乏IP与MAC核对功能。既然可以实现,我现在需要是思路,我好自己编写一款软件。

追答

直接连IP获取mac必然有限制,如果电脑有防火墙之类不让你访问它就不行了。每个网段都有网关的,网关设备上必然有ip与mac的对应信息,如果网关设备支持snmp,你就可以通过snmp读到这些信息。

参考技术B 不同网段获取主机MAC地址是可以得,但是需要对方开启netbios可以探测的服务,我们在使用工具的时候扫描的时候,netbios回复报文带有MAC地址信息

Docker 容器跨主机多网段通信解决方案

一、MacVlan
实现Docker的跨主机网络通信的方案有很多,如之前博文中写到的通过部署 Consul服务实现Docker容器跨主机通信

Macvlan工作原理:

Macvlan是Linux内核支持的网络接口。要求的Linux内部版本是v3.9–3.19和4.0+;
通过为物理网卡创建Macvlan子接口,允许一块物理网卡拥有多个独立的MAC地址和IP地址。虚拟出来的子接口将直接暴露在相邻物理网络中。从外部看来,就像是把网线隔开多股,分别接受了不同的主机上一样;
物理网卡收到包后,会根据收到包的目的MAC地址判断这个包需要交给其中虚拟网卡。

当容器需要直连入物理网络时,可以使用Macvlan。Macvlan本身不创建网络,本质上首先使宿主机物理网卡工作在‘混杂模式’,这样物理网卡的MAC地址将会失效,所有二层网络中的流量物理网卡都能收到。接下来就是在这张物理网卡上创建虚拟网卡,并为虚拟网卡指定MAC地址,实现一卡多用,在物理网络看来,每张虚拟网卡都是一个单独的接口。

使用Macvlan注意:

  • 容器直接连接物理网络,由物理网络负责分配IP地址,可能的结果是物理网络IP地址被耗尽,另一个后果是网络性能问题,物理网络中接入的主机变多,广播包占比快速升高而引起的网络性能下降问题;
  • 宿主机上的某张网上需要工作在‘混乱模式’下;
  • 前面说到,工作在混乱模式下的物理网卡,其MAC地址会失效,所以,此模式中运行的容器并不能与外网进行通信,但是不会影响宿主机与外网通信;
  • 从长远来看bridge网络与overlay网络是更好的选择,原因就是虚拟网络应该与物理网络隔离而不是共享。

工作示意图:
技术图片
二、配置实例
实例1(实现容器基于macvlan的单网段跨主机通信)

实现效果:

两台centos 7.3,分别运行着docker服务;
两台docker服务器创建相同的一个MacVlan网络,使docker服务器上的容器可以实现跨主机通信。

开始配置
1、第一台docker服务器配置如下

[root@docker01 ~]# ip link set ens33 promisc on             # 开启ens33网卡的混杂模式
[root@docker01 ~]# ip link show ens33      # 确定查看的信息包含以下标红的字样
2: ens33: <BROADCAST,MULTICAST,‘PROMISC‘,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
    link/ether 00:0c:29:9f:33:9f brd ff:ff:ff:ff:ff:ff
[root@docker01 ~]# docker network create -d macvlan --subnet 172.22.16.0/24 --gateway 172.22.16.1 -o pa
rent=ens33 mac_net1
#创建macvlan网络,指定网关、网段等信息,“-o”指定绑定在哪张网卡之上
[root@docker01 ~]# docker run -itd --name test1 --ip 172.22.16.10 --network mac_net1 busybox     # 基于新创建的macvlan网络运行一个容器,并指定其IP

确认运行的容器的IP地址

[root@docker01 ~]# docker exec test1 ip a     # 查看IP,确定以下标红与配置的一样
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
6: eth0@if2: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:16:10:0a brd ff:ff:ff:ff:ff:ff
    inet ‘172.22.16.10/24‘ brd 172.22.16.255 scope global eth0
       valid_lft forever preferred_lft forever

2、第二台docker服务器配置如下(与第一台docker服务器基本相似)

[root@docker02 ~]# ip link set ens33 promisc on       # 开启混杂模式
[root@docker02 ~]# ip link show ens33 
2: ens33: <BROADCAST,MULTICAST,‘PROMISC‘,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
    link/ether 00:0c:29:b5:bc:ed brd ff:ff:ff:ff:ff:ff
[root@docker02 ~]# docker network create -d macvlan --subnet 172.22.16.0/24 --gateway=172.22.16.1 -o parent=ens33 mac_net1
#创建一个与第一台docker服务器的网段、网关相同的macvlan。并绑定到物理网卡上。
#为了可以直观的看出其他docker服务器上的macvlan和第这台是在同一个网段的。所以,建议设置的网络名称一样。
[root@docker02 ~]# docker run -itd --name test2 --ip 172.22.16.11 --network mac_net1 busybox
#运行一个容器,并指定是基于macvlan网络的
#注意,其IP地址不要与其他docker服务器上的容器IP地址冲突

确认运行的容器的IP地址

[root@docker02 ~]# docker exec test2 ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
6: eth0@if2: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:16:10:0b brd ff:ff:ff:ff:ff:ff
    inet ‘172.22.16.11/24‘ brd 172.22.16.255 scope global eth0
       valid_lft forever preferred_lft forever

使用第二台docker服务器上的容器test2对第一台docker服务器上的容器test1进行ping测试
技术图片
OK,跨主机的容器通信就通过macvlan实现了。由于使用混杂模式会造成物理网卡的MAC地址失效,所以容器并不能通过此模式进行与外网的通信。

实例2(基于macvlan的跨主机网络多网段的解决方案)

实现的效果如下:

  • 两台centos 7.3,分别运行着docker服务;
  • 每台宿主机创建了两个MacVlan网段供容器使用(172.10.16.0/24和172.20.16.0/24);
  • 第一台docker服务器上运行容器test1和test2,第二台docker服务器运行容器test3和test4。
  • 最终实现跨主机的同网段容器互相通信。

开始配置:
1、第一台docker服务器配置如下

[root@docker01 ~]# ip link set ens33 promisc on             # 开启ens33网卡的混杂模式
#也就是开启网卡的多个虚拟interface(接口)  
[root@docker01 ~]# ip link show ens33      # 确定查看的信息包含以下标红的字样
2: ens33: <BROADCAST,MULTICAST,‘PROMISC‘,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
    link/ether 00:0c:29:9f:33:9f brd ff:ff:ff:ff:ff:ff
[root@docker01 ~]# modinfo 8021q
 #查看是否加载8021q模块,如果有信息返回,则表示该模块已经加载

modinfo 8021q命令返回的信息如下
技术图片

[root@docker01 ~]# modprobe 8021q     #若没有加载8021q模块,则执行此命令
[root@docker01 ~]# cd /etc/sysconfig/network-scripts/
[root@docker01 network-scripts]# vim ifcfg-ens33  
                     ...................
BOOTPROTO=manual             # 将此配置项改为“manual”,也是手动的意思
[root@docker01 network-scripts]# cp -p ifcfg-ens33 ifcfg-ens33.10             # 复制一份网卡配置文件,-p保留原本文件的属性
[root@docker01 network-scripts]# vim ifcfg-ens33.10 
BOOTPROTO=none 
NAME=ens33.10               #注意更改名称
DEVICE=ens33.10      #注意更改名称
ONBOOT=yes
IPADDR=192.168.10.11             # 给虚拟网卡设置一个IP
PREFIX=24
GATEWAY=192.168.10.2
VLAN=yes
[root@docker01 network-scripts]# cp ifcfg-ens33.10 ifcfg-ens33.20 
[root@docker01 network-scripts]# vim ifcfg-ens33.20 
BOOTPROTO=none
NAME=ens33.20
DEVICE=ens33.20
ONBOOT=yes
IPADDR=192.168.20.10               #  注意,此处的IP与ens33.10并不在同一网段
PREFIX=24
GATEWAY=192.168.20.2
VLAN=yes
[root@docker01 network-scripts]# ifdown ens33;ifup ens33          #重启网卡,使更改生效
[root@docker01 network-scripts]# ifup ens33.10      # 启动该网卡
[root@docker01 network-scripts]# ifup ens33.20     # 启动
[root@docker01 ~]# docker network create -d macvlan --subnet 172.10.16.0/24 --gateway 172.10.16.1 -o parent=ens33.10 mac_net10
#创建一个macvlan网络,给其定义一个网段、网关及绑定到ens33.10
[root@docker01 ~]# docker network create -d macvlan --subnet 172.20.16.0/24 --gateway 172.20.16.1 -o parent=ens33.20 mac_net20
#创建一个macvlan网络,给其定义一个网段、网关及绑定到ens33.20
#接下来分别基于刚刚创建的macvlan网络运行一个容器

2、第二台docker服务器配置如下(基本与第一台操作类似,要注意IP不要冲突)

[root@docker02 ~]# ip link set ens33 promisc on       # 开启混杂模式
[root@docker02 ~]# ip link show ens33 
2: ens33: <BROADCAST,MULTICAST,‘PROMISC‘,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
    link/ether 00:0c:29:b5:bc:ed brd ff:ff:ff:ff:ff:ff
[root@docker02 ~]# modinfo 8021q
返回信息可参考图一
[root@docker02 ~]# modprobe 8021q     #若没有加载8021q模块,则执行此命令
[root@docker02 ~]# cd /etc/sysconfig/network-scripts/
[root@docker02 network-scripts]# vim ifcfg-ens33 
            ...............#省略部分内容
BOOTPROTO=manual        
[root@docker02 network-scripts]# scp root@192.168.171.151:/etc/sysconfig/network-scripts/ifcfg-ens33.* .                 # 要注意后面的“.”
ifcfg-ens33.10                                                       100%  128    83.4KB/s   00:00    
ifcfg-ens33.20                                                       100%  124    75.0KB/s   00:00  
[root@docker02 network-scripts]# vim ifcfg-ens33.10 
BOOTPROTO=none
NAME=ens33.10
DEVICE=ens33.10
ONBOOT=yes
IPADDR=192.168.10.11           # 更改IP,以防和第一台冲突
PREFIX=24
GATEWAY=192.168.10.2
VLAN=yes
[root@docker02 network-scripts]# vim ifcfg-ens33.20 

BOOTPROTO=none
NAME=ens33.20
DEVICE=ens33.20
ONBOOT=yes
IPADDR=192.168.20.11
PREFIX=24
GATEWAY=192.168.20.2
VLAN=yes
[root@docker02 network-scripts]# ifdown ens33;ifup ens33         # 重启网卡 ,使配置生效
[root@docker02 network-scripts]# ifup ens33.10     # 启动网卡
[root@docker02 network-scripts]# ifup ens33.20
#接下来创建macvlan网络,与第一台docker服务器创建的网络一样
[root@docker02 ~]# docker network create -d macvlan --subnet 172.10.16.0/24 --gateway 172.10.16.1 -o parent=ens33.10 mac_net10
[root@docker02 ~]# docker network create -d macvlan --subnet 172.20.16.0/24 --gateway 172.20.16.1 -o parent=ens33.20 mac_net20 
[root@docker02 ~]# docker run -itd --name test3 --network mac_net10 --ip 172.10.16.11 busybox
[root@docker02 ~]# docker run -itd --name test4 --network mac_net20 --ip 172.20.16.21 busybox

配置至此,即可进行ping测试了,如果配置无误,则test3应该和test1互通(因为其都是基于mac_net10网络);test4应该和test2互通(同理)。
但test3和test1不能和test4和test2互通(因为其不是基于同一个虚拟局域网)。
容器test3 ping 容器test1测试(注意:若是使用vmware虚拟机进行测试,由于vmware的特性,需将其网络适配器改为“桥接模式”,而不是NAT模式等。否则无法通信)
技术图片
容器test4 ping 容器test2测试:
技术图片
至此,跨主机网络多网段已经实现,同样,各个容器无法与外网进行通信。若有耐心,还是建议阅读docker官方文档

以上是关于如何跨网段取MAC地址的主要内容,如果未能解决你的问题,请参考以下文章

三层交换机端口配置ip地址及绑定MAC地址的方法

三层交换机如何设置IP-MAC绑定?跨网段IP-MAC绑定方案。

ARP 协议工作原理(同网段及跨网段)

什么是MAC地址泛洪

链路层

在C语言中,如何将字符串“192.168.1.1”转换成MAC地址或IP地址?