golang跨平台以太网帧收发插件库ether的使用
golang跨平台以太网帧收发插件库ether的使用
ether是一个用于发送和接收以太网帧的Go语言包。
支持平台
目前支持以下平台:
- 基于BPF的平台:
- OS X
- FreeBSD
- 基于AF_PACKET的平台:
- Linux
完整示例demo
下面是一个使用ether库发送和接收以太网帧的完整示例:
package main
import (
"log"
"time"
"github.com/songgao/ether"
"github.com/songgao/packets/ethernet"
)
func main() {
// 打开网络接口,这里使用"eth0"作为示例,请根据实际情况修改
iface, err := ether.NewInterface("eth0")
if err != nil {
log.Fatal(err)
}
defer iface.Close()
// 启动接收协程
go func() {
for {
// 接收以太网帧
frame, err := iface.Receive()
if err != nil {
log.Printf("接收错误: %v", err)
continue
}
// 解析以太网帧
var eth ethernet.Ethernet
if err := eth.Unmarshal(frame); err != nil {
log.Printf("解析以太网帧错误: %v", err)
continue
}
log.Printf("收到帧: 源MAC: %s, 目标MAC: %s, 类型: 0x%x, 数据长度: %d",
eth.Source, eth.Destination, eth.EtherType, len(eth.Payload))
}
}()
// 构造一个简单的以太网帧
frame := ethernet.Ethernet{
Source: iface.HardwareAddr, // 使用接口的MAC地址作为源地址
Destination: ethernet.Broadcast, // 广播地址
EtherType: 0x8888, // 自定义以太网类型
Payload: []byte("Hello, ether!"),
}
// 发送以太网帧
for i := 0; i < 5; i++ {
if err := iface.Send(frame); err != nil {
log.Printf("发送错误: %v", err)
}
log.Println("已发送以太网帧")
time.Sleep(1 * time.Second)
}
}
代码说明
-
初始化接口:
iface, err := ether.NewInterface("eth0")
创建一个新的网络接口对象,参数是网络接口名称(如"eth0"、"en0"等)。
-
接收帧:
frame, err := iface.Receive()
从接口接收一个以太网帧,返回的是原始字节数据。
-
解析以太网帧:
var eth ethernet.Ethernet eth.Unmarshal(frame)
使用
ethernet
包解析原始帧数据为结构化的以太网帧。 -
发送帧:
iface.Send(frame)
发送一个构造好的以太网帧。
注意事项
- 运行此代码通常需要管理员/root权限
- 请根据实际网络环境修改接口名称
- 广播帧可能会被交换机过滤,具体行为取决于网络配置
待办功能
- 内核级数据包过滤
许可证
BSD 3-Clause License
更多关于golang跨平台以太网帧收发插件库ether的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于golang跨平台以太网帧收发插件库ether的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Golang跨平台以太网帧收发插件库ether使用指南
ether是一个Go语言编写的跨平台以太网帧收发库,它允许开发者在不同操作系统上直接发送和接收原始以太网帧。下面我将详细介绍如何使用这个库。
安装
首先安装ether库:
go get github.com/songgao/ether
基本使用
1. 获取网络接口列表
package main
import (
"fmt"
"github.com/songgao/ether"
)
func main() {
ifaces, err := ether.Interfaces()
if err != nil {
panic(err)
}
for _, iface := range ifaces {
fmt.Printf("Interface: %s\n", iface.Name)
fmt.Printf(" MAC: %s\n", iface.HardwareAddr)
fmt.Printf(" MTU: %d\n", iface.MTU)
}
}
2. 打开网络接口
ifaceName := "eth0" // 替换为你的网络接口名
conn, err := ether.New(ifaceName)
if err != nil {
panic(err)
}
defer conn.Close()
3. 发送以太网帧
package main
import (
"github.com/songgao/ether"
"net"
)
func main() {
// 打开网络接口
conn, err := ether.New("eth0")
if err != nil {
panic(err)
}
defer conn.Close()
// 目标MAC地址(广播地址)
dstMAC, _ := net.ParseMAC("ff:ff:ff:ff:ff:ff")
// 源MAC地址(你的网卡MAC)
srcMAC, _ := net.ParseMAC("00:11:22:33:44:55")
// 构造以太网帧
frame := make([]byte, 14+10) // 14字节头部 + 10字节负载
// 目标MAC
copy(frame[0:6], dstMAC)
// 源MAC
copy(frame[6:12], srcMAC)
// 以太网类型(0x0800是IPv4)
frame[12] = 0x08
frame[13] = 0x00
// 负载数据
copy(frame[14:], []byte("helloworld"))
// 发送帧
_, err = conn.Write(frame)
if err != nil {
panic(err)
}
}
4. 接收以太网帧
package main
import (
"fmt"
"github.com/songgao/ether"
)
func main() {
conn, err := ether.New("eth0")
if err != nil {
panic(err)
}
defer conn.Close()
buf := make([]byte, 1514) // 标准以太网MTU
for {
n, err := conn.Read(buf)
if err != nil {
panic(err)
}
fmt.Printf("Received %d bytes\n", n)
// 解析以太网帧
dstMAC := buf[0:6]
srcMAC := buf[6:12]
etherType := (uint16(buf[12]) << 8) | uint16(buf[13])
payload := buf[14:n]
fmt.Printf("Destination MAC: %02x:%02x:%02x:%02x:%02x:%02x\n",
dstMAC[0], dstMAC[1], dstMAC[2], dstMAC[3], dstMAC[4], dstMAC[5])
fmt.Printf("Source MAC: %02x:%02x:%02x:%02x:%02x:%02x\n",
srcMAC[0], srcMAC[1], srcMAC[2], srcMAC[3], srcMAC[4], srcMAC[5])
fmt.Printf("EtherType: 0x%04x\n", etherType)
fmt.Printf("Payload: % x\n", payload)
}
}
高级功能
1. 设置混杂模式
conn, err := ether.New("eth0")
if err != nil {
panic(err)
}
defer conn.Close()
// 启用混杂模式
err = conn.SetPromiscuous(true)
if err != nil {
panic(err)
}
2. 过滤特定类型的帧
// 只接收ARP包(以太网类型0x0806)
err = conn.SetBPFFilter("ether proto 0x0806")
if err != nil {
panic(err)
}
注意事项
- 权限要求:在Linux上需要root权限或CAP_NET_RAW能力
- 跨平台支持:支持Linux、macOS和Windows
- 性能考虑:对于高性能应用,考虑使用更大的缓冲区或批处理
- 安全考虑:原始套接字操作有安全风险,谨慎使用
完整示例 - 简单的ARP监听器
package main
import (
"fmt"
"github.com/songgao/ether"
"net"
)
func main() {
conn, err := ether.New("eth0")
if err != nil {
panic(err)
}
defer conn.Close()
// 只接收ARP包
err = conn.SetBPFFilter("ether proto 0x0806")
if err != nil {
panic(err)
}
buf := make([]byte, 1514)
for {
n, err := conn.Read(buf)
if err != nil {
panic(err)
}
if n < 14+28 { // 以太网头+ARP包最小长度
continue
}
// 解析ARP包
opcode := (uint16(buf[20]) << 8) | uint16(buf[21])
srcMAC := net.HardwareAddr(buf[22:28])
srcIP := net.IP(buf[28:32])
dstMAC := net.HardwareAddr(buf[32:38])
dstIP := net.IP(buf[38:42])
var op string
switch opcode {
case 1:
op = "ARP Request"
case 2:
op = "ARP Reply"
default:
op = fmt.Sprintf("Unknown (%d)", opcode)
}
fmt.Printf("%s: %s (%s) is at %s -> %s (%s)\n",
op, srcIP, srcMAC, dstMAC, dstIP)
}
}
这个库非常适合开发网络监控工具、自定义协议实现或网络安全工具。使用时请确保遵守当地法律法规和网络使用政策。