Beyond gopacket: Introducing goscapy, the Powerful Go Network Library
The article examines goscapy, a pure‑Go network library that brings Scapy‑style stream‑builder APIs, automatic checksum calculation, protocol inference and zero‑copy serialization to Go, and compares it in depth with gopacket, showing code examples, performance tricks, and practical use‑cases such as ARP and TCP SYN scanning.
Core Design: Builder API and Shortcut Functions
goscapy provides two ways to construct packets:
Builder API – chainable methods that add protocol layers. Example:
pkt, err := goscapy.NewEthernet().
SrcMAC("aa:bb:cc:dd:ee:ff").
DstMAC("ff:ff:ff:ff:ff:ff").
Over(goscapy.NewIP().SrcIP("192.168.1.1").DstIP("8.8.8.8")).
Over(goscapy.NewICMP().Type(8).Code(0)).
Build()Shortcut functions – common layer combinations in a single call. Example:
pkt, _ := goscapy.EtherIPTCP("aa:bb:cc:dd:ee:ff", "ff:ff:ff:ff:ff:ff", "192.168.1.1", "10.0.0.1", 12345, 80, layers.TCPSyn)
pkt, _ := goscapy.EtherARP("aa:bb:cc:dd:ee:ff", "ff:ff:ff:ff:ff:ff", "192.168.1.1", "192.168.1.2", layers.ARPWhoHas)Both approaches are type‑safe and validated at compile time.
Automatic Checksums and Layer Binding
When Build() is invoked, each layer registers a BuildHook that automatically computes total lengths, IP header checksums, TCP/UDP pseudo‑header checksums, and other derived fields. No manual SerializeOptions{ComputeChecksums:true} is required.
Layer‑to‑layer binding rules (e.g., Ethernet type 0x0800 → IP, IP proto 6 → TCP) are stored in a registration table. Calling Over() automatically sets the correct magic numbers, eliminating the need to remember protocol constants.
Packet Dissection: Automatic Protocol Inference
Dissect()walks the registration‑driven table to infer the full protocol stack from raw bytes. Heuristic rules map well‑known ports to applications (e.g., UDP 53 → DNS, TCP 80 → HTTP). Nested tunnels such as VXLAN are supported up to eight layers.
Send/Receive and Sniffing
Sending mirrors Scapy’s sr() / sr1() model:
pkt := goscapy.NewEthernet().
DstMAC("ff:ff:ff:ff:ff:ff").
Over(goscapy.NewIP().SrcIP("192.168.1.1").DstIP("8.8.8.8")).
Over(goscapy.NewICMP().Type(8).Code(0)).
Packet()
sendrecv.Send(pkt, "eth0") // L3 send (OS adds Ethernet)
sendrecv.Sendp(pkt, "eth0") // L2 send (full Ethernet frame)Response matching is handled by DefaultMatch, which automatically pairs ICMP Echo‑Request/Reply, TCP SYN/SYN‑ACK, UDP port pairs, DNS transaction IDs, ARP requests/replies, etc., without user‑written matching logic.
Sniffing offers two APIs:
Callback‑style for streaming processing.
Channel‑style for batch collection.
Both use BPF filters that run in the kernel for high performance.
Protocol Coverage
goscapy ships with built‑in support for more than 30 protocols across multiple layers:
Link: Ethernet, ARP, 802.1Q (VLAN), 802.11 (WiFi), RadioTap, Bluetooth HCI/L2CAP/ATT
Network: IPv4, IPv6, IPv6 extension headers, ICMPv6, NDP
Transport: TCP (with options), UDP, ICMP, GRE, VXLAN
Routing: OSPF, BGP, LLDP
Application: DNS, DHCP, HTTP, NTP, TLS, QUIC, SNMP, RADIUS, LDAP, Kerberos
IoT/Wireless: Zigbee (NWK/APS/Cluster), LoRaWAN, Bluetooth
Monitoring/Stream: Netflow V5/V9, IPFIX, RTP, RTCP, SIP, ERSPAN
Tunnel: VXLAN, GRE, ERSPAN v3, QinQ
Practical Examples
ARP Scanner (≈200 LOC)
Build an ARP request, send it with Srp1(), extract the MAC address, and limit concurrency with a semaphore. A /24 subnet scan completes in a few seconds.
pkt := goscapy.NewEthernet().
DstMAC("ff:ff:ff:ff:ff:ff").
SrcMAC(srcMAC).
Type(layers.EtherTypeARP).
Over(goscapy.NewARP().
Op(layers.ARPWhoHas).
SrcMAC(srcMAC).
SrcIP(srcIP).
DstIP(targetIP)).
Packet()
_, reply, err := sendrecv.Srp1(pkt, iface, timeout, nil)
arpLayer := reply.GetLayer("ARP")
hwSrc, _ := arpLayer.Get("hwsrc")TCP SYN Scan
Construct a SYN packet, send it, and verify the reply flags for SYN‑ACK using DefaultMatch:
pkt := goscapy.NewIP().SrcIP(srcIP).DstIP(targetIP).
Over(goscapy.NewTCP().SrcPort(12345).DstPort(port).Flags(layers.TCPSyn)).
Packet()
_, reply, err := sendrecv.Sr1(pkt, iface, 2*time.Second, nil)
if err == nil && reply != nil {
tcpLayer := reply.GetLayer("TCP")
flags, _ := tcpLayer.Get("flags")
if flags.(uint8)&layers.TCPSyn != 0 && flags.(uint8)&layers.TCPAck != 0 {
fmt.Printf("Port %d: OPEN
", port)
}
}Internal Architecture: Three‑Layer Abstraction
goscapy layer – user‑facing Builder API and shortcut functions.
packet layer – core abstractions Packet, Layer, Dissect, BindingRule, and BuildHook.
fields layer – type‑safe field implementations ( ByteField, ShortField, MACField, etc.) that support zero‑copy PackInto and SerializeInto.
This separation makes adding a new protocol straightforward: define the field list, register binding rules, and provide a BuildHook.
Performance: Zero‑Copy Serialization
SerializeInto– writes directly into a user‑provided buffer. BuildInto – builds the whole packet in‑place into a caller‑supplied slice. RecvInto – reads packets directly into a buffer.
Checksum calculation folds multiple memory regions without extra copies.
Linux‑specific high‑throughput paths such as AF_PACKET mmap, PACKET_QDISC_BYPASS, and io_uring are demonstrated in the examples directory.
buf := make([]byte, 1500) // MTU‑size buffer
result, err := pkt.BuildInto(buf) // zero‑copy writeRich Example Suite
More than 50 examples cover basic tasks (ping, traceroute, ARP/TCP scans), protocol clients (DNS, DHCP, NTP), tunneling (VXLAN, GRE, ERSPAN), advanced features (pcap I/O, TCP stream reassembly, BPF filtering), wireless frames, and security use‑cases. Each can be run with go run.
When to Use Which Library
gopacket – excels when deep libpcap integration, obscure protocol support, or heavy pcap file processing is required.
goscapy – better suited for security tools, fast packet generation, and network monitoring where a pure‑Go, easy‑to‑use API and zero‑dependency deployment are valuable.
Conclusion
goscapy brings Scapy‑style ergonomics to Go, offering stream‑builder APIs, automatic checksum and binding, protocol inference, zero‑copy performance, and a large example collection, making Go network programming more concise and productive.
Project URL: https://github.com/smallnest/goscapy
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
BirdNest Tech Talk
Author of the rpcx microservice framework, original book author, and chair of Baidu's Go CMC committee.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
