如何使用Golang将物理网卡绑定到发送IP数据包?

huangapple go评论94阅读模式
英文:

How to bind physical nic to send a ip package with golang?

问题

我在Windows客户端上设置了一个虚拟网络卡(TUN)用于VPN流量的获取。在捕获虚拟网络卡流量时,我执行以下资源判断逻辑:当访问特定资源时,流量(IP数据包)将不会通过VPN通道发送。我想要将流量(IP数据包)直接发送到物理网络适配器。

现在的问题是如何将流量直接发送到物理网卡。

--系统:WINDOWS
--语言:GOLANG

我尝试通过解析IP数据包并绑定网络适配器地址进行TCP/UDP模拟发送,但速度太慢。是否有一种直接绑定物理网卡并发送IP数据包的方法?

英文:

I set up a virtual network card(TUN) on the windows client for the vpn to get traffic. When capturing virtual NIC traffic, I perform the following resource judgment logic: When accessing certain resources, the traffic (IP packets) will not be sent through the VPN channel. I want to send the traffic (IP packets) directly through the physical NIC.
The problem now is how do I get the traffic sent directly through the physical network card.

--SYSTEM:WINDOWS
--LANGUAGE:GOLANG

I tried to simulate TCP/UDP by parsing IP packets and binding network adapter addresses for sending, but this was too slow.
Is there a way to directly bind the physical NIC and send IP packets?

答案1

得分: 0

原始套接字自Windows XP以来已被禁用,因此您需要第三方软件来注入IP数据包。

我使用了WinPcap库来实现这一点。Go语言的绑定存在:https://pkg.go.dev/github.com/google/gopacket/pcap

将以太网帧写入数据链路层的函数是Handle.WritePacketData

具体步骤如下:

  1. 使用OpenLive创建与物理网卡的句柄。
  2. 将IP数据包封装到数据链路层帧中。
  3. 使用Handle.WritePacketData将帧写入句柄。

第1步中的棘手之处在于接口的名称。在Windows中,没有eth0这样的名称。所需的名称看起来像\Device\NPF_{BBECCD43-3F2B-4594-B17B-5F38E73787E8}

要获取设备的正确名称,可以查询FindAllDevs函数。需要以管理员身份运行!

package main

import (
	"fmt"

	"github.com/google/gopacket/pcap"
)

func main() {
	// 获取设备列表 - 以管理员身份运行!
	devices, err := pcap.FindAllDevs()
	if err != nil {
		panic(err)
	}

	// 打印设备信息
	fmt.Println("设备:")
	for _, device := range devices {
		fmt.Println("-----------------------")
		fmt.Println("名称: ", device.Name)
		fmt.Println("描述: ", device.Description)
		fmt.Println("地址: ", device.Description)
		for _, address := range device.Addresses {
			fmt.Println("  IP地址: ", address.IP)
			fmt.Println("  子网掩码: ", address.Netmask)
		}
	}
}

示例输出(这是我的WiFi适配器):

-----------------------
名称:  \Device\NPF_{BBECCD43-3F2B-4594-B17B-5F38E73787E8}
描述:  Microsoft
地址:  Microsoft
  IP地址:  fe80::de52:6717:446:57a1
  子网掩码:  <nil>
  IP地址:  172.30.1.95
  子网掩码:  ffffff00
英文:

Raw sockets are disabled since Windows XP, so you need third party software to inject IP packets.

I used WinPcap library for this. The Go binding exists: https://pkg.go.dev/github.com/google/gopacket/pcap

The function that writes Ethernet frames to the datalink is Handle.WritePacketData

The steps are:

  1. Create a handle to your physical NIC with OpenLive
  2. Wrap IP packed into datalink layer frame
  3. Write the frame to the handle with Handle.WritePacketData

The tricky part with the step 1 is the name of the interface. In windows there are no such names as eth0. The required name looks like \Device\NPF_{BBECCD43-3F2B-4594-B17B-5F38E73787E8}

To get the proper names of the devices you can query FindAllDevs function. As Administrator!

package main

import (
	&quot;fmt&quot;

	&quot;github.com/google/gopacket/pcap&quot;
)

func main() {
	// Get device list - run as ADMINISTRATOR!
	devices, err := pcap.FindAllDevs()
	if err != nil {
		panic(err)
	}

	// Print device information
	fmt.Println(&quot;Devices:&quot;)
	for _, device := range devices {
		fmt.Println(&quot;-----------------------&quot;)
		fmt.Println(&quot;Name: &quot;, device.Name)
		fmt.Println(&quot;Description: &quot;, device.Description)
		fmt.Println(&quot;Addresses: &quot;, device.Description)
		for _, address := range device.Addresses {
			fmt.Println(&quot;  IP address: &quot;, address.IP)
			fmt.Println(&quot;  Netmask: &quot;, address.Netmask)
		}
	}
}

Sample output (this is my WiFi adapter):

-----------------------
Name:  \Device\NPF_{BBECCD43-3F2B-4594-B17B-5F38E73787E8}
Description:  Microsoft
Addresses:  Microsoft
  IP address:  fe80::de52:6717:446:57a1
  Netmask:  &lt;nil&gt;
  IP address:  172.30.1.95
  Netmask:  ffffff00

huangapple
  • 本文由 发表于 2023年3月6日 19:46:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/75650480.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定