Reputation: 1
I'm trying to use gopacket to snoop on a socket and print tcp packet payloads. If I start the snooper app first and then connect a tcp socket, things work correctly. If the socket is already connected when the snooper app starts, nothing is printed.
If I pass this option -assembly_debug_log, I get this output:
2022/04/22 11:36:10 assembly.go:582: [127.0.0.1->127.0.0.1 43584->80] waiting for start, storing into connection
2022/04/22 11:36:10 assembly.go:582: [127.0.0.1->127.0.0.1 80->43584] waiting for start, storing into connection
2022/04/22 11:36:10 assembly.go:537: ignoring useless packet
2022/04/22 11:36:12 assembly.go:582: [127.0.0.1->127.0.0.1 43584->80] waiting for start, storing into connection
2022/04/22 11:36:12 assembly.go:582: [127.0.0.1->127.0.0.1 80->43584] waiting for start, storing into connection
2022/04/22 11:36:12 assembly.go:537: ignoring useless packet
That debug message is under this 'if' in assembly.go:
if conn.nextSeq == invalidSequence
I don't see any way to set the value of conn.nextSeq.
So it appears that this assembler will squirrel away packets until a SYN packet is received, which it won't since the connection is already established.
Is there a way to print tcp packets from a socket connection that has already been established?
Here is the code:
package main
import (
"io"
"log"
"github.com/google/gopacket"
"github.com/google/gopacket/examples/util"
"github.com/google/gopacket/layers"
"github.com/google/gopacket/pcap"
"github.com/google/gopacket/tcpassembly"
"github.com/google/gopacket/tcpassembly/tcpreader"
)
type myStream struct {
r tcpreader.ReaderStream
}
func (ms *myStream) run() {
buf := make([]byte, 4096)
for {
n, err := ms.r.Read(buf)
if err == io.EOF {
return
} else if err != nil {
log.Fatal(err)
}
log.Println(string(buf[:n]))
}
}
type myStreamFactory struct{}
func (msf *myStreamFactory) New(_, _ gopacket.Flow) tcpassembly.Stream {
stream := &myStream{tcpreader.NewReaderStream()}
go stream.run()
return &stream.r
}
func main() {
defer util.Run()()
flags := log.Flags()
log.SetFlags(flags | log.Lshortfile)
handle, err := pcap.OpenLive("lo", 262144, true, pcap.BlockForever)
if err != nil {
log.Fatal(err)
}
if err = handle.SetBPFFilter("tcp and port 80"); err != nil {
log.Fatal(err)
}
streamFactory := &myStreamFactory{}
streamPool := tcpassembly.NewStreamPool(streamFactory)
assembler := tcpassembly.NewAssembler(streamPool)
packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
for packet := range packetSource.Packets() {
if packet.NetworkLayer() == nil || packet.TransportLayer() == nil || packet.TransportLayer().LayerType() != layers.LayerTypeTCP {
log.Println("Unusable packet")
continue
}
tcp := packet.TransportLayer().(*layers.TCP)
assembler.AssembleWithTimestamp(packet.NetworkLayer().NetworkFlow(), tcp, packet.Metadata().Timestamp)
}
}
Upvotes: 0
Views: 370
Reputation: 1
I added a call to assembler.FlushWithOptions
after creating a new stream, and it seems to be working correctly now.
package main
import (
"io"
"log"
"time"
"github.com/google/gopacket"
"github.com/google/gopacket/examples/util"
"github.com/google/gopacket/layers"
"github.com/google/gopacket/pcap"
"github.com/google/gopacket/tcpassembly"
"github.com/google/gopacket/tcpassembly/tcpreader"
)
type myStream struct {
r tcpreader.ReaderStream
}
func (ms *myStream) run() {
buf := make([]byte, 4096)
for {
n, err := ms.r.Read(buf)
if err == io.EOF {
return
} else if err != nil {
log.Fatal(err)
}
log.Println(string(buf[:n]))
}
}
type myStreamFactory struct {
iWantFlush bool
}
func (msf *myStreamFactory) New(_, _ gopacket.Flow) tcpassembly.Stream {
stream := &myStream{tcpreader.NewReaderStream()}
go stream.run()
msf.iWantFlush = true
return &stream.r
}
func main() {
defer util.Run()()
flags := log.Flags()
log.SetFlags(flags | log.Lshortfile)
handle, err := pcap.OpenLive("lo", 262144, true, pcap.BlockForever)
if err != nil {
log.Fatal(err)
}
if err = handle.SetBPFFilter("tcp and port 80"); err != nil {
log.Fatal(err)
}
streamFactory := &myStreamFactory{}
streamPool := tcpassembly.NewStreamPool(streamFactory)
assembler := tcpassembly.NewAssembler(streamPool)
packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
for packet := range packetSource.Packets() {
if packet.NetworkLayer() == nil || packet.TransportLayer() == nil || packet.TransportLayer().LayerType() != layers.LayerTypeTCP {
log.Println("Unusable packet")
continue
}
tcp := packet.TransportLayer().(*layers.TCP)
assembler.AssembleWithTimestamp(packet.NetworkLayer().NetworkFlow(), tcp, packet.Metadata().Timestamp)
if streamFactory.iWantFlush {
assembler.FlushWithOptions(tcpassembly.FlushOptions{time.Now(), false})
streamFactory.iWantFlush = false
}
}
}
Upvotes: 0