使用go实现arp客户端
net包是Go语言标准库中与网络编程有关的包,它提供了一套用于创建各种类型的网络连接的函数和接口,提供了TCP、UDP、Unix 域套接字等传输层协议的支持。
net包的主要功能如下所示:
- 创建和管理 TCP 和 UDP 连接;
- 解析和格式化 IP 地址和域名;
- 实现 DNS 查询;
- 提供了可移植的网络 I/O 接口,包括对非阻塞模式和超时控制的支持;
1、使用 net.ParseIP() 方法将字符串形式的 IP 地址解析成 net.IP 类型的变量。
类型net.IP定义表示了一个 IPv4 或 IPv6 地址,它是一个字节数组类型[]byte 的别名。
2 、使用net.Interfaces()方法获取网络接口信息
这个方法会返回一个[]net.Interface切片,其中包含了主机上所有网络接口的信息。
3、使用pcap.OpenLive() 打开指定的网络设备进行实时捕获数据包
        func OpenLive(device string, snaplen int32, promisc bool, timeout time.Duration) (handle *Handle, _ error)- 
device:网络设备的名称,如eth0; 也可以使用通过 pcap.FindAllDevs()获得的设备的名称;
- 
snaplen: 每个数据包读取的最大长度 65535;
- 
promisc:是否将网口设置为混杂模式,即是否接收目的地址不为本机的包, true;
- 
timeout:设置抓到包返回的超时。如果设置成30s,那么每30s才会刷新一次数据包;设置成负数,会立刻刷新数据包,即不做等待; 
- 
handler :是一个*Handle类型的返回值,可以作为gopacket其他函数调用时作为函数参数来传递。 package main import ( 
 "fmt"
 "net"
 "os"
 "time""github.com/google/gopacket" "github.com/google/gopacket/layers" "github.com/google/gopacket/pcap") func main() { 
 if len(os.Args) != 3 {
 fmt.Println("Usage: ./arp_client <interface> <target_ip>")
 return
 }ifaceName := os.Args[1] targetIP := net.ParseIP(os.Args[2]) if targetIP == nil { fmt.Println("Invalid target IP address") return } // 获取接口信息 iface, err := net.InterfaceByName(ifaceName) if err != nil { fmt.Printf("Failed to get interface %s: %v\n", ifaceName, err) return } // 打开pcap句柄 handle, err := pcap.OpenLive(ifaceName, 65536, true, pcap.BlockForever) if err != nil { fmt.Printf("Failed to open pcap handle: %v\n", err) return } defer handle.Close() // 构造第二层(Layer 2)的数据结构 eth := layers.Ethernet{ SrcMAC: iface.HardwareAddr, DstMAC: net.HardwareAddr{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, EthernetType: layers.EthernetTypeARP, }// 构造ARP(第三层 layer 3)请求数据结构 
 arp := layers.ARP{
 AddrType: layers.LinkTypeEthernet,
 Protocol: layers.EthernetTypeIPv4,
 HwAddressSize: 6,
 ProtAddressSize: 4,
 Operation: layers.ARPRequest,
 SourceHwAddress: []byte(iface.HardwareAddr),
 SourceProtAddress: []byte{0, 0, 0, 0}, // 通常设为0.0.0.0
 DstHwAddress: []byte{0, 0, 0, 0, 0, 0},
 DstProtAddress: []byte(targetIP.To4()),
 }buf := gopacket.NewSerializeBuffer() opts := gopacket.SerializeOptions{ FixLengths: true, ComputeChecksums: true, } // 序列化数据包 err = gopacket.SerializeLayers(buf, opts, ð, &arp) if err != nil { fmt.Printf("Failed to serialize packet: %v\n", err) return } // 发送ARP请求 err = handle.WritePacketData(buf.Bytes()) if err != nil { fmt.Printf("Failed to send packet: %v\n", err) return } fmt.Printf("ARP request sent to %s via %s\n", targetIP, ifaceName) // 设置超时并监听响应 start := time.Now() timeout := 5 * time.Second packetSource := gopacket.NewPacketSource(handle, handle.LinkType()) for { if time.Since(start) > timeout { fmt.Println("Timeout waiting for ARP response") return } packet, err := packetSource.NextPacket() if err != nil { continue } arpLayer := packet.Layer(layers.LayerTypeARP) if arpLayer == nil { continue } arpResponse, _ := arpLayer.(*layers.ARP) if arpResponse.Operation == layers.ARPReply && net.IP(arpResponse.SourceProtAddress).Equal(targetIP) { fmt.Printf("ARP response received: %s is at %s\n", targetIP, net.HardwareAddr(arpResponse.SourceHwAddress)) return } }} 
<- 仅供参考->