mirror of
https://github.com/kubeshark/kubeshark.git
synced 2025-07-04 03:48:58 +00:00
Add a uprobe for net/http.(*gzipReader).Read
to read chunked HTTP response body
This commit is contained in:
parent
a2da15ef2d
commit
9fc8e0eb50
@ -17,6 +17,7 @@ struct golang_read_write {
|
|||||||
__u32 fd;
|
__u32 fd;
|
||||||
__u32 conn_addr;
|
__u32 conn_addr;
|
||||||
bool is_request;
|
bool is_request;
|
||||||
|
bool is_gzip_chunk;
|
||||||
__u8 data[BUFFER_SIZE_READ_WRITE];
|
__u8 data[BUFFER_SIZE_READ_WRITE];
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -54,6 +55,7 @@ static __always_inline int golang_crypto_tls_write_uprobe(struct pt_regs *ctx) {
|
|||||||
// ctx->rsi is common between golang_crypto_tls_write_uprobe and golang_crypto_tls_read_uprobe
|
// ctx->rsi is common between golang_crypto_tls_write_uprobe and golang_crypto_tls_read_uprobe
|
||||||
b->conn_addr = ctx->rsi; // go.itab.*net.TCPConn,net.Conn address
|
b->conn_addr = ctx->rsi; // go.itab.*net.TCPConn,net.Conn address
|
||||||
b->is_request = true;
|
b->is_request = true;
|
||||||
|
b->is_gzip_chunk = false;
|
||||||
|
|
||||||
status = bpf_probe_read_str(&b->data, sizeof(b->data), (void*)ctx->rbx);
|
status = bpf_probe_read_str(&b->data, sizeof(b->data), (void*)ctx->rbx);
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
@ -80,6 +82,7 @@ static __always_inline int golang_crypto_tls_read_uprobe(struct pt_regs *ctx) {
|
|||||||
// ctx->rsi is common between golang_crypto_tls_write_uprobe and golang_crypto_tls_read_uprobe
|
// ctx->rsi is common between golang_crypto_tls_write_uprobe and golang_crypto_tls_read_uprobe
|
||||||
b->conn_addr = ctx->rsi; // go.itab.*net.TCPConn,net.Conn address
|
b->conn_addr = ctx->rsi; // go.itab.*net.TCPConn,net.Conn address
|
||||||
b->is_request = false;
|
b->is_request = false;
|
||||||
|
b->is_gzip_chunk = false;
|
||||||
|
|
||||||
void* stack_addr = (void*)ctx->rsp;
|
void* stack_addr = (void*)ctx->rsp;
|
||||||
__u64 data_p;
|
__u64 data_p;
|
||||||
@ -103,6 +106,43 @@ static __always_inline int golang_crypto_tls_read_uprobe(struct pt_regs *ctx) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SEC("uprobe/golang_net_http_gzipreader_read")
|
||||||
|
static __always_inline int golang_net_http_gzipreader_read_uprobe(struct pt_regs *ctx) {
|
||||||
|
struct golang_read_write *b = NULL;
|
||||||
|
b = bpf_ringbuf_reserve(&golang_read_writes, sizeof(struct golang_read_write), 0);
|
||||||
|
if (!b) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// __u64 pid_tgid = bpf_get_current_pid_tgid();
|
||||||
|
// b->pid = pid_tgid >> 32;
|
||||||
|
// // ctx->rsi is common between golang_crypto_tls_write_uprobe and golang_crypto_tls_read_uprobe
|
||||||
|
// b->conn_addr = ctx->rsi; // go.itab.*net.TCPConn,net.Conn address
|
||||||
|
b->is_request = false;
|
||||||
|
b->is_gzip_chunk = true;
|
||||||
|
|
||||||
|
void* stack_addr = (void*)ctx->rsp;
|
||||||
|
__u64 data_p;
|
||||||
|
// Address at ctx->rsp + 0x8 holds the data
|
||||||
|
__u32 status = bpf_probe_read(&data_p, sizeof(data_p), stack_addr + 0x8);
|
||||||
|
if (status < 0) {
|
||||||
|
bpf_printk("[golang_net_http_gzipreader_read_uprobe] error reading data pointer: %d", status);
|
||||||
|
bpf_ringbuf_discard(b, BPF_RB_FORCE_WAKEUP);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = bpf_probe_read_str(&b->data, sizeof(b->data), (void*)(data_p));
|
||||||
|
if (status < 0) {
|
||||||
|
bpf_printk("[golang_net_http_gzipreader_read_uprobe] error reading data: %d", status);
|
||||||
|
bpf_ringbuf_discard(b, BPF_RB_FORCE_WAKEUP);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bpf_ringbuf_submit(b, 0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
SEC("uprobe/golang_net_socket")
|
SEC("uprobe/golang_net_socket")
|
||||||
static __always_inline int golang_net_socket_uprobe(struct pt_regs *ctx) {
|
static __always_inline int golang_net_socket_uprobe(struct pt_regs *ctx) {
|
||||||
__u64 pid_tgid = bpf_get_current_pid_tgid();
|
__u64 pid_tgid = bpf_get_current_pid_tgid();
|
||||||
|
@ -10,6 +10,7 @@ type golangHooks struct {
|
|||||||
golangSocketProbe link.Link
|
golangSocketProbe link.Link
|
||||||
golangWriteProbe link.Link
|
golangWriteProbe link.Link
|
||||||
golangReadProbe link.Link
|
golangReadProbe link.Link
|
||||||
|
golangGzipProbe link.Link
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *golangHooks) installUprobes(bpfObjects *tlsTapperObjects, filePath string) error {
|
func (s *golangHooks) installUprobes(bpfObjects *tlsTapperObjects, filePath string) error {
|
||||||
@ -71,6 +72,16 @@ func (s *golangHooks) installHooks(bpfObjects *tlsTapperObjects, ex *link.Execut
|
|||||||
return errors.Wrap(err, 0)
|
return errors.Wrap(err, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Relative offset points to
|
||||||
|
// [`net/http.(*gzipReader).Read+363`](https://github.com/golang/go/blob/fe4de36198794c447fbd9d7cc2d7199a506c76a5/src/net/http/transport.go#L2837)
|
||||||
|
s.golangGzipProbe, err = ex.Uprobe(golangReadSymbol, bpfObjects.GolangNetHttpGzipreaderReadUprobe, &link.UprobeOptions{
|
||||||
|
Offset: offsets.GolangGzipOffset + 0x16b,
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, 0)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,5 +104,9 @@ func (s *golangHooks) close() []error {
|
|||||||
errors = append(errors, err)
|
errors = append(errors, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := s.golangGzipProbe.Close(); err != nil {
|
||||||
|
errors = append(errors, err)
|
||||||
|
}
|
||||||
|
|
||||||
return errors
|
return errors
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@ type golangOffsets struct {
|
|||||||
GolangSocketOffset uint64
|
GolangSocketOffset uint64
|
||||||
GolangWriteOffset uint64
|
GolangWriteOffset uint64
|
||||||
GolangReadOffset uint64
|
GolangReadOffset uint64
|
||||||
|
GolangGzipOffset uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -22,6 +23,7 @@ const (
|
|||||||
golangVersionSymbol = "runtime.buildVersion.str"
|
golangVersionSymbol = "runtime.buildVersion.str"
|
||||||
golangWriteSymbol = "crypto/tls.(*Conn).Write"
|
golangWriteSymbol = "crypto/tls.(*Conn).Write"
|
||||||
golangReadSymbol = "crypto/tls.(*Conn).Read"
|
golangReadSymbol = "crypto/tls.(*Conn).Read"
|
||||||
|
golangGzipSymbol = "net/http.(*gzipReader).Read"
|
||||||
golangSocketSymbol = "net.socket"
|
golangSocketSymbol = "net.socket"
|
||||||
golangDialSymbol = "net/http.(*Transport).dialConn"
|
golangDialSymbol = "net/http.(*Transport).dialConn"
|
||||||
)
|
)
|
||||||
@ -66,11 +68,17 @@ func findGolangOffsets(filePath string) (golangOffsets, error) {
|
|||||||
return golangOffsets{}, fmt.Errorf("reading offset [%s]: %s", golangReadSymbol, err)
|
return golangOffsets{}, fmt.Errorf("reading offset [%s]: %s", golangReadSymbol, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gzipOffset, err := getOffset(offsets, golangGzipSymbol)
|
||||||
|
if err != nil {
|
||||||
|
return golangOffsets{}, fmt.Errorf("reading offset [%s]: %s", golangGzipSymbol, err)
|
||||||
|
}
|
||||||
|
|
||||||
return golangOffsets{
|
return golangOffsets{
|
||||||
GolangDialOffset: dialOffset,
|
GolangDialOffset: dialOffset,
|
||||||
GolangSocketOffset: socketOffset,
|
GolangSocketOffset: socketOffset,
|
||||||
GolangWriteOffset: writeOffset,
|
GolangWriteOffset: writeOffset,
|
||||||
GolangReadOffset: readOffset,
|
GolangReadOffset: readOffset,
|
||||||
|
GolangGzipOffset: gzipOffset,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ import (
|
|||||||
"github.com/up9inc/mizu/logger"
|
"github.com/up9inc/mizu/logger"
|
||||||
"github.com/up9inc/mizu/tap/api"
|
"github.com/up9inc/mizu/tap/api"
|
||||||
orderedmap "github.com/wk8/go-ordered-map"
|
orderedmap "github.com/wk8/go-ordered-map"
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -137,6 +138,12 @@ func (p *tlsPoller) pollGolangReadWrite(rd *ringbuf.Reader, emitter api.Emitter,
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if b.IsGzipChunk {
|
||||||
|
chunk := unix.ByteSliceToString(b.Data[:])
|
||||||
|
fmt.Printf("chunk: %v\n", chunk)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
if p.golangReadWriteMap.Len()+1 > golangMapLimit {
|
if p.golangReadWriteMap.Len()+1 > golangMapLimit {
|
||||||
pair := p.golangReadWriteMap.Oldest()
|
pair := p.golangReadWriteMap.Oldest()
|
||||||
p.golangReadWriteMap.Delete(pair.Key)
|
p.golangReadWriteMap.Delete(pair.Key)
|
||||||
|
@ -18,8 +18,9 @@ type tlsTapperGolangReadWrite struct {
|
|||||||
Fd uint32
|
Fd uint32
|
||||||
ConnAddr uint32
|
ConnAddr uint32
|
||||||
IsRequest bool
|
IsRequest bool
|
||||||
|
IsGzipChunk bool
|
||||||
Data [524288]uint8
|
Data [524288]uint8
|
||||||
_ [3]byte
|
_ [2]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
type tlsTapperTlsChunk struct {
|
type tlsTapperTlsChunk struct {
|
||||||
@ -78,6 +79,7 @@ type tlsTapperProgramSpecs struct {
|
|||||||
GolangCryptoTlsReadUprobe *ebpf.ProgramSpec `ebpf:"golang_crypto_tls_read_uprobe"`
|
GolangCryptoTlsReadUprobe *ebpf.ProgramSpec `ebpf:"golang_crypto_tls_read_uprobe"`
|
||||||
GolangCryptoTlsWriteUprobe *ebpf.ProgramSpec `ebpf:"golang_crypto_tls_write_uprobe"`
|
GolangCryptoTlsWriteUprobe *ebpf.ProgramSpec `ebpf:"golang_crypto_tls_write_uprobe"`
|
||||||
GolangNetHttpDialconnUprobe *ebpf.ProgramSpec `ebpf:"golang_net_http_dialconn_uprobe"`
|
GolangNetHttpDialconnUprobe *ebpf.ProgramSpec `ebpf:"golang_net_http_dialconn_uprobe"`
|
||||||
|
GolangNetHttpGzipreaderReadUprobe *ebpf.ProgramSpec `ebpf:"golang_net_http_gzipreader_read_uprobe"`
|
||||||
GolangNetSocketUprobe *ebpf.ProgramSpec `ebpf:"golang_net_socket_uprobe"`
|
GolangNetSocketUprobe *ebpf.ProgramSpec `ebpf:"golang_net_socket_uprobe"`
|
||||||
SslRead *ebpf.ProgramSpec `ebpf:"ssl_read"`
|
SslRead *ebpf.ProgramSpec `ebpf:"ssl_read"`
|
||||||
SslReadEx *ebpf.ProgramSpec `ebpf:"ssl_read_ex"`
|
SslReadEx *ebpf.ProgramSpec `ebpf:"ssl_read_ex"`
|
||||||
@ -170,6 +172,7 @@ type tlsTapperPrograms struct {
|
|||||||
GolangCryptoTlsReadUprobe *ebpf.Program `ebpf:"golang_crypto_tls_read_uprobe"`
|
GolangCryptoTlsReadUprobe *ebpf.Program `ebpf:"golang_crypto_tls_read_uprobe"`
|
||||||
GolangCryptoTlsWriteUprobe *ebpf.Program `ebpf:"golang_crypto_tls_write_uprobe"`
|
GolangCryptoTlsWriteUprobe *ebpf.Program `ebpf:"golang_crypto_tls_write_uprobe"`
|
||||||
GolangNetHttpDialconnUprobe *ebpf.Program `ebpf:"golang_net_http_dialconn_uprobe"`
|
GolangNetHttpDialconnUprobe *ebpf.Program `ebpf:"golang_net_http_dialconn_uprobe"`
|
||||||
|
GolangNetHttpGzipreaderReadUprobe *ebpf.Program `ebpf:"golang_net_http_gzipreader_read_uprobe"`
|
||||||
GolangNetSocketUprobe *ebpf.Program `ebpf:"golang_net_socket_uprobe"`
|
GolangNetSocketUprobe *ebpf.Program `ebpf:"golang_net_socket_uprobe"`
|
||||||
SslRead *ebpf.Program `ebpf:"ssl_read"`
|
SslRead *ebpf.Program `ebpf:"ssl_read"`
|
||||||
SslReadEx *ebpf.Program `ebpf:"ssl_read_ex"`
|
SslReadEx *ebpf.Program `ebpf:"ssl_read_ex"`
|
||||||
@ -192,6 +195,7 @@ func (p *tlsTapperPrograms) Close() error {
|
|||||||
p.GolangCryptoTlsReadUprobe,
|
p.GolangCryptoTlsReadUprobe,
|
||||||
p.GolangCryptoTlsWriteUprobe,
|
p.GolangCryptoTlsWriteUprobe,
|
||||||
p.GolangNetHttpDialconnUprobe,
|
p.GolangNetHttpDialconnUprobe,
|
||||||
|
p.GolangNetHttpGzipreaderReadUprobe,
|
||||||
p.GolangNetSocketUprobe,
|
p.GolangNetSocketUprobe,
|
||||||
p.SslRead,
|
p.SslRead,
|
||||||
p.SslReadEx,
|
p.SslReadEx,
|
||||||
|
Binary file not shown.
@ -18,8 +18,9 @@ type tlsTapperGolangReadWrite struct {
|
|||||||
Fd uint32
|
Fd uint32
|
||||||
ConnAddr uint32
|
ConnAddr uint32
|
||||||
IsRequest bool
|
IsRequest bool
|
||||||
|
IsGzipChunk bool
|
||||||
Data [524288]uint8
|
Data [524288]uint8
|
||||||
_ [3]byte
|
_ [2]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
type tlsTapperTlsChunk struct {
|
type tlsTapperTlsChunk struct {
|
||||||
@ -78,6 +79,7 @@ type tlsTapperProgramSpecs struct {
|
|||||||
GolangCryptoTlsReadUprobe *ebpf.ProgramSpec `ebpf:"golang_crypto_tls_read_uprobe"`
|
GolangCryptoTlsReadUprobe *ebpf.ProgramSpec `ebpf:"golang_crypto_tls_read_uprobe"`
|
||||||
GolangCryptoTlsWriteUprobe *ebpf.ProgramSpec `ebpf:"golang_crypto_tls_write_uprobe"`
|
GolangCryptoTlsWriteUprobe *ebpf.ProgramSpec `ebpf:"golang_crypto_tls_write_uprobe"`
|
||||||
GolangNetHttpDialconnUprobe *ebpf.ProgramSpec `ebpf:"golang_net_http_dialconn_uprobe"`
|
GolangNetHttpDialconnUprobe *ebpf.ProgramSpec `ebpf:"golang_net_http_dialconn_uprobe"`
|
||||||
|
GolangNetHttpGzipreaderReadUprobe *ebpf.ProgramSpec `ebpf:"golang_net_http_gzipreader_read_uprobe"`
|
||||||
GolangNetSocketUprobe *ebpf.ProgramSpec `ebpf:"golang_net_socket_uprobe"`
|
GolangNetSocketUprobe *ebpf.ProgramSpec `ebpf:"golang_net_socket_uprobe"`
|
||||||
SslRead *ebpf.ProgramSpec `ebpf:"ssl_read"`
|
SslRead *ebpf.ProgramSpec `ebpf:"ssl_read"`
|
||||||
SslReadEx *ebpf.ProgramSpec `ebpf:"ssl_read_ex"`
|
SslReadEx *ebpf.ProgramSpec `ebpf:"ssl_read_ex"`
|
||||||
@ -170,6 +172,7 @@ type tlsTapperPrograms struct {
|
|||||||
GolangCryptoTlsReadUprobe *ebpf.Program `ebpf:"golang_crypto_tls_read_uprobe"`
|
GolangCryptoTlsReadUprobe *ebpf.Program `ebpf:"golang_crypto_tls_read_uprobe"`
|
||||||
GolangCryptoTlsWriteUprobe *ebpf.Program `ebpf:"golang_crypto_tls_write_uprobe"`
|
GolangCryptoTlsWriteUprobe *ebpf.Program `ebpf:"golang_crypto_tls_write_uprobe"`
|
||||||
GolangNetHttpDialconnUprobe *ebpf.Program `ebpf:"golang_net_http_dialconn_uprobe"`
|
GolangNetHttpDialconnUprobe *ebpf.Program `ebpf:"golang_net_http_dialconn_uprobe"`
|
||||||
|
GolangNetHttpGzipreaderReadUprobe *ebpf.Program `ebpf:"golang_net_http_gzipreader_read_uprobe"`
|
||||||
GolangNetSocketUprobe *ebpf.Program `ebpf:"golang_net_socket_uprobe"`
|
GolangNetSocketUprobe *ebpf.Program `ebpf:"golang_net_socket_uprobe"`
|
||||||
SslRead *ebpf.Program `ebpf:"ssl_read"`
|
SslRead *ebpf.Program `ebpf:"ssl_read"`
|
||||||
SslReadEx *ebpf.Program `ebpf:"ssl_read_ex"`
|
SslReadEx *ebpf.Program `ebpf:"ssl_read_ex"`
|
||||||
@ -192,6 +195,7 @@ func (p *tlsTapperPrograms) Close() error {
|
|||||||
p.GolangCryptoTlsReadUprobe,
|
p.GolangCryptoTlsReadUprobe,
|
||||||
p.GolangCryptoTlsWriteUprobe,
|
p.GolangCryptoTlsWriteUprobe,
|
||||||
p.GolangNetHttpDialconnUprobe,
|
p.GolangNetHttpDialconnUprobe,
|
||||||
|
p.GolangNetHttpGzipreaderReadUprobe,
|
||||||
p.GolangNetSocketUprobe,
|
p.GolangNetSocketUprobe,
|
||||||
p.SslRead,
|
p.SslRead,
|
||||||
p.SslReadEx,
|
p.SslReadEx,
|
||||||
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user