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