mirror of
https://github.com/kubeshark/kubeshark.git
synced 2026-08-25 00:47:27 +00:00
* Update .gitignore
* WIP
* WIP
* Update README.md, root.go, and 4 more files...
* Update README.md
* Update README.md
* Update root.go
* Update provider.go
* Update provider.go
* Update root.go, go.mod, and go.sum
* Update mizu.go
* Update go.sum and provider.go
* Update portForward.go, watch.go, and mizu.go
* Update README.md
* Update watch.go
* Update mizu.go
* Update mizu.go
* no message
* no message
* remove unused things and use external for object id (instead of copy)
* no message
* Update mizu.go
* Update go.mod, go.sum, and 2 more files...
* no message
* Update README.md, go.mod, and resolver.go
* Update README.md
* Update go.mod
* Update loader.go
* some refactor
* Update loader.go
* no message
* status to statusCode
* return data directly
* Traffic viewer
* cleaning
* css
* no message
* Clean warnings
* Makefile - first draft
* Update Makefile
* Update Makefile
* Update Makefile, README.md, and 4 more files...
* Add api build and clean to makefile (files restructure) (#9)
* no message
* add clean api command
* no message
* stating with web socket
* Add tap as a separate executable (#10)
* Added tap.
* Ignore build directories.
* Added tapper build to Makefile.
* Improvements (#12)
* no message
* no message
* Feature/makefile (#11)
* minor fixes
* makefile fixes - docker build
* minor fix in Makefile
Co-authored-by: Alex Haiut <alex@up9.com>
* Update Dockerfile, multi-runner.sh, and 31 more files...
* Update multi-runner.sh
* no message
* Update .dockerignore, Dockerfile, and 30 more files...
* Update cleaner.go, grpc_assembler.go, and 2 more files...
* start the pod with host network and privileged
* fix multi runner passive tapper command
* add HOST_MODE env var
* do not return true in the should tap function
* remove line in the end
* default value in api is input
fix description and pass the parameter in the multi runner script
* missing flag.parse
* no message
* fix image
* Create main.yml
* Update main.yml
* Update main.yml
* Update main.yml
* Update main.yml
* Update main.yml
* Update main.yml
* Update main.yml
* Update main.yml
* Update main.yml
* Update main.yml
* Update main.yml
* Update main.yml
* Update main.yml
* Update main.yml
* Update main.yml
* Update main.yml
* Update main.yml
* Update main.yml
* Update main.yml
* Small fixes - permission + har writing exception (#17)
* Select node by pod (#18)
* Select node by pod.
* Removed watch pod by regex. Irrelevant for now.
* Changed default image to develop:latest.
* Features/clifix (#19)
* makefile fixes - docker build
* readme update, CLI usage fix
* added chmod
Co-authored-by: Alex Haiut <alex@up9.com>
* meta information
* Only record traffic of the requested pod. Filtered by pod IP. (#21)
* fixed readme and reduced batch size to 5 (#22)
Co-authored-by: Alex Haiut <alex@up9.com>
* API and TAP in single process (#24)
* no message
* no message
* CLI make --pod required flag and faster api image build (#25)
* makefile fixes - docker build
* readme update, CLI usage fix
* added chmod
* typo
* run example incorreect in makefile
* no message
* no message
* no message
Co-authored-by: Alex Haiut <alex@up9.com>
* Reduce delay between tap and UI - Skip dump to file (#26)
* Pass HARs between tap and api via channel.
* Fixed make docker commad.
* Various fixes.
* Added .DS_Store to .gitignore.
* Parse flags in Mizu main instead of in tap_output.go.
* Use channel to pass HAR by default instead of files.
* Infinite scroll (#28)
* no message
* infinite scroll + new ws implementation
* no message
* scrolling top
* fetch button
* more Backend changes
* fix go mod and sum
* mire fixes against develop
* unused code
* small ui refactor
Co-authored-by: Roee Gadot <roee.gadot@up9.com>
* Fix gRPC crash, display gRPC as base64, display gRPC URL and status code (#27)
* Added Method (POST) and URL (emtpy) to gRPC requests.
* Removed quickfix that skips writing HTTP/2 to HAR.
* Use HTTP/2 body to fill out http.Request and htt.Response.
* Make sure that in HARs request.postData.mimeType and response.content.mimeType are application/grpc in case of grpc.
* Comment.
* Add URL and status code for gRPC.
* Don't assume http scheme.
* Use http.Header.Set instead of manually acccessing the underlaying map.
* General stats api fix (#29)
* refactor and validation
* Show gRPC as ASCII (#31)
* Moved try-catch up one block.
* Display grpc as ASCII.
* Better code in entries fetch endpoint (#30)
* no message
* no message
* Feature/UI/filters (#32)
* UI filters
* refactor
* Revert "refactor"
This reverts commit 70e7d4b6ac.
* remove recursive func
* CLI cleanup (#33)
* Moved cli root command to tap subcommand.
* tap subcommand works.
* Added view and fetch placeholders.
* Updated descriptions.
* Fixed indentation.
* Added versio subcommand.
* Removed version flag.
* gofmt.
* Changed pod from flag to arg.
* Commented out "all namespaces" flag.
* CLI cleanup 2 (#34)
* Renamed dashboard -> GUI/web interface.
* Commented out --quiet, removed unused config variables.
* Quiter output when calling unimplemented subcommands.
* Leftovers from PR #30 (#36)
Co-authored-by: up9-github <info@up9.com>
Co-authored-by: RamiBerm <54766858+RamiBerm@users.noreply.github.com>
Co-authored-by: Liraz Yehezkel <lirazy@up9.com>
Co-authored-by: Alex Haiut <alex@testr.io>
Co-authored-by: lirazyehezkel <61656597+lirazyehezkel@users.noreply.github.com>
Co-authored-by: Alex Haiut <alex@up9.com>
Co-authored-by: nimrod-up9 <59927337+nimrod-up9@users.noreply.github.com>
Co-authored-by: RamiBerm <rami.berman@up9.com>
Co-authored-by: Alex Haiut <alex.haiut@gmail.com>
169 lines
5.0 KiB
Go
169 lines
5.0 KiB
Go
package tap
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"encoding/hex"
|
|
"fmt"
|
|
"sync"
|
|
|
|
"github.com/google/gopacket"
|
|
"github.com/google/gopacket/layers" // pulls in all layers decoders
|
|
"github.com/google/gopacket/reassembly"
|
|
)
|
|
|
|
/* It's a connection (bidirectional)
|
|
* Implements gopacket.reassembly.Stream interface (Accept, ReassembledSG, ReassemblyComplete)
|
|
* ReassembledSG gets called when new reassembled data is ready (i.e. bytes in order, no duplicates, complete)
|
|
* In our implementation, we pass information from ReassembledSG to the httpReader through a shared channel.
|
|
*/
|
|
type tcpStream struct {
|
|
tcpstate *reassembly.TCPSimpleFSM
|
|
fsmerr bool
|
|
optchecker reassembly.TCPOptionCheck
|
|
net, transport gopacket.Flow
|
|
isDNS bool
|
|
isHTTP bool
|
|
reversed bool
|
|
client httpReader
|
|
server httpReader
|
|
urls []string
|
|
ident string
|
|
sync.Mutex
|
|
}
|
|
|
|
func (t *tcpStream) Accept(tcp *layers.TCP, ci gopacket.CaptureInfo, dir reassembly.TCPFlowDirection, nextSeq reassembly.Sequence, start *bool, ac reassembly.AssemblerContext) bool {
|
|
// FSM
|
|
if !t.tcpstate.CheckState(tcp, dir) {
|
|
//SilentError("FSM", "%s: Packet rejected by FSM (state:%s)\n", t.ident, t.tcpstate.String())
|
|
stats.rejectFsm++
|
|
if !t.fsmerr {
|
|
t.fsmerr = true
|
|
stats.rejectConnFsm++
|
|
}
|
|
if !*ignorefsmerr {
|
|
return false
|
|
}
|
|
}
|
|
// Options
|
|
err := t.optchecker.Accept(tcp, ci, dir, nextSeq, start)
|
|
if err != nil {
|
|
//SilentError("OptionChecker", "%s: Packet rejected by OptionChecker: %s\n", t.ident, err)
|
|
stats.rejectOpt++
|
|
if !*nooptcheck {
|
|
return false
|
|
}
|
|
}
|
|
// Checksum
|
|
accept := true
|
|
if *checksum {
|
|
c, err := tcp.ComputeChecksum()
|
|
if err != nil {
|
|
SilentError("ChecksumCompute", "%s: Got error computing checksum: %s\n", t.ident, err)
|
|
accept = false
|
|
} else if c != 0x0 {
|
|
SilentError("Checksum", "%s: Invalid checksum: 0x%x\n", t.ident, c)
|
|
accept = false
|
|
}
|
|
}
|
|
if !accept {
|
|
stats.rejectOpt++
|
|
}
|
|
return accept
|
|
}
|
|
|
|
func (t *tcpStream) ReassembledSG(sg reassembly.ScatterGather, ac reassembly.AssemblerContext) {
|
|
dir, start, end, skip := sg.Info()
|
|
length, saved := sg.Lengths()
|
|
// update stats
|
|
sgStats := sg.Stats()
|
|
if skip > 0 {
|
|
stats.missedBytes += skip
|
|
}
|
|
stats.sz += length - saved
|
|
stats.pkt += sgStats.Packets
|
|
if sgStats.Chunks > 1 {
|
|
stats.reassembled++
|
|
}
|
|
stats.outOfOrderPackets += sgStats.QueuedPackets
|
|
stats.outOfOrderBytes += sgStats.QueuedBytes
|
|
if length > stats.biggestChunkBytes {
|
|
stats.biggestChunkBytes = length
|
|
}
|
|
if sgStats.Packets > stats.biggestChunkPackets {
|
|
stats.biggestChunkPackets = sgStats.Packets
|
|
}
|
|
if sgStats.OverlapBytes != 0 && sgStats.OverlapPackets == 0 {
|
|
// In the original example this was handled with panic().
|
|
// I don't know what this error means or how to handle it properly.
|
|
SilentError("Invalid-Overlap", "bytes:%d, pkts:%d\n", sgStats.OverlapBytes, sgStats.OverlapPackets)
|
|
}
|
|
stats.overlapBytes += sgStats.OverlapBytes
|
|
stats.overlapPackets += sgStats.OverlapPackets
|
|
|
|
var ident string
|
|
if dir == reassembly.TCPDirClientToServer {
|
|
ident = fmt.Sprintf("%v %v(%s): ", t.net, t.transport, dir)
|
|
} else {
|
|
ident = fmt.Sprintf("%v %v(%s): ", t.net.Reverse(), t.transport.Reverse(), dir)
|
|
}
|
|
Debug("%s: SG reassembled packet with %d bytes (start:%v,end:%v,skip:%d,saved:%d,nb:%d,%d,overlap:%d,%d)\n", ident, length, start, end, skip, saved, sgStats.Packets, sgStats.Chunks, sgStats.OverlapBytes, sgStats.OverlapPackets)
|
|
if skip == -1 && *allowmissinginit {
|
|
// this is allowed
|
|
} else if skip != 0 {
|
|
// Missing bytes in stream: do not even try to parse it
|
|
return
|
|
}
|
|
data := sg.Fetch(length)
|
|
if t.isDNS {
|
|
dns := &layers.DNS{}
|
|
var decoded []gopacket.LayerType
|
|
if len(data) < 2 {
|
|
if len(data) > 0 {
|
|
sg.KeepFrom(0)
|
|
}
|
|
return
|
|
}
|
|
dnsSize := binary.BigEndian.Uint16(data[:2])
|
|
missing := int(dnsSize) - len(data[2:])
|
|
Debug("dnsSize: %d, missing: %d\n", dnsSize, missing)
|
|
if missing > 0 {
|
|
Info("Missing some bytes: %d\n", missing)
|
|
sg.KeepFrom(0)
|
|
return
|
|
}
|
|
p := gopacket.NewDecodingLayerParser(layers.LayerTypeDNS, dns)
|
|
err := p.DecodeLayers(data[2:], &decoded)
|
|
if err != nil {
|
|
SilentError("DNS-parser", "Failed to decode DNS: %v\n", err)
|
|
} else {
|
|
Debug("DNS: %s\n", gopacket.LayerDump(dns))
|
|
}
|
|
if len(data) > 2+int(dnsSize) {
|
|
sg.KeepFrom(2 + int(dnsSize))
|
|
}
|
|
} else if t.isHTTP {
|
|
if length > 0 {
|
|
if *hexdump {
|
|
Debug("Feeding http with:\n%s", hex.Dump(data))
|
|
}
|
|
// This is where we pass the reassembled information onwards
|
|
// This channel is read by an httpReader object
|
|
if dir == reassembly.TCPDirClientToServer && !t.reversed {
|
|
t.client.msgQueue <- httpReaderDataMsg{data, ac.GetCaptureInfo().Timestamp}
|
|
} else {
|
|
t.server.msgQueue <- httpReaderDataMsg{data, ac.GetCaptureInfo().Timestamp}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func (t *tcpStream) ReassemblyComplete(ac reassembly.AssemblerContext) bool {
|
|
Debug("%s: Connection closed\n", t.ident)
|
|
if t.isHTTP {
|
|
close(t.client.msgQueue)
|
|
close(t.server.msgQueue)
|
|
}
|
|
// do not remove the connection to allow last ACK
|
|
return false
|
|
}
|