You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@skywalking.apache.org by li...@apache.org on 2022/08/05 01:29:45 UTC

[skywalking-rover] branch main updated: Support BoringSSL in Envoy (#44)

This is an automated email from the ASF dual-hosted git repository.

liuhan pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/skywalking-rover.git


The following commit(s) were added to refs/heads/main by this push:
     new 6d6f622  Support BoringSSL in Envoy (#44)
6d6f622 is described below

commit 6d6f62210717464e5170c92e3c99c2900ffe10c0
Author: mrproliu <74...@qq.com>
AuthorDate: Fri Aug 5 09:29:42 2022 +0800

    Support BoringSSL in Envoy (#44)
---
 CHANGES.md                               |  2 +-
 bpf/profiling/network/netmonitor.c       |  6 +++++
 bpf/profiling/network/openssl.c          | 16 ++++----------
 bpf/profiling/network/openssl.h          |  8 -------
 bpf/profiling/network/sock_stats.h       | 11 ++++++++-
 docs/en/setup/configuration/profiling.md | 23 +++++++++++++++++--
 pkg/profiling/task/network/context.go    |  6 +++++
 pkg/profiling/task/network/runner.go     |  9 ++++----
 pkg/profiling/task/network/ssl.go        | 38 ++++++++++++++++++++++++++++++++
 9 files changed, 90 insertions(+), 29 deletions(-)

diff --git a/CHANGES.md b/CHANGES.md
index 8c74a6b..5213e78 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -7,7 +7,7 @@ Release Notes.
 #### Features
 * Support `NETWORK` Profiling.
 * Let the logger as a configurable module.
-* Support analyze the data of OpenSSL library in `NETWORK` Profiling.
+* Support analyze the data of OpenSSL, BoringSSL library in `NETWORK` Profiling.
 
 #### Bug Fixes
 * Fixed reading process paths incorrect when running as a container.
diff --git a/bpf/profiling/network/netmonitor.c b/bpf/profiling/network/netmonitor.c
index b7262fc..c929b22 100644
--- a/bpf/profiling/network/netmonitor.c
+++ b/bpf/profiling/network/netmonitor.c
@@ -307,6 +307,12 @@ static __always_inline void process_write_data(struct pt_regs *ctx, __u64 id, st
     if (family_should_trace(conn->socket_family) == false) {
         return;
     }
+    // process the ssl request if the fd not found
+    struct sock_data_args_t *ssl_data_args = bpf_map_lookup_elem(&openssl_sock_data_args, &id);
+    if (ssl_data_args != NULL && ssl_data_args->fd == 0) {
+        ssl_data_args->fd = args->fd;
+        conn->ssl = true;
+    }
 
     // if connect event is not sent
     if (conn->connect_event_send == false) {
diff --git a/bpf/profiling/network/openssl.c b/bpf/profiling/network/openssl.c
index 3bd81ed..124c34d 100644
--- a/bpf/profiling/network/openssl.c
+++ b/bpf/profiling/network/openssl.c
@@ -39,14 +39,14 @@ static int get_fd_symaddr(__u32 tgid, bool read, void* ssl) {
 }
 
 static int get_fd(uint32_t tgid, bool read, void* ssl) {
-    int fd = -1;
+    int fd = 0;
 
     fd = get_fd_symaddr(tgid, read, ssl);
     if (fd > 2) {
         return fd;
     }
 
-    return -1;
+    return 0;
 }
 
 SEC("uprobe/ssl_write")
@@ -56,10 +56,6 @@ int openssl_write(struct pt_regs* ctx) {
 
     void* ssl = (void*)PT_REGS_PARM1(ctx);
     __u32 fd = get_fd(tgid, false, ssl);
-    bpf_printk("ssl_write fd: %d\n", fd);
-    if (fd < 0) {
-        return 0;
-    }
 
     char* buf = (char*)PT_REGS_PARM2(ctx);
     struct sock_data_args_t data_args = {};
@@ -75,7 +71,7 @@ SEC("uretprobe/ssl_write")
 int openssl_write_ret(struct pt_regs* ctx) {
     __u64 id = bpf_get_current_pid_tgid();
     struct sock_data_args_t *args = bpf_map_lookup_elem(&openssl_sock_data_args, &id);
-    if (args) {
+    if (args && args->fd > 0) {
         process_openssl_data(ctx, id, SOCK_DATA_DIRECTION_EGRESS, args, SOCKET_OPTS_TYPE_SSL_WRITE);
     }
     bpf_map_delete_elem(&openssl_sock_data_args, &id);
@@ -89,10 +85,6 @@ int openssl_read(struct pt_regs* ctx) {
 
     void* ssl = (void*)PT_REGS_PARM1(ctx);
     __u32 fd = get_fd(tgid, true, ssl);
-    bpf_printk("ssl_read fd: %d\n", fd);
-    if (fd < 0) {
-        return 0;
-    }
 
     char* buf = (char*)PT_REGS_PARM2(ctx);
     struct sock_data_args_t data_args = {};
@@ -108,7 +100,7 @@ SEC("uretprobe/ssl_read")
 int openssl_read_ret(struct pt_regs* ctx) {
     __u64 id = bpf_get_current_pid_tgid();
     struct sock_data_args_t *args = bpf_map_lookup_elem(&openssl_sock_data_args, &id);
-    if (args) {
+    if (args && args->fd > 0) {
         process_openssl_data(ctx, id, SOCK_DATA_DIRECTION_INGRESS, args, SOCKET_OPTS_TYPE_SSL_READ);
     }
     bpf_map_delete_elem(&openssl_sock_data_args, &id);
diff --git a/bpf/profiling/network/openssl.h b/bpf/profiling/network/openssl.h
index 11536be..61e8425 100644
--- a/bpf/profiling/network/openssl.h
+++ b/bpf/profiling/network/openssl.h
@@ -33,11 +33,3 @@ static __inline struct openssl_fd_symaddr* get_openssl_fd_symaddr(__u32 tgid) {
     struct openssl_fd_symaddr *addr = bpf_map_lookup_elem(&openssl_fd_symaddr_finder, &tgid);
     return addr;
 }
-
-// openssl read or write
-struct {
-	__uint(type, BPF_MAP_TYPE_HASH);
-	__uint(max_entries, 10000);
-	__type(key, __u64);
-	__type(value, struct sock_data_args_t);
-} openssl_sock_data_args SEC(".maps");
\ No newline at end of file
diff --git a/bpf/profiling/network/sock_stats.h b/bpf/profiling/network/sock_stats.h
index 018bc69..f3fde47 100644
--- a/bpf/profiling/network/sock_stats.h
+++ b/bpf/profiling/network/sock_stats.h
@@ -56,6 +56,7 @@ struct active_connection_t {
 
     // for protocol analyze
     __u32 protocol;
+    __u32 fix;
     __u64 prev_count;
     char prev_buf[4];
     __u32 prepend_length_header;
@@ -245,4 +246,12 @@ struct socket_exception_operation_event_t {
 };
 struct {
 	__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
-} socket_exception_operation_event_queue SEC(".maps");
\ No newline at end of file
+} socket_exception_operation_event_queue SEC(".maps");
+
+// openssl read or write
+struct {
+	__uint(type, BPF_MAP_TYPE_HASH);
+	__uint(max_entries, 10000);
+	__type(key, __u64);
+	__type(value, struct sock_data_args_t);
+} openssl_sock_data_args SEC(".maps");
\ No newline at end of file
diff --git a/docs/en/setup/configuration/profiling.md b/docs/en/setup/configuration/profiling.md
index 1a3db98..0e3ba42 100644
--- a/docs/en/setup/configuration/profiling.md
+++ b/docs/en/setup/configuration/profiling.md
@@ -9,17 +9,36 @@ and send the snapshot to the backend server.
 |------|---------|-----------------|-------------|
 | profiling.active | true | ROVER_PROFILING_ACTIVE | Is active the process profiling. |
 | profiling.check_interval | 10s | ROVER_PROFILING_CHECK_INTERVAL | Check the profiling task interval. |
-| profiling.flush_interval | 5s | Combine existing profiling data and report to the backend interval |
+| profiling.flush_interval | 5s | Combine existing profiling data and report to the backend interval. |
+| task.on_cpu.dump_period | 9ms | The on CPU profiling thread stack dump period. |
+| task.network.report_interval | 2s | The interval of send network profiling metrics to the backend. |
+| task.network.meter_prefix | rover_net_p | The prefix of network profiling metrics name. |
 
 ## Profiling Type
 
-All the profiling tasks are using the [Linux Official Function](https://man7.org/linux/man-pages/man2/perf_event_open.2.html) to open perf event,
+All the profiling tasks are using the [Linux Official Function](https://man7.org/linux/man-pages/man2/perf_event_open.2.html) and `kprobe` or `uprobe` to open perf event,
 and attach the eBPF Program to dump stacks.
 
 ### On CPU
 
 On CPU Profiling task is using `PERF_COUNT_SW_CPU_CLOCK` to profiling the process with the CPU clock.
 
+### Off CPU
+
+Off CPU Profiling task is attach the `finish_task_switch` in `krobe` to profiling the process.
+
+### Network
+
+Network Profiling task is intercept IO-related syscall and `urprobe` in process to identify the network traffic and generate the metrics.
+Also, the following protocol are supported for analyzing using OpenSSL library, BoringSSL library or plaintext:
+
+1. HTTP
+2. MySQL
+3. CQL(The Cassandra Query Language)
+4. MongoDB
+5. Kafka
+6. DNS
+
 ## Configuration
 
 | Name | Default | Environment Key | Description |
diff --git a/pkg/profiling/task/network/context.go b/pkg/profiling/task/network/context.go
index cba0ce2..644d220 100644
--- a/pkg/profiling/task/network/context.go
+++ b/pkg/profiling/task/network/context.go
@@ -282,6 +282,7 @@ type ActiveConnectionInBPF struct {
 
 	// Protocol analyze context
 	Protocol              ConnectionProtocol
+	Fix                   uint32
 	ProtocolPrevCount     uint64
 	ProtocolPrevBuf       [4]byte
 	ProtocolPrependHeader uint32
@@ -325,6 +326,11 @@ func (c *Context) fillConnectionMetrics(ccs []*ConnectionContext) {
 				continue
 			}
 
+			if log.Enable(logrus.DebugLevel) {
+				marshal, _ := json.Marshal(activeConnection)
+				log.Debugf("found the active connection, conid: %d, data: %s", cc.ConnectionID, string(marshal))
+			}
+
 			if cc.Role == ConnectionRoleUnknown && activeConnection.Role != ConnectionRoleUnknown {
 				cc.Role = activeConnection.Role
 			}
diff --git a/pkg/profiling/task/network/runner.go b/pkg/profiling/task/network/runner.go
index 7581ade..7b00c19 100644
--- a/pkg/profiling/task/network/runner.go
+++ b/pkg/profiling/task/network/runner.go
@@ -107,6 +107,7 @@ func (r *Runner) Start(ctx context.Context, processes []api.ProcessInterface) er
 	r.bpfContext.StartSocketAddressParser(r.ctx)
 
 	// sock opts
+	r.linker.AddSysCall("close", objs.SysClose, objs.SysCloseRet)
 	r.linker.AddSysCall("connect", objs.SysConnect, objs.SysConnectRet)
 	r.linker.AddSysCall("accept", objs.SysAccept, objs.SysAcceptRet)
 	r.linker.AddSysCall("accept4", objs.SysAccept, objs.SysAcceptRet)
@@ -136,9 +137,6 @@ func (r *Runner) Start(ctx context.Context, processes []api.ProcessInterface) er
 	r.linker.AddLink(link.Kprobe, objs.TcpRetransmit, "tcp_retransmit_skb")
 	r.linker.AddLink(link.Kprobe, objs.TcpDrop, "tcp_drop")
 
-	// close socket
-	r.linker.AddSysCall("close", objs.SysClose, objs.SysCloseRet)
-
 	if err := r.linker.HasError(); err != nil {
 		_ = r.linker.Close()
 		return err
@@ -178,9 +176,10 @@ func (r *Runner) flushMetrics() error {
 
 	if log.Enable(logrus.DebugLevel) {
 		for _, con := range connections {
-			log.Debugf("found connection: %d, %s relation: %s:%d(%d) -> %s:%d, read: %d bytes/%d, write: %d bytes/%d",
+			log.Debugf("found connection: %d, %s relation: %s:%d(%d) -> %s:%d, protocol: %s, is_ssl: %t, read: %d bytes/%d, write: %d bytes/%d",
 				con.ConnectionID, con.Role.String(),
-				con.LocalIP, con.LocalPort, con.LocalPid, con.RemoteIP, con.RemotePort, con.WriteCounter.Cur.Bytes, con.WriteCounter.Cur.Count,
+				con.LocalIP, con.LocalPort, con.LocalPid, con.RemoteIP, con.RemotePort,
+				con.Protocol.String(), con.IsSSL, con.WriteCounter.Cur.Bytes, con.WriteCounter.Cur.Count,
 				con.ReadCounter.Cur.Bytes, con.ReadCounter.Cur.Count)
 		}
 	}
diff --git a/pkg/profiling/task/network/ssl.go b/pkg/profiling/task/network/ssl.go
index a69782b..aac49bf 100644
--- a/pkg/profiling/task/network/ssl.go
+++ b/pkg/profiling/task/network/ssl.go
@@ -50,6 +50,11 @@ func addSSLProcess(pid int, bpf *bpfObjects, linker *Linker) error {
 		return err1
 	}
 
+	// envoy with boring ssl
+	if err1 := processEnvoyProcess(pid, bpf, linker, modules); err1 != nil {
+		return err1
+	}
+
 	return nil
 }
 
@@ -90,6 +95,39 @@ func processOpenSSLProcess(pid int, bpf *bpfObjects, linker *Linker, modules []*
 	return linker.HasError()
 }
 
+func processEnvoyProcess(pid int, bpf *bpfObjects, linker *Linker, modules []*profiling.Module) error {
+	moduleName := "/envoy"
+	processModules, err := findProcessModules(modules, moduleName)
+	if err != nil {
+		return err
+	}
+	envoyModule := processModules[moduleName]
+	if envoyModule == nil {
+		return nil
+	}
+	var readSymbol, writeSymbol bool
+	for _, sym := range envoyModule.Symbols {
+		if sym.Name == "SSL_read" {
+			readSymbol = true
+		} else if sym.Name == "SSL_write" {
+			writeSymbol = true
+		}
+	}
+	if !readSymbol || !writeSymbol {
+		log.Debugf("found the envoy process, but the ssl read or write symbol not exists, so ignore. read: %t, write: %t",
+			readSymbol, writeSymbol)
+		return nil
+	}
+
+	log.Debugf("found current module is envoy, so attach to the SSL read and write")
+
+	// attach the linker
+	libSSLLinker := linker.OpenUProbeExeFile(envoyModule.Path)
+	libSSLLinker.AddLink("SSL_write", bpf.OpensslWrite, bpf.OpensslWriteRet, pid)
+	libSSLLinker.AddLink("SSL_read", bpf.OpensslRead, bpf.OpensslReadRet, pid)
+	return linker.HasError()
+}
+
 func findProcessModules(modules []*profiling.Module, moduleNames ...string) (map[string]*profiling.Module, error) {
 	result := make(map[string]*profiling.Module)
 	for _, mod := range modules {