Skip to content

Instantly share code, notes, and snippets.

@alibo
Last active September 3, 2020 17:22
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save alibo/a8ee7040d75f756f376f9fc95073e513 to your computer and use it in GitHub Desktop.
Save alibo/a8ee7040d75f756f376f9fc95073e513 to your computer and use it in GitHub Desktop.
Capture TLS traffic and log SNI and TLS version using GoPacket and TLSx: (https://github.com/google/gopacket & https://github.com/dreadl0ck/tlsx)
// It's modified version of: https://github.com/dreadl0ck/tlsx/blob/master/example/main.go
package main
import (
"flag"
"fmt"
"log"
"os"
"sync"
"github.com/dreadl0ck/tlsx"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
"github.com/google/gopacket/pcap"
)
func main() {
var (
flagInterface = flag.String("iface", "any", "Network interface to capture on")
flagPcap = flag.String("pcap", "", "use pcap file")
flagBPF = flag.String("bpf", "tcp", "bpf filter")
)
flag.Parse()
// redirect to stdout (log pkg logs to stderr by default)
// to allow grepping the result through a simple pipe
log.SetOutput(os.Stdout)
var (
handle *pcap.Handle
err error
)
if *flagPcap != "" {
fmt.Println("Opening file", *flagPcap)
handle, err = pcap.OpenOffline(*flagPcap)
} else {
fmt.Println("Listening on", *flagInterface)
// snapLen = 1514 (1500 Ethernet MTU + 14 byte Ethernet Header)
handle, err = pcap.OpenLive(*flagInterface, 1514, false, pcap.BlockForever)
}
if err != nil {
log.Fatal(err)
}
// set bpf
err = handle.SetBPFFilter(*flagBPF)
if err != nil {
log.Fatal(err)
}
// create packet source
packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
var wg sync.WaitGroup
// handle packets
for packet := range packetSource.Packets() {
wg.Add(1)
go readPacket(packet, &wg)
}
wg.Wait()
}
func readPacket(packet gopacket.Packet, wg *sync.WaitGroup) {
if tcpLayer := packet.Layer(layers.LayerTypeTCP); tcpLayer != nil {
// cast TCP layer
tcp, ok := tcpLayer.(*layers.TCP)
if !ok {
log.Println("Could not decode TCP layer")
return
}
if tcp.SYN {
// Connection setup
} else if tcp.FIN {
// Connection teardown
} else if tcp.ACK && len(tcp.LayerPayload()) == 0 {
// Acknowledgement packet
} else if tcp.RST {
// Unexpected packet
} else {
// data packet
// process TLS client hello
clientHello := tlsx.GetClientHello(packet)
if clientHello != nil {
source := packet.NetworkLayer().NetworkFlow().Src().String() + ":" + packet.TransportLayer().TransportFlow().Src().String()
serverName := clientHello.SNI
tlsVersion := clientHello.HandshakeVersion.String()
log.Printf("[%s] %s - %s", source, tlsVersion, serverName)
}
}
}
wg.Done()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment