使用 gopacket 向 127.0.0.1 发送 UDP 数据包数据包、gopacket、UDP

2023-09-07 13:26:38 作者:明明说好不哭的

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

I'm trying to send a UDP packet to 127.0.0.1 with gopacket. Here is my code:

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
", 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', '
'}

    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
", err.Error())
        return
    }
    outgoingPacket := buffer.Bytes()

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

}

在终端中,我使用 netcat 监听传入的数据包:

And in a terminal I listen to incoming packets with netcat:

nc -ulp 8080 -s 127.0.0.1

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

When I run my code, I can see the generated packet in wireshark on loopback interface with correct checksums but the packet never arrives to netcat. What may be the problem?

推荐答案

如果你看这个 如图,您会注意到tcpdump 作用于Ethernet 层.然后是IP,然后是TCP/UDP,然后是Sockets.nc 运行在 TCP/UDP 层.

If you look at this diagram, you'll notice tcpdump acts on the Ethernet layer. Then comes, IP then TCP/UDP, then Sockets. nc operates at TCP/UDP layer.

IP 级别,数据包可能会被丢弃.很多情况下是反向路径过滤.

In the IP level, the packets might be getting dropped. Very often the case is Reverse Path Filtering.

因此,您可以看到到达以太网层的数据包,这可以通过 tcpdump 看到,但是对于 nc 的数据包没有到达,因为它们可能被路由其他地方,或丢弃.

So, you are able to see the packets arriving at the ethernet layer which can be seen by tcpdump, but packets are not arriving for nc because they might be routed somewhere else, or dropped.

所以,最好检查一下是否禁用 RP 过滤 并检查 iptable 规则,有帮助!

So, it's better to check if disabling RP filtering and checking iptable rules, helps!

更新:

当您在环回接口上操作时:

As you're operating on the loopback interface:

MAC 用于最低级别的以太网流量,并且仅在一个 LAN 中使用,并帮助在其中引导流量.在本地网络接口 (lo) 上不需要它,因为数据包正在内部处理.

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.

环回地址直接在 IP 层连接到同一台计算机,而不使用任何物理硬件.因此,它可以让您绕过以太网、PPP 和其他驱动程序.

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
", 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', '
'}

    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
", err.Error())
    //  return
    // }
    if err = gopacket.SerializeLayers(buffer, options,
        &lo,
        &ip,
        &udp,
        gopacket.Payload(payload),
    ); err != nil {
        fmt.Printf("[-] Serialize error: %s
", err.Error())
        return
    }
    outgoingPacket := buffer.Bytes()

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

}

我正在 macOS Catalina 上运行该程序,如果您看到屏幕截图,它正在运行.nc 可以接收自定义生成的数据包.如果校验和不正确,则将其丢弃.

I'm running the program on macOS Catalina, and if you see the screenshot it's working. nc can receive the custom generated packet. In case the checksum isn't ok, then it would be dropped.

希望对你有帮助!