Sockets 如何使用Golang编写原始TCP数据包(使用gopacket)并通过原始套接字发送

Sockets 如何使用Golang编写原始TCP数据包(使用gopacket)并通过原始套接字发送,sockets,go,tcp,raw-sockets,gopacket,Sockets,Go,Tcp,Raw Sockets,Gopacket,我想用gopacket定制TCP数据包,然后 使用原始套接字发送它们 下面是一个简短易读的围棋程序示例 演示我想做什么: package main import ( "code.google.com/p/gopacket" "code.google.com/p/gopacket/examples/util" "code.google.com/p/gopacket/layers" "log" "net" ) func main() { defer

我想用gopacket定制TCP数据包,然后 使用原始套接字发送它们

下面是一个简短易读的围棋程序示例 演示我想做什么:

package main

import (
    "code.google.com/p/gopacket"
    "code.google.com/p/gopacket/examples/util"
    "code.google.com/p/gopacket/layers"
    "log"
    "net"
)

func main() {
    defer util.Run()()

    // XXX create tcp/ip packet
    srcIP := net.ParseIP("127.0.0.1")
    dstIP := net.ParseIP("192.168.0.1")
    //srcIPaddr := net.IPAddr{
    //  IP: srcIP,
    //}
    dstIPaddr := net.IPAddr{
        IP: dstIP,
    }
    ipLayer := layers.IPv4{
        SrcIP:    srcIP,
        DstIP:    dstIP,
        Protocol: layers.IPProtocolTCP,
    }
    tcpLayer := layers.TCP{
        SrcPort: layers.TCPPort(666),
        DstPort: layers.TCPPort(22),
        SYN:     true,
    }
    tcpLayer.SetNetworkLayerForChecksum(&ipLayer)
    buf := gopacket.NewSerializeBuffer()
    opts := gopacket.SerializeOptions{
        FixLengths:       true,
        ComputeChecksums: true,
    }
    err := gopacket.SerializeLayers(buf, opts, &ipLayer, &tcpLayer)
    if err != nil {
        panic(err)
    }
    // XXX end of packet creation

    // XXX send packet
    ipConn, err := net.ListenPacket("ip4:tcp", "0.0.0.0")
    if err != nil {
        panic(err)
    }
    _, err = ipConn.WriteTo(buf.Bytes(), &dstIPaddr)
    if err != nil {
        panic(err)
    }
    log.Print("packet sent!\n")
}
但是运行此程序不起作用。。。序列化层失败。 下面是恐慌:

死机:src IP 127.0.0.1无效

goroutine 16[正在运行]:runtime.panic(0x5bb020、0xc2090723e0) /home/human/golang empire/go/src/pkg/runtime/panic.c:279+0xf5 main.main() /home/human/golang empire/gopkg/src/github.com/david415/honeybecger/packetSendTest.go:41+0x464

goroutine 19[终结器等待]:runtime.park(0x413cc0,0x7bc6c0, 0x7bb189) /home/human/golang empire/go/src/pkg/runtime/proc.c:1369+0x89 runtime.parkunlock(0x7bc6c0,0x7bb189) /home/human/golang empire/go/src/pkg/runtime/proc.c:1385+0x3b runfinq() /home/human/golang empire/go/src/pkg/runtime/mgc0.c:2644+0xcf runtime.goexit() /home/human/golang empire/go/src/pkg/runtime/proc.c:1445

您的问题是“craft custome[sic]TCP packets”,但您的代码清楚地表明,您还希望创建自定义IP层3头,这两者之间存在差异。此外,您没有提到IPv4与IPv6,但您的代码似乎是特定于IPv4的

给出您的示例代码,我假设您希望设置完整的IPv4头

从Go 1.3.3和即将发布的Go 1.4开始,您无法使用核心Go软件包做您想要做的事情。要实现你的愿望,你需要做两件事:

  • 您需要在Go中创建一个原始套接字。与此网站上的其他错误答案相反,您可以使用
    net.ListenPacket
    net.DialIP
    net.ListenIP
    中的一种在Go中创建原始套接字
  • 例如:

    conn, err := net.ListenIP("ip4:tcp", netaddr)
    if err != nil {
        log.Fatalf("ListenIP: %s\n", err)
    }
    
    创建原始套接字

  • 如果要设置自己的IPv4第3层标头,则需要设置套接字选项以启用功能
  • 您的问题没有说明您正在使用什么操作系统和体系结构。在运行Mac OS X的笔记本电脑上:

    % man ip
    . . .
    Outgoing packets automatically have an IP header prepended to them
    (based on the destination address and the protocol number the socket is created with),
    unless the IP_HDRINCL option has been set.
    
    IP_HDRINCL
    在Linux上也可用。不幸的是,Core Go无法设置
    IP\u HDRINCL
    套接字选项,也无法设置其他IP套接字选项,如
    IP\u TTL
    。我有一套专用补丁,可以通过Core Go实现此功能,但这对您没有帮助

    我相信下面的软件包具有您想要的所有功能。请注意,这是一个大包裹,我自己也没用过。我做了grep,它在多个平台上支持
    IP\u HDRINCL
    。您想调用
    NewRawConn
    来创建一个原始连接,此函数创建一个原始套接字并设置
    IP_HDRINCL
    socket选项


    另请参见此处:以及他在此处编写的代码,以了解一种更简单的方法,如果您只想设置TCP头,这种方法可能适合您的需要。但是,请注意,此代码不允许您在IPv4 IP头中设置IP地址,我怀疑您希望这样做。

    OK。。。我修复了“无效src ip”错误。。。这是因为ParseIP返回了错误的类型。。。它需要用它的.To4()方法进行转换;-)目前,我的简单简明示例是发送精心编制的TCP/IP数据包。。。但是,端口号和其他部分的格式不正确。也许TCP端口的“endian ness”设置错误?这里有一个简单简明的示例:这个新的提交通过将srcPort和dstPort与数据包解析后的预期值进行比较,证明生成的TCP/IP数据包格式不正确:谢谢!对这非常有效。让它在这个提交中起作用:下面是你链接的博客文章的后续内容,它会下降到IP头级别: