我想使用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") }
但是,运行此程序不起作用... SerializeLayer失败.这是恐慌:
恐慌:无效的src IP 127.0.0.1
goroutine 16 [running]: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+ 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
小智.. 10
您的问题是"工艺客户[原文如此] TCP数据包",但您的代码清楚地表明您还希望制作自定义IP第3层标头,两者之间存在差异.此外,您没有提到IPv4与IPv6,但您的代码似乎也是IPv4特定的.
鉴于您的示例代码,我假设您要设置完整的IPv4标头.
从Go 1.3.3和即将发布的Go 1.4开始,你无法使用Core Go软件包做你想做的事.要实现您的愿望,您需要做两件事:
您需要在Go中创建一个原始套接字.相反,在这个网站上,你可以创建一个使用中的一个围棋原始套接字等不正确的答案net.ListenPacket
,net.DialIP
或net.ListenIP
.
例如:
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_HDRINCL
套接字选项,也没有办法设置其他IP套接字选项,如IP_TTL
.我有一组私有补丁,可以使用Core Go实现此功能,但这对您没有帮助.
我相信以下软件包具有您想要的所有功能ipv4.请注意它是一个大包装,我自己没有使用它.我做了grep,它支持IP_HDRINCL
多个平台.您想调用NewRawConn
以创建原始连接,此函数创建一个原始套接字并设置IP_HDRINCL
套接字选项.
另请参见此处:raw-socket-in-go以及他在此处编写的代码延迟,以便了解更简单的方法,如果您只想设置TCP标头,则可能适合您的需求.但请注意,此代码不允许您设置我怀疑您想要执行的IPv4 IP标头中的IP地址.
您的问题是"工艺客户[原文如此] TCP数据包",但您的代码清楚地表明您还希望制作自定义IP第3层标头,两者之间存在差异.此外,您没有提到IPv4与IPv6,但您的代码似乎也是IPv4特定的.
鉴于您的示例代码,我假设您要设置完整的IPv4标头.
从Go 1.3.3和即将发布的Go 1.4开始,你无法使用Core Go软件包做你想做的事.要实现您的愿望,您需要做两件事:
您需要在Go中创建一个原始套接字.相反,在这个网站上,你可以创建一个使用中的一个围棋原始套接字等不正确的答案net.ListenPacket
,net.DialIP
或net.ListenIP
.
例如:
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_HDRINCL
套接字选项,也没有办法设置其他IP套接字选项,如IP_TTL
.我有一组私有补丁,可以使用Core Go实现此功能,但这对您没有帮助.
我相信以下软件包具有您想要的所有功能ipv4.请注意它是一个大包装,我自己没有使用它.我做了grep,它支持IP_HDRINCL
多个平台.您想调用NewRawConn
以创建原始连接,此函数创建一个原始套接字并设置IP_HDRINCL
套接字选项.
另请参见此处:raw-socket-in-go以及他在此处编写的代码延迟,以便了解更简单的方法,如果您只想设置TCP标头,则可能适合您的需求.但请注意,此代码不允许您设置我怀疑您想要执行的IPv4 IP标头中的IP地址.