Skip to content

Instantly share code, notes, and snippets.

@kkyouhei
Last active December 15, 2015 09:54
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 kkyouhei/5034afaf4508eb5a8129 to your computer and use it in GitHub Desktop.
Save kkyouhei/5034afaf4508eb5a8129 to your computer and use it in GitHub Desktop.
Goでパケットキャプチャを実践してみる ref: http://qiita.com/kkyouhei/items/846e74c6a9653b069e5f
package main
import (
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
"github.com/google/gopacket/pcap"
"log"
"net"
"time"
)
var (
device string = "eth1"
snapshot_len int32 = 1024
promiscuous bool = false
err error
timeout time.Duration = 30 * time.Second
handle *pcap.Handle
buffer gopacket.SerializeBuffer
options gopacket.SerializeOptions
)
func main() {
// Open device
handle, err = pcap.OpenLive(device, snapshot_len, promiscuous, timeout)
if err != nil {log.Fatal(err) }
defer handle.Close()
// Send raw bytes over wire
rawBytes := []byte{10, 20, 30}
err = handle.WritePacketData(rawBytes)
if err != nil {
log.Fatal(err)
}
// Create a properly formed packet, just with
// empty details. Should fill out MAC addresses,
// IP addresses, etc.
buffer = gopacket.NewSerializeBuffer()
gopacket.SerializeLayers(buffer, options,
&layers.Ethernet{},
&layers.IPv4{},
&layers.TCP{},
gopacket.Payload(rawBytes),
)
outgoingPacket := buffer.Bytes()
// Send our packet
err = handle.WritePacketData(outgoingPacket)
if err != nil {
log.Fatal(err)
}
// This time lets fill out some information
ipLayer := &layers.IPv4{
SrcIP: net.IP{127, 0, 0, 1},
DstIP: net.IP{8, 8, 8, 8},
}
ethernetLayer := &layers.Ethernet{
SrcMAC: net.HardwareAddr{0xFF, 0xAA, 0xFA, 0xAA, 0xFF, 0xAA, 0xFA, 0xAA},
DstMAC: net.HardwareAddr{0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD},
}
tcpLayer := &layers.TCP{
SrcPort: layers.TCPPort(4321),
DstPort: layers.TCPPort(80),
}
// And create the packet with the layers
buffer = gopacket.NewSerializeBuffer()
gopacket.SerializeLayers(buffer, options,
ethernetLayer,
ipLayer,
tcpLayer,
gopacket.Payload(rawBytes),
)
outgoingPacket = buffer.Bytes()
}
package main
import (
"fmt"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
"github.com/google/gopacket/pcap"
"log"
"strings"
"time"
)
var (
device string = "eth0"
snapshotLen int32 = 1024
promiscuous bool = false
err error
timeout time.Duration = 30 * time.Second
handle *pcap.Handle
)
func main() {
// Open device
handle, err = pcap.OpenLive(device, snapshotLen, promiscuous, timeout)
if err != nil {log.Fatal(err) }
defer handle.Close()
packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
for packet := range packetSource.Packets() {
printPacketInfo(packet)
}
}
func printPacketInfo(packet gopacket.Packet) {
// Ethernet 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()
}
// IPパケットへキャスト
// 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()
}
// IPパケットへキャスト
// 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()
}
// All packet layers???
// 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)
}
}
package main
import (
"fmt"
"github.com/google/gopacket"
"github.com/google/gopacket/pcap"
"log"
"time"
)
var (
device string = "eth1"
snapshot_len int32 = 1024
promiscuous bool = false
err error
timeout time.Duration = 30 * time.Second
handle *pcap.Handle
)
func main() {
// Open device
handle, err = pcap.OpenLive(device, snapshot_len, promiscuous, timeout)
if err != nil {log.Fatal(err) }
defer handle.Close()
// Use the handle as a packet source to process all packets
packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
for packet := range packetSource.Packets() {
// Process packet here
fmt.Println(packet)
}
}
sudo yum -y install libpcap-devel
sudo yum -y install libnet
# パケットに関してのライブラリ
go get github.com/google/gopacket
// キャスト出来るプロトコルは下記パッケージから参照できる
// https://github.com/google/gopacket/blob/master/layers/layertypes.go
packet.Layer(layers.プロトコル)
sudo /usr/local/go/bin/go run decoding_packet.go
############## Ethernet layers ##############
Ethernet layer detected.
Source MAC: 08:00:27:4f:b8:06
Destination MAC: 52:54:00:12:35:02
Ethernet type: IPv4
############## IP layers ##############
IPv4 layer detected.
From 10.0.2.15 to 10.0.2.2
Protocol: TCP
############## TCP layers ##############
TCP layer detected.
From port 22 to 59180
Sequence number: 262547368
############## All packet layers ##############
All packet layers:
- Ethernet
- IPv4
- TCP
- Payload
############## Application layers ##############
Application layer/Payload found.
�!$��}�K~E2�(m����v޹�-
է��(�At��q��܀Nƛ�E�Nݚ�˹���x]�@)���n�L_9'��T<AUU]0qo�P@�?���t��8��b�W �s�H�"�
;bs�XL����t��X���ļ*�"��3�V� �:�ᱩ�{$�i��s�Xˁ�u
p/���N�K��{����Nu�E�G2��i�����[
��F9��/����>x:@Lxw+�{��四�4���
޿�#UO���ӶjT�y��!~ �u��΂�Њ�X�Y��1�C.��aG<���A+���\���4��ʬ���uB�}�w
������wYP1�]�O>
� л$$x�
.8�+��65�<RZ�y5�sε�M�8��,�Y���{_��׌#9�@�A?Sғ�*���#.�Cb���Z?AQ'l�88d��}䎪��V�G�&V��-����*0*B
�.Ơu�UrEJ/����;��6oS-����L����l���_�*�{rL�5���
�D_t<��2( ]U!s�#�V���(_@(��,
��wqJ-uh���1�g`�ӫm\Y�����B��F"�~��px��8lD��Rݘ�TŻ�.�I
(E���G���#c������{��i��p� �_!C�o��Rx�]B��7�nW���>�:�
bO�Kd�Bon��9p��b��s�@_j�S�,(3���K��s��j�+Џ����`�(��#�ݟ���
���4���HlF�wa�#�XH�ݥ�9O�:MhM]*��f&!rg՗q�
���)^�A�\I9����_1dv
# パケットキャプチャ用に作ったgoスクリプトを実行しておく
sudo /usr/local/go/bin/go run devise_for_live_cap.go
# パケットを送信するgoスクリプトを実行
sudo /usr/local/go/bin/go run create_and_send.go
PACKET: 3 bytes, wire length 3 cap length 3 @ 2015-12-15 07:25:51.101255 +0000 UTC
- Layer 1 (03 bytes) = DecodeFailure Packet decoding error: Ethernet packet too small
PACKET: 43 bytes, wire length 43 cap length 43 @ 2015-12-15 07:25:51.101924 +0000 UTC
- Layer 1 (14 bytes) = Ethernet {Contents=[..14..] Payload=[] SrcMAC=00:00:00:00:00:00 DstMAC=00:00:00:00:00:00 EthernetType=LLC Length=0}
[vagrant@vagrant-centos65 ~]$ sudo /usr/local/go/bin/go run find_devise.go
Devices found:
Name: eth0
Description:
Devices addresses:
- IP address: 10.0.2.15
- Subnet mask: ffffff00
- IP address: fe80::a00:27ff:fe4f:b806
- Subnet mask: ffffffffffffffff0000000000000000
Name: nflog
Description: Linux netfilter log (NFLOG) interface
Devices addresses: Linux netfilter log (NFLOG) interface
Name: nfqueue
Description: Linux netfilter queue (NFQUEUE) interface
Devices addresses: Linux netfilter queue (NFQUEUE) interface
Name: eth1
Description:
Devices addresses:
- IP address: 192.168.33.28
- Subnet mask: ffffff00
- IP address: fe80::a00:27ff:fe2e:e4a5
- Subnet mask: ffffffffffffffff0000000000000000
Name: any
Description: Pseudo-device that captures on all interfaces
Devices addresses: Pseudo-device that captures on all interfaces
Name: lo
Description:
Devices addresses:
- IP address: 127.0.0.1
- Subnet mask: ff000000
- IP address: ::1
- Subnet mask: ffffffffffffffffffffffffffffffff
sudo /usr/local/go/bin/go run devise_for_live_cap.go
# vagrantのIP
ping 192.168.1.2
PACKET: 42 bytes, wire length 42 cap length 42 @ 2015-12-15 05:01:19.220701 +0000 UTC
- Layer 1 (14 bytes) = Ethernet {Contents=[..14..] Payload=[..28..] SrcMAC=08:00:27:2e:e4:a5 DstMAC=0a:00:27:00:00:00 EthernetType=ARP Length=0}
- Layer 2 (28 bytes) = ARP {Contents=[..28..] Payload=[] AddrType=Ethernet Protocol=IPv4 HwAddressSize=6 ProtAddressSize=4 Operation=1 SourceHwAddress=[..6..] SourceProtAddress=[192, 168, 33, 28] DstHwAddress=[..6..] DstProtAddress=[192, 168, 33, 1]}
PACKET: 42 bytes, wire length 42 cap length 42 @ 2015-12-15 05:01:19.221124 +0000 UTC
- Layer 1 (14 bytes) = Ethernet {Contents=[..14..] Payload=[..28..] SrcMAC=0a:00:27:00:00:00 DstMAC=08:00:27:2e:e4:a5 EthernetType=ARP Length=0}
- Layer 2 (28 bytes) = ARP {Contents=[..28..] Payload=[] AddrType=Ethernet Protocol=IPv4 HwAddressSize=6 ProtAddressSize=4 Operation=2 SourceHwAddress=[..6..] SourceProtAddress=[192, 168, 33, 1] DstHwAddress=[..6..] DstProtAddress=[192, 168, 33, 28]}
PACKET: 98 bytes, wire length 98 cap length 98 @ 2015-12-15 05:01:27.90845 +0000 UTC
- Layer 1 (14 bytes) = Ethernet {Contents=[..14..] Payload=[..84..] SrcMAC=0a:00:27:00:00:00 DstMAC=08:00:27:2e:e4:a5 EthernetType=IPv4 Length=0}
- Layer 2 (20 bytes) = IPv4 {Contents=[..20..] Payload=[..64..] Version=4 IHL=5 TOS=0 Length=84 Id=19530 Flags= FragOffset=0 TTL=64 Protocol=ICMPv4 Checksum=27377 SrcIP=192.168.33.1 DstIP=192.168.33.28 Options=[] Padding=[]}
- Layer 3 (08 bytes) = ICMPv4 {Contents=[..8..] Payload=[..56..] TypeCode=EchoRequest(0) Checksum=37266 Id=24886 Seq=0}
- Layer 4 (56 bytes) = Payload 56 byte(s)
# インストール
sudo yum -y install nginx
# 起動
sudo service nginx restart
package main
import (
"fmt"
"log"
"github.com/google/gopacket/pcap"
)
func main() {
// Find all devices
devices, err := pcap.FindAllDevs()
if err != nil {
log.Fatal(err)
}
// Print device information
fmt.Println("Devices found:")
for _, device := range devices {
fmt.Println("\nName: ", device.Name)
fmt.Println("Description: ", device.Description)
fmt.Println("Devices addresses: ", device.Description)
for _, address := range device.Addresses {
fmt.Println("- IP address: ", address.IP)
fmt.Println("- Subnet mask: ", address.Netmask)
}
}
}
sudo /usr/local/go/bin/go run settings_filter.go
PACKET: 54 bytes, wire length 54 cap length 54 @ 2015-12-15 05:30:39.730514 +0000 UTC
- Layer 1 (14 bytes) = Ethernet {Contents=[..14..] Payload=[..40..] SrcMAC=0a:00:27:00:00:00 DstMAC=08:00:27:2e:e4:a5 EthernetType=IPv4 Length=0}
- Layer 2 (20 bytes) = IPv4 {Contents=[..20..] Payload=[..20..] Version=4 IHL=5 TOS=0 Length=40 Id=13015 Flags= FragOffset=0 TTL=64 Protocol=TCP Checksum=33931 SrcIP=192.168.33.1 DstIP=192.168.33.28 Options=[] Padding=[]}
- Layer 3 (20 bytes) = TCP {Contents=[..20..] Payload=[] SrcPort=61656 DstPort=80(http) Seq=2755802527 Ack=3043451509 DataOffset=5 FIN=false SYN=false RST=false PSH=false ACK=true URG=false ECE=false CWR=false NS=false Window=4096 Checksum=63870 Urgent=0 Options=[] Padding=[]}
PACKET: 66 bytes, wire length 66 cap length 66 @ 2015-12-15 05:30:39.730534 +0000 UTC
- Layer 1 (14 bytes) = Ethernet {Contents=[..14..] Payload=[..52..] SrcMAC=08:00:27:2e:e4:a5 DstMAC=0a:00:27:00:00:00 EthernetType=IPv4 Length=0}
- Layer 2 (20 bytes) = IPv4 {Contents=[..20..] Payload=[..32..] Version=4 IHL=5 TOS=0 Length=52 Id=39 Flags=DF FragOffset=0 TTL=64 Protocol=TCP Checksum=30511 SrcIP=192.168.33.28 DstIP=192.168.33.1 Options=[] Padding=[]}
- Layer 3 (32 bytes) = TCP {Contents=[..32..] Payload=[] SrcPort=80(http) DstPort=61656 Seq=3043451509 Ack=2755802528 DataOffset=8 FIN=false SYN=false RST=false PSH=false ACK=true URG=false ECE=false CWR=false NS=false Window=361 Checksum=17752 Urgent=0 Options=[NOP, NOP, TSOPT:11667222/479225165] Padding=[]}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment