gojue/ecapture

TLS 模式下,对被检测程序的性能影响。

Closed this issue · 9 comments

机器开一个Nginx服务,然后使用wget https下载文件,开启ecapture与关闭ecapture有接近20%的性能下降,只测试ssl write函数的话更有接近5倍的性能下降,分析主要耗时是在内核态与用户态的切换上,这个如何解决?

有性能报告吗?

公司内网数据发不出来,这个在第一个wget下很好复现,我可以口述一下,使用nginx在本机启动,然后本地使用 wget https://xxxx 下载一个大文件,观察ecapture关闭前后的两次下载带宽就可以发现明显影响。如果是第二种的话,同样针对刚才的Nginx服务,使用

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>

#define SERVER "127.0.0.1"
#define PORT 443
#define REQUEST "GET / HTTP/1.1\r\nHost: www.example.com\r\n\r\n"
#define TEST_CNT 10000000

char g_requests[TEST_CNT][strlen(REQUEST) + 1];
int create_socket(const char *host, int port) {
    int sockfd;
    struct sockaddr_in dest_addr;

    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1) {
        perror("socket");
        exit(EXIT_FAILURE);
    }

    dest_addr.sin_family = AF_INET;
    dest_addr.sin_port = htons(port);
    dest_addr.sin_addr.s_addr = inet_addr(host);

    memset(&(dest_addr.sin_zero), '\0', 8);

    if (connect(sockfd, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr)) == -1) {
        perror("connect");
        exit(EXIT_FAILURE);
    }

    return sockfd;
}

void init_request() {
    int i;
    for (i = 0; i < TEST_CNT; i++) {
        memcpy(g_requests[i], REQUEST, strlen(REQUEST));
    }

}

int main() {
    SSL_CTX *ctx;
    SSL *ssl;
    int server;
    char reply[4096];

    SSL_library_init();
    SSL_load_error_strings();
    OpenSSL_add_all_algorithms();

    ctx = SSL_CTX_new(TLS_client_method());
    if (ctx == NULL) {
        ERR_print_errors_fp(stderr);
        exit(EXIT_FAILURE);
    }

    server = create_socket(SERVER, PORT);
    ssl = SSL_new(ctx);
    SSL_set_fd(ssl, server);
    SSL_connect(ssl);

    init_request();
    int request_len = strlen(REQUEST);

    // Perform SSL_write performance test
    int i;
    for (i = 0; i < TEST_CNT; i++) {
        char *request = g_requests[i];
        int bytes_written = SSL_write(ssl, request, request_len);  // Perform SSL_write
        if (bytes_written <= 0) {
            fprintf(stderr, "SSL_write failed\n");
            ERR_print_errors_fp(stderr);
            break;
        }
    }

    SSL_read(ssl, reply, sizeof(reply));  // Read server response

    SSL_free(ssl);
    close(server);
    SSL_CTX_free(ctx);
    return 0;
}

去运行,性能差异大概是 开启前 6s左右跑完,开启后,30s跑完,

启用eCapture   的命令是什么?

另外,你可以试试 keylog模式,只HOOK了一个函数,性能开销比较小,之后你用wireshark来读取。

./ecapture tls -m keylog -keylogfile=openssl_keylog.log

避免刷屏影响,使用的就是这个输出文件模式。这个您可以测试一下,应该不难复现。

你的服务器系统版本是哪个? openssl的类库版本呢?

Ubuntu2204,libssl.so.6

确实存在这个性能问题,我近期尝试优化一下。
image

优化结果来了,10000000次的数据发送,耗时从30降低到7.1,比不启用eCapture多了1.5S,目前先做到这样,可以试试PR #471

ping?