网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
"fmt"
"net"
)
func main() {
interfaces, err := net.Interfaces()
if err != nil {
fmt.Println(“Failed to get interfaces:”, err)
return
}
fmt.Println("Network interfaces:")
for \_, iface := range interfaces {
fmt.Println("- Name:", iface.Name)
}
}
执行上述代码,会输出计算机上所有的网络设备名称。
可以通过以下代码来打开一个网络设备:
package main
import (
“fmt”
“log”
“net”
"github.com/google/gopacket/pcap"
)
func main() {
device := “eth0” // 要打开的网络设备名称
handle, err := pcap.OpenLive(device, 65536, true, pcap.BlockForever)
if err != nil {
log.Fatal(err)
}
defer handle.Close()
fmt.Println("Device opened:", device)
}
在上述代码中,我们使用`pcap.OpenLive`函数来打开一个网络设备。该函数接受设备名称、数据包最大长度、是否要抓取数据包的全部内容以及超时时间作为参数。如果打开成功,将返回一个`pcap.Handle`对象,可以用于后续的数据包捕获和分析。
#### 捕获数据包
在打开网络设备之后,我们可以开始捕获数据包。可以通过以下代码来捕获指定数量的数据包:
package main
import (
“fmt”
“log”
“net”
“time”
"github.com/google/gopacket/pcap"
)
func main() {
device, err := pcap.FindAllDevs()
if err != nil {
log.Fatal(err)
}
handle, err := pcap.OpenLive(device[0].Name, 65536, true, pcap.BlockForever)
if err != nil {
log.Fatal(err)
}
defer handle.Close()
packetCount := 0
packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
for packet := range packetSource.Packets() {
packetCount++
fmt.Println("Packet:", packetCount)
// TODO: 进行数据包分析
time.Sleep(1 \* time.Second) // 仅用于示例,避免数据包流量过大
}
}
上述代码中,我们使用`gopacket.NewPacketSource`函数将打开的设备与`pcap.Handle`对象关联起来,然后使用`PacketSource`的`Packets`方法来获取捕获到的数据包。每次从`Packets`方法获取到一个数据包,我们都会对其进行处理,即打印出数据包的序号(用于示例,实际应用中可能需要根据需求进行其他操作)。
#### 数据包分析
在捕获到数据包后,我们可以对其进行分析并提取所需的信息。gopacket库提供了丰富的工具和功能,用于数据包分析。
以下是一些常见的数据包分析方法:
##### 解析以太网帧
ethernetLayer := packet.Layer(layers.LayerTypeEthernet)
if ethernetLayer != nil {
ethernetPacket, _ := ethernetLayer.(*layers.Ethernet)
fmt.Println(“Ethernet source MAC:”, ethernetPacket.SrcMAC)
fmt.Println(“Ethernet destination MAC:”, ethernetPacket.DstMAC)
fmt.Println(“Ethernet type:”, ethernetPacket.EthernetType)
}
以上代码演示了如何解析以太网帧中的源MAC地址、目的MAC地址和以太网类型。
##### 解析IP包
ipLayer := packet.Layer(layers.LayerTypeIPv4)
if ipLayer != nil {
ipPacket, _ := ipLayer.(*layers.IPv4)
fmt.Println(“IP version:”, ipPacket.Version)
fmt.Println(“IP source address:”, ipPacket.SrcIP)
fmt.Println(“IP destination address:”, ipPacket.DstIP)
fmt.Println(“IP protocol:”, ipPacket.Protocol)
}
以上代码演示了如何解析IPv4包中的版本、源IP地址、目的IP地址和协议。
##### 解析TCP包
tcpLayer := packet.Layer(layers.LayerTypeTCP)
if tcpLayer != nil {
tcpPacket, _ := tcpLayer.(*layers.TCP)
fmt.Println(“TCP source port:”, tcpPacket.SrcPort)
fmt.Println(“TCP destination port:”, tcpPacket.DstPort)
fmt.Println(“TCP sequence number:”, tcpPacket.Sequence)
fmt.Println(“TCP acknowledgment number:”, tcpPacket.Acknowledgment)
fmt.Println(“TCP flags:”, tcpPacket.Flags)
}
以上代码演示了如何解析TCP包中的源端口、目的端口、序列号、确认号和标志位。
##### 解析UDP包
udpLayer := packet.Layer(layers.LayerTypeUDP)
if udpLayer != nil {
udpPacket, _ := udpLayer.(*layers.UDP)
fmt.Println(“UDP source port:”, udpPacket.SrcPort)
fmt.Println(“UDP destination port:”, udpPacket.DstPort)
}
以上代码演示了如何解析UDP包中的源端口和目的端口。
##### 解析应用层协议
在数据包的应用层有各种各样的协议,如HTTP、DNS等。gopacket库提供了根据协议类型解析数据包的方法。以下是解析HTTP协议的示例代码:
httpLayer := packet.Layer(layers.LayerTypeHTTP)
if httpLayer != nil {
httpPacket, _ := httpLayer.(*layers.HTTP)
fmt.Println(“HTTP method:”, httpPacket.Method)
fmt.Println(“HTTP host:”, httpPacket.Host)
fmt.Println(“HTTP user-agent:”, httpPacket.UserAgent)
}
以上代码演示了如何解析HTTP包中的方法、主机和用户代理信息。
#### 示例:捕获HTTP请求
现在,我们将结合以上的知识来实现一个简单的示例:捕获HTTP请求,并提取请求的URL和请求头信息。
package main
import (
“fmt”
“log”
“net”
“strings”
“time”
"github.com/google/gopacket"
"github.com/google/gopacket/pcap"
"github.com/google/gopacket/layers"
)
func main() {
device, err := pcap.FindAllDevs()
if err != nil {
log.Fatal(err)
}
handle, err := pcap.OpenLive(device[0].Name, 65536, true, pcap.BlockForever)
if err != nil {
log.Fatal(err)
}
defer handle.Close()
packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
for packet := range packetSource.Packets() {
ethernetLayer := packet.Layer(layers.LayerTypeEthernet)
if ethernetLayer != nil {
ethernetPacket, \_ := ethernetLayer.(\*layers.Ethernet)
ipLayer := packet.Layer(layers.LayerTypeIPv4)
if ipLayer != nil {
ipPacket, \_ := ipLayer.(\*layers.IPv4)
tcpLayer := packet.Layer(layers.LayerTypeTCP)
if tcpLayer != nil {
tcpPacket, \_ := tcpLayer.(\*layers.TCP)
httpLayer := packet.Layer(layers.LayerTypeHTTP)
if httpLayer != nil {
httpPacket, \_ := httpLayer.(\*layers.HTTP)
fmt.Println("Source MAC:", ethernetPacket.SrcMAC)
fmt.Println("Destination MAC:", ethernetPacket.DstMAC)
fmt.Println("Source IP:", ipPacket.SrcIP)
fmt.Println("Destination IP:", ipPacket.DstIP)
fmt.Println("Source Port:", tcpPacket.SrcPort)
fmt.Println("Destination Port:", tcpPacket.DstPort)
fmt.Println("HTTP Method:", httpPacket.Method)
fmt.Println("HTTP Host:", httpPacket.Host)
headers := strings.Split(string(httpPacket.Headers), "\r\n")
for \_, header := range headers {
fmt.Println("HTTP Header:", header)
}
fmt.Println("--------")
}
}
}
}
time.Sleep(1 \* time.Second) // 仅用于示例,避免数据包流量过大
}
}
以上示例代码中,我们使用了嵌套的条件语句来逐级解析数据包的各个层级,并提取所需的信息。其中,我们关注以太网帧、IPv4包、TCP包和HTTP协议,提取了包括源MAC地址、目的MAC地址、源IP地址、目的IP地址、源端口、目的端口、HTTP方法、主机和请求头信息等。
### 案例
#### 案例一:统计流量
我们可以使用抓包技术来统计特定端口的流量。以下示例代码演示了如何捕获HTTP流量,并统计总共传输的数据量:
package main
import (
“fmt”
“log”
“net”
“strings”
“time”
"github.com/google/gopacket"
"github.com/google/gopacket/pcap"
"github.com/google/gopacket/layers"
)
func main() {
device, err := pcap.FindAllDevs()
if err != nil {
log.Fatal(err)
}
handle, err := pcap.OpenLive(device[0].Name, 65536, true, pcap.BlockForever)
if err != nil {
log.Fatal(err)
}
defer handle.Close()
packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
totalBytes := 0
startTime := time.Now()
for packet := range packetSource.Packets() {
ethernetLayer := packet.Layer(layers.LayerTypeEthernet)
if ethernetLayer != nil {
ethernetPacket, \_ := ethernetLayer.(\*layers.Ethernet)
ipLayer := packet.Layer(layers.LayerTypeIPv4)
if ipLayer != nil {
ipPacket, \_ := ipLayer.(\*layers.IPv4)
tcpLayer := packet.Layer(layers.LayerTypeTCP)
if tcpLayer != nil {
tcpPacket, \_ := tcpLayer.(\*layers.TCP)
httpLayer := packet.Layer(layers.LayerTypeHTTP)
if httpLayer != nil {
httpPacket, \_ := httpLayer.(\*layers.HTTP)
if tcpPacket.SrcPort.String() == "80" || tcpPacket.DstPort.String() == "80" {
totalBytes += len(packet.Data())
}
}
}
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
ata())
}
}
}
[外链图片转存中…(img-RJiZhDLe-1715837051744)]
[外链图片转存中…(img-D59Awg80-1715837051744)]
[外链图片转存中…(img-usRH4Qq1-1715837051744)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新