为了账号安全,请及时绑定邮箱和手机立即绑定

使用原始套接字发送自定义以太网数据包

使用原始套接字发送自定义以太网数据包

Go
哈士奇WWW 2022-10-24 15:44:11
我搜索了如何使用自定义以太网类型发送原始以太网数据包,但很多人都在谈论 tcp 和 udp 协议。我需要打开一个原始套接字,获取所有具有我自定义以太网类型的数据包,读取有效负载并发送回具有不同自定义以太网类型的数据包。func main() {    //set promiscuos mode    cmd := exec.Command("ifconfig", "eth0", "promisc")    err := cmd.Run()    if err != nil {        fmt.Println("Error: " + err.Error())        return    }    //open raw socket with custom ethertype_1 and bind to interface    fd, err := syscall.Socket(syscall.AF_PACKET, syscall.SOCK_RAW, Htons(ETHER_TYPE_1))    if err != nil {        fmt.Println("Error: " + err.Error())        return    }    err = syscall.BindToDevice(fd, "eth0")    if err != nil {        fmt.Println("Error: " + err.Error())        return    }    f := os.NewFile(uintptr(fd), fmt.Sprintf("fd %d", fd))    for {        buf := make([]byte, 1024)        numRead, err := f.Read(buf)        if err != nil {            fmt.Println(err)        }        go ReadSocket(buf, numRead)    }func ReadSocket(buf []byte, numRead int) {    packet := BufToEthPacket(buf, numRead)    fmt.Printf("Destination MAC: % X\n", packet.dstMac)    fmt.Printf("Source MAC:      % X\n", packet.srcMac)    fmt.Printf("ether type:      %X\n", packet.ethType)    fmt.Printf("Payload:         % X\n", packet.payload)    var myPacket EthPacket    myPacket.srcMac = packet.dstMac    myPacket.dstMac = packet.srcMac    myPacket.ethType = ETHER_TYPE_2    myPacket.payload = packet.payload    var myBuf = EthPacketToBuf(myPacket)    //open raw socket with custom ethertype_2 and bind to interface    fd, err := syscall.Socket(syscall.AF_PACKET, syscall.SOCK_RAW, Htons(ETHER_TYPE_2))    if err != nil {        fmt.Println("Error: " + err.Error())        return    }    err = syscall.BindToDevice(fd, "eth0")    if err != nil {        fmt.Println("Error: " + err.Error())        return    }}我收到了数据包,但f.Write(myBuf)返回以下错误:Error: write fd 5: no such device or address我做错了什么?
查看完整描述

1 回答

?
海绵宝宝撒

TA贡献1809条经验 获得超8个赞

Usingos.Write将在后台执行write系统调用,这意味着实际文件。要将数据“写入”到网络套接字,您需要使用sendto系统调用。


以下示例使用自定义以太类型发送数据。所以只是一个带有一些数据的以太网数据包。


package main


import (

    "log"

    "net"

    "os"

    "syscall"

)


func main() {

    ifname := os.Args[1]

    iface, err := net.InterfaceByName(ifname)

    if err != nil {

        log.Fatal("get link by name:", err)

    }


    srcMac := iface.HardwareAddr

    if len(srcMac) == 0 {

        srcMac = []byte{0, 0, 0, 0, 0, 0}

    }

    dstMac := []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05}


    fd, _ := syscall.Socket(syscall.AF_PACKET, syscall.SOCK_RAW, int(htons(syscall.ETH_P_ALL)))

    addr := syscall.SockaddrLinklayer{

        Ifindex: iface.Index,

        Halen:   6, // Ethernet address length is 6 bytes

        Addr: [8]uint8{

            dstMac[0],

            dstMac[1],

            dstMac[2],

            dstMac[3],

            dstMac[4],

            dstMac[5],

        },

    }


    ethHeader := []byte{

        dstMac[0], dstMac[1], dstMac[2], dstMac[3], dstMac[4], dstMac[5],

        srcMac[0], srcMac[1], srcMac[2], srcMac[3], srcMac[4], srcMac[5],

        0x12, 0x34, // your custom ethertype

    }


    // Your custom data

    p := append(ethHeader, []byte("Hello World")...)


    err = syscall.Sendto(fd, p, 0, &addr)

    if err != nil {

        log.Fatal("Sendto:", err)

    }

}


// htons converts a short (uint16) from host-to-network byte order.

func htons(i uint16) uint16 {

    return (i<<8)&0xff00 | i>>8

}


查看完整回答
反对 回复 2022-10-24
  • 1 回答
  • 0 关注
  • 118 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号