Masui Masanori
Posted on October 12, 2022
Intro
I will try capturing TCP packets.
TCP socket communication
To capture packets, I will create applications for TCP socket communication.
tcp-server-sample
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-client-sample
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
}
}
Capturing TCP packets
I will capturing TCP packets by gopacket/pcap.
libpcap-dev
Because I had already installed Wireshark on Windows and Xubuntu, I didn't need install any other software for Windows.
But when I tried executing gopacket/pcap on Xubuntu, I would get error.
# github.com/google/gopacket/pcap
../../../pkg/mod/github.com/google/gopacket@v1.1.19/pcap/pcap_unix.go:34:10: fatal error: pcap.h: No such file or directory
34 | #include <pcap.h>
| ^~~~~~~~
compilation terminated.
I should install "libpcap-dev".
sudo apt install -y libpcap-dev
Capturing sample
tcp-capture-sample
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 ""
}
Results
...
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
...
According to the result, the captured packet was decoded into several layer data.
...
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)
}
}
💖 💪 🙅 🚩
Masui Masanori
Posted on October 12, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.