Last active
September 3, 2020 17:22
-
-
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)
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
// 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