Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Tangkap trafik dengan Golang

Tangkap trafik dengan Golang

王林
王林asal
2024-09-04 11:07:29622semak imbas

Capture traffic with Golang

pengenalan

Kebanyakan orang dari dunia Kejuruteraan Perisian mendengar tentang TCPDump, WireShark, dll.
Dan kemungkinan besar anda pernah mendengar tentang pustaka libpcap1 yang dibangunkan oleh pasukan TCPDump untuk menangkap trafik dan digunakan oleh Wireshark juga.

Pustaka ini1 menyediakan antara muka yang fleksibel untuk menangkap trafik daripada antara muka rangkaian dan memprosesnya dalam kod. Ia menyediakan fleksibiliti untuk menulis kod prestasi dan memasukkan sebanyak logik perniagaan yang diperlukan untuk mengumpul data yang diperlukan sahaja.

Baru-baru ini saya telah mengenal pasti tugas di mana adalah idea yang baik untuk mengumpul paket yang diperlukan, menganalisisnya dan menyimpannya untuk semakan manual masa hadapan. Untuk menyemak secara manual WireShak boleh digunakan untuk memuatkan fail pcap dan menyemak secara manual paket yang dikumpul menggunakan UI yang bagus.

Dan bahagian yang paling penting, kenapa Pergi? Go ialah bahasa yang cukup mudah untuk menulis kod dan menyokongnya oleh berbilang ahli pasukan. Ia jauh lebih selamat daripada C dan C++ dan memerlukan lebih sedikit pengalaman untuk orang lain menyokongnya tanpa kejutan yang tidak dijangka. Sehingga kami tidak mempunyai keperluan apabila kami TERPAKSA menggunakan banyak bahasa berprestasi (C, C++, karat, dll.), saya lebih suka memilih Golang.

Definisi tugas

Sebelum kita melakukan sesuatu, alangkah baiknya untuk memahami, apakah yang ingin kita capai dalam sesuatu keputusan? Mari kita tentukan senarai ringkas keperluan.

Keperluan

Untuk memastikan pelaksanaan semudah mungkin, mari kita tentukan hanya beberapa perkara:

  1. Kami mahu mengumpul trafik keluar
  2. Jom kumpul trafik IPv4
  3. Abaikan trafik rangkaian peribadi
  4. Dan mari kita simpan paket UDP

Beberapa perkara mudah ini sudah cukup untuk mendapatkan idea tentang cara menggunakan libpcap1 dari Golang.
Selepas itu, ia hanya soal imaginasi tentang logik apa yang akan ditambah di atasnya.

Perlaksanaan

Sebelum kita mula, mari kita tentukan bahawa kod tidak sepatutnya menjadi pengeluaran sedia. Matlamat kami adalah untuk melihat contoh minimum dan menguji bahawa ia berfungsi dengan baik.

Kami akan menggunakan perpustakaan ini:

  1. slog untuk log masuk
  2. github.com/google/gopacket untuk menangkap paket dan memformat format fail pcap

Antara muka dalam kod akan datang ialah eth0, walaupun kemungkinan besar sistem anda akan mempunyai nama antara muka yang berbeza.

Kod kerja

Ini ialah kod dengan ulasan yang anda boleh salin dan cuba dalam persekitaran anda sendiri.
Memandangkan kami menggunakan libpcap1, aplikasi kami akan menggunakan CGO dan kami perlu menjalankan aplikasi daripada pengguna root.

package main

import (
    "bytes"
    "log/slog"
    "net"
    "os"

    "github.com/google/gopacket"
    "github.com/google/gopacket/layers"
    "github.com/google/gopacket/pcap"
    "github.com/google/gopacket/pcapgo"
)

const (
    interfaceName = "eth0"
    snaplen       = 1500
)

func main() {
    slog.Info("Running our applicaiton...")

    // Get handler attached to an interface.
    handle, err := pcap.OpenLive(interfaceName, snaplen, true, pcap.BlockForever)
    if err != nil {
        slog.Error("Could not OpenLive", slog.String("err", err.Error()))
        os.Exit(1)
    }

    iface, err := net.InterfaceByName(interfaceName)
    if err != nil {
        slog.Error("Could not OpenLive", slog.String("err", err.Error()))
        os.Exit(1)
    }

    // Start new Source reader.
    source := gopacket.NewPacketSource(handle, handle.LinkType())

    // This is suppose to be a file writer, but we will use memory, just for simplification.
    fileWriter := bytes.NewBuffer(nil)
    pcapWriter := pcapgo.NewWriterNanos(fileWriter)
    err = pcapWriter.WriteFileHeader(snaplen, handle.LinkType())
    if err != nil {
        slog.Error("Could not write pcap header", slog.String("err", err.Error()))
        os.Exit(1)
    }

    // Reading packages.
    for packet := range source.Packets() {
        // Filter by outcoming traffic only.
        // To filter it, we need to compare MAC addresses from out interface and source MAC.
        // To access a mac Address we need to get an Ethernet layer.
        layer := packet.Layer(layers.LayerTypeEthernet)

        ethernet, ok := layer.(*layers.Ethernet)
        if !ok {
            slog.Error("Could not get Ethernet layer")
            continue
        }

        if !bytes.Equal(ethernet.SrcMAC, iface.HardwareAddr) {
            // Our interface did not send this packet. It's not outcoming.
            continue
        }

        // Now we need to identify IPv4 layer.
        layer = packet.Layer(layers.LayerTypeIPv4)

        ipv4, ok := layer.(*layers.IPv4)
        if !ok {
            // It's not IPv4 traffic.
            continue
        }

        if ipv4.DstIP.IsPrivate() {
            // Do not collect private traffic.
            continue
        }

        if ipv4.Protocol != layers.IPProtocolUDP {
            // Ignore not UDP protocol.
            continue
        }

        err = pcapWriter.WritePacket(packet.Metadata().CaptureInfo, packet.Data())
        if err != nil {
            slog.Error("Could not write a packet to a pcap writer", slog.String("err", err.Error()))

            continue
        }

        slog.Info("Stored packet", slog.Any("packet", packet))

        // Let's collect ONLY 100K bytes, just for example perposes.
        if fileWriter.Len() > 100000 {
            break
        }
    }

    slog.Info("We have successfuly collected bytes", slog.Int("bytes", fileWriter.Len()))
}

Dan selepas dijalankan di sana output yang dipotong kelihatan seperti itu:

2024/08/31 13:35:36 INFO Running our applicaiton...
2024/08/31 13:37:48 INFO Stored packet packet="PACKET: 105 bytes, wire length 105 cap length 105 ..."
...
2024/08/31 13:37:48 INFO Stored packet packet="PACKET: 1291 bytes, wire length 1291 cap length 1291 ..."
2024/08/31 13:37:48 INFO We have successfuly collected bytes bytes=101018

Saya harap contoh minimum ini akan membantu seseorang untuk memulakan jorney mereka di kawasan ini menggunakan Go.

Akhir kata

Jika anda memenuhi sebarang keperluan baharu dalam tugas harian anda yang anda tidak tahu cara melakukannya. Jangan tergesa-gesa untuk bertanya kepada orang sekeliling, tulis saya secara tertutup dan buat kajian sendiri.

Penyelidikan dan komunikasi adalah kunci kepada semua penyelesaian masalah.


  1. libpcap ialah perpustakaan C/C++ mudah alih untuk menangkap trafik rangkaian ↩

Atas ialah kandungan terperinci Tangkap trafik dengan Golang. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn