golang利用原始套接字构造UDP包的示例

  介绍

小编给大家分享一下golang利用原始套接字构造UDP包的示例,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获、下面让我们一起去了解一下吧!

<强>原始套接字介绍

TCP/IP协议中,最常见的就是原始(SOCKET_RAW), TCP (SOCKET_STREAM), UDP (SOCKET_DGRA)三种套接字。原始套接字能够对底层传输进行控制,允许自行组装数据包,比如修改本地IP,发送Ping包,进行网络监听。这里不做详细介绍,要了解更多可以网上自己查询。

<强>实现

这里先看IP头结构:

 golang利用原始套接字构造UDP包的示例

其中16位总长度包括IP头长度和数据的长度,8位协议填写17日,因为UDP协议类型为17。这里要说明一下IP头中的首部校验,这个值只校验IP头部,不包含数据。

这里给出校验算法,IP头和UDP头中使用的校验算法是一样的。

func 校验和(msg []字节),uint16  {   ,sum :=0   ,for  n :=, 1;, n  & lt;, len(味精)1;,n  +=, 2, {   sum 才能+=,int(味精[n]) * 256, +, int(味精(n + 1))   ,}=,sum  (sum 在祝辞,16),+,(sum ,, 0 xffff)   ,sum  +=, (sum 在祝辞,16)   ,var  ans =, uint16(^总和)   return 答   }

下面开始填充IP头,这里使用了golang.org/x/net下的ipv4包

,//目的IP   ,dst :=, net.IPv4 (192,, 168,, 1,, 2)//源IP   ,src :=, net.IPv4 (192,, 168,, 1,, 3)   ,//填充ip首部   ,iph :=,, ipv4.Header {   ,,版本:ipv4.Version,//IP头才能长一般是20   Len:,,才能ipv4.HeaderLen,   服务条款才能:,,0 x00,//迷才能为数据   TotalLen才能:ipv4.HeaderLen  +, len(浅黄色),   TTL才能:,,64年,   国旗:才能,ipv4.DontFragment,   ,,FragOff: 0,   协议:才能,17日   校验和才能:0,   Src才能:,,Src,   Dst才能:,,Dst,   ,}   ,   ,h, err :=, iph.Marshal ()   ,if  err  !=, nil  {   log.Fatalln才能(err)   ,}   ,//计算IP头部校验值   ,iph.Checksum =, int(校验和(h))

下面开始处理UDP头部,先来看UDP头结构:

 golang利用原始套接字构造UDP包的示例

UDP头结构就很简单了,16位UDP校验和涉及到一个UDP伪首部的东西,我们先来看下UDP伪首部的构成。

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -   |,,,32 bit  Source  IP  address  |   -----------------------------------------   |,,,32 bit  Destination  IP  addr  |   -----------------------------------------   | 0 |还以为;8 bit 原型|,16 bit  header 长度|   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

伪首部包含了源IP、目的IP,协议号,16位的长度。这个伪首部仅仅参与校验计算。

下面开始填充UDP头:

,//填充UDP首部   ,//udp伪首部   ,udph :=,([]字节,,20)   ,//源ip地址   ,udph [0], udph [1],, udph [2],, udph [3],=, src [12],, src [13],,, src src [14], [15]   ,//目的ip地址   ,udph [4], udph [5],, udph [6],, udph [7],=, dst.IP [12],, dst.IP [13],, dst.IP [14],, dst.IP [15]   ,//协议类型   ,udph [8], udph [9],=, 0 x00, 0 x11   ,//udp头长度   ,udph [10], udph[11],=,,,字节0 x00 (len(浅黄色)+ 8)   ,//下面开始就真正的udp头部   ,//源端口号   ,udph [12], udph [13],=, 0 x27 0 x10   ,//目的端口号   ,udph [14], udph [15],=, 0 x17, 0 x70   ,//udp头长度   ,udph [16], udph[17],=,,,字节0 x00 (len(浅黄色)+ 8)   ,//校验和   ,udph [18], udph [19],=, 0 x00, 0 x00   ,//计算校验值   ,check :=,校验和(附加(udph,迷……)   ,udph [18], udph[19],=,字节(check>在8和255),,字节(check& 255)

下面我们需要发送自己构造的UDP包,可以使用净下的ListenPacket。

,侦听器,err :=, net.ListenPacket (“ip4: udp",,“192.168.1.104")   ,if  err  !=, nil  {   log.Fatal才能(err)   ,}   ,defer  listener.Close ()   ,   ,//listener 实现了net.PacketConn接口   ,r, err :=, ipv4.NewRawConn (c)   ,if  err  !=, nil  {   log.Fatal才能(err)   ,}      ,//发送自己构造的UDP包   ,if  err =, r.WriteTo (iph,附加(udph[12:20],迷…),,nil);, err  !=, nil  {   log.Fatal才能(err)   以前,}

golang利用原始套接字构造UDP包的示例