【问题标题】:how to listen on L3 network layer?如何监听 L3 网络层?
【发布时间】:2017-09-02 04:24:28
【问题描述】:

我正在创建一个聊天应用程序后端,并希望考虑可扩展性。

我想创建一个负载均衡器,但不是在 HTTP 所在的 L7 层上,而是在 IP 网络所在的 L3 层上,以直接连接到特定服务器,然后我可以在其中创建TCP

net.ListenIP 是用于侦听 IP 层数据包的正确函数吗?

例如,它与更高的Listen("tcp") 相同吗?我需要实现负载均衡器的方法是否正确?

是否有关于数据包结构的参考,以便我能够从中获取源 IP 和目标 IP 来转发它们?

如果不告诉我使用哪个函数来监听 L3 网络层以平衡其他服务器的负载。

【问题讨论】:

    标签: networking go ip load-balancing packet


    【解决方案1】:

    我个人使用gopacket来捕获多个网络层,这个库非常令人印象深刻。

    当您使用 gopacket 时,您可以通过指定它们来捕获多个网络层,例如 Ipv4TCPEthernet... 如需更多信息,请参阅layers packet

    然后,您将能够使用 packet.Data() 分析您的层,这是组成整个数据包的一组字节,然后打开数据包类型以执行一些操作。

    例如,在eth0 上捕获多个网络层:

    package main
    
    import (
        "fmt"
        "github.com/google/gopacket"
        "github.com/google/gopacket/layers"
        "github.com/google/gopacket/pcap"
        "time"
    )
    
    //Layers we want to decode
    var (
        ip4 layers.IPv4
        eth layers.Ethernet
        tcp layers.TCP
    )
    
    func main() {
    
        //Array to store decoded layers
        decodedLayers := []gopacket.LayerType{}
    
        //Create parser
        parser := gopacket.NewDecodingLayerParser(layers.LayerTypeEthernet, &eth, &ip4, &tcp)
    
        //Here we use pcap to capture packet on eth0 interface, we can also use afpacket for example, which is more efficient
        handle, err := pcap.OpenLive("eth0", 65536, true, pcap.BlockForever)
        if err != nil {
            panic("Error opening pcap: " + err.Error())
        }
    
        datasource := gopacket.NewPacketSource(handle, layers.LayerTypeEthernet)
    
        //packets will be a channel of packets
        packets := datasource.Packets()
    
        for {
            select {
            case packet := <-packets:
                //We are decoding layers, and switching on the layer type
                err := parser.DecodeLayers(packet.Data(), &decodedLayers)
                for _, typ := range decodedLayers {
                    switch typ {
                    case layers.LayerTypeIPv4:
                        fmt.Printf("Source ip = %s - Destination ip = %s \n", ip4.SrcIP.String(), ip4.DstIP.String())
                    case layers.LayerTypeTCP:
                        //Here, we can access tcp packet properties
                        fmt.Println("Capture tcp traffic")
                    }
                    //etc ....
                }
                if len(decodedLayers) == 0 {
                    fmt.Println("Packet truncated")
                }
    
                //If the DecodeLayers is unable to decode the next layer type
                if err != nil {
                    //fmt.Printf("Layer not found : %s", err)
                }
            }
        }
    
    }
    

    【讨论】:

    • 所以我看到并听到了很多数据包,我将它们转发到我的服务器来处理它们并打开 tcp 对吗?平衡器充当桥梁?
    【解决方案2】:

    reading the Docs之后,是的,这个功能会帮助你接收IP包。

    ListenIP 的作用类似于 IP 网络的 ListenPacket。

    ListenIP 类似于ListenPacket("tcp"),但用于 IP 数据包。

    至于 IP 数据包的结构以及使用它们,net 包似乎没有。

    还有另一个包gopacket,它看起来可以帮助您从任何层读取和修改数据包。

    gopacket 中有一个Packet 类型,它允许使用网络层。

    Packet.NetworkLayer().LayerContent()Packet.NetworkLayer().LayerPayload() 将分别返回 byte[],您可以将其解释为预期的 structure of an IP packet


    注意既然我已经写了这整件事,我不得不想象那里有人写了一个很好的覆盖/包装器来使这更容易。这只是我谷歌搜索 10 分钟的结果。也许其他人会用更好的工具/方法来回答

    【讨论】:

    • 我读了你的笔记,但你的回答一定是最好的,因为我想自己实现负载均衡器
    • 所以我看到并听到了很多数据包,我将它们转发到我的服务器来处理它们并打开 tcp 对吗?平衡器充当桥梁?
    猜你喜欢
    • 1970-01-01
    • 2010-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-07
    • 2016-05-15
    • 1970-01-01
    • 2021-09-16
    相关资源
    最近更新 更多