Skip to content

Instantly share code, notes, and snippets.

@jilyaluk
Last active December 6, 2022 16:29
Show Gist options
  • Save jilyaluk/b4ba658c7cd3764c6ccb030e1212bd4d to your computer and use it in GitHub Desktop.
Save jilyaluk/b4ba658c7cd3764c6ccb030e1212bd4d to your computer and use it in GitHub Desktop.
Wraps your net.Conn and saves data in it to pcap
var (
pcapWriter *pcapgo.Writer
tcpPort uint16 = 1023
)
func init() {
f, err := os.Create("/tmp/test.pcap")
if err != nil {
panic(err)
}
pcapWriter = pcapgo.NewWriter(f)
pcapWriter.WriteFileHeader(65536, layers.LinkTypeIPv4)
}
type pcapLoggingNetConn struct {
net.Conn
tcpPort uint16
sentSrc uint32
sentDst uint32
}
func newPcapLoggingNetConn(conn net.Conn) net.Conn {
// that's not safe, huh
tcpPort++
p := &pcapLoggingNetConn{Conn: conn, tcpPort: tcpPort, sentSrc: 1, sentDst: 1}
writePacket(
p.getIP(false),
p.getTCP(false, true, false, false, 0, 0),
)
writePacket(
p.getIP(true),
p.getTCP(true, true, true, false, 0, 1),
)
writePacket(
p.getIP(false),
p.getTCP(false, false, true, false, 1, 1),
)
return p
}
func (c *pcapLoggingNetConn) Read(b []byte) (int, error) {
n, err := c.Conn.Read(b)
if err != nil {
return n, err
}
if n > 0 {
c.writePacket(b[:n], false)
}
return n, nil
}
func (c *pcapLoggingNetConn) Write(b []byte) (int, error) {
n, err := c.Conn.Write(b)
if err != nil {
return n, err
}
if n > 0 {
c.writePacket(b[:n], true)
}
return n, nil
}
func (c *pcapLoggingNetConn) writePacket(b []byte, isWrite bool) {
seq, ack := &c.sentSrc, &c.sentDst
if isWrite {
seq, ack = &c.sentDst, &c.sentSrc
}
glog.V(10).Infof("writing packet: (port=%d,len=%d,wr=%v,seq=%v,ack=%v) %v", c.tcpPort, len(b), isWrite, *seq, *ack, b)
writePacket(
c.getIP(isWrite),
c.getTCP(isWrite, false, true, true, *seq, *ack),
gopacket.Payload(b),
)
*seq += uint32(len(b))
writePacket(
c.getIP(!isWrite),
c.getTCP(!isWrite, false, true, false, *ack, *seq),
)
}
func writePacket(layers ...gopacket.SerializableLayer) {
buf := gopacket.NewSerializeBuffer()
opts := gopacket.SerializeOptions{FixLengths: true}
err := gopacket.SerializeLayers(buf, opts, layers...)
if err != nil {
glog.V(10).Infof("error serializing packet: %v", err)
}
ci := gopacket.CaptureInfo{
Timestamp: time.Now(),
CaptureLength: len(buf.Bytes()),
Length: len(buf.Bytes()),
InterfaceIndex: 0,
}
err = pcapWriter.WritePacket(ci, buf.Bytes())
if err != nil {
glog.V(10).Infof("error writing packet: %v", err)
}
}
func (c *pcapLoggingNetConn) getIP(rev bool) gopacket.SerializableLayer {
res := &layers.IPv4{
Version: 4,
TTL: 64,
SrcIP: net.IP{127, 0, 0, byte(c.tcpPort % 256)},
DstIP: net.IP{32, 0, 0, byte(c.tcpPort % 256)},
Protocol: layers.IPProtocolTCP,
}
if rev {
res.SrcIP, res.DstIP = res.DstIP, res.SrcIP
}
return res
}
func (c *pcapLoggingNetConn) getTCP(rev, SYN, ACK, PSH bool, seq, ack uint32) *layers.TCP {
src, dst := layers.TCPPort(c.tcpPort), layers.TCPPort(80)
if rev {
src, dst = dst, src
}
return &layers.TCP{
Window: 65535,
SrcPort: src,
DstPort: dst,
SYN: SYN,
PSH: PSH,
ACK: ACK,
Seq: seq,
Ack: ack,
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment