Windos下通过Wpcap抓包实现两个网卡桥接
目录
1. 背景:
一台电脑允许接多个网口,当然大部分只有一个网口其余都是USB扩展而来,而每个网口之间需要配置不同的网段IP,这就造成了和同一台电脑不通网口相连的设备处于不通的网段,虽然电脑与两台设备沟通无压力,但是两台设备间通信由于处于不通网段而变得相对比较困难。对于开发人员,这并不是一个问题,直接接到交换机或者HUB上一样工作。。。而且扩展性也无与伦比。。。对一般windows系统而言,都支持网卡桥接,因此两设备间通信也是很好的选择。但是总有一些人不喜欢桥接这种模式,甚至不允许网卡间的桥接,也不采用交换机这种神器。
简单的说,使用场合的不同导致好多很容易的事情变成了问题,这就要求具体情况具体分析。

如上图所示,这是简单的拓扑,其中DHCP Server 和DHCP Client 可以自行替换成不同设备,但是具体的功能实现可能不同,但是原理都是一样的。
条件:
1)电脑的网卡1IP设置为192.168.1.6/24,电脑的网卡2 IP设置无要求,无要求,无要求(任意但是不得同一网段,因为同一网段电脑提示设置失败。如果你能设置上那这篇文章就无需阅读了)。
2)DHCP Server 的IP设置为192.168.1.1/24,并且开启DHCP功能
目标:
DHCP Client可以成功的获取到DHCP Server分配的IP。
2. 需要的技术手段:
a. 实现此目标有需要几个简单的技术手段:
1)电脑上实现一个数据包转发软件,也就是上图的界面;
2)获取到电脑网卡MAC信息;
3)获取到DHCP Server的MAC信息;
4)电脑上分别抓取到流经网卡1和网卡2的链路层数据包;
b. 相关技术手段的实现:
1)转发软件可以使用任何一种编程语言,但是要求能提供获取到链路层信息的库。我当时用的是C实现的控制台程序。这并不是关键问题。
2)获取本机的mac信息对任何语言都不是什么问题,视具体情况去百度
3)获取DHCP Server的Mac信息,这需要电脑和DHCP Server之间有信息的交互,而我们可以利用获取到的链路层报文将其MAC地址提取到。至于如何进行信息交互,这里不提供具体的方法,是具体情况而定,方法肯定是存在的。实在没有,ping一包亦可以。(注:一般情况DHCP Server都集成到某些主控设备上,而主控设备和电脑间是存在报文交互的,因此获取主控设备与电脑相连的那个网卡MAC就很简单了)
4)至于如何采集链路层数据包,这个也是具体情况具体分析。我用的Wpcap提供的动态库函数,然后去分别监控两个网卡信息。
3. 实现逻辑:
具体的实现逻辑和原理倒是很简单:
与DHCP Server 相连的网卡1:转发源Mac 为DHCP Server且不是发给本机IP的报文
与DHCP Client 相连的网卡2:转发除了(源mac为DHCP Server,或者本机发出的报文)以外的其他报文
逻辑就是这么简单,而且使用范围不仅限于文章提供的拓扑,因为从实现上将它的转发条件很大,可以实现多个设备间的数据转发。
4. 应用实例:
注:此实例只是工程中的一小部分,但是是该功能实现的精华所在,它只提供参考,并不是拿来就可以使用的。
unsigned char hostMAC[6][6]; /*记录本机电脑的mac*/
unsigned char remoteMAC[6];  /*记录远端mac*/
unsigned char broadcastMAC[6];/*记录广播mac(全0xff)*/
unsigned char netCnt;		 /*记录本机中网卡的个数,*/
unsigned char netZeboxLink;  /*记录本机中那个网卡与远端设备连接*/
/****************************************************************************
* getLocalMac2  :
*  		获取本机的所有网卡的mac地址,经将其存起来
*
*****************************************************************************/
int getLocalMac2() /*sunzd 20181129*/
{
	ULONG ulSize=0;
	PIP_ADAPTER_INFO pInfo=NULL,pInfoTemp;
    int temp=0;
	PIP_ADDR_STRING pIpAddress;
	while(netCnt<2){
		ulSize=0;pInfo=NULL;temp=0;pInfoTemp=NULL;netCnt=0;
		PILMemSet(hostMAC,0xff,sizeof(hostMAC));
		PILMemSet(remoteMAC,0xff,sizeof(remoteMAC));
		PILMemSet(broadcastMAC,0xff,sizeof(broadcastMAC));
		temp = GetAdaptersInfo(pInfo,&ulSize);//第一处调用,获取缓冲区大小
		pInfo=(PIP_ADAPTER_INFO)malloc(ulSize);
		temp = GetAdaptersInfo(pInfo,&ulSize);
		pInfoTemp = pInfo;
		while(pInfoTemp)//遍历每一张网卡
		{
		    pIpAddress	= 	&pInfoTemp->IpAddressList;
		    while(pIpAddress){//遍历网卡下的IP
				PILMemCpy(hostMAC[netCnt++], pInfoTemp->Address, (int)pInfoTemp->AddressLength);
				break;
		    }
		    pInfoTemp = pInfoTemp->Next;
		}
		free(pInfo);
		if(netCnt<2) PILSleep(10000);
	}
    return -1;
}
void	PacketWpcapProc1()
{
	struct pcap_pkthdr *header;
	U8	*packHdr;
	S32	retVal;
	U8 packetBuf[2048];
	U32 bufLength;
	U8 pcapNum,i,flag_mac=0;
	U8 pktHead[4] = {0x68,0x01,0x08,0x13};
	while(1){
		retVal	= pcap_next_ex(wpcapFp[0], &header, &packHdr);
		if(retVal <= 0){
			continue;
		}
		bufLength = header->len;
		PILMemCpy(packetBuf, packHdr, bufLength);
		for(i=0;i<netCnt;i++){
			if(!PILMemCmp(broadcastMAC, packetBuf, 6) && !PILMemCmp(pktHead, packetBuf+0x2a, 4)){
				PILMemCpy(remoteMAC, packetBuf+6, 6);
				netZeboxLink = 1;/*发给电脑的KA*/
				flag_mac = 1;
				break;
			}else if(!PILMemCmp(hostMAC[i], packetBuf + 6, 6)){
				flag_mac = 1; //本机发出
				break;
			}
		}
		if(netZeboxLink==1){/*wpcapFp[0] ---- zebox*/
			if(!PILMemCmp(remoteMAC, packetBuf + 6, 6)&&!flag_mac){
				retVal = pcap_sendpacket(wpcapFp[1], packetBuf, bufLength);
				if(retVal == -1){
					continue;
				}
			}
		}else if(netZeboxLink==2){/*wpcapFp[1] ---- zebox*/
			if((!PILMemCmp(remoteMAC, packetBuf + 6, 6))||flag_mac){
				flag_mac = 0;
				continue;
			}
			retVal = pcap_sendpacket(wpcapFp[1], packetBuf, bufLength);
		}else{
		}
		flag_mac = 0;
	}
	return SUCCESS;
}
void	PacketWpcapProc2()
{
	struct pcap_pkthdr *header;
	U8	*packHdr;
	S32	retVal;
	U8 packetBuf[2048];
	U32 bufLength;
	U8 pcapNum,i,flag_mac=0;
	U8 pktHead[4] = {0x68,0x01,0x08,0x13};
	while(1){
		retVal	= pcap_next_ex(wpcapFp[1], &header, &packHdr);
		if(retVal <= 0){
			continue;
		}
		bufLength = header->len;
		PILMemCpy(packetBuf, packHdr, bufLength);
		for(i=0;i<netCnt;i++){
			if(!PILMemCmp(broadcastMAC, packetBuf, 6) && !PILMemCmp(pktHead, packetBuf+0x2a, 4)){
				PILMemCpy(remoteMAC, packetBuf+6, 6);
				netZeboxLink = 2;/*发给电脑的KA*/
				flag_mac = 1;  //发给本机
				break;
			}else if(!PILMemCmp(hostMAC[i], packetBuf + 6, 6)){
				flag_mac = 1; //本机发出
				break;
			}
		}
		if(netZeboxLink==1){/*wpcapFp[0] ---- zebox*/
			if((!PILMemCmp(remoteMAC, packetBuf + 6, 6))||flag_mac){
				flag_mac = 0;
				continue;
			}
			retVal = pcap_sendpacket(wpcapFp[0], packetBuf, bufLength);
		}else if(netZeboxLink==2){/*wpcapFp[1] ---- zebox*/
			if(!PILMemCmp(remoteMAC, packetBuf + 6, 6)&&!flag_mac){
				retVal = pcap_sendpacket(wpcapFp[0], packetBuf, bufLength);
				if(retVal == -1){
					continue;
				}
			}
		}else{
		}
		flag_mac = 0;
	}
	return SUCCESS;
}
												
											Windos下通过Wpcap抓包实现两个网卡桥接的更多相关文章
- 在MacOS下使用Fiddler抓包
		
在MacOS下使用Fiddler抓包 有两种方式,分别是安装Mac版的Fiddler,或者是用虚拟机,安装Windows系统,在Windows系统下运行Fiddler对Mac系统中的内容进行抓包. M ...
 - 【转载】linux下的usb抓包方法
		
1 linux下的usb抓包方法 1.配置内核使能usb monitor: make menuconfig Device Drivers --> ...
 - linux下的usb抓包方法
		
1 linux下的usb抓包方法1.配置内核使能usb monitor: make menuconfig Device Drivers --> ...
 - Mac 下安装Fiddler抓包工具
		
需求 我们都知道在Mac电脑下面有一个非常好的抓包工具:Charles.但是这个只能抓代理的数据包.但是有时候想要调试本地网卡的数据库 Charles 就没办法了.就想到了在windows下面的一个F ...
 - linux下利用tcpdump抓包工具排查nginx获取客户端真实IP实例
		
一.nginx后端负载服务器的API在获取客户端IP时始终只能获取nginx的代理服务器IP,排查nginx配置如下 upstream sms-resp { server ; server ; } s ...
 - MAC下安装Fiddler抓包工具
		
需求 我们都知道在Mac电脑下面有一个非常好的抓包工具:Charles.但是这个只能抓代理的数据包.但是有时候想要调试本地网卡的数据库 Charles 就没办法了.就想到了在windows下面的一个F ...
 - centos下安装wireshark 抓包
		
