go的实现arp客户端
使用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 mainimport ("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.0DstHwAddress: []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.SecondpacketSource := 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}}
}
<- 仅供参考->