首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用Golang编写原始TCP数据包(使用gopacket)并通过原始套接字发送

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

Stack Overflow用户
提问于 2014-11-30 22:23:16
回答 1查看 21.4K关注 0票数 10

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

下面是一个简短的、可读的go程序,它演示了我想做的事情:

代码语言:javascript
复制
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")
}

但是运行这个程序不起作用..。SerializeLayer失败。恐慌是这样的:

恐慌:无效的src IP 127.0.0.1 运行: /home/human/golang-empire/go/src/pkg/runtime/panic.c:279 (0x5bb020,0xc2090723e0) runtime.panic +0xf5 main.main() main.main +0x464 /home/human/golang-empire/go/src/pkg/runtime/proc.c:1369 +0x89 runtime.parkunlock(0x7bc6c0,0x7bc6c0)/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

EN

回答 1

Stack Overflow用户

发布于 2014-12-01 08:00:19

您的问题是“手工定制TCP数据包”,但是您的代码清楚地表明,您也希望创建定制的IP层3报头,这两者之间存在差异。另外,您没有提到IPv4与IPv6,但是您的代码似乎是IPv4特定的。

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

从Go 1.3.3到即将发布的Go 1.4,您不能使用Core包来做您想做的事情。要实现你的愿望,你需要做两件事:

  1. 您需要在Go中创建一个原始套接字。与本网站上的其他错误答案相反,您可以使用net.ListenPacketnet.DialIPnet.ListenIP之一在Go中创建原始套接字。

例如:

代码语言:javascript
复制
conn, err := net.ListenIP("ip4:tcp", netaddr)
if err != nil {
    log.Fatalf("ListenIP: %s\n", err)
}

创建一个原始套接字。

  1. 如果您想设置您自己的IPv4第3层报头,您需要设置一个套接字选项来启用功能。

您的问题没有说明您正在使用的操作系统和体系结构。在我的笔记本电脑上运行Mac:

代码语言:javascript
复制
% 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没有设置IP_HDRINCL套接字选项的方法,也没有设置其他IP套接字选项(如IP_TTL )的方法。我有一组私有修补程序,可以使用Core启用此功能,但这不会对您有所帮助。

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

还请参阅这里:raw-sockets-in-go和他在这里编写的代码,latency以获得一种更简单的方法,如果您只想设置TCP,这种方法可能更适合您的需要。但是,请注意,此代码不允许您在IPv4 IP报头中设置IP地址,我怀疑您想这样做。

票数 11
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27218989

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档