Created
June 17, 2019 08:37
-
-
Save rongyi/ca94f01ebf1fbcb7023e69a2a429e6f3 to your computer and use it in GitHub Desktop.
gopacket demo
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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