go - 使用 gopacket 向 127.0.0.1 发送 UDP 数据包

标签 go networking udp gopacket

我正在尝试使用 gopacket 向 127.0.0.1 发送一个 UDP 数据包。这是我的代码:

package main

import (
    "fmt"
    "net"

    "github.com/google/gopacket"
    "github.com/google/gopacket/layers"
    "github.com/google/gopacket/pcap"
)

func main() {
    handle, err := pcap.OpenLive("lo", 1500, false, pcap.BlockForever)
    if err != nil {
        fmt.Printf("%s\n", err.Error())
        return
    }

    eth := layers.Ethernet{
        EthernetType: layers.EthernetTypeIPv4,
        SrcMAC:       net.HardwareAddr{0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
        DstMAC:       net.HardwareAddr{0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    }

    ip := layers.IPv4{
        Version:  4,
        TTL:      64,
        SrcIP:    net.IP{127, 0, 0, 1},
        DstIP:    net.IP{127, 0, 0, 1},
        Protocol: layers.IPProtocolUDP,
    }

    udp := layers.UDP{
        SrcPort: 62003,
        DstPort: 8080,
    }
    udp.SetNetworkLayerForChecksum(&ip)

    payload := []byte{'a', 'b', 'c', '\n'}

    options := gopacket.SerializeOptions{
        ComputeChecksums: true,
        FixLengths:       true,
    }

    buffer := gopacket.NewSerializeBuffer()

    err = gopacket.SerializeLayers(buffer, options,
        &eth,
        &ip,
        &udp,
        gopacket.Payload(payload),
    )
    if err != nil {
        fmt.Printf("[-] Serialize error: %s\n", err.Error())
        return
    }
    outgoingPacket := buffer.Bytes()

    err = handle.WritePacketData(outgoingPacket)
    if err != nil {
        fmt.Printf("[-] Error while sending: %s\n", err.Error())
        return
    }

}

在终端中,我使用 netcat 监听传入的数据包:
nc -ulp 8080 -s 127.0.0.1

当我运行我的代码时,我可以在环回接口(interface)上的wireshark中看到生成的数据包具有正确的校验和,但数据包永远不会到达netcat。可能是什么问题?

最佳答案

如果你看这个diagram ,你会注意到 tcpdump作用于 Ethernet层。然后来了,IP然后 TCP/UDP ,然后 Sockets . ncTCP/UDP 运营层。
IP级别,数据包可能会被丢弃。很多情况下是Reverse Path Filtering .
因此,您可以看到到达以太网层的数据包,tcpdump 可以看到这些数据包。 ,但未到达 nc 的数据包因为它们可能会被路由到其他地方,或者被丢弃。
因此,最好检查是否禁用 RP filtering并检查 iptable规则,有帮助!
更新:
当您在环回接口(interface)上操作时:

MAC's are used at the lowest level of ethernet traffic, and only within one LAN and help direct traffic around within it. It isn't needed on a local network interface (lo) because packets are being handled internally.

The loopback address connects to the same computer directly in the IP layer without using any physical hardware. So, it lets you bypass Ethernet, PPP, other drivers.


package main

import (
    "fmt"
    "net"

    "github.com/google/gopacket"
    "github.com/google/gopacket/layers"
    "github.com/google/gopacket/pcap"
)

func main() {
    handle, err := pcap.OpenLive("lo0", 1500, false, pcap.BlockForever)
    if err != nil {
        fmt.Printf("%s\n", err.Error())
        return
    }

    eth := layers.Ethernet{
        EthernetType: layers.EthernetTypeIPv4,
        SrcMAC:       net.HardwareAddr{0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
        DstMAC:       net.HardwareAddr{0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    }

    _ = eth // Ignore. Use where ethernet interface is used

    // Used for loopback interface
    lo := layers.Loopback{
        Family: layers.ProtocolFamilyIPv4,
    }

    ip := layers.IPv4{
        Version:  4,
        TTL:      64,
        SrcIP:    net.IP{127, 0, 0, 1},
        DstIP:    net.IP{127, 0, 0, 1},
        Protocol: layers.IPProtocolUDP,
    }

    udp := layers.UDP{
        SrcPort: 62003,
        DstPort: 9000,
    }
    udp.SetNetworkLayerForChecksum(&ip)

    payload := []byte{'a', 'b', 'c', '\n'}

    options := gopacket.SerializeOptions{
        ComputeChecksums: true,
        FixLengths:       true,
    }

    buffer := gopacket.NewSerializeBuffer()

    // if err = gopacket.SerializeLayers(buffer, options,
    //  &eth,
    //  &ip,
    //  &udp,
    //  gopacket.Payload(payload),
    // ); err != nil {
    //  fmt.Printf("[-] Serialize error: %s\n", err.Error())
    //  return
    // }
    if err = gopacket.SerializeLayers(buffer, options,
        &lo,
        &ip,
        &udp,
        gopacket.Payload(payload),
    ); err != nil {
        fmt.Printf("[-] Serialize error: %s\n", err.Error())
        return
    }
    outgoingPacket := buffer.Bytes()

    if err = handle.WritePacketData(outgoingPacket); err != nil {
        fmt.Printf("[-] Error while sending: %s\n", err.Error())
        return
    }

}
enter image description here
我在 macOS Catalina 上运行该程序,如果您看到屏幕截图,它正在运行。 nc可以接收自定义生成的数据包。如果校验和不正确,那么它将被丢弃。
我希望它有帮助!

关于go - 使用 gopacket 向 127.0.0.1 发送 UDP 数据包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59985676/

相关文章:

c - 什么是网络套接字的文件描述符?以及如何得到它?

networking - VPN 客户端是如何工作的?

sockets - UDP 未连接套接字发送失败,直到它收到第一个数据报

windows - Windows 上 IPC 的命名管道与 UDP

java - 如何以编程方式访问 IPTV 服务器?

go - 如何使用 viper 将环境变量解码到 slice ?

go - TFS 和 golang 持续集成

.net - 如何使用 .net 中的 RX 扩展来使用 UDP 字节流

go - 如果存在,如何获得值(value)指数?

go: var declared but not used 错误 - 如何解决?