使用gopacket向127.0.0.1发送UDP数据包

6

我试图使用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

当我运行我的代码时,我可以在回环接口上的wireshark中看到生成的数据包,其中包含正确的校验和,但该数据包却从未到达netcat。可能的问题是什么?
1个回答

4
如果您查看这个图表,您会注意到tcpdumpEthernet层上起作用。然后是IP,然后是TCP/UDP,然后是SocketsncTCP/UDP层操作。
IP级别,数据包可能会被丢弃。很多时候情况是反向路径过滤
因此,您能够看到到达以太网层的数据包,可以通过tcpdump进行观察,但对于nc来说,数据包可能被路由到其他地方或被丢弃了。
因此,最好检查是否禁用RP过滤并检查iptable规则是否有所帮助!
更新:
由于您正在操作回环接口:
MAC地址用于以太网流量的最低级别,仅在一个局域网内使用,并帮助指导其内部的流量。在本地网络接口(lo)上不需要它,因为数据包在内部处理。
环回地址直接在IP层连接到同一台计算机,而不使用任何物理硬件。因此,它允许您绕过以太网、PPP和其他驱动程序。
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 可以接收自定义生成的数据包。如果校验和不正确,则会被丢弃。
希望这有所帮助!

它解决了你的问题吗? - shmsr
我在/proc/sys/net/ipv4/conf/lo和/all中关闭了rp_filter,然后将所有的iptables规则更改为ACCEPT,但没有效果。RP过滤似乎不是数据包被丢弃的原因,特别是这些都是来自127.0.0.1 -> 127.0.0.1的有效调用。 - user1634494
对我来说,rp_filtering已经被禁用了,并且将“layers.Ethernet”更改为“layers.Loopback”,我甚至在tcpdump中看不到数据包。 - paddlesteamer
如果你还没有这样做,请将“lo0”更改为“lo”。是的,“rp_filtering”在这里无关紧要;如果你想启用它,也可以。 - shmsr
如果您愿意,我们可以在聊天中对此进行调试。加入此房间 https://chat.stackoverflow.com/rooms/215469/gopacket 并分享您所使用的命令和操作系统。 - shmsr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接