Skip to content

Instantly share code, notes, and snippets.

@rongyi
Created June 17, 2019 08:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rongyi/ca94f01ebf1fbcb7023e69a2a429e6f3 to your computer and use it in GitHub Desktop.
Save rongyi/ca94f01ebf1fbcb7023e69a2a429e6f3 to your computer and use it in GitHub Desktop.
gopacket demo
package main
import (
"errors"
"fmt"
"io"
"log"
"net"
"strings"
"time"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
"github.com/google/gopacket/pcap"
)
func main() {
ifs, err := pcap.FindAllDevs()
var theiface pcap.Interface
if err != nil {
log.Fatal(err)
}
for _, iface := range ifs {
log.Printf("------%s-------", iface.Name)
if iface.Name == "lo" {
theiface = iface
break
}
for _, ip := range iface.Addresses {
if ip.IP.To4() != nil {
log.Println(ip.IP.String())
}
}
log.Printf("------%s-------", iface.Name)
}
capOnInterface(theiface)
}
func capOnInterface(device pcap.Interface) error {
inactive, err := pcap.NewInactiveHandle(device.Name)
if err != nil {
log.Println("Pcap Error while opening device", device.Name, err)
return errors.New("fail to create inactive pcap handle")
}
if it, err := net.InterfaceByName(device.Name); err == nil {
// Auto-guess max length of packet to capture
if err := inactive.SetSnapLen(it.MTU + 68*2); err != nil {
return errors.New("fail to set snaplen")
}
} else {
inactive.SetSnapLen(65536)
}
inactive.SetTimeout(time.Second * 2)
inactive.SetPromisc(true)
inactive.SetImmediateMode(false)
log.Println("Setting immediate mode off")
handle, herr := inactive.Activate()
if herr != nil {
log.Println("PCAP Activate error:", herr)
return errors.New("fail to activate handle")
}
defer handle.Close()
// only interested in IN direction
handle.SetDirection(pcap.DirectionIn)
if err := handle.SetBPFFilter("tcp port 8080"); err != nil {
return errors.New("fail to set bpf filter")
}
var decoder gopacket.Decoder
// Special case for tunnel interface https://github.com/google/gopacket/issues/99
if handle.LinkType() == 12 {
decoder = layers.LayerTypeIPv4
} else {
decoder = handle.LinkType()
}
source := gopacket.NewPacketSource(handle, decoder)
source.Lazy = true
source.NoCopy = true
for {
packet, err := source.NextPacket()
if err == io.EOF {
break
} else if err != nil {
continue
}
log.Println("in packet--------->>>>")
// var of int
// switch decoder {
// case layers.LinkTypeEthernet:
// log.Println("ether packet")
// of = 14
// case layers.LinkTypePPP:
// of = 1
// case layers.LinkTypeFDDI:
// of = 13
// case layers.LinkTypeNull:
// of = 4
// case layers.LinkTypeLoop:
// of = 4
// case layers.LinkTypeRaw, layers.LayerTypeIPv4:
// of = 0
// case layers.LinkTypeLinuxSLL:
// of = 16
// default:
// log.Println("Unknown packet layer", decoder, packet)
// break
// }
printPacketInfo(packet)
}
return nil
}
func printPacketInfo(packet gopacket.Packet) {
// Let's see if the packet is an ethernet packet
ethernetLayer := packet.Layer(layers.LayerTypeEthernet)
if ethernetLayer != nil {
fmt.Println("Ethernet layer detected.")
ethernetPacket, _ := ethernetLayer.(*layers.Ethernet)
fmt.Println("Source MAC: ", ethernetPacket.SrcMAC)
fmt.Println("Destination MAC: ", ethernetPacket.DstMAC)
// Ethernet type is typically IPv4 but could be ARP or other
fmt.Println("Ethernet type: ", ethernetPacket.EthernetType)
fmt.Println()
}
// Let's see if the packet is IP (even though the ether type told us)
ipLayer := packet.Layer(layers.LayerTypeIPv4)
if ipLayer != nil {
fmt.Println("IPv4 layer detected.")
ip, _ := ipLayer.(*layers.IPv4)
// IP layer variables:
// Version (Either 4 or 6)
// IHL (IP Header Length in 32-bit words)
// TOS, Length, Id, Flags, FragOffset, TTL, Protocol (TCP?),
// Checksum, SrcIP, DstIP
fmt.Printf("From %s to %s\n", ip.SrcIP, ip.DstIP)
fmt.Println("Protocol: ", ip.Protocol)
fmt.Println()
}
// Let's see if the packet is TCP
tcpLayer := packet.Layer(layers.LayerTypeTCP)
if tcpLayer != nil {
fmt.Println("TCP layer detected.")
tcp, _ := tcpLayer.(*layers.TCP)
// TCP layer variables:
// SrcPort, DstPort, Seq, Ack, DataOffset, Window, Checksum, Urgent
// Bool flags: FIN, SYN, RST, PSH, ACK, URG, ECE, CWR, NS
fmt.Printf("From port %d to %d\n", tcp.SrcPort, tcp.DstPort)
fmt.Println("Sequence number: ", tcp.Seq)
fmt.Println()
}
// Iterate over all layers, printing out each layer type
fmt.Println("All packet layers:")
for _, layer := range packet.Layers() {
fmt.Println("- ", layer.LayerType())
}
// When iterating through packet.Layers() above,
// if it lists Payload layer then that is the same as
// this applicationLayer. applicationLayer contains the payload
applicationLayer := packet.ApplicationLayer()
if applicationLayer != nil {
fmt.Println("Application layer/Payload found.")
fmt.Printf("%s\n", applicationLayer.Payload())
// Search for a string inside the payload
if strings.Contains(string(applicationLayer.Payload()), "HTTP") {
fmt.Println("HTTP found!")
}
}
// Check for errors
if err := packet.ErrorLayer(); err != nil {
fmt.Println("Error decoding some part of the packet:", err)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment