[가기] TCP 패킷 캡처 시도

21561 단어 beginnersgopcap

소개



TCP 패킷 캡처를 시도합니다.

TCP 소켓 통신



패킷을 캡처하기 위해 TCP 소켓 통신을 위한 애플리케이션을 만들 것입니다.

TCP 서버 샘플




package main

import (
    "fmt"
    "io"
    "log"
    "net"
)

func main() {
    ln, err := net.Listen("tcp", ":8099")
    if err != nil {
        fmt.Println("cannot listen", err)
    }
    for {
        conn, e := ln.Accept()
        if e != nil {
            log.Fatal(e)
            return
        }
        go echo_handler(conn)
    }
}

func echo_handler(conn net.Conn) {
    defer conn.Close()
    io.Copy(conn, conn)
}


tcp-클라이언트-샘플




package main

import (
    "fmt"
    "log"
    "net"
    "time"
)

func main() {
    ticker := time.NewTicker(time.Millisecond * 1000)
    var conn net.Conn
    var err error
    defer func() {
        ticker.Stop()
        if conn != nil {
            conn.Close()
        }
    }()

    count := 0
    for range ticker.C {
        if count > 1000 {
            break
        }
        conn, err = net.Dial("tcp", ":8099")
        if err != nil {
            log.Fatal(err)
        }
        sendData := []byte(fmt.Sprintf("Hello_%d", count))
        _, err = conn.Write(sendData)
        if err != nil {
            log.Fatal(err)
        }
        buf := make([]byte, 1024)
        n, err := conn.Read(buf)
        if err != nil {
            log.Fatal(err)
        }
        log.Println(string(buf[:n]))
        conn.Close()
        conn = nil
        count += 1
    }
}


  • net package - net - Go Packages
  • Go言語を使ったTCPクライアントの作り方 - Qiita

  • TCP 패킷 캡처



    gopacket/pcap으로 TCP 패킷을 캡처합니다.

    libpcap-dev



    Windows와 Xubuntu에 Wireshark를 이미 설치했기 때문에 다른 Windows용 소프트웨어를 설치할 필요가 없었습니다.

    하지만 Xubuntu에서 gopacket/pcap을 실행하려고 하면 오류가 발생합니다.

    # github.com/google/gopacket/pcap
    ../../../pkg/mod/github.com/google/[email protected]/pcap/pcap_unix.go:34:10: fatal error: pcap.h: No such file or directory
       34 | #include <pcap.h>
          |          ^~~~~~~~
    compilation terminated.
    


    "libpcap-dev"를 설치해야 합니다.

    sudo apt install -y libpcap-dev
    


  • fatal error: pcap.h: No such file or directory #125 - projectdiscovery/naabu - GitHub

  • 샘플 캡처



    tcp-캡처-샘플




    package main
    
    import (
        "fmt"
        "log"
        "strings"
        "time"
    
        "github.com/google/gopacket"
        "github.com/google/gopacket/layers"
        "github.com/google/gopacket/pcap"
    )
    
    func main() {
        loopbackDevice := getLoopbackDeviceName()
        if loopbackDevice == "" {
            log.Println("No loopback devices")
            return
        }
        handle, err := pcap.OpenLive(loopbackDevice, 1024, false, 3*time.Second)
        if err != nil {
            log.Fatal(err)
        }
        defer handle.Close()
        // Filtering capture targets
        err = handle.SetBPFFilter("tcp and port 8099")
        if err != nil {
            log.Fatal(err)
        }
        packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
       // Get decoded packets through chann
        for packet := range packetSource.Packets() {
            log.Println("S-------S")
            log.Println(packet)
            log.Println("E-------E")
        }
    }
    func getLoopbackDeviceName() string {
        // Find all devices
        devices, err := pcap.FindAllDevs()
        if err != nil {
            log.Fatal(err.Error())
        }
        for _, device := range devices {
            // for Windows
            if strings.Contains(strings.ToLower(device.Name), "loopback") ||
                // for Xubuntu
                device.Name == "lo" {
                return device.Name
            }
        }
        return ""
    }
    


    결과




    ...
    2022/10/12 21:19:27 S-------S
    2022/10/12 21:19:27 PACKET: 74 bytes, wire length 74 cap length 74 @ 2022-10-12 21:19:27.764308 +0900 JST
    - Layer 1 (14 bytes) = Ethernet {Contents=[..14..] Payload=[..60..] SrcMAC=00:00:00:00:00:00 DstMAC=00:00:00:00:00:00 EthernetType=IPv4 Length=0}
    - Layer 2 (20 bytes) = IPv4 {Contents=[..20..] Payload=[..40..] Version=4 IHL=5 TOS=0 Length=60 Id=36925 Flags=DF FragOffset=0 TTL=64 Protocol=TCP Checksum=44156 SrcIP=127.0.0.1 DstIP=127.0.0.1 Options=[] Padding=[]}
    - Layer 3 (32 bytes) = TCP  {Contents=[..32..] Payload=[..8..] SrcPort=8099 DstPort=57632 Seq=2020353806 Ack=775619635 DataOffset=8 FIN=false SYN=false RST=false PSH=true ACK=true URG=false ECE=false CWR=false NS=false Window=512 Checksum=65072 Urgent=0 Options=[TCPOption(NOP:), TCPOption(NOP:), TCPOption(Timestamps:3776381494/3776381494 0xe1170236e1170236)] Padding=[]}
    - Layer 4 (08 bytes) = Payload  8 byte(s)
    
    2022/10/12 21:19:27 E-------E
    ...
    


    그 결과, 캡처된 패킷은 여러 계층의 데이터로 디코딩되었습니다.

    ...
    
    func main() {
    ... 
       // Get decoded packets through chann
        for packet := range packetSource.Packets() {
            printPacketInfo(packet)
        }
    }
    ...
    func printPacketInfo(packet gopacket.Packet) {
       // TCP
        tcpLayer := packet.Layer(layers.LayerTypeTCP)
        if tcpLayer != nil {
            tcp, _ := tcpLayer.(*layers.TCP)
    
            fmt.Printf("From port %d to %d\n", tcp.SrcPort, tcp.DstPort)
            fmt.Println("Sequence number: ", tcp.Seq)
        }
       // TCP/IPV4 Payload
        applicationLayer := packet.ApplicationLayer()
        if applicationLayer != nil {
            fmt.Println("Application layer/Payload found.")
            fmt.Printf("%s\n", applicationLayer.Payload())
        }
    
        // Check for errors
        if err := packet.ErrorLayer(); err != nil {
            fmt.Println("Error decoding some part of the packet:", err)
        }
    }
    


  • google/gopacket - GitHub
  • GoPacket - github.com/google/gopacket - Go Packages
  • Packet Capture, Injection, and Analysis with Gopacket - DevDungeon
  • Goでパケットキャプチャを実践してみる - Qiita

  • RFC 9293 - Transmission Control Protocol (TCP)
    * RFC791 - INTERNET PROTOCOL
  • 좋은 웹페이지 즐겨찾기