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 2023/02/24 01:58:59 UTC

[skywalking-rover] branch main updated: Support monitoring TLS-based network data in continuous profiling (#79)

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 8252217  Support monitoring TLS-based network data in continuous profiling (#79)
8252217 is described below

commit 8252217ce94bf2f8cdc00fd7f708f04ae344449e
Author: mrproliu <74...@qq.com>
AuthorDate: Fri Feb 24 09:58:53 2023 +0800

    Support monitoring TLS-based network data in continuous profiling (#79)
---
 bpf/include/goid.c                                 |  70 +++
 .../network/go_tls.h => include/symbol_offsets.h}  | 146 +++--
 bpf/profiling/{network => continuous}/go_tls.c     | 106 ++--
 .../{network/openssl.h => continuous/go_tls.h}     |  25 +-
 bpf/profiling/continuous/network.c                 |  32 +-
 bpf/profiling/continuous/network.h                 |   2 +-
 bpf/profiling/continuous/openssl.c                 | 106 ++++
 bpf/profiling/{network => continuous}/openssl.h    |  20 +-
 bpf/profiling/network/go_tls.c                     |  46 +-
 bpf/profiling/network/go_tls.h                     | 104 +---
 bpf/profiling/network/netmonitor.c                 |   4 -
 bpf/profiling/network/openssl.c                    |   3 +-
 bpf/profiling/network/openssl.h                    |  18 -
 pkg/process/finders/base/tool.go                   |   4 +-
 .../continuous/checker/bpf/network/http1.go        |   2 +-
 .../continuous/checker/bpf/network/network.go      |  55 +-
 .../continuous/checker/bpf/network/process.go      |  82 +++
 .../continuous/checker/bpf/network/reader.go       |   2 +-
 .../continuous/checker/bpf/network/ssl.go          |  37 +-
 pkg/profiling/task/network/analyze/base/enums.go   |   7 -
 pkg/profiling/task/network/ssl.go                  | 595 +--------------------
 pkg/profiling/task/offcpu/runner.go                |  10 +-
 pkg/profiling/task/oncpu/runner.go                 |  10 +-
 pkg/tools/btf/linker.go                            |   4 +-
 pkg/tools/{ => process}/process.go                 |  10 +-
 pkg/tools/ssl/envoy.go                             |  75 +++
 pkg/tools/ssl/gotls.go                             | 258 +++++++++
 pkg/tools/ssl/node.go                              | 211 ++++++++
 pkg/tools/ssl/openssl.go                           | 141 +++++
 .../ssl_test.go => tools/ssl/openssl_test.go}      |  19 +-
 pkg/tools/ssl/ssl.go                               | 146 +++++
 31 files changed, 1335 insertions(+), 1015 deletions(-)

diff --git a/bpf/include/goid.c b/bpf/include/goid.c
new file mode 100644
index 0000000..80c0813
--- /dev/null
+++ b/bpf/include/goid.c
@@ -0,0 +1,70 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "symbol_offsets.h"
+
+struct {
+	__uint(type, BPF_MAP_TYPE_HASH);
+	__uint(max_entries, 1024);
+	__type(key, __u64);
+	__type(value, __u64);
+} go_tgid_goid_map SEC(".maps");
+static __inline __u64 get_goid(__u64 id) {
+    __u64 *val;
+    val = bpf_map_lookup_elem(&go_tgid_goid_map, &id);
+    return !val ? 0 : *val;
+}
+static __inline void set_goid(__u64 id, __u64 goid) {
+    bpf_map_update_elem(&go_tgid_goid_map, &id, &goid, 0);
+}
+
+SEC("uprobe/casgstatus")
+int go_casgstatus(struct pt_regs* ctx) {
+    const void* sp = (const void*)PT_REGS_SP(ctx);
+    __u64* regs = go_regabi_regs(ctx);
+    if (regs == NULL) {
+       return 0;
+    }
+
+    __u64 id = bpf_get_current_pid_tgid();
+    __u32 tgid = id >> 32;
+    struct go_tls_args_symaddr_t* symaddrs = get_go_tls_args_symaddr(tgid);
+    if (symaddrs == NULL) {
+       return 0;
+    }
+
+    // get runtime.g
+    void* gptr = NULL;
+    assign_go_tls_arg(&gptr, sizeof(gptr), symaddrs->casg_status_gp_loc, sp, regs);
+    if (gptr == NULL) {
+        return 0;
+    }
+
+    // get goid in runtime.g
+    int64_t goid;
+    bpf_probe_read(&goid, sizeof(goid), gptr + symaddrs->gid_offset);
+
+    // newval in runtime.g
+    __u32 status;
+    assign_go_tls_arg(&status, sizeof(status), symaddrs->casg_status_new_val_loc, sp, regs);
+
+    // check the status is running
+    if (status == 2) {
+        set_goid(id, goid);
+    }
+    return 0;
+}
\ No newline at end of file
diff --git a/bpf/profiling/network/go_tls.h b/bpf/include/symbol_offsets.h
similarity index 66%
copy from bpf/profiling/network/go_tls.h
copy to bpf/include/symbol_offsets.h
index 1428a4e..33b19ef 100644
--- a/bpf/profiling/network/go_tls.h
+++ b/bpf/include/symbol_offsets.h
@@ -15,61 +15,36 @@
 // specific language governing permissions and limitations
 // under the License.
 
-struct go_tls_arg_location_t {
-    __u32 type;
-    __u32 offset;
-};
-
-struct go_tls_args_symaddr_t {
-    __u64 fd_sys_offset;
-    __u64 tls_conn_offset;
-    __u64 gid_offset;
-    __u64 tcp_conn_offset;
-
-    // casg
-    struct go_tls_arg_location_t casg_status_gp_loc;
-    struct go_tls_arg_location_t casg_status_new_val_loc;
-
-    // read
-    struct go_tls_arg_location_t read_connection_loc;
-    struct go_tls_arg_location_t read_buffer_loc;
-    struct go_tls_arg_location_t read_ret0_loc;
-    struct go_tls_arg_location_t read_ret1_loc;
-
-    // write
-    struct go_tls_arg_location_t write_connection_loc;
-    struct go_tls_arg_location_t write_buffer_loc;
-    struct go_tls_arg_location_t write_ret0_loc;
-    struct go_tls_arg_location_t write_ret1_loc;
+#pragma once
+
+// ------------------------------------------ openssl start -------------------------------------------------------
+struct openssl_symaddr {
+    // read the BIO offset from ssl
+    __u32 bio_read_offset;
+    __u32 bio_write_offset;
+    // read the fd offset from BIO
+    __u32 fd_offset;
+    // read the SSL is server side or not
+    __u32 server_offset;
 };
 
 struct {
 	__uint(type, BPF_MAP_TYPE_HASH);
 	__uint(max_entries, 10000);
 	__type(key, __u32);
-	__type(value, struct go_tls_args_symaddr_t);
-} go_tls_args_symaddr_map SEC(".maps");
-static __always_inline struct go_tls_args_symaddr_t* get_go_tls_args_symaddr(__u32 tgid) {
-    struct go_tls_args_symaddr_t *addr = bpf_map_lookup_elem(&go_tls_args_symaddr_map, &tgid);
+	__type(value, struct openssl_symaddr);
+} openssl_symaddr_map SEC(".maps");
+static __inline struct openssl_symaddr* get_openssl_symaddr(__u32 tgid) {
+    struct openssl_symaddr *addr = bpf_map_lookup_elem(&openssl_symaddr_map, &tgid);
     return addr;
 }
+// ------------------------------------------ openssl end -------------------------------------------------------
 
-struct go_tls_tgid_goid_t {
-    __u64 tgid;
-    __u64 goid;
-};
-struct go_tls_connection_args_t {
-    void* connection_ptr;
-    char* buffer_ptr;
-    __u64 start_nacs;
+// ------------------------------------------ go tls start -------------------------------------------------------
+struct go_tls_arg_location_t {
+    __u32 type;
+    __u32 offset;
 };
-struct {
-	__uint(type, BPF_MAP_TYPE_HASH);
-	__uint(max_entries, 10000);
-	__type(key, struct go_tls_tgid_goid_t);
-	__type(value, struct go_tls_connection_args_t);
-} go_tls_active_connection_args SEC(".maps");
-
 
 struct go_regabi_regs_t {
     __u64 regs[9];
@@ -82,7 +57,7 @@ struct {
 } go_regabi_regs_map SEC(".maps");
 // Copies the registers of the golang ABI, so that they can be
 // easily accessed using an offset.
-static __always_inline uint64_t* go_regabi_regs(const struct pt_regs* ctx) {
+static __always_inline __u64* go_regabi_regs(const struct pt_regs* ctx) {
     __u32 zero = 0;
     struct go_regabi_regs_t* regs_heap_var = bpf_map_lookup_elem(&go_regabi_regs_map, &zero);
     if (regs_heap_var == NULL) {
@@ -102,13 +77,43 @@ static __always_inline uint64_t* go_regabi_regs(const struct pt_regs* ctx) {
     return regs_heap_var->regs;
 }
 
-struct go_interface {
-    int64_t type;
-    void* ptr;
+struct go_tls_args_symaddr_t {
+    __u64 fd_sys_offset;
+    __u64 tls_conn_offset;
+    __u64 gid_offset;
+    __u64 tcp_conn_offset;
+    __u64 is_client_offset;
+
+    // casg
+    struct go_tls_arg_location_t casg_status_gp_loc;
+    struct go_tls_arg_location_t casg_status_new_val_loc;
+
+    // read
+    struct go_tls_arg_location_t read_connection_loc;
+    struct go_tls_arg_location_t read_buffer_loc;
+    struct go_tls_arg_location_t read_ret0_loc;
+    struct go_tls_arg_location_t read_ret1_loc;
+
+    // write
+    struct go_tls_arg_location_t write_connection_loc;
+    struct go_tls_arg_location_t write_buffer_loc;
+    struct go_tls_arg_location_t write_ret0_loc;
+    struct go_tls_arg_location_t write_ret1_loc;
 };
 
+struct {
+	__uint(type, BPF_MAP_TYPE_HASH);
+	__uint(max_entries, 10000);
+	__type(key, __u32);
+	__type(value, struct go_tls_args_symaddr_t);
+} go_tls_args_symaddr_map SEC(".maps");
+static __always_inline struct go_tls_args_symaddr_t* get_go_tls_args_symaddr(__u32 tgid) {
+    struct go_tls_args_symaddr_t *addr = bpf_map_lookup_elem(&go_tls_args_symaddr_map, &tgid);
+    return addr;
+}
+
 static __always_inline void assign_go_tls_arg(void* arg, size_t arg_size, struct go_tls_arg_location_t loc, const void* sp,
-                                uint64_t* regs) {
+                                __u64* regs) {
     // stack type
     if (loc.type == 1) {
         bpf_probe_read(arg, arg_size, sp + loc.offset);
@@ -120,32 +125,25 @@ static __always_inline void assign_go_tls_arg(void* arg, size_t arg_size, struct
     }
 }
 
-static __always_inline int get_fd_from_go_tls_conn(struct go_interface conn, struct go_tls_args_symaddr_t* symaddr) {
-    // read connection
-    bpf_probe_read(&conn, sizeof(conn), conn.ptr + symaddr->tls_conn_offset);
-
-    if (conn.type != symaddr->tcp_conn_offset) {
-        return 0;
-    }
+struct go_interface {
+    int64_t type;
+    void* ptr;
+};
+// ------------------------------------------ go tls end -------------------------------------------------------
 
-    void* fd_ptr;
-    bpf_probe_read(&fd_ptr, sizeof(fd_ptr), conn.ptr);
-    __u64 sysfd;
-    bpf_probe_read(&sysfd, sizeof(sysfd), fd_ptr + symaddr->fd_sys_offset);
-    return sysfd;
-}
+// ------------------------------------------ envoy tls start -------------------------------------------------------
+struct envoy_tls_args_symaddr_t {
+    __u64 is_server_offset;
+};
 
 struct {
 	__uint(type, BPF_MAP_TYPE_HASH);
-	__uint(max_entries, 1024);
-	__type(key, __u64);
-	__type(value, __u64);
-} go_tgid_goid_map SEC(".maps");
-static __inline __u64 get_goid(__u64 tgid) {
-    __u64 *val;
-    val = bpf_map_lookup_elem(&go_tgid_goid_map, &tgid);
-    return !val ? 0 : *val;
+	__uint(max_entries, 10000);
+	__type(key, __u32);
+	__type(value, struct envoy_tls_args_symaddr_t);
+} envoy_tls_args_symaddr_map SEC(".maps");
+static __always_inline struct envoy_tls_args_symaddr_t* get_envoy_tls_args_symaddr(__u32 tgid) {
+    struct envoy_tls_args_symaddr_t *addr = bpf_map_lookup_elem(&envoy_tls_args_symaddr_map, &tgid);
+    return addr;
 }
-static __inline void set_goid(__u64 tgid, __u64 goid) {
-    bpf_map_update_elem(&go_tgid_goid_map, &tgid, &goid, 0);
-}
\ No newline at end of file
+// ------------------------------------------ envoy tls end -------------------------------------------------------
\ No newline at end of file
diff --git a/bpf/profiling/network/go_tls.c b/bpf/profiling/continuous/go_tls.c
similarity index 67%
copy from bpf/profiling/network/go_tls.c
copy to bpf/profiling/continuous/go_tls.c
index d7af96b..60ed538 100644
--- a/bpf/profiling/network/go_tls.c
+++ b/bpf/profiling/continuous/go_tls.c
@@ -16,49 +16,17 @@
 // under the License.
 
 #include "go_tls.h"
+#include "goid.c"
 
-SEC("uprobe/casgstatus")
-int go_casgstatus(struct pt_regs* ctx) {
-    const void* sp = (const void*)PT_REGS_SP(ctx);
-    uint64_t* regs = go_regabi_regs(ctx);
-    if (regs == NULL) {
-       return 0;
-    }
-
+SEC("uprobe/go_tls_write")
+int go_tls_write(struct pt_regs* ctx) {
     __u64 id = bpf_get_current_pid_tgid();
     __u32 tgid = id >> 32;
-    struct go_tls_args_symaddr_t* symaddrs = get_go_tls_args_symaddr(tgid);
-    if (symaddrs == NULL) {
-       return 0;
-    }
 
-    // get runtime.g
-    void* gptr = NULL;
-    assign_go_tls_arg(&gptr, sizeof(gptr), symaddrs->casg_status_gp_loc, sp, regs);
-    if (gptr == NULL) {
+    if (tgid_should_trace(tgid) == false) {
         return 0;
     }
 
-    // get goid in runtime.g
-    int64_t goid;
-    bpf_probe_read(&goid, sizeof(goid), gptr + symaddrs->gid_offset);
-
-    // newval in runtime.g
-    __u32 status;
-    assign_go_tls_arg(&status, sizeof(status), symaddrs->casg_status_new_val_loc, sp, regs);
-
-    // check the status is running
-    if (status == 2) {
-        set_goid(id, goid);
-    }
-    return 0;
-}
-
-SEC("uprobe/go_tls_write")
-int go_tls_write(struct pt_regs* ctx) {
-    __u64 id = bpf_get_current_pid_tgid();
-    __u32 tgid = id >> 32;
-
     __u64 goid = get_goid(id);
     if (goid == 0) {
         return 0;
@@ -70,17 +38,24 @@ int go_tls_write(struct pt_regs* ctx) {
     }
 
     const void* sp = (const void*)PT_REGS_SP(ctx);
-    uint64_t* regs = go_regabi_regs(ctx);
+    __u64* regs = go_regabi_regs(ctx);
     if (regs == NULL) {
         return 0;
     }
 
+    // ignore if the connection is client side
+    struct go_tls_connection_args_t data_args = {};
+    assign_go_tls_arg(&data_args.connection_ptr, sizeof(data_args.connection_ptr), symaddrs->write_connection_loc, sp, regs);
+    __u8 is_client;
+    bpf_probe_read(&is_client, sizeof(is_client), data_args.connection_ptr + symaddrs->is_client_offset);
+    if (is_client == 1) {
+        return 0;
+    }
+
     struct go_tls_tgid_goid_t tgid_goid = {};
     tgid_goid.tgid = tgid;
     tgid_goid.goid = goid;
 
-    struct go_tls_connection_args_t data_args = {};
-    assign_go_tls_arg(&data_args.connection_ptr, sizeof(data_args.connection_ptr), symaddrs->write_connection_loc, sp, regs);
     assign_go_tls_arg(&data_args.buffer_ptr, sizeof(data_args.buffer_ptr), symaddrs->write_buffer_loc, sp, regs);
     data_args.start_nacs = bpf_ktime_get_ns();
     bpf_map_update_elem(&go_tls_active_connection_args, &tgid_goid, &data_args, 0);
@@ -103,7 +78,7 @@ int go_tls_write_ret(struct pt_regs* ctx) {
     }
 
     const void* sp = (const void*)PT_REGS_SP(ctx);
-    uint64_t* regs = go_regabi_regs(ctx);
+    __u64* regs = go_regabi_regs(ctx);
     if (regs == NULL) {
         return 0;
     }
@@ -122,22 +97,10 @@ int go_tls_write_ret(struct pt_regs* ctx) {
 
     struct go_tls_connection_args_t *args = bpf_map_lookup_elem(&go_tls_active_connection_args, &tgid_goid);
     if (args) {
-        struct go_interface conn_intf = {};
-        conn_intf.type = 1;
-        conn_intf.ptr = args->connection_ptr;
-        int fd = get_fd_from_go_tls_conn(conn_intf, symaddrs);
-
-        set_conn_as_ssl(ctx, tgid, fd, SOCKET_OPTS_TYPE_GOTLS_WRITE);
-
-        struct sock_data_args_t data_args = {};
-        data_args.fd = fd;
-        data_args.buf = args->buffer_ptr;
-        data_args.start_nacs = args->start_nacs;
-        data_args.data_id = ssl_get_data_id(6, id, fd);
-
-        process_write_data(ctx, id, &data_args, retval0, SOCK_DATA_DIRECTION_EGRESS, false, SOCKET_OPTS_TYPE_GOTLS_WRITE, true);
+        process_data(ctx, id, args->connection_ptr, args->buffer_ptr, retval0, args->start_nacs);
     }
     bpf_map_delete_elem(&go_tls_active_connection_args, &tgid_goid);
+
     return 0;
 }
 
@@ -146,6 +109,10 @@ int go_tls_read(struct pt_regs* ctx) {
     __u64 id = bpf_get_current_pid_tgid();
     __u32 tgid = id >> 32;
 
+    if (tgid_should_trace(tgid) == false) {
+        return 0;
+    }
+
     __u64 goid = get_goid(id);
     if (goid == 0) {
         return 0;
@@ -157,19 +124,25 @@ int go_tls_read(struct pt_regs* ctx) {
     }
 
     const void* sp = (const void*)PT_REGS_SP(ctx);
-    uint64_t* regs = go_regabi_regs(ctx);
+    __u64* regs = go_regabi_regs(ctx);
     if (regs == NULL) {
         return 0;
     }
 
+    // ignore if the connection is client side
+    struct go_tls_connection_args_t data_args = {};
+    assign_go_tls_arg(&data_args.connection_ptr, sizeof(data_args.connection_ptr), symaddrs->write_connection_loc, sp, regs);
+    __u8 is_client;
+    bpf_probe_read(&is_client, sizeof(is_client), data_args.connection_ptr + symaddrs->is_client_offset);
+    if (is_client == 1) {
+        return 0;
+    }
+
     struct go_tls_tgid_goid_t tgid_goid = {};
     tgid_goid.tgid = tgid;
     tgid_goid.goid = goid;
 
-    struct go_tls_connection_args_t data_args = {};
-    assign_go_tls_arg(&data_args.connection_ptr, sizeof(data_args.connection_ptr), symaddrs->read_connection_loc, sp, regs);
     assign_go_tls_arg(&data_args.buffer_ptr, sizeof(data_args.buffer_ptr), symaddrs->read_buffer_loc, sp, regs);
-    data_args.start_nacs = bpf_ktime_get_ns();
     bpf_map_update_elem(&go_tls_active_connection_args, &tgid_goid, &data_args, 0);
     return 0;
 }
@@ -190,7 +163,7 @@ int go_tls_read_ret(struct pt_regs* ctx) {
     }
 
     const void* sp = (const void*)PT_REGS_SP(ctx);
-    uint64_t* regs = go_regabi_regs(ctx);
+    __u64* regs = go_regabi_regs(ctx);
     if (regs == NULL) {
         return 0;
     }
@@ -209,20 +182,7 @@ int go_tls_read_ret(struct pt_regs* ctx) {
 
     struct go_tls_connection_args_t *args = bpf_map_lookup_elem(&go_tls_active_connection_args, &tgid_goid);
     if (args) {
-        struct go_interface conn_intf = {};
-        conn_intf.type = 1;
-        conn_intf.ptr = args->connection_ptr;
-        int fd = get_fd_from_go_tls_conn(conn_intf, symaddrs);
-
-        set_conn_as_ssl(ctx, tgid, fd, SOCKET_OPTS_TYPE_GOTLS_READ);
-
-        struct sock_data_args_t data_args = {};
-        data_args.fd = fd;
-        data_args.buf = args->buffer_ptr;
-        data_args.start_nacs = args->start_nacs;
-        data_args.data_id = ssl_get_data_id(8, id, fd);
-
-        process_write_data(ctx, id, &data_args, retval0, SOCK_DATA_DIRECTION_INGRESS, false, SOCKET_OPTS_TYPE_GOTLS_WRITE, true);
+        process_data(ctx, id, args->connection_ptr, args->buffer_ptr, retval0, bpf_ktime_get_ns());
     }
     bpf_map_delete_elem(&go_tls_active_connection_args, &tgid_goid);
     return 0;
diff --git a/bpf/profiling/network/openssl.h b/bpf/profiling/continuous/go_tls.h
similarity index 65%
copy from bpf/profiling/network/openssl.h
copy to bpf/profiling/continuous/go_tls.h
index 61e8425..43d3bff 100644
--- a/bpf/profiling/network/openssl.h
+++ b/bpf/profiling/continuous/go_tls.h
@@ -15,21 +15,18 @@
 // specific language governing permissions and limitations
 // under the License.
 
-struct openssl_fd_symaddr {
-    // read the BIO offset from ssl
-    __u32 bio_read_offset;
-    __u32 bio_write_offset;
-    // read the fd offset from BIO
-    __u32 fd_offset;
+struct go_tls_tgid_goid_t {
+    __u64 tgid;
+    __u64 goid;
+};
+struct go_tls_connection_args_t {
+    void* connection_ptr;
+    char* buffer_ptr;
+    __u64 start_nacs;
 };
-
 struct {
 	__uint(type, BPF_MAP_TYPE_HASH);
 	__uint(max_entries, 10000);
-	__type(key, __u32);
-	__type(value, struct openssl_fd_symaddr);
-} openssl_fd_symaddr_finder SEC(".maps");
-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;
-}
+	__type(key, struct go_tls_tgid_goid_t);
+	__type(value, struct go_tls_connection_args_t);
+} go_tls_active_connection_args SEC(".maps");
\ No newline at end of file
diff --git a/bpf/profiling/continuous/network.c b/bpf/profiling/continuous/network.c
index cd0a603..c37bdfc 100644
--- a/bpf/profiling/continuous/network.c
+++ b/bpf/profiling/continuous/network.c
@@ -53,13 +53,7 @@ static __always_inline bool socket_should_trace(__u64 id, struct sock *sock) {
     return true;
 }
 
-static __always_inline void process_data(struct pt_regs *ctx, __u64 id, void *channel_ref, struct msghdr *msg) {
-    const struct iovec *iovec;
-    iovec = _KERNEL(msg->msg_iter.iov);
-    struct iovec iov;
-    bpf_probe_read(&iov, sizeof(iov), iovec);
-    char* buf = (char *)iov.iov_base;
-    __u64 size = iov.iov_len;
+static __always_inline void process_data(struct pt_regs *ctx, __u64 id, void *channel_ref, char *buf, __u64 size, __u64 timestamp) {
     if (size <= 0) {
         return;
     }
@@ -72,12 +66,12 @@ static __always_inline void process_data(struct pt_regs *ctx, __u64 id, void *ch
     if (reader == NULL) {
         return;
     }
-    asm volatile("%[size] &= 0x9f;\n" ::[size] "+r"(size) :);
+    asm volatile("%[size] &= 0xff;\n" ::[size] "+r"(size) :);
     bpf_probe_read(&reader->buffer, size & MAX_PROTOCOL_SOCKET_READ_LENGTH, buf);
     __u8 protocol;
     __u32 direction = analyze_protocol(reader->buffer, size & MAX_PROTOCOL_SOCKET_READ_LENGTH, &protocol);
     if (protocol != CONNECTION_PROTOCOL_UNKNOWN) {
-        reader->timestamp = bpf_ktime_get_ns();
+        reader->timestamp = timestamp;
         reader->channel_ref = channel_ref;
         reader->pid = (__u32)(id >> 32);
         reader->protocol = protocol;
@@ -87,6 +81,17 @@ static __always_inline void process_data(struct pt_regs *ctx, __u64 id, void *ch
     }
 }
 
+static __always_inline void process_msghdr_data(struct pt_regs *ctx, __u64 id, void *channel_ref, struct msghdr *msg) {
+    const struct iovec *iovec;
+    iovec = _KERNEL(msg->msg_iter.iov);
+    struct iovec iov;
+    bpf_probe_read(&iov, sizeof(iov), iovec);
+    char* buf = (char *)iov.iov_base;
+    __u64 size = iov.iov_len;
+
+    return process_data(ctx, id, channel_ref, buf, size, bpf_ktime_get_ns());
+}
+
 SEC("kprobe/tcp_sendmsg")
 int tcp_sendmsg(struct pt_regs *ctx) {
     __u64 id = bpf_get_current_pid_tgid();
@@ -96,7 +101,7 @@ int tcp_sendmsg(struct pt_regs *ctx) {
     }
 
     struct msghdr *msg = (void *)PT_REGS_PARM2(ctx);
-    process_data(ctx, id, s, msg);
+    process_msghdr_data(ctx, id, s, msg);
     return 0;
 }
 
@@ -122,8 +127,11 @@ int ret_tcp_recvmsg(struct pt_regs *ctx) {
     struct recv_msg_args *args = bpf_map_lookup_elem(&receiving_args, &id);
     int bytes_count = PT_REGS_RC(ctx);
     if (args != NULL && bytes_count > 0) {
-        process_data(ctx, id, args->sock, args->msg);
+        process_msghdr_data(ctx, id, args->sock, args->msg);
     }
     bpf_map_delete_elem(&receiving_args, &id);
     return 0;
-}
\ No newline at end of file
+}
+
+#include "openssl.c"
+#include "go_tls.c"
diff --git a/bpf/profiling/continuous/network.h b/bpf/profiling/continuous/network.h
index b8c4dd3..461b037 100644
--- a/bpf/profiling/continuous/network.h
+++ b/bpf/profiling/continuous/network.h
@@ -18,7 +18,7 @@
 #include "api.h"
 #include "skb.h"
 
-#define MAX_PROTOCOL_SOCKET_READ_LENGTH 158
+#define MAX_PROTOCOL_SOCKET_READ_LENGTH 255
 
 struct {
 	__uint(type, BPF_MAP_TYPE_HASH);
diff --git a/bpf/profiling/continuous/openssl.c b/bpf/profiling/continuous/openssl.c
new file mode 100644
index 0000000..fe24eef
--- /dev/null
+++ b/bpf/profiling/continuous/openssl.c
@@ -0,0 +1,106 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "symbol_offsets.h"
+#include "openssl.h"
+
+static __always_inline bool openssl_should_trace(__u64 id, void *ssl) {
+    // check the pid is monitoring
+    __u32 tgid = (__u32)(id >> 32);
+    if (tgid_should_trace(tgid) == false) {
+        return false;
+    }
+
+    // check the socket if server side
+    struct openssl_symaddr* addr = get_openssl_symaddr(tgid);
+    if (addr != NULL) {
+        int is_server;
+        bpf_probe_read(&is_server, sizeof(is_server), ssl + addr->server_offset);
+        if (is_server == 1) {
+            return true;
+        }
+        return false;
+    }
+    struct envoy_tls_args_symaddr_t *envoy_addr = get_envoy_tls_args_symaddr(tgid);
+    if (envoy_addr != NULL) {
+        __u8 is_server_from_nginx;
+        bpf_probe_read(&is_server_from_nginx, sizeof(is_server_from_nginx), ssl + envoy_addr->is_server_offset);
+        if (is_server_from_nginx == 1) {
+            return true;
+        }
+        return false;
+    }
+
+    // could not check is server or client, just ignore it
+    return false;
+}
+
+SEC("uprobe/ssl_write")
+int openssl_write(struct pt_regs* ctx) {
+    __u64 id = bpf_get_current_pid_tgid();
+    void* ssl = (void*)PT_REGS_PARM1(ctx);
+    if (openssl_should_trace(id, ssl) == false) {
+        return 0;
+    }
+    char* buf = (char*)PT_REGS_PARM2(ctx);
+
+    struct openssl_args args = {};
+    args.ssl = ssl;
+    args.buf = buf;
+    args.timestamp = bpf_ktime_get_ns();
+    bpf_map_update_elem(&openssl_args_map, &id, &args, 0);
+    return 0;
+}
+
+SEC("uretprobe/ssl_write")
+int openssl_write_ret(struct pt_regs* ctx) {
+    __u64 id = bpf_get_current_pid_tgid();
+    struct openssl_args *args = bpf_map_lookup_elem(&openssl_args_map, &id);
+    int bytes_count = PT_REGS_RC(ctx);
+    if (args && bytes_count > 0) {
+        process_data(ctx, id, args->ssl, args->buf, bytes_count, args->timestamp);
+    }
+    bpf_map_delete_elem(&openssl_args_map, &id);
+    return 0;
+}
+
+SEC("uprobe/ssl_read")
+int openssl_read(struct pt_regs* ctx) {
+    __u64 id = bpf_get_current_pid_tgid();
+    void* ssl = (void*)PT_REGS_PARM1(ctx);
+    if (openssl_should_trace(id, ssl) == false) {
+        return 0;
+    }
+    char* buf = (char*)PT_REGS_PARM2(ctx);
+    struct openssl_args args = {};
+    args.ssl = ssl;
+    args.buf = buf;
+    bpf_map_update_elem(&openssl_args_map, &id, &args, 0);
+    return 0;
+}
+
+SEC("uretprobe/ssl_read")
+int openssl_read_ret(struct pt_regs* ctx) {
+    __u64 id = bpf_get_current_pid_tgid();
+    struct openssl_args *args = bpf_map_lookup_elem(&openssl_args_map, &id);
+    int bytes_count = PT_REGS_RC(ctx);
+    if (args && bytes_count > 0) {
+        process_data(ctx, id, args->ssl, args->buf, bytes_count, bpf_ktime_get_ns());
+    }
+    bpf_map_delete_elem(&openssl_args_map, &id);
+    return 0;
+}
\ No newline at end of file
diff --git a/bpf/profiling/network/openssl.h b/bpf/profiling/continuous/openssl.h
similarity index 65%
copy from bpf/profiling/network/openssl.h
copy to bpf/profiling/continuous/openssl.h
index 61e8425..ee0ef84 100644
--- a/bpf/profiling/network/openssl.h
+++ b/bpf/profiling/continuous/openssl.h
@@ -15,21 +15,15 @@
 // specific language governing permissions and limitations
 // under the License.
 
-struct openssl_fd_symaddr {
-    // read the BIO offset from ssl
-    __u32 bio_read_offset;
-    __u32 bio_write_offset;
-    // read the fd offset from BIO
-    __u32 fd_offset;
+struct openssl_args {
+    void* ssl;
+    char* buf;
+    __u64 timestamp;
 };
 
 struct {
 	__uint(type, BPF_MAP_TYPE_HASH);
 	__uint(max_entries, 10000);
-	__type(key, __u32);
-	__type(value, struct openssl_fd_symaddr);
-} openssl_fd_symaddr_finder SEC(".maps");
-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;
-}
+	__type(key, __u64);
+	__type(value, struct openssl_args);
+} openssl_args_map SEC(".maps");
diff --git a/bpf/profiling/network/go_tls.c b/bpf/profiling/network/go_tls.c
index d7af96b..3fde4a5 100644
--- a/bpf/profiling/network/go_tls.c
+++ b/bpf/profiling/network/go_tls.c
@@ -16,43 +16,7 @@
 // under the License.
 
 #include "go_tls.h"
-
-SEC("uprobe/casgstatus")
-int go_casgstatus(struct pt_regs* ctx) {
-    const void* sp = (const void*)PT_REGS_SP(ctx);
-    uint64_t* regs = go_regabi_regs(ctx);
-    if (regs == NULL) {
-       return 0;
-    }
-
-    __u64 id = bpf_get_current_pid_tgid();
-    __u32 tgid = id >> 32;
-    struct go_tls_args_symaddr_t* symaddrs = get_go_tls_args_symaddr(tgid);
-    if (symaddrs == NULL) {
-       return 0;
-    }
-
-    // get runtime.g
-    void* gptr = NULL;
-    assign_go_tls_arg(&gptr, sizeof(gptr), symaddrs->casg_status_gp_loc, sp, regs);
-    if (gptr == NULL) {
-        return 0;
-    }
-
-    // get goid in runtime.g
-    int64_t goid;
-    bpf_probe_read(&goid, sizeof(goid), gptr + symaddrs->gid_offset);
-
-    // newval in runtime.g
-    __u32 status;
-    assign_go_tls_arg(&status, sizeof(status), symaddrs->casg_status_new_val_loc, sp, regs);
-
-    // check the status is running
-    if (status == 2) {
-        set_goid(id, goid);
-    }
-    return 0;
-}
+#include "goid.c"
 
 SEC("uprobe/go_tls_write")
 int go_tls_write(struct pt_regs* ctx) {
@@ -70,7 +34,7 @@ int go_tls_write(struct pt_regs* ctx) {
     }
 
     const void* sp = (const void*)PT_REGS_SP(ctx);
-    uint64_t* regs = go_regabi_regs(ctx);
+    __u64* regs = go_regabi_regs(ctx);
     if (regs == NULL) {
         return 0;
     }
@@ -103,7 +67,7 @@ int go_tls_write_ret(struct pt_regs* ctx) {
     }
 
     const void* sp = (const void*)PT_REGS_SP(ctx);
-    uint64_t* regs = go_regabi_regs(ctx);
+    __u64* regs = go_regabi_regs(ctx);
     if (regs == NULL) {
         return 0;
     }
@@ -157,7 +121,7 @@ int go_tls_read(struct pt_regs* ctx) {
     }
 
     const void* sp = (const void*)PT_REGS_SP(ctx);
-    uint64_t* regs = go_regabi_regs(ctx);
+    __u64* regs = go_regabi_regs(ctx);
     if (regs == NULL) {
         return 0;
     }
@@ -190,7 +154,7 @@ int go_tls_read_ret(struct pt_regs* ctx) {
     }
 
     const void* sp = (const void*)PT_REGS_SP(ctx);
-    uint64_t* regs = go_regabi_regs(ctx);
+    __u64* regs = go_regabi_regs(ctx);
     if (regs == NULL) {
         return 0;
     }
diff --git a/bpf/profiling/network/go_tls.h b/bpf/profiling/network/go_tls.h
index 1428a4e..1057ef9 100644
--- a/bpf/profiling/network/go_tls.h
+++ b/bpf/profiling/network/go_tls.h
@@ -15,44 +15,7 @@
 // specific language governing permissions and limitations
 // under the License.
 
-struct go_tls_arg_location_t {
-    __u32 type;
-    __u32 offset;
-};
-
-struct go_tls_args_symaddr_t {
-    __u64 fd_sys_offset;
-    __u64 tls_conn_offset;
-    __u64 gid_offset;
-    __u64 tcp_conn_offset;
-
-    // casg
-    struct go_tls_arg_location_t casg_status_gp_loc;
-    struct go_tls_arg_location_t casg_status_new_val_loc;
-
-    // read
-    struct go_tls_arg_location_t read_connection_loc;
-    struct go_tls_arg_location_t read_buffer_loc;
-    struct go_tls_arg_location_t read_ret0_loc;
-    struct go_tls_arg_location_t read_ret1_loc;
-
-    // write
-    struct go_tls_arg_location_t write_connection_loc;
-    struct go_tls_arg_location_t write_buffer_loc;
-    struct go_tls_arg_location_t write_ret0_loc;
-    struct go_tls_arg_location_t write_ret1_loc;
-};
-
-struct {
-	__uint(type, BPF_MAP_TYPE_HASH);
-	__uint(max_entries, 10000);
-	__type(key, __u32);
-	__type(value, struct go_tls_args_symaddr_t);
-} go_tls_args_symaddr_map SEC(".maps");
-static __always_inline struct go_tls_args_symaddr_t* get_go_tls_args_symaddr(__u32 tgid) {
-    struct go_tls_args_symaddr_t *addr = bpf_map_lookup_elem(&go_tls_args_symaddr_map, &tgid);
-    return addr;
-}
+#include "symbol_offsets.h"
 
 struct go_tls_tgid_goid_t {
     __u64 tgid;
@@ -70,56 +33,6 @@ struct {
 	__type(value, struct go_tls_connection_args_t);
 } go_tls_active_connection_args SEC(".maps");
 
-
-struct go_regabi_regs_t {
-    __u64 regs[9];
-};
-struct {
-    __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
-    __type(key, __u32);
-    __type(value, struct go_regabi_regs_t);
-    __uint(max_entries, 1);
-} go_regabi_regs_map SEC(".maps");
-// Copies the registers of the golang ABI, so that they can be
-// easily accessed using an offset.
-static __always_inline uint64_t* go_regabi_regs(const struct pt_regs* ctx) {
-    __u32 zero = 0;
-    struct go_regabi_regs_t* regs_heap_var = bpf_map_lookup_elem(&go_regabi_regs_map, &zero);
-    if (regs_heap_var == NULL) {
-        return NULL;
-    }
-
-    regs_heap_var->regs[0] = ctx->rax;
-    regs_heap_var->regs[1] = ctx->rbx;
-    regs_heap_var->regs[2] = ctx->rcx;
-    regs_heap_var->regs[3] = ctx->rdi;
-    regs_heap_var->regs[4] = ctx->rsi;
-    regs_heap_var->regs[5] = ctx->r8;
-    regs_heap_var->regs[6] = ctx->r9;
-    regs_heap_var->regs[7] = ctx->r10;
-    regs_heap_var->regs[8] = ctx->r11;
-
-    return regs_heap_var->regs;
-}
-
-struct go_interface {
-    int64_t type;
-    void* ptr;
-};
-
-static __always_inline void assign_go_tls_arg(void* arg, size_t arg_size, struct go_tls_arg_location_t loc, const void* sp,
-                                uint64_t* regs) {
-    // stack type
-    if (loc.type == 1) {
-        bpf_probe_read(arg, arg_size, sp + loc.offset);
-    } else if (loc.type == 2) {
-        // register type
-        if (loc.offset >= 0 && loc.offset <= 30) {
-            bpf_probe_read(arg, arg_size, (char*)regs + loc.offset);
-        }
-    }
-}
-
 static __always_inline int get_fd_from_go_tls_conn(struct go_interface conn, struct go_tls_args_symaddr_t* symaddr) {
     // read connection
     bpf_probe_read(&conn, sizeof(conn), conn.ptr + symaddr->tls_conn_offset);
@@ -133,19 +46,4 @@ static __always_inline int get_fd_from_go_tls_conn(struct go_interface conn, str
     __u64 sysfd;
     bpf_probe_read(&sysfd, sizeof(sysfd), fd_ptr + symaddr->fd_sys_offset);
     return sysfd;
-}
-
-struct {
-	__uint(type, BPF_MAP_TYPE_HASH);
-	__uint(max_entries, 1024);
-	__type(key, __u64);
-	__type(value, __u64);
-} go_tgid_goid_map SEC(".maps");
-static __inline __u64 get_goid(__u64 tgid) {
-    __u64 *val;
-    val = bpf_map_lookup_elem(&go_tgid_goid_map, &tgid);
-    return !val ? 0 : *val;
-}
-static __inline void set_goid(__u64 tgid, __u64 goid) {
-    bpf_map_update_elem(&go_tgid_goid_map, &tgid, &goid, 0);
 }
\ No newline at end of file
diff --git a/bpf/profiling/network/netmonitor.c b/bpf/profiling/network/netmonitor.c
index 13abc00..1636cea 100644
--- a/bpf/profiling/network/netmonitor.c
+++ b/bpf/profiling/network/netmonitor.c
@@ -108,10 +108,6 @@ static __always_inline void submit_new_connection(struct pt_regs* ctx, __u32 fun
         con.socket_family = AF_UNKNOWN;
     }
 
-    if (con.remote_port == 53) {
-        bpf_printk("found the remote port is 53");
-    }
-
     // save to the active connection map
     __u64 conid = gen_tgid_fd(tgid, fd);
     struct socket_connect_event_t *event = create_socket_connect_event();
diff --git a/bpf/profiling/network/openssl.c b/bpf/profiling/network/openssl.c
index 0db64e0..ef09f73 100644
--- a/bpf/profiling/network/openssl.c
+++ b/bpf/profiling/network/openssl.c
@@ -16,6 +16,7 @@
 // under the License.
 
 #include "args.h"
+#include "symbol_offsets.h"
 #include "openssl.h"
 #include "node_tls.h"
 
@@ -36,7 +37,7 @@ static __inline void process_openssl_data(struct pt_regs* ctx, __u64 id, __u32 d
 }
 
 static int get_fd_symaddr(__u32 tgid, bool read, void* ssl) {
-    struct openssl_fd_symaddr* addr = get_openssl_fd_symaddr(tgid);
+    struct openssl_symaddr* addr = get_openssl_symaddr(tgid);
     if (addr == NULL) {
         return -1;
     }
diff --git a/bpf/profiling/network/openssl.h b/bpf/profiling/network/openssl.h
index 61e8425..3fa197d 100644
--- a/bpf/profiling/network/openssl.h
+++ b/bpf/profiling/network/openssl.h
@@ -15,21 +15,3 @@
 // specific language governing permissions and limitations
 // under the License.
 
-struct openssl_fd_symaddr {
-    // read the BIO offset from ssl
-    __u32 bio_read_offset;
-    __u32 bio_write_offset;
-    // read the fd offset from BIO
-    __u32 fd_offset;
-};
-
-struct {
-	__uint(type, BPF_MAP_TYPE_HASH);
-	__uint(max_entries, 10000);
-	__type(key, __u32);
-	__type(value, struct openssl_fd_symaddr);
-} openssl_fd_symaddr_finder SEC(".maps");
-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;
-}
diff --git a/pkg/process/finders/base/tool.go b/pkg/process/finders/base/tool.go
index 408693c..749d4f6 100644
--- a/pkg/process/finders/base/tool.go
+++ b/pkg/process/finders/base/tool.go
@@ -25,9 +25,9 @@ import (
 	v3 "skywalking.apache.org/repo/goapi/collect/ebpf/profiling/process/v3"
 
 	"github.com/apache/skywalking-rover/pkg/process/api"
-	"github.com/apache/skywalking-rover/pkg/tools"
 	"github.com/apache/skywalking-rover/pkg/tools/host"
 	"github.com/apache/skywalking-rover/pkg/tools/path"
+	process_tool "github.com/apache/skywalking-rover/pkg/tools/process"
 	"github.com/apache/skywalking-rover/pkg/tools/profiling"
 
 	"github.com/shirou/gopsutil/process"
@@ -41,7 +41,7 @@ func BuildProfilingStat(ps *process.Process) (*profiling.Info, error) {
 	}
 
 	// check support profiling
-	return tools.ProcessProfilingStat(ps.Pid, exePath)
+	return process_tool.ProfilingStat(ps.Pid, exePath)
 }
 
 func tryToFindFileExecutePath(ps *process.Process) string {
diff --git a/pkg/profiling/continuous/checker/bpf/network/http1.go b/pkg/profiling/continuous/checker/bpf/network/http1.go
index 77ba21e..2a91647 100644
--- a/pkg/profiling/continuous/checker/bpf/network/http1.go
+++ b/pkg/profiling/continuous/checker/bpf/network/http1.go
@@ -66,7 +66,7 @@ func (h *HTTP1Analyzer) HandleBufferEvent(buffer *networkBufferInBPF) BufferEven
 		return nil
 	}
 	// clean the request buffer
-	h.channelEvents[buffer.ChannelRef] = nil
+	delete(h.channelEvents, buffer.ChannelRef)
 
 	code, err := h.analyzeResponseStatus(buffer)
 	if err != nil {
diff --git a/pkg/profiling/continuous/checker/bpf/network/network.go b/pkg/profiling/continuous/checker/bpf/network/network.go
index 4bcda76..26bdded 100644
--- a/pkg/profiling/continuous/checker/bpf/network/network.go
+++ b/pkg/profiling/continuous/checker/bpf/network/network.go
@@ -18,6 +18,7 @@
 package network
 
 import (
+	"os"
 	"sync"
 	"time"
 
@@ -39,11 +40,11 @@ var log = logger.GetLogger("profiling", "continuous", "checker", "network", "bpf
 var locker sync.Mutex
 var bpf *bpfObjects
 var bpfLinker *btf.Linker
-var monitoringProcesses map[int32]map[string]bool
+var monitoringProcesses map[int32]*monitoringProcessInfo
 var notifiers []EventNotify
 
 func init() {
-	monitoringProcesses = make(map[int32]map[string]bool)
+	monitoringProcesses = make(map[int32]*monitoringProcessInfo)
 }
 
 type BufferEvent interface {
@@ -69,21 +70,21 @@ func AddWatchProcess(pid int32, from string) error {
 		return e
 	}
 
-	// first, update to the monitor control
-	if e := bpf.ProcessMonitorControl.Update(uint32(pid), uint32(1), ebpf.UpdateAny); e != nil {
-		// if add failure, then check the BPF should be shutdown or not
-		_ = shutdownBPFIfNoProcesses()
-		return e
-	}
-
-	// then, add to the monitoring cache
+	// adding to the cache
 	monitoring := monitoringProcesses[pid]
 	if monitoring == nil {
-		monitoring = make(map[string]bool)
+		monitoring = newMonitoringProcessInfo(pid)
 		monitoringProcesses[pid] = monitoring
 	}
 
-	monitoring[from] = true
+	// start monitoring process
+	if e := monitoring.AddSource(from); e != nil {
+		// remove the source if add failure
+		if deleteProcess, _ := monitoring.RemoveSource(from); deleteProcess {
+			delete(monitoringProcesses, pid)
+		}
+		return e
+	}
 	return nil
 }
 
@@ -100,23 +101,27 @@ func RemoveWatchProcess(pid int32, from string) error {
 		return nil
 	}
 
-	delete(monitoring, from)
-	shouldRemoveMonitor := false
-	if len(monitoringProcesses[pid]) == 0 {
+	deleteProcess, err := monitoring.RemoveSource(from)
+	if deleteProcess {
 		delete(monitoringProcesses, pid)
-		shouldRemoveMonitor = true
-	}
-
-	if shouldRemoveMonitor {
-		if err := bpf.ProcessMonitorControl.Delete(uint32(pid)); err != nil {
-			return err
-		}
 	}
-	return nil
+	return err
 }
 
 func ForceShutdownBPF() error {
-	return shutdownBPF()
+	// shutdown all processes
+	var err error
+	for _, p := range monitoringProcesses {
+		if e := p.Shutdown(); e != nil {
+			err = multierror.Append(err, e)
+		}
+	}
+	// shutdown the main BPF
+	monitoringProcesses = make(map[int32]*monitoringProcessInfo)
+	if e := shutdownBPF(); e != nil {
+		err = multierror.Append(err, e)
+	}
+	return err
 }
 
 // start the BPF program if contains process that needs monitor
@@ -142,7 +147,7 @@ func startBPFIfNeed() error {
 			n.ReceiveBufferEvent(event)
 		}
 	})
-	bpfLinker.ReadEventAsync(bpf.SocketBufferSendQueue, reader.Read, reader.BufferDataBPFSupplier)
+	bpfLinker.ReadEventAsyncWithBufferSize(bpf.SocketBufferSendQueue, reader.Read, os.Getpagesize()*100, reader.BufferDataBPFSupplier)
 
 	if err := bpfLinker.HasError(); err != nil {
 		_ = bpfLinker.Close()
diff --git a/pkg/profiling/continuous/checker/bpf/network/process.go b/pkg/profiling/continuous/checker/bpf/network/process.go
new file mode 100644
index 0000000..f2447bc
--- /dev/null
+++ b/pkg/profiling/continuous/checker/bpf/network/process.go
@@ -0,0 +1,82 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package network
+
+import (
+	"github.com/cilium/ebpf"
+
+	"github.com/apache/skywalking-rover/pkg/tools/btf"
+
+	"github.com/hashicorp/go-multierror"
+)
+
+type monitoringProcessInfo struct {
+	pid    int32
+	linker *btf.Linker
+	source map[string]bool
+}
+
+func newMonitoringProcessInfo(pid int32) *monitoringProcessInfo {
+	return &monitoringProcessInfo{
+		pid:    pid,
+		linker: btf.NewLinker(),
+		source: make(map[string]bool),
+	}
+}
+
+func (m *monitoringProcessInfo) AddSource(from string) error {
+	// if already have source, then just added
+	if len(m.source) != 0 {
+		m.source[from] = true
+	}
+
+	// start the TLS first
+	if err := addSSLProcess(int(m.pid), m.linker, bpf); err != nil {
+		return err
+	}
+
+	// add to the process control
+	if e := bpf.ProcessMonitorControl.Update(uint32(m.pid), uint32(1), ebpf.UpdateAny); e != nil {
+		return e
+	}
+	m.source[from] = true
+	return nil
+}
+
+func (m *monitoringProcessInfo) RemoveSource(from string) (bool, error) {
+	delete(m.source, from)
+
+	// if still have source monitoring, then just ignore to shut down process monitoring
+	if len(m.source) > 0 {
+		return false, nil
+	}
+
+	var err error
+	if e := m.linker.Close(); e != nil {
+		err = multierror.Append(err, e)
+	}
+	if e := bpf.ProcessMonitorControl.Delete(uint32(m.pid)); e != nil {
+		err = multierror.Append(err, e)
+	}
+
+	return true, err
+}
+
+func (m *monitoringProcessInfo) Shutdown() error {
+	return m.linker.Close()
+}
diff --git a/pkg/profiling/continuous/checker/bpf/network/reader.go b/pkg/profiling/continuous/checker/bpf/network/reader.go
index 7530e5c..c5893f0 100644
--- a/pkg/profiling/continuous/checker/bpf/network/reader.go
+++ b/pkg/profiling/continuous/checker/bpf/network/reader.go
@@ -42,7 +42,7 @@ type networkBufferInBPF struct {
 	Direction  BufferDirection
 	Size       uint16
 	Pid        uint32
-	Buffer     [159]byte
+	Buffer     [256]byte
 }
 
 type networkBufferReader struct {
diff --git a/bpf/profiling/network/openssl.h b/pkg/profiling/continuous/checker/bpf/network/ssl.go
similarity index 51%
copy from bpf/profiling/network/openssl.h
copy to pkg/profiling/continuous/checker/bpf/network/ssl.go
index 61e8425..50261f4 100644
--- a/bpf/profiling/network/openssl.h
+++ b/pkg/profiling/continuous/checker/bpf/network/ssl.go
@@ -15,21 +15,24 @@
 // specific language governing permissions and limitations
 // under the License.
 
-struct openssl_fd_symaddr {
-    // read the BIO offset from ssl
-    __u32 bio_read_offset;
-    __u32 bio_write_offset;
-    // read the fd offset from BIO
-    __u32 fd_offset;
-};
-
-struct {
-	__uint(type, BPF_MAP_TYPE_HASH);
-	__uint(max_entries, 10000);
-	__type(key, __u32);
-	__type(value, struct openssl_fd_symaddr);
-} openssl_fd_symaddr_finder SEC(".maps");
-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;
+package network
+
+import (
+	"github.com/apache/skywalking-rover/pkg/tools/btf"
+	"github.com/apache/skywalking-rover/pkg/tools/ssl"
+)
+
+func addSSLProcess(pid int, linker *btf.Linker, bpf *bpfObjects) error {
+	register := ssl.NewSSLRegister(pid, linker)
+
+	register.OpenSSL(bpf.OpensslSymaddrMap, bpf.OpensslWrite, bpf.OpensslWriteRet, bpf.OpensslRead, bpf.OpensslReadRet)
+
+	register.Envoy(bpf.EnvoyTlsArgsSymaddrMap, bpf.OpensslWrite, bpf.OpensslWriteRet, bpf.OpensslRead, bpf.OpensslReadRet)
+
+	register.GoTLS(bpf.GoTlsArgsSymaddrMap, bpf.GoCasgstatus, bpf.GoTlsWrite, bpf.GoTlsWriteRet, bpf.GoTlsRead, bpf.GoTlsReadRet)
+
+	register.Node(bpf.OpensslSymaddrMap, nil, bpf.OpensslWrite, bpf.OpensslWriteRet, bpf.OpensslRead, bpf.OpensslReadRet,
+		nil, nil, nil)
+
+	return register.Execute()
 }
diff --git a/pkg/profiling/task/network/analyze/base/enums.go b/pkg/profiling/task/network/analyze/base/enums.go
index ad4aa60..04173dc 100644
--- a/pkg/profiling/task/network/analyze/base/enums.go
+++ b/pkg/profiling/task/network/analyze/base/enums.go
@@ -111,13 +111,6 @@ func (c ConnectionProtocol) String() string {
 	}
 }
 
-type GoTLSArgsLocationType uint32
-
-const (
-	GoTLSArgsLocationTypeStack    GoTLSArgsLocationType = 1
-	GoTLSArgsLocationTypeRegister GoTLSArgsLocationType = 2
-)
-
 type SocketMessageType uint8
 
 const (
diff --git a/pkg/profiling/task/network/ssl.go b/pkg/profiling/task/network/ssl.go
index 5591d53..d3fd33e 100644
--- a/pkg/profiling/task/network/ssl.go
+++ b/pkg/profiling/task/network/ssl.go
@@ -18,600 +18,21 @@
 package network
 
 import (
-	"bytes"
-	"encoding/binary"
-	"fmt"
-	"os/exec"
-	"regexp"
-	"strconv"
-	"strings"
-
-	"github.com/apache/skywalking-rover/pkg/profiling/task/network/analyze/base"
 	"github.com/apache/skywalking-rover/pkg/profiling/task/network/bpf"
-	"github.com/apache/skywalking-rover/pkg/tools"
-	"github.com/apache/skywalking-rover/pkg/tools/btf"
-	"github.com/apache/skywalking-rover/pkg/tools/elf"
-	"github.com/apache/skywalking-rover/pkg/tools/host"
-	"github.com/apache/skywalking-rover/pkg/tools/path"
-	"github.com/apache/skywalking-rover/pkg/tools/profiling"
-	"github.com/apache/skywalking-rover/pkg/tools/version"
-)
-
-var (
-	openSSLVersionRegex  = regexp.MustCompile(`^OpenSSL\s+(?P<Major>\d)\.(?P<Minor>\d)\.(?P<Fix>\d+)\w?\s+`)
-	goVersionRegex       = regexp.MustCompile(`^go(?P<Major>\d)\.(?P<Minor>\d+)`)
-	goTLSWriteSymbol     = "crypto/tls.(*Conn).Write"
-	goTLSReadSymbol      = "crypto/tls.(*Conn).Read"
-	goTLSGIDStatusSymbol = "runtime.casgstatus"
-	goTLSPollFDSymbol    = "internal/poll.FD"
-	goTLSConnSymbol      = "crypto/tls.Conn"
-	goTLSRuntimeG        = "runtime.g"
-	nodeVersionRegex     = regexp.MustCompile(`^node\.js/v(?P<Major>\d+)\.(?P<Minor>\d+)\.(?P<Patch>\d+)$`)
+	"github.com/apache/skywalking-rover/pkg/tools/ssl"
 )
 
-type OpenSSLFdSymAddrConfigInBPF struct {
-	BIOReadOffset  uint32
-	BIOWriteOffset uint32
-	FDOffset       uint32
-}
-
 func addSSLProcess(pid int, loader *bpf.Loader) error {
-	modules, err := tools.ProcessModules(int32(pid))
-	if err != nil {
-		return fmt.Errorf("read process modules error: %d, error: %v", pid, err)
-	}
-
-	// openssl process
-	if err1 := processOpenSSLProcess(pid, loader, modules); err1 != nil {
-		return err1
-	}
-
-	// envoy with boring ssl
-	if err1 := processEnvoyProcess(pid, loader, modules); err1 != nil {
-		return err1
-	}
-
-	// GoTLS
-	if err1 := processGoProcess(pid, loader, modules); err1 != nil {
-		return err1
-	}
-
-	// Nodejs
-	if err1 := processNodeProcess(pid, loader, modules); err1 != nil {
-		return err1
-	}
-
-	return nil
-}
-
-func processOpenSSLProcess(pid int, loader *bpf.Loader, modules []*profiling.Module) error {
-	var libcryptoName, libsslName = "libcrypto.so", "libssl.so"
-	var libcryptoPath, libsslPath string
-	processModules, err := findProcessModules(modules, libcryptoName, libsslName)
-	if err != nil {
-		return err
-	}
-	// the openssl not exists, so ignore
-	if len(processModules) == 0 {
-		return nil
-	}
-	if libcrypto := processModules[libcryptoName]; libcrypto != nil {
-		libcryptoPath = libcrypto.Path
-	}
-	if libssl := processModules[libsslName]; libssl != nil {
-		libsslPath = libssl.Path
-	}
-	if libcryptoPath == "" || libsslPath == "" {
-		return fmt.Errorf("the OpenSSL library not complete, libcrypto: %s, libssl: %s", libcryptoPath, libsslPath)
-	}
-
-	// build the symbol address config and write to the bpf
-	conf, err := buildSSLSymAddrConfig(libcryptoPath)
-	if err != nil {
-		return err
-	}
-	if err := loader.OpensslFdSymaddrFinder.Put(uint32(pid), conf); err != nil {
-		return err
-	}
-
-	// attach the linker
-	return processOpenSSLModule(loader, processModules[libsslName])
-}
-
-func processOpenSSLModule(loader *bpf.Loader, libSSLModule *profiling.Module) error {
-	libSSLLinker := loader.OpenUProbeExeFile(libSSLModule.Path)
-	libSSLLinker.AddLink("SSL_write", loader.OpensslWrite, loader.OpensslWriteRet)
-	libSSLLinker.AddLink("SSL_read", loader.OpensslRead, loader.OpensslReadRet)
-	return loader.HasError()
-}
-
-func processEnvoyProcess(_ int, loader *bpf.Loader, 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 := loader.OpenUProbeExeFile(envoyModule.Path)
-	libSSLLinker.AddLink("SSL_write", loader.OpensslWrite, loader.OpensslWriteRet)
-	libSSLLinker.AddLink("SSL_read", loader.OpensslRead, loader.OpensslReadRet)
-	return loader.HasError()
-}
-
-type SymbolLocation struct {
-	Type   base.GoTLSArgsLocationType
-	Offset uint32
-}
-
-type GoTLSSymbolAddresses struct {
-	// net.Conn addresses
-	FDSysFDOffset uint64
-	TLSConnOffset uint64
-	GIDOffset     uint64
-	TCPConnOffset uint64
-
-	// casgstatus(goroutine status change) function relate locations
-	CasgStatusGPLoc     SymbolLocation
-	CasgStatusNEWValLoc SymbolLocation
-
-	// write function relate locations
-	WriteConnectionLoc SymbolLocation
-	WriteBufferLoc     SymbolLocation
-	WriteRet0Loc       SymbolLocation
-	WriteRet1Loc       SymbolLocation
-
-	// write function relate locations
-	ReadConnectionLoc SymbolLocation
-	ReadBufferLoc     SymbolLocation
-	ReadRet0Loc       SymbolLocation
-	ReadRet1Loc       SymbolLocation
-}
-
-type GoStringInC struct {
-	Ptr  uint64
-	Size uint64
-}
+	register := ssl.NewSSLRegister(pid, loader.Linker)
 
-func processGoProcess(pid int, loader *bpf.Loader, modules []*profiling.Module) error {
-	// check current process is go program
-	buildVersionSymbol := searchSymbol(modules, func(a, b string) bool {
-		return a == b
-	}, "runtime.buildVersion")
-	if buildVersionSymbol == nil {
-		log.Debugf("current process is not Go program, so won't add the GoTLS protos. pid: %d", pid)
-		return nil
-	}
-	pidExeFile := host.GetFileInHost(fmt.Sprintf("/proc/%d/exe", pid))
-	elfFile, err := elf.NewFile(pidExeFile)
-	if err != nil {
-		return fmt.Errorf("read executable file error: %v", err)
-	}
-	defer elfFile.Close()
+	register.OpenSSL(loader.OpensslSymaddrMap, loader.OpensslWrite, loader.OpensslWriteRet, loader.OpensslRead, loader.OpensslReadRet)
 
-	v, err := getGoVersion(elfFile, buildVersionSymbol)
-	if err != nil {
-		return err
-	}
+	register.Envoy(nil, loader.OpensslWrite, loader.OpensslWriteRet, loader.OpensslRead, loader.OpensslReadRet)
 
-	// generate symbol offsets
-	symbolConfig, elfFile, err := generateGOTLSSymbolOffsets(modules, pid, elfFile, v)
-	if err != nil {
-		return err
-	}
-	if symbolConfig == nil || elfFile == nil {
-		return nil
-	}
-
-	// setting the locations
-	if err := loader.GoTlsArgsSymaddrMap.Put(uint32(pid), symbolConfig); err != nil {
-		return fmt.Errorf("setting the Go TLS argument location failure, pid: %d, error: %v", pid, err)
-	}
-
-	// uprobes
-	exeFile := loader.OpenUProbeExeFile(pidExeFile)
-	exeFile.AddLinkWithType("runtime.casgstatus", true, loader.GoCasgstatus)
-	exeFile.AddGoLink(goTLSWriteSymbol, loader.GoTlsWrite, loader.GoTlsWriteRet, elfFile)
-	exeFile.AddGoLink(goTLSReadSymbol, loader.GoTlsRead, loader.GoTlsReadRet, elfFile)
-
-	return loader.HasError()
-}
-
-func processNodeProcess(pid int, loader *bpf.Loader, modules []*profiling.Module) error {
-	moduleName1, moduleName2, libsslName := "/nodejs", "/node", "libssl.so"
-	processModules, err := findProcessModules(modules, moduleName1, moduleName2, libsslName)
-	if err != nil {
-		return err
-	}
-	nodeModule := processModules[moduleName1]
-	libsslModule := processModules[libsslName]
-	needsReAttachSSL := false
-	if nodeModule == nil {
-		nodeModule = processModules[moduleName2]
-	}
-	if nodeModule == nil {
-		log.Debugf("current process is not nodejs program, so won't add the nodejs protos. pid: %d", pid)
-		return nil
-	}
-	if libsslModule == nil {
-		if searchSymbol([]*profiling.Module{nodeModule}, func(a, b string) bool {
-			return a == b
-		}, "SSL_read") == nil || searchSymbol([]*profiling.Module{nodeModule}, func(a, b string) bool {
-			return a == b
-		}, "SSL_write") == nil {
-			log.Warnf("could not found the SSL_read/SSL_write under the nodejs program, so ignore. pid: %d", pid)
-			return nil
-		}
-		libsslModule = nodeModule
-		needsReAttachSSL = true
-	}
-	v, err := getNodeVersion(nodeModule.Path)
-	if err != nil {
-		return fmt.Errorf("read nodejs version failure, pid: %d, error: %v", pid, err)
-	}
-	log.Debugf("read the nodejs version, pid: %d, version: %s", pid, v)
-	config, err := findNodeTLSAddrConfig(v)
-	if err != nil {
-		return err
-	}
-	// setting the locations
-	if err := loader.NodeTlsSymaddrMap.Put(uint32(pid), config); err != nil {
-		return fmt.Errorf("setting the node TLS location failure, pid: %d, error: %v", pid, err)
-	}
-	// register node tls
-	if err := registerNodeTLSProbes(v, loader, nodeModule, libsslModule); err != nil {
-		return fmt.Errorf("register node TLS probes failure, pid: %d, error: %v", pid, err)
-	}
-	// attach the OpenSSL Probe if needs
-	if needsReAttachSSL {
-		return processOpenSSLModule(loader, libsslModule)
-	}
-	return nil
-}
-
-var nodeTLSAddrWithVersions = []struct {
-	v    *version.Version
-	conf *NodeTLSAddrInBPF
-}{
-	{version.Build(10, 19, 0), &NodeTLSAddrInBPF{0x0130, 0x08, 0x00, 0x50, 0x90, 0x88, 0x30}},
-	{version.Build(12, 3, 1), &NodeTLSAddrInBPF{0x0130, 0x08, 0x00, 0x50, 0x90, 0x88, 0x30}},
-	{version.Build(12, 16, 2), &NodeTLSAddrInBPF{0x0138, 0x08, 0x00, 0x58, 0x98, 0x88, 0x30}},
-	{version.Build(13, 0, 0), &NodeTLSAddrInBPF{0x0130, 0x08, 0x00, 0x50, 0x90, 0x88, 0x30}},
-	{version.Build(13, 2, 0), &NodeTLSAddrInBPF{0x0130, 0x08, 0x00, 0x58, 0x98, 0x88, 0x30}},
-	{version.Build(13, 10, 1), &NodeTLSAddrInBPF{0x0140, 0x08, 0x00, 0x60, 0xa0, 0x88, 0x30}},
-	{version.Build(14, 5, 0), &NodeTLSAddrInBPF{0x138, 0x08, 0x00, 0x58, 0x98, 0x88, 0x30}},
-	{version.Build(15, 0, 0), &NodeTLSAddrInBPF{0x78, 0x08, 0x00, 0x58, 0x98, 0x88, 0x30}},
-}
-
-var nodeTLSProbeWithVersions = []struct {
-	v *version.Version
-	f func(uprobe *btf.UProbeExeFile, bpf *bpf.Loader, nodeModule *profiling.Module)
-}{
-	{version.Build(10, 19, 0), func(uprobe *btf.UProbeExeFile, bpf *bpf.Loader, nodeModule *profiling.Module) {
-		uprobe.AddLinkWithSymbols(searchSymbolNames([]*profiling.Module{nodeModule}, strings.HasPrefix, "_ZN4node7TLSWrapC2E"),
-			bpf.NodeTlsWrap, bpf.NodeTlsWrapRet)
-		uprobe.AddLinkWithSymbols(searchSymbolNames([]*profiling.Module{nodeModule}, strings.HasPrefix, "_ZN4node7TLSWrap7ClearInE"),
-			bpf.NodeTlsWrap, bpf.NodeTlsWrapRet)
-		uprobe.AddLinkWithSymbols(searchSymbolNames([]*profiling.Module{nodeModule}, strings.HasPrefix, "_ZN4node7TLSWrap8ClearOutE"),
-			bpf.NodeTlsWrap, bpf.NodeTlsWrapRet)
-	}},
-	{version.Build(15, 0, 0), func(uprobe *btf.UProbeExeFile, bpf *bpf.Loader, nodeModule *profiling.Module) {
-		uprobe.AddLinkWithSymbols(searchSymbolNames([]*profiling.Module{nodeModule}, strings.HasPrefix, "_ZN4node6crypto7TLSWrapC2E"),
-			bpf.NodeTlsWrap, bpf.NodeTlsWrapRet)
-		uprobe.AddLinkWithSymbols(searchSymbolNames([]*profiling.Module{nodeModule}, strings.HasPrefix, "_ZN4node6crypto7TLSWrap7ClearInE"),
-			bpf.NodeTlsWrap, bpf.NodeTlsWrapRet)
-		uprobe.AddLinkWithSymbols(searchSymbolNames([]*profiling.Module{nodeModule}, strings.HasPrefix, "_ZN4node6crypto7TLSWrap8ClearOutE"),
-			bpf.NodeTlsWrap, bpf.NodeTlsWrapRet)
-	}},
-}
+	register.GoTLS(loader.GoTlsArgsSymaddrMap, loader.GoCasgstatus, loader.GoTlsWrite, loader.GoTlsWriteRet, loader.GoTlsRead, loader.GoTlsReadRet)
 
-type NodeTLSAddrInBPF struct {
-	TLSWrapStreamListenerOffset     uint32
-	StreamListenerStreamOffset      uint32
-	StreamBaseStreamResourceOffset  uint32
-	LibuvStreamWrapStreamBaseOffset uint32
-	LibuvStreamWrapStreamOffset     uint32
-	UVStreamSIOWatcherOffset        uint32
-	UVIOSFDOffset                   uint32
-}
-
-func findNodeTLSAddrConfig(v *version.Version) (*NodeTLSAddrInBPF, error) {
-	var lastest *NodeTLSAddrInBPF
-	for _, c := range nodeTLSAddrWithVersions {
-		if v.GreaterOrEquals(c.v) {
-			lastest = c.conf
-		}
-	}
-	if lastest != nil {
-		return lastest, nil
-	}
-	return nil, fmt.Errorf("could not support version: %s", v)
-}
-
-func registerNodeTLSProbes(v *version.Version, loader *bpf.Loader, nodeModule, libSSLModule *profiling.Module) error {
-	var probeFunc func(uprobe *btf.UProbeExeFile, bpf *bpf.Loader, nodeModule *profiling.Module)
-	for _, c := range nodeTLSProbeWithVersions {
-		if v.GreaterOrEquals(c.v) {
-			probeFunc = c.f
-		}
-	}
-	if probeFunc == nil {
-		return fmt.Errorf("the version is not support: %v", v)
-	}
-	file := loader.OpenUProbeExeFile(nodeModule.Path)
-	probeFunc(file, loader, nodeModule)
-
-	// find the SSL_new, and register
-	file = loader.OpenUProbeExeFile(libSSLModule.Path)
-	file.AddLinkWithType("SSL_new", false, loader.NodeTlsRetSsl)
-	return loader.HasError()
-}
-
-func getNodeVersion(p string) (*version.Version, error) {
-	result, err := exec.Command("strings", p).Output()
-	if err != nil {
-		return nil, err
-	}
-	for _, d := range strings.Split(string(result), "\n") {
-		versionInfo := nodeVersionRegex.FindStringSubmatch(strings.TrimSpace(d))
-		if len(versionInfo) != 4 {
-			continue
-		}
-		return version.Read(versionInfo[1], versionInfo[2], versionInfo[3])
-	}
-
-	return nil, fmt.Errorf("nodejs version is not found")
-}
-
-func getGoVersion(elfFile *elf.File, versionSymbol *profiling.Symbol) (*version.Version, error) {
-	buffer, err := elfFile.ReadSymbolData(".data", versionSymbol.Location, versionSymbol.Size)
-	if err != nil {
-		return nil, fmt.Errorf("reading go version struct info failure: %v", err)
-	}
-	var t = GoStringInC{}
-	buf := bytes.NewReader(buffer)
-	err = binary.Read(buf, binary.LittleEndian, &t)
-	if err != nil {
-		return nil, fmt.Errorf("read the go structure failure: %v", err)
-	}
-	buffer, err = elfFile.ReadSymbolData(".data", t.Ptr, t.Size)
-	if err != nil {
-		return nil, fmt.Errorf("read the go version failure: %v", err)
-	}
-
-	// parse versions
-	submatch := goVersionRegex.FindStringSubmatch(string(buffer))
-	if len(submatch) != 3 {
-		return nil, fmt.Errorf("the go version is failure to identify, version: %s", string(buffer))
-	}
-	return version.Read(submatch[1], submatch[2], "")
-}
-
-func generateGOTLSSymbolOffsets(modules []*profiling.Module, _ int, elfFile *elf.File, v *version.Version) (*GoTLSSymbolAddresses, *elf.File, error) {
-	reader, err := elfFile.NewDwarfReader(
-		goTLSReadSymbol, goTLSWriteSymbol, goTLSGIDStatusSymbol,
-		goTLSPollFDSymbol, goTLSConnSymbol, goTLSRuntimeG)
-	if err != nil {
-		return nil, nil, err
-	}
-
-	symbolAddresses := &GoTLSSymbolAddresses{}
-
-	sym := searchSymbol(modules, func(a, b string) bool {
-		return a == b
-	}, "go.itab.*net.TCPConn,net.Conn")
-	if sym == nil {
-		log.Warnf("could not found the tcp connection symbol: go.itab.*net.TCPConn,net.Conn")
-		return nil, nil, nil
-	}
-	symbolAddresses.TCPConnOffset = sym.Location
-
-	readFunction := reader.GetFunction(goTLSReadSymbol)
-	if readFunction == nil {
-		log.Warnf("could not found the go tls read symbol: %s", goTLSReadSymbol)
-		return nil, nil, nil
-	}
-	writeFunction := reader.GetFunction(goTLSWriteSymbol)
-	if writeFunction == nil {
-		log.Warnf("could not found the go tls write symbol: %s", goTLSWriteSymbol)
-		return nil, nil, nil
-	}
-	gidStatusFunction := reader.GetFunction(goTLSGIDStatusSymbol)
-	if gidStatusFunction == nil {
-		log.Warnf("could not found the goid status change symbol: %s", goTLSGIDStatusSymbol)
-		return nil, nil, nil
-	}
-
-	var retValArg0, retValArg1 = "~r1", "~r2"
-	if v.Minor >= 18 {
-		retValArg0, retValArg1 = "~r0", "~r1"
-	}
-
-	// build the symbols
-	var assignError error
-	// offset
-	assignError = assignGoTLSStructureOffset(assignError, reader, goTLSPollFDSymbol, "Sysfd", &symbolAddresses.FDSysFDOffset)
-	assignError = assignGoTLSStructureOffset(assignError, reader, goTLSConnSymbol, "conn", &symbolAddresses.TLSConnOffset)
-	assignError = assignGoTLSStructureOffset(assignError, reader, goTLSRuntimeG, "goid", &symbolAddresses.GIDOffset)
-
-	// gid status change
-	assignError = assignGoTLSArgsLocation(assignError, gidStatusFunction, "gp", &symbolAddresses.CasgStatusGPLoc)
-	assignError = assignGoTLSArgsLocation(assignError, gidStatusFunction, "newval", &symbolAddresses.CasgStatusNEWValLoc)
-
-	// write
-	assignError = assignGoTLSArgsLocation(assignError, writeFunction, "c", &symbolAddresses.WriteConnectionLoc)
-	assignError = assignGoTLSArgsLocation(assignError, writeFunction, "b", &symbolAddresses.WriteBufferLoc)
-	assignError = assignGoTLSArgsLocation(assignError, writeFunction, retValArg0, &symbolAddresses.WriteRet0Loc)
-	assignError = assignGoTLSArgsLocation(assignError, writeFunction, retValArg1, &symbolAddresses.WriteRet1Loc)
-	// read
-	assignError = assignGoTLSArgsLocation(assignError, readFunction, "c", &symbolAddresses.ReadConnectionLoc)
-	assignError = assignGoTLSArgsLocation(assignError, readFunction, "b", &symbolAddresses.ReadBufferLoc)
-	assignError = assignGoTLSArgsLocation(assignError, readFunction, retValArg0, &symbolAddresses.ReadRet0Loc)
-	assignError = assignGoTLSArgsLocation(assignError, readFunction, retValArg1, &symbolAddresses.ReadRet1Loc)
-
-	return symbolAddresses, elfFile, assignError
-}
-
-func assignGoTLSStructureOffset(err error, reader *elf.DwarfReader, structName, fieldName string, dest *uint64) error {
-	if err != nil {
-		return err
-	}
-	structure := reader.GetStructure(structName)
-	if structure == nil {
-		return fmt.Errorf("the structure is not found, name: %s", structName)
-	}
-	field := structure.GetField(fieldName)
-	if field == nil {
-		return fmt.Errorf("the field is not found in structure, structure name: %s, field name: %s", structName, fieldName)
-	}
-	*dest = uint64(field.Offset)
-	return nil
-}
-
-func assignGoTLSArgsLocation(err error, function *elf.FunctionInfo, argName string, dest *SymbolLocation) error {
-	if err != nil {
-		return err
-	}
-	var kSPOffset uint32 = 8
-	args := function.Args(argName)
-	if args == nil {
-		return fmt.Errorf("the args is not found, function: %s, args name: %s", function.Name(), argName)
-	}
-	if args.Location.Type == elf.ArgLocationTypeStack {
-		dest.Type = base.GoTLSArgsLocationTypeStack
-		dest.Offset = uint32(args.Location.Offset) + kSPOffset
-	} else if args.Location.Type == elf.ArgLocationTypeRegister {
-		dest.Type = base.GoTLSArgsLocationTypeRegister
-		dest.Offset = uint32(args.Location.Offset)
-	} else {
-		return fmt.Errorf("the location type is not support, function: %s, args name: %s, type: %d",
-			function.Name(), argName, args.Location.Type)
-	}
-	return nil
-}
-
-func findProcessModules(modules []*profiling.Module, moduleNames ...string) (map[string]*profiling.Module, error) {
-	result := make(map[string]*profiling.Module)
-	for _, mod := range modules {
-		for _, modName := range moduleNames {
-			if strings.Contains(mod.Name, modName) {
-				if !path.Exists(mod.Path) {
-					return nil, fmt.Errorf("the module path not exists, path: %s", mod.Path)
-				}
-				result[modName] = mod
-			}
-		}
-	}
-	return result, nil
-}
-
-func buildSSLSymAddrConfig(libcryptoPath string) (*OpenSSLFdSymAddrConfigInBPF, error) {
-	// using "strings" command to query the symbol in the libcrypto library
-	result, err := exec.Command("strings", libcryptoPath).Output()
-	if err != nil {
-		return nil, err
-	}
-	for _, p := range strings.Split(string(result), "\n") {
-		submatch := openSSLVersionRegex.FindStringSubmatch(p)
-		if len(submatch) != 4 {
-			continue
-		}
-		major := submatch[1]
-		minor := submatch[2]
-		fix := submatch[3]
-
-		log.Debugf("found the libcrypto.so version: %s.%s.%s", major, minor, fix)
-		conf := &OpenSSLFdSymAddrConfigInBPF{}
-
-		// must be number, already validate in the regex
-		majorVal, _ := strconv.Atoi(major)
-		minorVal, _ := strconv.Atoi(minor)
-		fixVal, _ := strconv.Atoi(fix)
-
-		// max support version is 3.0.x
-		if majorVal > 3 || (majorVal == 3 && minorVal > 0) {
-			return nil, fmt.Errorf("the version of the libcrypto is not support: %s.%s.%s", major, minor, fix)
-		}
-
-		// bio offset
-		// https://github.com/openssl/openssl/blob/OpenSSL_1_0_0-stable/ssl/ssl.h#L1093-L1111
-		// https://github.com/openssl/openssl/blob/OpenSSL_1_1_1-stable/ssl/ssl_local.h#L1068-L1083
-		// https://github.com/openssl/openssl/blob/openssl-3.0.7/ssl/ssl_local.h#L1212-L1227
-		conf.BIOReadOffset = 16
-		conf.BIOWriteOffset = 24
-		// fd offset
-		if majorVal == 3 && minorVal == 0 {
-			// 3.0.x
-			// https://github.com/openssl/openssl/blob/openssl-3.0.7/crypto/bio/bio_local.h#L115-L128
-			// OPENSSL_NO_DEPRECATED_3_0 is not defined by default unless the user pass the specific build option
-			conf.FDOffset = 56
-		} else if (minorVal == 0) || (minorVal == 1 && fixVal == 0) {
-			// 1.0.x || 1.1.0
-			// https://github.com/openssl/openssl/blob/OpenSSL_1_0_0-stable/crypto/bio/bio.h#L297-L306
-			conf.FDOffset = 40
-		} else {
-			// 1.1.1
-			// https://github.com/openssl/openssl/blob/OpenSSL_1_1_1-stable/crypto/bio/bio_local.h#L115-L125
-			conf.FDOffset = 48
-		}
-		log.Debugf("the lobcrypto.so library symbol verson config, version: %s.%s.%s, bio offset: %d",
-			major, minor, fix, conf.FDOffset)
-		return conf, nil
-	}
-	return nil, fmt.Errorf("could not fount the version of the libcrypto.so")
-}
-
-type stringVerify func(a, b string) bool
-
-func searchSymbolNames(modules []*profiling.Module, verify stringVerify, values ...string) []string {
-	list := searchSymbolList(modules, verify, values...)
-	if len(list) > 0 {
-		result := make([]string, 0)
-		for _, i := range list {
-			result = append(result, i.Name)
-		}
-		return result
-	}
-	return nil
-}
-
-func searchSymbol(modules []*profiling.Module, verify stringVerify, values ...string) *profiling.Symbol {
-	list := searchSymbolList(modules, verify, values...)
-	if len(list) > 0 {
-		return list[0]
-	}
-	return nil
-}
+	register.Node(nil, loader.NodeTlsSymaddrMap, loader.OpensslWrite, loader.OpensslWriteRet, loader.OpensslRead, loader.OpensslReadRet,
+		loader.NodeTlsRetSsl, loader.NodeTlsWrap, loader.NodeTlsWrapRet)
 
-func searchSymbolList(modules []*profiling.Module, verify stringVerify, values ...string) []*profiling.Symbol {
-	var result []*profiling.Symbol
-	for _, mod := range modules {
-		for _, s := range mod.Symbols {
-			for _, validator := range values {
-				if verify(s.Name, validator) {
-					result = append(result, s)
-				}
-			}
-		}
-	}
-	return result
+	return register.Execute()
 }
diff --git a/pkg/profiling/task/offcpu/runner.go b/pkg/profiling/task/offcpu/runner.go
index 149747e..9c8c7e9 100644
--- a/pkg/profiling/task/offcpu/runner.go
+++ b/pkg/profiling/task/offcpu/runner.go
@@ -32,8 +32,8 @@ import (
 	"github.com/apache/skywalking-rover/pkg/module"
 	"github.com/apache/skywalking-rover/pkg/process/api"
 	"github.com/apache/skywalking-rover/pkg/profiling/task/base"
-	"github.com/apache/skywalking-rover/pkg/tools"
 	"github.com/apache/skywalking-rover/pkg/tools/btf"
+	"github.com/apache/skywalking-rover/pkg/tools/process"
 	"github.com/apache/skywalking-rover/pkg/tools/profiling"
 
 	v3 "skywalking.apache.org/repo/goapi/collect/ebpf/profiling/v3"
@@ -80,10 +80,10 @@ func (r *Runner) Init(task *base.ProfilingTask, processes []api.ProcessInterface
 	if len(processes) != 1 {
 		return fmt.Errorf("the processes count must be 1, current is: %d", len(processes))
 	}
-	process := processes[0]
-	r.pid = process.Pid()
-	r.processProfiling = process.ProfilingStat()
-	kernelProfiling, err := tools.KernelFileProfilingStat()
+	curProcess := processes[0]
+	r.pid = curProcess.Pid()
+	r.processProfiling = curProcess.ProfilingStat()
+	kernelProfiling, err := process.KernelFileProfilingStat()
 	if err != nil {
 		log.Warnf("could not analyze kernel profiling stats: %v", err)
 	}
diff --git a/pkg/profiling/task/oncpu/runner.go b/pkg/profiling/task/oncpu/runner.go
index b346372..01287f6 100644
--- a/pkg/profiling/task/oncpu/runner.go
+++ b/pkg/profiling/task/oncpu/runner.go
@@ -31,7 +31,7 @@ import (
 	"github.com/apache/skywalking-rover/pkg/module"
 	"github.com/apache/skywalking-rover/pkg/process/api"
 	"github.com/apache/skywalking-rover/pkg/profiling/task/base"
-	"github.com/apache/skywalking-rover/pkg/tools"
+	"github.com/apache/skywalking-rover/pkg/tools/process"
 	"github.com/apache/skywalking-rover/pkg/tools/profiling"
 
 	"golang.org/x/sys/unix"
@@ -86,14 +86,14 @@ func (r *Runner) Init(task *base.ProfilingTask, processes []api.ProcessInterface
 	if len(processes) != 1 {
 		return fmt.Errorf("the processes count must be 1, current is: %d", len(processes))
 	}
-	process := processes[0]
-	r.pid = process.Pid()
+	curProcess := processes[0]
+	r.pid = curProcess.Pid()
 	// process profiling stat
-	if r.processProfiling = process.ProfilingStat(); r.processProfiling == nil {
+	if r.processProfiling = curProcess.ProfilingStat(); r.processProfiling == nil {
 		return fmt.Errorf("this process could not be profiling")
 	}
 	// kernel profiling stat
-	kernelProfiling, err := tools.KernelFileProfilingStat()
+	kernelProfiling, err := process.KernelFileProfilingStat()
 	if err != nil {
 		log.Warnf("could not analyze kernel profiling stats: %v", err)
 	}
diff --git a/pkg/tools/btf/linker.go b/pkg/tools/btf/linker.go
index 8c80726..d08242a 100644
--- a/pkg/tools/btf/linker.go
+++ b/pkg/tools/btf/linker.go
@@ -28,8 +28,8 @@ import (
 
 	"golang.org/x/arch/x86/x86asm"
 
-	"github.com/apache/skywalking-rover/pkg/tools"
 	"github.com/apache/skywalking-rover/pkg/tools/elf"
+	"github.com/apache/skywalking-rover/pkg/tools/process"
 
 	"github.com/cilium/ebpf"
 	"github.com/cilium/ebpf/link"
@@ -46,7 +46,7 @@ type RingBufferReader func(data interface{})
 var syscallPrefix string
 
 func init() {
-	stat, err := tools.KernelFileProfilingStat()
+	stat, err := process.KernelFileProfilingStat()
 	if err != nil {
 		syscallPrefix = defaultSymbolPrefix
 		return
diff --git a/pkg/tools/process.go b/pkg/tools/process/process.go
similarity index 94%
rename from pkg/tools/process.go
rename to pkg/tools/process/process.go
index 9539093..1186b8e 100644
--- a/pkg/tools/process.go
+++ b/pkg/tools/process/process.go
@@ -15,7 +15,7 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package tools
+package process
 
 import (
 	"bufio"
@@ -61,8 +61,8 @@ func KernelFileProfilingStat() (*profiling.Info, error) {
 	return kernelFinder.Analyze(profiling.KernelSymbolFilePath)
 }
 
-// ProcessProfilingStat is validating the exe file could be profiling and get info
-func ProcessProfilingStat(pid int32, exePath string) (*profiling.Info, error) {
+// ProfilingStat is validating the exe file could be profiling and get info
+func ProfilingStat(pid int32, exePath string) (*profiling.Info, error) {
 	stat, err := os.Stat(exePath)
 	if err != nil {
 		return nil, fmt.Errorf("check file error: %v", err)
@@ -83,8 +83,8 @@ func ProcessProfilingStat(pid int32, exePath string) (*profiling.Info, error) {
 	return analyzeProfilingInfo(context, pid)
 }
 
-// ProcessModules Read the profiling info of the process, without the symbol check
-func ProcessModules(pid int32) ([]*profiling.Module, error) {
+// Modules Read the profiling info of the process, without the symbol check
+func Modules(pid int32) ([]*profiling.Module, error) {
 	context := newAnalyzeContext()
 	info, err := analyzeProfilingInfo(context, pid)
 	if err != nil {
diff --git a/pkg/tools/ssl/envoy.go b/pkg/tools/ssl/envoy.go
new file mode 100644
index 0000000..7ccc298
--- /dev/null
+++ b/pkg/tools/ssl/envoy.go
@@ -0,0 +1,75 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package ssl
+
+import (
+	"fmt"
+
+	"github.com/cilium/ebpf"
+)
+
+type EnvoySymbolAddress struct {
+	IsServerOffset uint64
+}
+
+func (r *Register) Envoy(envoySymbolAddrMap *ebpf.Map, sslWrite, sslWriteRet, sslRead, sslReadRet *ebpf.Program) {
+	r.addHandler("Envoy", func() (bool, error) {
+		moduleName := "/envoy"
+		processModules, err := r.findModules(moduleName)
+		if err != nil {
+			return false, err
+		}
+		envoyModule := processModules[moduleName]
+		if envoyModule == nil {
+			return false, 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 false, nil
+		}
+
+		if envoySymbolAddrMap != nil {
+			addr := &EnvoySymbolAddress{
+				// for now the server field have fixed position
+				// https://github.com/google/boringssl/blob/master/ssl/internal.h#L3734-L3812
+				IsServerOffset: 164,
+			}
+
+			if err := envoySymbolAddrMap.Put(uint32(r.pid), addr); err != nil {
+				return false, fmt.Errorf("setting the envoy symbol offsets failure, pid: %d, error: %v", r.pid, err)
+			}
+		}
+
+		envoy := r.linker.OpenUProbeExeFile(envoyModule.Path)
+		envoy.AddLink("SSL_write", sslWrite, sslWriteRet)
+		envoy.AddLink("SSL_read", sslRead, sslReadRet)
+		if e := r.linker.HasError(); e != nil {
+			return false, e
+		}
+		return true, nil
+	})
+}
diff --git a/pkg/tools/ssl/gotls.go b/pkg/tools/ssl/gotls.go
new file mode 100644
index 0000000..2a88498
--- /dev/null
+++ b/pkg/tools/ssl/gotls.go
@@ -0,0 +1,258 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package ssl
+
+import (
+	"bytes"
+	"encoding/binary"
+	"fmt"
+	"regexp"
+
+	"github.com/apache/skywalking-rover/pkg/tools/elf"
+	"github.com/apache/skywalking-rover/pkg/tools/host"
+	"github.com/apache/skywalking-rover/pkg/tools/profiling"
+	"github.com/apache/skywalking-rover/pkg/tools/version"
+
+	"github.com/cilium/ebpf"
+)
+
+var (
+	goVersionRegex = regexp.MustCompile(`^go(?P<Major>\d)\.(?P<Minor>\d+)`)
+
+	goTLSWriteSymbol     = "crypto/tls.(*Conn).Write"
+	goTLSReadSymbol      = "crypto/tls.(*Conn).Read"
+	goTLSGIDStatusSymbol = "runtime.casgstatus"
+	goTLSPollFDSymbol    = "internal/poll.FD"
+	goTLSConnSymbol      = "crypto/tls.Conn"
+	goTLSRuntimeG        = "runtime.g"
+)
+
+type GoTLSArgsLocationType uint32
+
+const (
+	GoTLSArgsLocationTypeStack    GoTLSArgsLocationType = 1
+	GoTLSArgsLocationTypeRegister GoTLSArgsLocationType = 2
+)
+
+type GoSymbolLocation struct {
+	Type   GoTLSArgsLocationType
+	Offset uint32
+}
+
+type GoTLSSymbolAddress struct {
+	// net.Conn addresses
+	FDSysFDOffset  uint64
+	TLSConnOffset  uint64
+	GIDOffset      uint64
+	TCPConnOffset  uint64
+	IsClientOffset uint64
+
+	// casgstatus(goroutine status change) function relate locations
+	CasgStatusGPLoc     GoSymbolLocation
+	CasgStatusNEWValLoc GoSymbolLocation
+
+	// write function relate locations
+	WriteConnectionLoc GoSymbolLocation
+	WriteBufferLoc     GoSymbolLocation
+	WriteRet0Loc       GoSymbolLocation
+	WriteRet1Loc       GoSymbolLocation
+
+	// write function relate locations
+	ReadConnectionLoc GoSymbolLocation
+	ReadBufferLoc     GoSymbolLocation
+	ReadRet0Loc       GoSymbolLocation
+	ReadRet1Loc       GoSymbolLocation
+}
+
+func (r *Register) GoTLS(symbolAddrMap *ebpf.Map, goIDChange, write, writeRet, read, readRet *ebpf.Program) {
+	r.addHandler("goTLS", func() (bool, error) {
+		buildVersionSymbol := r.searchSymbolInModules(r.modules, func(a, b string) bool {
+			return a == b
+		}, "runtime.buildVersion")
+		if buildVersionSymbol == nil {
+			return false, nil
+		}
+		pidExeFile := host.GetFileInHost(fmt.Sprintf("/proc/%d/exe", r.pid))
+		elfFile, err := elf.NewFile(pidExeFile)
+		if err != nil {
+			return false, fmt.Errorf("read executable file error: %v", err)
+		}
+		defer elfFile.Close()
+
+		v, err := r.getGoVersion(elfFile, buildVersionSymbol)
+		if err != nil {
+			return false, err
+		}
+
+		offsets, err := r.generateGOTLSSymbolOffsets(r, elfFile, v)
+		if err != nil {
+			return false, err
+		}
+		if offsets == nil {
+			return false, nil
+		}
+
+		// setting the locations
+		if err := symbolAddrMap.Put(uint32(r.pid), offsets); err != nil {
+			return false, fmt.Errorf("setting the Go TLS argument location failure, pid: %d, error: %v", r.pid, err)
+		}
+
+		exeFile := r.linker.OpenUProbeExeFile(pidExeFile)
+		exeFile.AddLinkWithType("runtime.casgstatus", true, goIDChange)
+		exeFile.AddGoLink(goTLSWriteSymbol, write, writeRet, elfFile)
+		exeFile.AddGoLink(goTLSReadSymbol, read, readRet, elfFile)
+		if e := r.linker.HasError(); e != nil {
+			return false, e
+		}
+
+		return true, nil
+	})
+}
+
+func (r *Register) getGoVersion(elfFile *elf.File, versionSymbol *profiling.Symbol) (*version.Version, error) {
+	buffer, err := elfFile.ReadSymbolData(".data", versionSymbol.Location, versionSymbol.Size)
+	if err != nil {
+		return nil, fmt.Errorf("reading go version struct info failure: %v", err)
+	}
+	var t = goStringInC{}
+	buf := bytes.NewReader(buffer)
+	err = binary.Read(buf, binary.LittleEndian, &t)
+	if err != nil {
+		return nil, fmt.Errorf("read the go structure failure: %v", err)
+	}
+	buffer, err = elfFile.ReadSymbolData(".data", t.Ptr, t.Size)
+	if err != nil {
+		return nil, fmt.Errorf("read the go version failure: %v", err)
+	}
+
+	// parse versions
+	submatch := goVersionRegex.FindStringSubmatch(string(buffer))
+	if len(submatch) != 3 {
+		return nil, fmt.Errorf("the go version is failure to identify, version: %s", string(buffer))
+	}
+	return version.Read(submatch[1], submatch[2], "")
+}
+
+type goStringInC struct {
+	Ptr  uint64
+	Size uint64
+}
+
+func (r *Register) generateGOTLSSymbolOffsets(register *Register, elfFile *elf.File, v *version.Version) (*GoTLSSymbolAddress, error) {
+	reader, err := elfFile.NewDwarfReader(
+		goTLSReadSymbol, goTLSWriteSymbol, goTLSGIDStatusSymbol,
+		goTLSPollFDSymbol, goTLSConnSymbol, goTLSRuntimeG)
+	if err != nil {
+		return nil, err
+	}
+
+	symbolAddresses := &GoTLSSymbolAddress{}
+
+	sym := register.SearchSymbol(func(a, b string) bool {
+		return a == b
+	}, "go.itab.*net.TCPConn,net.Conn")
+	if sym == nil {
+		log.Warnf("could not found the tcp connection symbol: go.itab.*net.TCPConn,net.Conn")
+		return nil, nil
+	}
+	symbolAddresses.TCPConnOffset = sym.Location
+
+	readFunction := reader.GetFunction(goTLSReadSymbol)
+	if readFunction == nil {
+		log.Warnf("could not found the go tls read symbol: %s", goTLSReadSymbol)
+		return nil, nil
+	}
+	writeFunction := reader.GetFunction(goTLSWriteSymbol)
+	if writeFunction == nil {
+		log.Warnf("could not found the go tls write symbol: %s", goTLSWriteSymbol)
+		return nil, nil
+	}
+	gidStatusFunction := reader.GetFunction(goTLSGIDStatusSymbol)
+	if gidStatusFunction == nil {
+		log.Warnf("could not found the goid status change symbol: %s", goTLSGIDStatusSymbol)
+		return nil, nil
+	}
+
+	var retValArg0, retValArg1 = "~r1", "~r2"
+	if v.Minor >= 18 {
+		retValArg0, retValArg1 = "~r0", "~r1"
+	}
+
+	// build the symbols
+	var assignError error
+	// offset
+	assignError = r.assignGoTLSStructureOffset(assignError, reader, goTLSPollFDSymbol, "Sysfd", &symbolAddresses.FDSysFDOffset)
+	assignError = r.assignGoTLSStructureOffset(assignError, reader, goTLSConnSymbol, "conn", &symbolAddresses.TLSConnOffset)
+	assignError = r.assignGoTLSStructureOffset(assignError, reader, goTLSRuntimeG, "goid", &symbolAddresses.GIDOffset)
+	assignError = r.assignGoTLSStructureOffset(assignError, reader, goTLSConnSymbol, "isClient", &symbolAddresses.IsClientOffset)
+
+	// gid status change
+	assignError = r.assignGoTLSArgsLocation(assignError, gidStatusFunction, "gp", &symbolAddresses.CasgStatusGPLoc)
+	assignError = r.assignGoTLSArgsLocation(assignError, gidStatusFunction, "newval", &symbolAddresses.CasgStatusNEWValLoc)
+
+	// write
+	assignError = r.assignGoTLSArgsLocation(assignError, writeFunction, "c", &symbolAddresses.WriteConnectionLoc)
+	assignError = r.assignGoTLSArgsLocation(assignError, writeFunction, "b", &symbolAddresses.WriteBufferLoc)
+	assignError = r.assignGoTLSArgsLocation(assignError, writeFunction, retValArg0, &symbolAddresses.WriteRet0Loc)
+	assignError = r.assignGoTLSArgsLocation(assignError, writeFunction, retValArg1, &symbolAddresses.WriteRet1Loc)
+	// read
+	assignError = r.assignGoTLSArgsLocation(assignError, readFunction, "c", &symbolAddresses.ReadConnectionLoc)
+	assignError = r.assignGoTLSArgsLocation(assignError, readFunction, "b", &symbolAddresses.ReadBufferLoc)
+	assignError = r.assignGoTLSArgsLocation(assignError, readFunction, retValArg0, &symbolAddresses.ReadRet0Loc)
+	assignError = r.assignGoTLSArgsLocation(assignError, readFunction, retValArg1, &symbolAddresses.ReadRet1Loc)
+
+	return symbolAddresses, assignError
+}
+
+func (r *Register) assignGoTLSStructureOffset(err error, reader *elf.DwarfReader, structName, fieldName string, dest *uint64) error {
+	if err != nil {
+		return err
+	}
+	structure := reader.GetStructure(structName)
+	if structure == nil {
+		return fmt.Errorf("the structure is not found, name: %s", structName)
+	}
+	field := structure.GetField(fieldName)
+	if field == nil {
+		return fmt.Errorf("the field is not found in structure, structure name: %s, field name: %s", structName, fieldName)
+	}
+	*dest = uint64(field.Offset)
+	return nil
+}
+
+func (r *Register) assignGoTLSArgsLocation(err error, function *elf.FunctionInfo, argName string, dest *GoSymbolLocation) error {
+	if err != nil {
+		return err
+	}
+	var kSPOffset uint32 = 8
+	args := function.Args(argName)
+	if args == nil {
+		return fmt.Errorf("the args is not found, function: %s, args name: %s", function.Name(), argName)
+	}
+	if args.Location.Type == elf.ArgLocationTypeStack {
+		dest.Type = GoTLSArgsLocationTypeStack
+		dest.Offset = uint32(args.Location.Offset) + kSPOffset
+	} else if args.Location.Type == elf.ArgLocationTypeRegister {
+		dest.Type = GoTLSArgsLocationTypeRegister
+		dest.Offset = uint32(args.Location.Offset)
+	} else {
+		return fmt.Errorf("the location type is not support, function: %s, args name: %s, type: %d",
+			function.Name(), argName, args.Location.Type)
+	}
+	return nil
+}
diff --git a/pkg/tools/ssl/node.go b/pkg/tools/ssl/node.go
new file mode 100644
index 0000000..e0f2f99
--- /dev/null
+++ b/pkg/tools/ssl/node.go
@@ -0,0 +1,211 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package ssl
+
+import (
+	"fmt"
+	"os/exec"
+	"regexp"
+	"strings"
+
+	"github.com/apache/skywalking-rover/pkg/tools/btf"
+	"github.com/apache/skywalking-rover/pkg/tools/profiling"
+	"github.com/apache/skywalking-rover/pkg/tools/version"
+
+	"github.com/cilium/ebpf"
+)
+
+var (
+	nodeVersionRegex = regexp.MustCompile(`^node\.js/v(?P<Major>\d+)\.(?P<Minor>\d+)\.(?P<Patch>\d+)$`)
+)
+
+type NodeTLSSymbolAddress struct {
+	TLSWrapStreamListenerOffset     uint32
+	StreamListenerStreamOffset      uint32
+	StreamBaseStreamResourceOffset  uint32
+	LibuvStreamWrapStreamBaseOffset uint32
+	LibuvStreamWrapStreamOffset     uint32
+	UVStreamSIOWatcherOffset        uint32
+	UVIOSFDOffset                   uint32
+}
+
+func (r *Register) Node(sslSymbolOffsetsMap, nodeTLSSymbolOffsetsMap *ebpf.Map,
+	sslWrite, sslWriteRet, sslRead, sslReadRet,
+	sslNew, tlsWrap, tlsWrapRet *ebpf.Program) {
+	r.addHandler("Node", func() (bool, error) {
+		libSSLModule, nodeModule, openSSLAttach, err := r.findNodeTLSModules()
+		if err != nil {
+			return false, err
+		}
+		if libSSLModule == nil || nodeModule == nil {
+			return false, nil
+		}
+		v, err := r.getNodeVersion(nodeModule.Path)
+		if err != nil {
+			return false, err
+		}
+		log.Debugf("read the nodejs version, pid: %d, version: %s", r.pid, v)
+		// openSSL symbol offsets
+		if sslSymbolOffsetsMap != nil {
+			config, err := r.buildOpenSSLSymAddrConfig(libSSLModule.Path)
+			if err != nil {
+				return false, err
+			}
+			if err := sslSymbolOffsetsMap.Put(uint32(r.pid), config); err != nil {
+				return false, err
+			}
+		}
+		if nodeTLSSymbolOffsetsMap != nil {
+			config, err := r.findNodeTLSAddrConfig(v)
+			if err != nil {
+				return false, err
+			}
+			// setting the locations
+			if err := nodeTLSSymbolOffsetsMap.Put(uint32(r.pid), config); err != nil {
+				return false, fmt.Errorf("setting the node TLS location failure, pid: %d, error: %v", r.pid, err)
+			}
+		}
+		libSSLLinker := r.linker.OpenUProbeExeFile(libSSLModule.Path)
+		if openSSLAttach {
+			libSSLLinker.AddLink("SSL_write", sslWrite, sslWriteRet)
+			libSSLLinker.AddLink("SSL_read", sslRead, sslReadRet)
+		}
+		if e := r.nodeTLSRegisterProbes(v, libSSLLinker, nodeModule, sslNew, tlsWrap, tlsWrapRet); e != nil {
+			return false, e
+		}
+		if e := r.linker.HasError(); e != nil {
+			return false, e
+		}
+		return true, nil
+	})
+}
+
+func (r *Register) getNodeVersion(p string) (*version.Version, error) {
+	result, err := exec.Command("strings", p).Output()
+	if err != nil {
+		return nil, err
+	}
+	for _, d := range strings.Split(string(result), "\n") {
+		versionInfo := nodeVersionRegex.FindStringSubmatch(strings.TrimSpace(d))
+		if len(versionInfo) != 4 {
+			continue
+		}
+		return version.Read(versionInfo[1], versionInfo[2], versionInfo[3])
+	}
+
+	return nil, fmt.Errorf("nodejs version is not found")
+}
+
+var nodeTLSAddrWithVersions = []struct {
+	v    *version.Version
+	conf *NodeTLSSymbolAddress
+}{
+	{version.Build(10, 19, 0), &NodeTLSSymbolAddress{0x0130, 0x08, 0x00, 0x50, 0x90, 0x88, 0x30}},
+	{version.Build(12, 3, 1), &NodeTLSSymbolAddress{0x0130, 0x08, 0x00, 0x50, 0x90, 0x88, 0x30}},
+	{version.Build(12, 16, 2), &NodeTLSSymbolAddress{0x0138, 0x08, 0x00, 0x58, 0x98, 0x88, 0x30}},
+	{version.Build(13, 0, 0), &NodeTLSSymbolAddress{0x0130, 0x08, 0x00, 0x50, 0x90, 0x88, 0x30}},
+	{version.Build(13, 2, 0), &NodeTLSSymbolAddress{0x0130, 0x08, 0x00, 0x58, 0x98, 0x88, 0x30}},
+	{version.Build(13, 10, 1), &NodeTLSSymbolAddress{0x0140, 0x08, 0x00, 0x60, 0xa0, 0x88, 0x30}},
+	{version.Build(14, 5, 0), &NodeTLSSymbolAddress{0x138, 0x08, 0x00, 0x58, 0x98, 0x88, 0x30}},
+	{version.Build(15, 0, 0), &NodeTLSSymbolAddress{0x78, 0x08, 0x00, 0x58, 0x98, 0x88, 0x30}},
+}
+
+var nodeTLSProbeWithVersions = []struct {
+	v *version.Version
+	f func(uprobe *btf.UProbeExeFile, register *Register, nodeModule *profiling.Module, tlsWrap, tlsWrapRet *ebpf.Program)
+}{
+	{version.Build(10, 19, 0), func(uprobe *btf.UProbeExeFile, register *Register, nodeModule *profiling.Module, tlsWrap, tlsWrapRet *ebpf.Program) {
+		uprobe.AddLinkWithSymbols(register.searchSymbolNames([]*profiling.Module{nodeModule}, strings.HasPrefix, "_ZN4node7TLSWrapC2E"),
+			tlsWrap, tlsWrapRet)
+		uprobe.AddLinkWithSymbols(register.searchSymbolNames([]*profiling.Module{nodeModule}, strings.HasPrefix, "_ZN4node7TLSWrap7ClearInE"),
+			tlsWrap, tlsWrapRet)
+		uprobe.AddLinkWithSymbols(register.searchSymbolNames([]*profiling.Module{nodeModule}, strings.HasPrefix, "_ZN4node7TLSWrap8ClearOutE"),
+			tlsWrap, tlsWrapRet)
+	}},
+	{version.Build(15, 0, 0), func(uprobe *btf.UProbeExeFile, register *Register, nodeModule *profiling.Module, tlsWrap, tlsWrapRet *ebpf.Program) {
+		uprobe.AddLinkWithSymbols(register.searchSymbolNames([]*profiling.Module{nodeModule}, strings.HasPrefix, "_ZN4node6crypto7TLSWrapC2E"),
+			tlsWrap, tlsWrapRet)
+		uprobe.AddLinkWithSymbols(register.searchSymbolNames([]*profiling.Module{nodeModule}, strings.HasPrefix, "_ZN4node6crypto7TLSWrap7ClearInE"),
+			tlsWrap, tlsWrapRet)
+		uprobe.AddLinkWithSymbols(register.searchSymbolNames([]*profiling.Module{nodeModule}, strings.HasPrefix, "_ZN4node6crypto7TLSWrap8ClearOutE"),
+			tlsWrap, tlsWrapRet)
+	}},
+}
+
+func (r *Register) findNodeTLSAddrConfig(v *version.Version) (*NodeTLSSymbolAddress, error) {
+	var lastest *NodeTLSSymbolAddress
+	for _, c := range nodeTLSAddrWithVersions {
+		if v.GreaterOrEquals(c.v) {
+			lastest = c.conf
+		}
+	}
+	if lastest != nil {
+		return lastest, nil
+	}
+	return nil, fmt.Errorf("could not support version: %s", v)
+}
+
+func (r *Register) findNodeTLSModules() (libSSLModule, nodeModule *profiling.Module, openSSLAttach bool, err error) {
+	moduleName1, moduleName2, libsslName := "/nodejs", "/node", "libssl.so"
+	processModules, err := r.findModules(moduleName1, moduleName2, libsslName)
+	if err != nil {
+		return nil, nil, false, err
+	}
+	nodeModule = processModules[moduleName1]
+	libSSLModule = processModules[libsslName]
+	if nodeModule == nil {
+		nodeModule = processModules[moduleName2]
+	}
+	if nodeModule == nil {
+		return nil, nil, false, nil
+	}
+	if libSSLModule == nil {
+		if r.searchSymbolInModules([]*profiling.Module{nodeModule}, func(a, b string) bool {
+			return a == b
+		}, "SSL_read") == nil || r.searchSymbolInModules([]*profiling.Module{nodeModule}, func(a, b string) bool {
+			return a == b
+		}, "SSL_write") == nil {
+			return nil, nil, false, nil
+		}
+		libSSLModule = nodeModule
+		openSSLAttach = true
+	}
+	return
+}
+
+func (r *Register) nodeTLSRegisterProbes(v *version.Version, libSSLLinker *btf.UProbeExeFile, nodeModule *profiling.Module,
+	sslNew, tlsWrap, tlsWrapRet *ebpf.Program) error {
+	if sslNew != nil {
+		libSSLLinker.AddLinkWithType("SSL_new", false, sslNew)
+	}
+	if tlsWrap != nil && tlsWrapRet != nil {
+		var probeFunc func(uprobe *btf.UProbeExeFile, register *Register, nodeModule *profiling.Module, tlsWrap, tlsWrapRet *ebpf.Program)
+		for _, c := range nodeTLSProbeWithVersions {
+			if v.GreaterOrEquals(c.v) {
+				probeFunc = c.f
+			}
+		}
+		if probeFunc == nil {
+			return fmt.Errorf("the version is not support to attach TLSWrap relate probes: %v, pid: %d", v, r.pid)
+		}
+		file := r.linker.OpenUProbeExeFile(nodeModule.Path)
+		probeFunc(file, r, nodeModule, tlsWrap, tlsWrapRet)
+	}
+
+	return nil
+}
diff --git a/pkg/tools/ssl/openssl.go b/pkg/tools/ssl/openssl.go
new file mode 100644
index 0000000..87f1931
--- /dev/null
+++ b/pkg/tools/ssl/openssl.go
@@ -0,0 +1,141 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package ssl
+
+import (
+	"fmt"
+	"os/exec"
+	"regexp"
+	"strconv"
+	"strings"
+
+	"github.com/cilium/ebpf"
+)
+
+var (
+	openSSLVersionRegex = regexp.MustCompile(`^OpenSSL\s+(?P<Major>\d)\.(?P<Minor>\d)\.(?P<Fix>\d+)\w?`)
+)
+
+type OpenSSLSymbolAddresses struct {
+	BIOReadOffset  uint32
+	BIOWriteOffset uint32
+	FDOffset       uint32
+	RoleOffset     uint32
+}
+
+func (r *Register) OpenSSL(symbolAddrMap *ebpf.Map, sslWrite, sslWriteRet, sslRead, sslReadRet *ebpf.Program) {
+	r.addHandler("OpenSSL", func() (bool, error) {
+		var libcryptoName, libsslName = "libcrypto.so", "libssl.so"
+		var libcryptoPath, libsslPath string
+		modules, err := r.findModules(libcryptoName, libsslName)
+		if err != nil {
+			return false, err
+		}
+		if len(modules) == 0 {
+			return false, nil
+		}
+		if libcrypto := modules[libcryptoName]; libcrypto != nil {
+			libcryptoPath = libcrypto.Path
+		}
+		if libssl := modules[libsslName]; libssl != nil {
+			libsslPath = libssl.Path
+		}
+		if libcryptoPath == "" || libsslPath == "" {
+			return false, fmt.Errorf("the OpenSSL library not complete, libcrypto: %s, libssl: %s", libcryptoPath, libsslPath)
+		}
+
+		addresses, err := r.buildOpenSSLSymAddrConfig(libcryptoPath)
+		if err != nil {
+			return false, err
+		}
+
+		if err := symbolAddrMap.Put(uint32(r.pid), addresses); err != nil {
+			return false, err
+		}
+
+		libSSLLinker := r.linker.OpenUProbeExeFile(libsslPath)
+		libSSLLinker.AddLink("SSL_write", sslWrite, sslWriteRet)
+		libSSLLinker.AddLink("SSL_read", sslRead, sslReadRet)
+		if err := r.linker.HasError(); err != nil {
+			return false, err
+		}
+		return true, nil
+	})
+}
+
+func (r *Register) buildOpenSSLSymAddrConfig(libcryptoPath string) (*OpenSSLSymbolAddresses, error) {
+	// using "strings" command to query the symbol in the libcrypto library
+	result, err := exec.Command("strings", libcryptoPath).Output()
+	if err != nil {
+		return nil, err
+	}
+	for _, p := range strings.Split(string(result), "\n") {
+		submatch := openSSLVersionRegex.FindStringSubmatch(p)
+		if len(submatch) != 4 {
+			continue
+		}
+		major := submatch[1]
+		minor := submatch[2]
+		fix := submatch[3]
+
+		log.Debugf("found the libcrypto.so version: %s.%s.%s", major, minor, fix)
+		conf := &OpenSSLSymbolAddresses{}
+
+		// must be number, already validate in the regex
+		majorVal, _ := strconv.Atoi(major)
+		minorVal, _ := strconv.Atoi(minor)
+		fixVal, _ := strconv.Atoi(fix)
+
+		// max support version is 3.0.x
+		if majorVal > 3 || (majorVal == 3 && minorVal > 0) {
+			return nil, fmt.Errorf("the version of the libcrypto is not support: %s.%s.%s", major, minor, fix)
+		}
+
+		// bio offset
+		// https://github.com/openssl/openssl/blob/OpenSSL_1_0_0-stable/ssl/ssl.h#L1093-L1111
+		// https://github.com/openssl/openssl/blob/OpenSSL_1_1_1-stable/ssl/ssl_local.h#L1068-L1083
+		// https://github.com/openssl/openssl/blob/openssl-3.0.7/ssl/ssl_local.h#L1212-L1227
+		conf.BIOReadOffset = 16
+		conf.BIOWriteOffset = 24
+		// fd offset
+		if majorVal == 3 && minorVal == 0 {
+			// 3.0.x
+			// https://github.com/openssl/openssl/blob/openssl-3.0.7/crypto/bio/bio_local.h#L115-L128
+			// OPENSSL_NO_DEPRECATED_3_0 is not defined by default unless the user pass the specific build option
+			conf.FDOffset = 56
+			// https://github.com/openssl/openssl/blob/openssl-3.0.7/ssl/ssl_local.h#L1212-L1245
+			conf.RoleOffset = 56
+		} else if (minorVal == 0) || (minorVal == 1 && fixVal == 0) {
+			// 1.0.x || 1.1.0
+			// https://github.com/openssl/openssl/blob/OpenSSL_1_0_0-stable/crypto/bio/bio.h#L297-L306
+			conf.FDOffset = 40
+			// https://github.com/openssl/openssl/blob/OpenSSL_1_0_0-stable/ssl/ssl.h#L1093-L1138
+			conf.RoleOffset = 72
+		} else {
+			// 1.1.1
+			// https://github.com/openssl/openssl/blob/OpenSSL_1_1_1-stable/crypto/bio/bio_local.h#L115-L125
+			conf.FDOffset = 48
+			// https://github.com/openssl/openssl/blob/OpenSSL_1_1_1-stable/ssl/ssl_local.h#L1068-L1101
+			conf.RoleOffset = 56
+		}
+		log.Debugf("the lobcrypto.so library symbol verson config, version: %s.%s.%s, bio offset: %d",
+			major, minor, fix, conf.FDOffset)
+		return conf, nil
+	}
+	return nil, fmt.Errorf("could not fount the version of the libcrypto.so")
+}
diff --git a/pkg/profiling/task/network/ssl_test.go b/pkg/tools/ssl/openssl_test.go
similarity index 76%
rename from pkg/profiling/task/network/ssl_test.go
rename to pkg/tools/ssl/openssl_test.go
index 1ed387d..cb0bb7c 100644
--- a/pkg/profiling/task/network/ssl_test.go
+++ b/pkg/tools/ssl/openssl_test.go
@@ -15,7 +15,7 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package network
+package ssl
 
 import (
 	"os/exec"
@@ -29,6 +29,7 @@ func TestBuildSSLSymAddrConfig(t *testing.T) {
 	mockOutput := func(out string) *exec.Cmd {
 		return exec.Command("echo", out)
 	}
+	register := NewSSLRegister(0, nil)
 
 	result := `%s:%d: OpenSSL internal error: %s
 OpenSSL 1.0.2o  31 Mar 2020
@@ -38,7 +39,7 @@ OpenSSL X9.42 DH method`
 		patches.Reset()
 	})
 
-	conf, err := buildSSLSymAddrConfig("/test")
+	conf, err := register.buildOpenSSLSymAddrConfig("/test")
 	assert.Nil(t, err)
 	assert.Equal(t, uint32(16), conf.BIOReadOffset)
 	assert.Equal(t, uint32(24), conf.BIOWriteOffset)
@@ -49,7 +50,17 @@ OpenSSL X9.42 DH method`
 OpenSSL 1.1.1f  31 Mar 2020
 OpenSSL X9.42 DH method`
 	patches = gomonkey.ApplyFuncReturn(exec.Command, mockOutput(result))
-	conf, err = buildSSLSymAddrConfig("/test")
+	conf, err = register.buildOpenSSLSymAddrConfig("/test")
+	assert.Nil(t, err)
+	assert.Equal(t, uint32(16), conf.BIOReadOffset)
+	assert.Equal(t, uint32(24), conf.BIOWriteOffset)
+	assert.Equal(t, uint32(48), conf.FDOffset)
+
+	// should same with 1.1.1, which from the NodeJS build-in version of OpenSSL
+	patches.Reset()
+	result = `OpenSSL 1.1.1q+quic  5 Jul 2022`
+	patches = gomonkey.ApplyFuncReturn(exec.Command, mockOutput(result))
+	conf, err = register.buildOpenSSLSymAddrConfig("/test")
 	assert.Nil(t, err)
 	assert.Equal(t, uint32(16), conf.BIOReadOffset)
 	assert.Equal(t, uint32(24), conf.BIOWriteOffset)
@@ -60,7 +71,7 @@ OpenSSL X9.42 DH method`
 OpenSSL 3.0.3 3 May 2022
 OpenSSL RSA method`
 	patches = gomonkey.ApplyFuncReturn(exec.Command, mockOutput(result))
-	conf, err = buildSSLSymAddrConfig("/test")
+	conf, err = register.buildOpenSSLSymAddrConfig("/test")
 	assert.Nil(t, err)
 	assert.Equal(t, uint32(16), conf.BIOReadOffset)
 	assert.Equal(t, uint32(24), conf.BIOWriteOffset)
diff --git a/pkg/tools/ssl/ssl.go b/pkg/tools/ssl/ssl.go
new file mode 100644
index 0000000..4830821
--- /dev/null
+++ b/pkg/tools/ssl/ssl.go
@@ -0,0 +1,146 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package ssl
+
+import (
+	"fmt"
+	"strings"
+
+	"github.com/apache/skywalking-rover/pkg/logger"
+	"github.com/apache/skywalking-rover/pkg/tools/btf"
+	"github.com/apache/skywalking-rover/pkg/tools/path"
+	"github.com/apache/skywalking-rover/pkg/tools/process"
+	"github.com/apache/skywalking-rover/pkg/tools/profiling"
+)
+
+type handler func() (bool, error)
+
+var log = logger.GetLogger("tools", "ssl")
+
+type Register struct {
+	pid    int
+	linker *btf.Linker
+
+	handlers map[string]handler
+	modules  []*profiling.Module
+}
+
+func NewSSLRegister(pid int, linker *btf.Linker) *Register {
+	return &Register{
+		pid:      pid,
+		linker:   linker,
+		handlers: make(map[string]handler),
+	}
+}
+
+func (r *Register) Execute() error {
+	modules, err := process.Modules(int32(r.pid))
+	if err != nil {
+		return fmt.Errorf("read process modules error: %v, error: %v", r.pid, err)
+	}
+	r.modules = modules
+
+	count := 0
+	for name, h := range r.handlers {
+		b, err := h()
+		if err != nil {
+			return err
+		}
+		if b {
+			count++
+			log.Debugf("success add register to process, pid: %d, name: %s", r.pid, name)
+		}
+	}
+	if count == 0 {
+		log.Debugf("cannot find any SSL register for process: %d", r.pid)
+	}
+	return nil
+}
+
+func (r *Register) addHandler(name string, h handler) {
+	r.handlers[name] = h
+}
+
+func (r *Register) findModules(names ...string) (map[string]*profiling.Module, error) {
+	result := make(map[string]*profiling.Module)
+	for _, mod := range r.modules {
+		for _, modName := range names {
+			if strings.Contains(mod.Name, modName) {
+				if !path.Exists(mod.Path) {
+					return nil, fmt.Errorf("the module path not exists, path: %s", mod.Path)
+				}
+				result[modName] = mod
+			}
+		}
+	}
+	return result, nil
+}
+
+func (r *Register) SearchSymbol(verify stringVerify, values ...string) *profiling.Symbol {
+	return r.searchSymbolInModules(r.modules, verify, values...)
+}
+
+func (r *Register) searchSymbolInModules(modules []*profiling.Module, verify stringVerify, values ...string) *profiling.Symbol {
+	list := r.searchSymbolListInModules(modules, verify, values...)
+	if len(list) > 0 {
+		return list[0]
+	}
+	return nil
+}
+
+func (r *Register) searchSymbolListInModules(modules []*profiling.Module, verify stringVerify, values ...string) []*profiling.Symbol {
+	var result []*profiling.Symbol
+	for _, mod := range modules {
+		for _, s := range mod.Symbols {
+			for _, validator := range values {
+				if verify(s.Name, validator) {
+					result = append(result, s)
+				}
+			}
+		}
+	}
+	return result
+}
+
+func (r *Register) searchSymbolNames(modules []*profiling.Module, verify stringVerify, values ...string) []string {
+	list := r.searchSymbolList(modules, verify, values...)
+	if len(list) > 0 {
+		result := make([]string, 0)
+		for _, i := range list {
+			result = append(result, i.Name)
+		}
+		return result
+	}
+	return nil
+}
+
+func (r *Register) searchSymbolList(modules []*profiling.Module, verify stringVerify, values ...string) []*profiling.Symbol {
+	var result []*profiling.Symbol
+	for _, mod := range modules {
+		for _, s := range mod.Symbols {
+			for _, validator := range values {
+				if verify(s.Name, validator) {
+					result = append(result, s)
+				}
+			}
+		}
+	}
+	return result
+}
+
+type stringVerify func(a, b string) bool