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

2023-11-27

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

这是一个简短易读的 go 程序示例 演示了我想做的事情:

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 失败。 这是恐慌:

恐慌:源 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/HoneyBadger/packetSendTest.go:41 +0x464

goroutine 19 [终结器等待]:runtime.park(0x413cc0, 0x7bc6c0, 0x7bb189) /home/ human/golang-empire/go/src/pkg/runtime/proc.c:1369 +0x89runtime.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


您的问题是“制作自定义[原文如此] TCP 数据包”,但您的代码清楚地表明您还想制作自定义 IP 第 3 层标头,并且两者之间存在差异。另外,您没有提到 IPv4 与 IPv6,但您的代码似乎又是特定于 IPv4 的。

鉴于您的示例代码,我假设您希望设置完整的 IPv4 标头。

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

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

例如:

conn, err := net.ListenIP("ip4:tcp", netaddr)
if err != nil {
    log.Fatalf("ListenIP: %s\n", err)
}

创建一个原始套接字。

  1. 如果您想设置自己的 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_HDRINCL套接字选项也没有办法设置其他 IP 套接字选项,例如IP_TTL。我有一组私有补丁可以使用 Core Go 启用此功能,但这对您没有帮助。

我相信以下软件包具有您想要的所有功能ipv4。请注意,这是一个大包装,我自己还没有使用过。我做了 grep 它支持IP_HDRINCL在多个平台上。你想打电话NewRawConn创建一个原始连接,此函数创建一个原始套接字并设置IP_HDRINCL套接字选项。

另请参见此处:原始套接字和他在这里写的代码latency如果您只想设置 TCP 标头,了解一种可能适合您需求的更简单的方法。但是,请注意此代码不允许您在 IPv4 IP 标头中设置 IP 地址,我怀疑您想要这样做。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

  • SO_BINDTODEVICE Linux 套接字选项的问题

    我有一台带有两个网卡的电脑 一 eth0 用于 LAN 互联网 另一个用于与一个微控制器设备进行 UDP 通信 微控制器有一个 IP 192 168 7 2 和一个 MAC 地址 第二个电脑网络适配器 eth1 有 192 168 7 1
  • SO_REUSEPORT 可以在 Unix 域套接字上使用吗?

    Linux 内核 gt 3 9 允许通过设置在内核负载平衡的进程之间共享套接字SO REUSEPORT http lwn net Articles 542629 http lwn net Articles 542629 这如何用于类型的套接
  • 用于实时传输协议的开源 .net C# 库

    net中有好的RTP开源库吗 我的目的是用于音频和视频同步问题并提高每秒帧数速率 我对 RTP 不太了解 但你可能想看看本文 http www codeproject com KB IP Using RTP in Multicasting
  • 给定方法值,获取接收者对象

    Go 有没有办法从方法值获取接收者对象 例如有没有这样的MagicFunc这将使以下程序输出字符串my info来自底层 Foo 实例 package main import fmt type Foo struct A string fun
  • 确定 TCP Listen() 队列中当前积压的连接数

    有没有办法找出currentLinux 上 TCP 套接字上等待 Accept 的连接尝试次数 我想我可以在每个事件循环上点击 EWOULDBLOCK 之前计算成功的 Accept 数量 但我使用的是隐藏这些细节的高级库 Python Tw
  • 我们如何在 Golang 中组合多个错误字符串?

    我是 golang 新手 我的应用程序需要在循环中返回多个错误 稍后需要组合并作为单个错误字符串返回 我无法使用字符串函数来组合错误消息 在返回之前可以使用什么方法将这些错误合并为一个错误 package main import fmt s
  • C# P2P聊天应用程序设计

    我想创建一个不使用显式服务器的简单聊天应用程序 主要要求是用户可以同时与许多朋友聊天 就像在 Skype 等上一样 我在这里指的不是会议聊天 而是多个单独的聊天窗口 目前 我只想要一个 LAN 消息应用程序 但如果设计能够轻松扩展到 Int
  • 在本地主机上使用相同的 IP 和端口创建套接字

    我在 Linux 上看到奇怪的行为 我看到远程端和本地端都显示相同的 IP 和端口组合 以下是 netstat 输出 netstat anp 网络统计grep 6102 tcp 0 0 139 185 44 123 61020 0 0 0
  • 投射回更专业的界面

    我正在用 Go 编写一个游戏 在 C 中 我将所有实体类存储在 BaseEntity 类的数组中 如果一个实体需要在世界中移动 那么它将是一个从 BaseEntity 派生的 PhysEntity 但添加了方法 我尝试模仿这是 go pac
  • 如何使用 HTML5 与 UDP 套接字通信?

    我拥有的 正在运行的 C 应用程序服务器 准备将数据发送到应该发送到 HTML5 页面或应用程序的客户端 我想要的是 考虑到 c 服务器和 HTML5 应用程序都是系统本地的 有没有办法使用 udp 端口 与 HTML5 进行通信 我知道的
  • 如何在C#中执行Go函数

    有没有办法从 C 执行 Go 函数 例如 对于 Python 我会使用 Ironpython 我知道我可以生成一个进程来执行 Go 脚本 但如果可能的话 我真的不想回退到这样的解决方案 Google 搜索没有显示任何内容 那么有什么方法可以
  • 在处理程序之后访问 HTTP 请求上下文

    在我的日志记录中间件 链中的第一个 中 我需要访问一些在链下游的某些身份验证中间件中编写的上下文 并且仅在处理程序本身执行之后 旁注 需要首先调用日志记录中间件 因为我需要记录请求的持续时间 包括在中间件中花费的时间 此外 当权限不足时 身
  • 在golang中获取TTFB(第一个字节的时间)值

    我正在尝试获取 TTFB 值和 Connect 值 c exec Command curl w Connect time connect TTFB time starttransfer Total time time total o dev
  • Gorm 总是返回带有 nil 值的结构

    我正在使用 Gorm 构建 Go Web API 作为 Amazon RDS 中 Postgresql 数据库的 ORM 问题是 Gorm 总是返回一片结构 其值全部为零 尽管数据库已经填充了数据 切片中的结构体数量是否合适取决于LIMIT
  • Golang中如何删除字符串的最后一个字符?

    我想删除字符串的最后一个字符 但在此之前我想检查最后一个字符是否是 如何才能做到这一点 以下是删除尾随加号的几种方法 package main import fmt strings func TrimSuffix s suffix stri
  • 使用 OpenTelemetry 统一不同服务的范围

    我刚刚开始使用 OpenTelemetry 并为此创建了两个 微 服务 Standard and GeoMap 最终用户将请求发送到Standard服务 该服务又将请求发送到GeoMap在将结果返回给最终用户之前获取信息 我使用 gRPC
  • 使用覆盖率信息测试 Go 中的 os.Exit 场景 (coveralls.io/Goveralls)

    这个问题 如何在 Go 中测试 os exit 场景 https stackoverflow com questions 26225513 how to test os exit scenarios in go 以及其中得票最高的答案 列出
  • Golang中如何获得100%的代码覆盖率? [复制]

    这个问题在这里已经有答案了 我无法获得 100 的代码覆盖率 因为我无法在 Golang 中测试 Fatals 我发现了一些问答 包括this one https stackoverflow com questions 30688554 h
  • 编写每个处理程序中间件

    我希望从处理程序中提取一些重复的逻辑 并将其放入一些每个处理程序的中间件中 特别是 CSRF 检查 检查现有会话值 即身份验证或预览页面 等 我读了关于此的几篇文章 http justinas org writing http middle
  • 如何在 Ubuntu 中将 Go 程序作为守护进程启动?

    在 Ubuntu 中将 Go 程序作为守护进程启动的正确方法是什么 然后我将使用 Monit 对其进行监控 我应该做这样的事情 go run myapp go 我应该考虑 Go 特有的事情吗 您应该为您的程序构建一个可执行文件 go bui

随机推荐