gpt4 book ai didi

sockets - 如何在数据链路层(以太网)监听并在传输层响应

转载 作者:行者123 更新时间:2023-12-04 11:32:53 24 4
gpt4 key购买 nike

我想要做的是监听 IPv6 的以太网帧并响应特定端口上的 UDP 调用。

我能够捕获我关心的以太网帧并解析出 UDP 有效负载,但是当我尝试回显该有效负载时,我遇到了问题。这是我的“服务器”代码:

func main() {
fd, err := syscall.Socket(syscall.AF_PACKET, syscall.SOCK_RAW, int(htons(syscall.ETH_P_IPV6)))
iface, err := net.InterfaceByName("lo")
if err != nil {
log.Fatal(err)
}

err = syscall.BindToDevice(fd, iface.Name)
if err != nil {
log.Fatal(err)
}

for {
buf := make([]byte, iface.MTU)
n, callerAddr, err := syscall.Recvfrom(fd, buf, 0)
if err != nil {
log.Fatal(err)
}
data := buf[:n]
packet := gopacket.NewPacket(data, layers.LayerTypeEthernet, gopacket.Default)
udpPacket := packet.Layer(layers.LayerTypeUDP)
if udpPacket != nil {
udpPck, _ := udpPacket.(*layers.UDP)

// I only care about calls to 8080 for this example
if udpPck.DstPort != 8080 {
continue
}

err = udpPck.SetNetworkLayerForChecksum(packet.NetworkLayer()); if err != nil {
log.Fatal(err)
}

log.Print(packet)
log.Printf("UDP Port from %v --> %v", udpPck.SrcPort, udpPck.DstPort)
log.Printf("Payload '%v'", string(udpPck.Payload))

// Flip the source and destination so it can go back to the caller
ogDst := udpPck.DstPort
udpPck.DstPort = udpPck.SrcPort
udpPck.SrcPort = ogDst

buffer := gopacket.NewSerializeBuffer()
options := gopacket.SerializeOptions{ComputeChecksums: true}

// Rebuild the packet with the new source and destination port
err := gopacket.SerializePacket(buffer, options, packet)
if err != nil {
log.Fatal(err)
}

log.Printf("Writing the payload back to the caller: %v", callerAddr)
log.Print(packet)

err = syscall.Sendto(fd, buffer.Bytes(), 0, callerAddr)
if err != nil {
log.Fatal(err)
}
}
}

然后我在同一台机器上运行的客户端代码:

func main() {
conn, err := net.DialUDP("udp6", &net.UDPAddr{
IP: net.IPv6loopback,
Port: 0,
}, &net.UDPAddr{
IP: net.IPv6loopback,
Port: 8080,
})
if err != nil {
log.Fatal(err)
}

_, _ = conn.Write([]byte("Hello World"))

log.Print("Waiting for response")
buf := make([]byte, 65535)
n, _, err := conn.ReadFrom(buf)
if err != nil {
log.Fatal(err)
}

log.Printf("Response message '%v'", string(buf[:n]))
}

来自客户端的问题是连接被拒绝 read udp6 [::1]:56346->[::1]:8080: recvfrom: connection refused我的猜测将来自 linux 内核,因为严格来说我没有将任何东西绑定(bind)到 8080。

我需要来自 IPv6 header (上面没有看到)的数据,这就是为什么我需要在数据链路层上进行监听,但是由于我还需要响应 UDP 请求,所以事情变得有点棘手。

我有但不喜欢的一个选项是在单独的 goroutine 中执行标准 net.ListenUDP然后在读取数据后阻塞,直到从系统调用套接字监听器读取 IPv6 header ,然后从那里响应 udp 连接。如果这是我唯一的选择,我会接受它,但我很想看看是否有更好的办法。

最佳答案

我认为即使您通过构建链路层帧进行响应,您仍然需要监听 UDP 端口。否则系统的网络堆栈将响应 ICMP 消息,即 caused “连接被拒绝”错误。
我还没有尝试过,但我认为如果从接口(interface)中删除 IP 地址,它会阻止内核 IP 堆栈在其上运行。但是,您可能需要处理一些 ARP 消息。
或者,您可以尝试使用 TUN/TAP interface ,以便您可以从用户空间完全控制其上发生的事情。

关于sockets - 如何在数据链路层(以太网)监听并在传输层响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62071469/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com