gojue / ecapture

Capturing SSL/TLS plaintext without a CA certificate using eBPF. Supported on Linux/Android kernels for amd64/arm64.
https://ecapture.cc
Apache License 2.0
13.41k stars 1.42k forks source link

以明文形式捕获 tls 内容时部分信息展示不正确 #609

Open xxxxxliil opened 2 months ago

xxxxxliil commented 2 months ago

Describe the bug 使用 ecapture 捕获时,日志展示夸张的 FD 和不能获得的访问地址 且在 /sys/kernel/debug/tracing/trace_pipe 中发现以下内容:

            curl-204590  [000] ...11 175870.494020: bpf_trace_printk: openssl uprobe/SSL_write pid :204590

            curl-204590  [000] ...11 175870.494022: bpf_trace_printk: openssl uprobe SSL_write FD:811562928, version:0

            curl-204590  [000] ...11 175870.495026: bpf_trace_printk: openssl uretprobe/SSL_write pid :204590

            curl-204590  [000] ...11 175870.495113: bpf_trace_printk: openssl uprobe/SSL_write pid :204590

            curl-204590  [000] ...11 175870.495116: bpf_trace_printk: openssl uprobe SSL_write FD:811562928, version:0

            curl-204590  [000] ...11 175870.495191: bpf_trace_printk: openssl uretprobe/SSL_write pid :204590

            curl-204590  [000] ...11 175870.710355: bpf_trace_printk: openssl uprobe/SSL_read pid :204590

            curl-204590  [000] ...11 175870.710365: bpf_trace_printk: openssl uprobe PID:204590, SSL_read FD:811562928

To Reproduce Steps to reproduce the behavior:

  1. build ebpf-tc-uid-filter branch
  2. # ecapture --debug tls
  3. $ curl -L 1.1.1.1/cdn-cgi/trace
  4. See error

Expected behavior 显示正确的 fd 和正确的地址

Screenshots image

Linux Server/Android (please complete the following information):

Additional context 每个程序的每个实例都有独立且固定的错误 fd

cfc4n commented 2 months ago

看上去只是数字比较大而已,你认为错误fd的依据是什么?

xxxxxliil commented 2 months ago

看上去只是数字比较大而已,你认为错误fd的依据是什么?

我用 sysdig 检查 curl 的 syscall,发现没有 syscall 返回过如此大的 fd,且 ulimit -n 的输出是 4096

cfc4n commented 2 months ago

4096只是同时打开的FD的总数,并不是FD这个数字最大值的限制。

如果再有这种现场,你可以配合lsof等命令,确认FD是不是正确的值。

xxxxxliil commented 2 months ago

4096只是同时打开的FD的总数,并不是FD这个数字最大值的限制。

如果再有这种现场,你可以配合lsof等命令,确认FD是不是正确的值。

怎么保持对应的 fd 为打开状态呢?

blaisewang commented 2 months ago

4096只是同时打开的FD的总数,并不是FD这个数字最大值的限制。 如果再有这种现场,你可以配合lsof等命令,确认FD是不是正确的值。

怎么保持对应的 fd 为打开状态呢?

单线程下个大文件

xxxxxliil commented 2 months ago

image image curl 在下载文件时暂停后截的图

补图: image image image

接下来也许还要怀疑发起请求的和传输下载内容的 tcp fd 不是同一个?虽然昨天我说过已经用 sysdig 看过没有任何 syscall 返回过那么大的文件描述符

这是码

#include <stdio.h>
#include <stdint.h>

#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[])
{
    system("echo $(($(ulimit -n) - 1)) is max fd");
    int udfd = atoi(argv[1]);
    int o_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    printf("open socket fd: %i, errno: %i, strerr: %s\n", o_fd, errno, strerror(errno));
    int n_fd = dup2(o_fd, udfd);
    printf("dup2 origin fd: %i, user define fd: %i, new fd: %i, errno: %i, strerr: %s\n",
        o_fd, udfd, n_fd, errno, strerror(errno));
    getchar();
    return 0;
}

最大 fd 数量就是 fd 最大值

$ gcc t.c; ./a.out 4095
4095 is max fd
open socket fd: 3, errno: 0, strerr: Success
dup2 origin fd: 3, user define fd: 4095, new fd: 4095, errno: 0, strerr: Success

如果尝试更高的值就会