centos下安装wireshark相当简单.两条命令就够了.这里.主要是记录写使用方面的东西 安装:1.yum install wireshark.注意这样并无法使用wireshark命令和图形界面 ...
 - linux下的usb抓包方法【转】
		
转自:http://blog.chinaunix.net/uid-11848011-id-4508834.html 1.配置内核使能usb monitor: make menuconfig ...
 - linux下使用tcpdump抓包分析tcp的三次握手
		
首先贴上tcp 三次握手的原理图服务器开启ftp服务并执行tcpdump抓包服务器:192.168.3.14 ftp服务客户端:192.168.3.100 服务器执行以下命令,客户端访问服务器ftp: ...
 
随机推荐
- 阿里云RocketMQ定时/延迟消息队列实现
			
新的阅读体验:http://www.zhouhong.icu/post/157 一.业务需求 需要实现一个提前二十分钟通知用户去做某件事的一个业务,拿到这个业务首先想到的最简单得方法就是使用Redis ...
 - IDEA创建Mapper.xml文件识别不成功的问题
			
在IDEA的maven项目中,创建一个EmpMapper.xml的文件识别不成功,图标显示为文本文档类型,在写代码时也不会弹出提示 解决方法: 在文件->设置->编辑器->文件类型中 ...
 - Python从零开始编写控制程序(一)
			
Python之从零开始编写控制程序(一) 在此声明:本博客仅供学习参考,任何产生相关违法犯罪行为与本人无关. 另外如果有师傅有好的思路和想法,可以和我一起沟通交流. 最近在一直尝试做Powershel ...
 - Linux-shell编程经验记录
			
Linux-shell编程经验总结 1.接收用户输入 #读取用户输入并且将输入保存到input变量中 read -p "请输入:" input #也可以先输出信息再进行读取,这里的 ...
 - Golang中如何正确的使用sarama包操作Kafka?
			
Golang中如何正确的使用sarama包操作Kafka? 一.背景 在一些业务系统中,模块之间通过引入Kafka解藕,拿IM举例(图来源): 用户A给B发送消息,msg_gateway收到消息后,投 ...
 - rancher v1.6.29部署K8s
			
1. 前提:上一文中,已部署好单节点Rancher v1.6.29 2. 在Rancher中,添加环境模板 修改k8s设置参数 参数修改明细: Private Registry for Add-Ons ...
 - Go连接到Linux服务器进行操作-执行shell命令&&上传文件
			
Go连接到Linux服务器进行操作 使用密码连接Linux服务器 package main import ( "fmt" "golang.org/x/crypto/ssh ...
 - Java的安装过程和开发环境
			
首先需要安装jdk(Java Development Kit开发工具包) 下载地址:https://www.oracle.com/java/technologies/javase-downloads. ...
 - Java之JSTL标签与JavaBean
			
Java之JSTL标签与JavaBean JSP.JSTL标签及 EL表达式 <!-- jstl表达式--> <dependency> <groupId>javax ...
 - 剑指 Offer 61. 扑克牌中的顺子
			
剑指 Offer 61. 扑克牌中的顺子 从扑克牌中随机抽5张牌,判断是不是一个顺子,即这5张牌是不是连续的.2-10为数字本身,A为1,J为11,Q为12,K为13,而大.小王为 0 ,可以看成任意 ...