Golang原始套接字UDP不起作用

Main Question

I am looking for a way of sending packets using the go language which grants me the ability to view and set the TTL and other low level fields of packets(I don't need to modify ethernet headers just ip & UDP headers). I have attempted to craft and send my own packets in the code below.

When running the below code no messages are received by the receiver. Can anyone either a.) alert me to any errors I have made in this code or b.) suggest another means of sending udp data using golang while retaining access to the ip & udp headers?

(I have removed the mac addresses, they would need to be replaced to run this code)

Code

(Sending)

package main

import (
    "syscall"
    "log"
    "github.com/google/gopacket"
    "github.com/google/gopacket/layers"
    "fmt"
    "encoding/hex"
    "encoding/json"
    "net"
)

type NameTag struct {
    Name string `json:"name"`
}

func main() {
    var err error
    fd, e := syscall.Socket(syscall.AF_INET, syscall.SOCK_RAW, syscall.IPPROTO_UDP)
    if e != nil {
        fmt.Println("Problem @ location 1")
    }
    addr := syscall.SockaddrInet4{
        Port: 27289,
        Addr: [4]byte{127, 0, 0, 1},
    }
    p := pkt()
    err = syscall.Sendto(fd, p, 0, &addr)
    if err != nil {
        log.Fatal("Sendto:", err)
    }
}

func pkt() []byte {
    sb := gopacket.NewSerializeBuffer()
    nt := NameTag{"Paul"}
    b, _ := json.Marshal(nt)
    pld := gopacket.Payload(b)
    l := uint16(len(pld))
    udp := layers.UDP{
        SrcPort:  27289,
        DstPort:  27288,
        Length:   l + 8,
        Checksum: 0,
    }
    l = l + 8
    ip := layers.IPv4{
        Version:    0x4,
        IHL:        5,
        Length:     20 + l,
        TTL:        255,
        Flags:      0x40,
        FragOffset: 0,
        Checksum:   0,
        Protocol:   syscall.IPPROTO_UDP,
        DstIP:      net.IPv4(127, 0, 0, 1),
        SrcIP:      net.IPv4(127, 0, 0, 1),
    }
    l = l + 20

    eth := layers.Ethernet{
        EthernetType: layers.EthernetTypeIPv4,
        SrcMAC: net.HardwareAddr{
            0x--, 0x--, 0x--, 0x--, 0x--, 0x--,
        },
        DstMAC: net.HardwareAddr{
            0x--, 0x--, 0x--, 0x--, 0x--, 0x--,
        },
    }
    fmt.Println(pld.SerializeTo(sb, gopacket.SerializeOptions{}))
    fmt.Println(udp.SerializeTo(sb, gopacket.SerializeOptions{}))
    fmt.Println(ip.SerializeTo(sb, gopacket.SerializeOptions{}))
    fmt.Println(eth.SerializeTo(sb, gopacket.SerializeOptions{}))

    //Debug prints here (first line is for dump to packet validator)
    fmt.Println(hex.EncodeToString(sb.Bytes()))
    fmt.Println(sb.Bytes())

    return sb.Bytes()
}

(Receiving)

package main

import (
    "syscall"
    "os"
    "fmt"
)

func main() {
    fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_RAW, syscall.IPPROTO_UDP)
    if err != nil {
        fmt.Println(err)
        return
    }
    sa:= &syscall.SockaddrInet4{
        Addr: [4]byte{127,0,0,1},
        Port:27288,
    }
    e := syscall.Bind(fd, sa)
    if e != nil {
        fmt.Println("problems @ location 1")
    }
    f := os.NewFile(uintptr(fd), fmt.Sprintf("fd%d", fd))
    fmt.Println("Entering main loop")
    for {
        fmt.Println("In loop")
        buf := make([]byte, 1024)
        numRead, err := f.Read(buf)
        if err != nil {
            fmt.Println("problems @ location 2")
        }
        fmt.Printf("Loop done %v
", buf[:numRead])
    }

}
dongluanan7163
dongluanan7163 使用“net”包时,有没有一种方法可以访问ip&udp标头?如果是这样,那是更好的选择,但我不知道该怎么做。
2 年多之前 回复
dongsicheng5262
dongsicheng5262 有趣的是,您在运行什么OS/体系结构?
2 年多之前 回复
dongqian2021
dongqian2021 它对我有用,我所做的就是构建二进制文件并以sudo权限运行。
2 年多之前 回复
dqusbxh44823
dqusbxh44823 为什么系统调用?“syscall的主要用途是在其他提供更便携式系统接口的软件包内部,例如“os”,“time”和“net”。请尽可能使用这些软件包,而不要使用这些软件包。”
2 年多之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