$ gcc t.c; ./a.out 4096
4095 is max fd
open socket fd: 3, errno: 0, strerr: Success
dup2 origin fd: 3, user define fd: 4096, new fd: -1, errno: 9, strerr: Bad file descriptor
cfc4n commented 2 months ago

偶尔close一些fd啊。否则都持有着,肯定超过不了4096

xxxxxliil commented 2 months ago

偶尔close一些fd啊。否则都持有着,肯定超过不了4096

在上面的示例中只有 5 个 fd,但是 fd 号仍然不能超过 ulimit 中同时打开的 fd 上限

man 2 dup:

ERRORS
       EBADF  oldfd isn't an open file descriptor.

       EBADF  newfd is out of the allowed range for file descriptors (see the discussion of RLIMIT_NOFILE in getrlimit(2)).

man 3p dup:

The dup2() function shall fail if:

EBADF  The fildes argument is not a valid open file descriptor or the argument fildes2 is negative or greater than or equal to {OPEN_MAX}.

man 3p getrlimit:

RLIMIT_NOFILE
This is a number one greater than the maximum value that the system may assign to a newly-created descriptor.
If this limit is exceeded, functions that allocate a file descriptor shall fail with errno set to [EMFILE].
This limit constrains the number of file descriptors that  a  process  may allocate.

我是真的想见识一下如何分配值大于 RLIMIT_NOFILE 的 fd。网上搜不行,自己测试不行,文档说不行。但你一直说这是可以随意做到的,请讲解一下如何做到

cfc4n commented 2 months ago

不好意思,工作日比较忙,我周末验证一下,再回复。

xxxxxliil commented 1 month ago

@cfc4n 我已经知道问题出在哪里了,但是因为个人原因(我承认是在赌气),请你先演示一下如何在主线内核中取得一个比 ulimit 中比 fd 上限更高数值的 fd

cfc4n commented 3 weeks ago

我找了点资料看了一下,是我对linux内核的fd回收机制理解不对,close的fd会被内核复用,做不到fd的值大于ulimit的情况。

看得出来,你还在赌气。 对我来说,个人精力有限,不能及时挨个回答用户问题,更何况是特定场景下的小众问题。你说你在赌气,我完全无法理解,换位思考一下,我是做开源软件的,你用我写的软件,没收你钱,还在持续帮你解决问题,凭什么要承诺解决方案的准确性、可靠性?

其次,我不是所有领域的专家,对个别知识点理解不对,给出错误结论是很正常的事情。 任何人在成长的过程中,都是伴随着错误知识不断迭代修正。

友好交流,有问题就互相纠正吧,情绪化不可取。

xxxxxliil commented 3 weeks ago

我找了点资料看了一下,是我对linux内核的fd回收机制理解不对,close的fd会被内核复用,做不到fd的值大于ulimit的情况。

看得出来,你还在赌气。 对我来说,个人精力有限,不能及时挨个回答用户问题,更何况是特定场景下的小众问题。你说你在赌气,我完全无法理解,换位思考一下,我是做开源软件的,你用我写的软件,没收你钱,还在持续帮你解决问题,凭什么要承诺解决方案的准确性、可靠性?

我没有要求承诺可用性,是有点难以接受在你第二次回复时提出的问题。在第一次的提问中我已经使用 syadig 检查过 curl 执行过程中调用的 syscall,curl 从未有过 ecapture 报告的那么巨大的 fd。但第二次回复中只是觉得它有点大,并希望我在下一次发现问题的现场用 lsof 看一看 fd 是不是正确的。

其次,我不是所有领域的专家,对个别知识点理解不对,给出错误结论是很正常的事情。 任何人在成长的过程中,都是伴随着错误知识不断迭代修正。

友好交流,有问题就互相纠正吧,情绪化不可取。

理解,但是交 pr 很可能因为前几天时不时用 codespace 看 commit 记录并且没及时停止导致免费市场用完,等下个月才能了。

xxxxxliil commented 1 day ago

这个问题本质上是 openssl 3 以上的 libssl.so .rodata 段中不再存在版本信息,且开 issue 时对于检查不到版本且根据文件后缀回退到默认的 3.0.0 时的日志输出时 info,导致使用时很难注意到是版本没有正确匹配导致的输出信息有误,同时发生的现象还有 keylog 和 pcap 都不能进行抓取解密的 tls 流量。