diff --git a/tls_client.c b/tls_client.c index a7a2357..4a88f1b 100644 --- a/tls_client.c +++ b/tls_client.c @@ -363,21 +363,93 @@ int create_tcp_connection(const char* hostname, int port) { } /** - * @brief 执行TLS握手 + * @brief 分析系统调用错误的详细信息 * @param ssl SSL连接对象 + * @param ret SSL函数返回值 + * @return void + */ +void analyze_syscall_error(SSL* ssl, int ret) { + int sockfd = SSL_get_fd(ssl); + int error = 0; + socklen_t len = sizeof(error); + + // 获取套接字错误 + if (sockfd > 0 && getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len) == 0) { + if (error != 0) { + fprintf(stderr, "套接字错误代码: %d (%s)\n", error, strerror(error)); + + // 详细分析套接字错误 + switch (error) { + case ECONNREFUSED: + fprintf(stderr, " -> 连接被拒绝,服务器可能未运行或端口错误\n"); + break; + case ETIMEDOUT: + fprintf(stderr, " -> 连接超时,网络可能有问题或服务器响应慢\n"); + break; + case EHOSTUNREACH: + fprintf(stderr, " -> 主机不可达,网络路由问题\n"); + break; + case ENETUNREACH: + fprintf(stderr, " -> 网络不可达,网络连接问题\n"); + break; + case ECONNRESET: + fprintf(stderr, " -> 连接被重置,服务器主动断开连接\n"); + break; + case EPIPE: + fprintf(stderr, " -> 管道破裂,连接意外断开\n"); + break; + case EINTR: + fprintf(stderr, " -> 系统调用被中断\n"); + break; + case EAGAIN: + fprintf(stderr, " -> 资源暂时不可用,可能需要重试\n"); + break; +#ifdef EWOULDBLOCK +#if EAGAIN != EWOULDBLOCK + case EWOULDBLOCK: + fprintf(stderr, " -> 资源暂时不可用,可能需要重试\n"); + break; +#endif +#endif + default: + fprintf(stderr, " -> 其他系统错误\n"); + break; + } + } + } + + // 检查errno + if (errno != 0) { + fprintf(stderr, "系统errno: %d (%s)\n", errno, strerror(errno)); + } + + // 检查SSL内部错误队列 + unsigned long ssl_err; + while ((ssl_err = ERR_get_error()) != 0) { + char err_buf[256]; + ERR_error_string_n(ssl_err, err_buf, sizeof(err_buf)); + fprintf(stderr, "SSL内部错误: %s\n", err_buf); + } +} + +/** + * @brief 执行TLS握手(带重试机制) + * @param ssl SSL连接对象 + * @param max_retries 最大重试次数 + * @param base_delay 基础延迟时间(秒) * @return int 成功返回1,失败返回0 */ -int perform_tls_handshake(SSL* ssl) { +int perform_tls_handshake_with_retry(SSL* ssl, int max_retries, int base_delay) { int ret; time_t start_time, end_time, step_time; double handshake_time, step_duration; + int retry_count = 0; + int sockfd = SSL_get_fd(ssl); - printf("开始TLS握手...\n"); + printf("开始TLS握手(最大重试次数: %d)...\n", max_retries); start_time = time(NULL); - step_time = start_time; // 设置握手超时 - int sockfd = SSL_get_fd(ssl); if (sockfd > 0) { struct timeval timeout; timeout.tv_sec = 30; // 30秒超时 @@ -387,65 +459,146 @@ int perform_tls_handshake(SSL* ssl) { printf("设置握手超时: 30秒\n"); } - // 执行SSL握手 - printf("正在执行SSL_connect()...\n"); - ret = SSL_connect(ssl); - - end_time = time(NULL); - handshake_time = difftime(end_time, start_time); - step_duration = difftime(end_time, step_time); - - printf("SSL_connect() 耗时: %.2f 秒\n", step_duration); - - if (ret != 1) { + while (retry_count <= max_retries) { + if (retry_count > 0) { + int delay = base_delay * (1 << (retry_count - 1)); // 指数退避 + printf("第 %d 次重试,等待 %d 秒...\n", retry_count, delay); + sleep(delay); + } + + step_time = time(NULL); + printf("正在执行SSL_connect()... (尝试 %d/%d)\n", retry_count + 1, max_retries + 1); + + // 执行SSL握手 + ret = SSL_connect(ssl); + + end_time = time(NULL); + handshake_time = difftime(end_time, start_time); + step_duration = difftime(end_time, step_time); + + printf("SSL_connect() 耗时: %.2f 秒\n", step_duration); + + if (ret == 1) { + // 握手成功 + printf("TLS握手成功!\n"); + printf("总握手耗时: %.2f 秒\n", handshake_time); + printf("重试次数: %d\n", retry_count); + printf("协议版本: %s\n", SSL_get_version(ssl)); + printf("密码套件: %s\n", SSL_get_cipher(ssl)); + + // 验证服务器证书 + X509* cert = SSL_get_peer_certificate(ssl); + if (cert) { + printf("服务器证书验证成功\n"); + X509_free(cert); + } else { + printf("警告: 无法获取服务器证书\n"); + } + + return 1; + } + + // 握手失败,分析错误 int err = SSL_get_error(ssl, ret); - fprintf(stderr, "TLS握手失败,错误代码: %d\n", err); + fprintf(stderr, "TLS握手失败,错误代码: %d (尝试 %d/%d)\n", err, retry_count + 1, max_retries + 1); // 详细的错误诊断 switch (err) { case SSL_ERROR_SSL: fprintf(stderr, "SSL协议错误,可能是证书验证失败\n"); + ERR_print_errors_fp(stderr); break; + case SSL_ERROR_SYSCALL: - fprintf(stderr, "系统调用错误\n"); + fprintf(stderr, "系统调用错误,详细分析:\n"); + analyze_syscall_error(ssl, ret); + + // 根据系统错误判断是否值得重试 + if (sockfd > 0) { + int error = 0; + socklen_t len = sizeof(error); + if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len) == 0) { + switch (error) { + case ECONNREFUSED: + case EHOSTUNREACH: + case ENETUNREACH: + fprintf(stderr, "网络连接问题,建议检查服务器地址和端口\n"); + break; + case ETIMEDOUT: + fprintf(stderr, "连接超时,可能是网络延迟或服务器负载高\n"); + break; + case ECONNRESET: + case EPIPE: + fprintf(stderr, "连接被重置,可能是服务器问题\n"); + break; + case EAGAIN: + fprintf(stderr, "资源暂时不可用,适合重试\n"); + break; +#ifdef EWOULDBLOCK +#if EAGAIN != EWOULDBLOCK + case EWOULDBLOCK: + fprintf(stderr, "资源暂时不可用,适合重试\n"); + break; +#endif +#endif + default: + fprintf(stderr, "其他系统错误\n"); + break; + } + } + } break; + case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: - fprintf(stderr, "需要更多数据\n"); + fprintf(stderr, "需要更多数据,这通常是正常的握手过程\n"); + // 对于WANT_READ/WANT_WRITE,通常不需要重试,这是正常的握手流程 + if (retry_count == 0) { + fprintf(stderr, "这是正常的握手流程,不需要重试\n"); + return 0; + } break; + default: fprintf(stderr, "未知SSL错误\n"); + ERR_print_errors_fp(stderr); break; } - ERR_print_errors_fp(stderr); + retry_count++; - // 提供解决建议 - fprintf(stderr, "\n解决建议:\n"); - fprintf(stderr, "1. 使用 --no-verify 选项禁用证书验证\n"); - fprintf(stderr, "2. 检查服务器证书是否有效\n"); - fprintf(stderr, "3. 确保CA证书文件正确\n"); - fprintf(stderr, "4. 检查系统时间是否正确\n"); - - return 0; + // 如果不是最后一次尝试,提供重试建议 + if (retry_count <= max_retries) { + fprintf(stderr, "\n重试建议:\n"); + fprintf(stderr, "1. 检查网络连接\n"); + fprintf(stderr, "2. 验证服务器地址和端口\n"); + fprintf(stderr, "3. 检查防火墙设置\n"); + fprintf(stderr, "4. 尝试使用 --no-verify 选项\n"); + fprintf(stderr, "5. 检查证书文件是否正确\n"); + } } - // 获取连接信息 - printf("TLS握手成功!\n"); - printf("握手耗时: %.2f 秒\n", handshake_time); - printf("协议版本: %s\n", SSL_get_version(ssl)); - printf("密码套件: %s\n", SSL_get_cipher(ssl)); + // 所有重试都失败了 + fprintf(stderr, "\n所有重试尝试都失败了\n"); + fprintf(stderr, "最终解决建议:\n"); + fprintf(stderr, "1. 使用 --no-verify 选项禁用证书验证\n"); + fprintf(stderr, "2. 检查服务器证书是否有效\n"); + fprintf(stderr, "3. 确保CA证书文件正确\n"); + fprintf(stderr, "4. 检查系统时间是否正确\n"); + fprintf(stderr, "5. 检查网络连接和防火墙设置\n"); + fprintf(stderr, "6. 尝试使用不同的TLS版本\n"); - // 验证服务器证书 - X509* cert = SSL_get_peer_certificate(ssl); - if (cert) { - printf("服务器证书验证成功\n"); - X509_free(cert); - } else { - printf("警告: 无法获取服务器证书\n"); - } - - return 1; + return 0; +} + +/** + * @brief 执行TLS握手(保持向后兼容) + * @param ssl SSL连接对象 + * @return int 成功返回1,失败返回0 + */ +int perform_tls_handshake(SSL* ssl) { + // 使用默认重试参数:最多重试3次,基础延迟2秒 + return perform_tls_handshake_with_retry(ssl, 3, 2); } /** @@ -549,10 +702,16 @@ int receive_response(SSL* ssl) { * @param cert_file 客户端证书文件 * @param key_file 客户端私钥文件 * @param ca_file CA证书文件 + * @param verify_peer 是否验证服务器证书 + * @param tls_version TLS版本 + * @param debug_level 调试级别 + * @param max_retries 最大重试次数 + * @param retry_delay 重试延迟 * @return int 成功返回1,失败返回0 */ int perform_tls_test(const char* hostname, int port, const char* cert_file, - const char* key_file, const char* ca_file, int verify_peer, int tls_version, int debug_level) { + const char* key_file, const char* ca_file, int verify_peer, + int tls_version, int debug_level, int max_retries, int retry_delay) { int sockfd; SSL* ssl; SSL_CTX* local_ctx = NULL; @@ -590,8 +749,8 @@ int perform_tls_test(const char* hostname, int port, const char* cert_file, // 将套接字绑定到SSL连接 SSL_set_fd(ssl, sockfd); - // 执行TLS握手 - if (perform_tls_handshake(ssl)) { + // 执行TLS握手(使用指定的重试参数) + if (perform_tls_handshake_with_retry(ssl, max_retries, retry_delay)) { // 发送测试数据 if (send_test_data(ssl)) { // 接收响应 @@ -679,11 +838,16 @@ int perform_tls_test(const char* hostname, int port, const char* cert_file, * @param verify_peer 是否验证服务器证书 * @param test_count 测试次数 (-1表示无限循环) * @param interval 测试间隔 + * @param continue_on_failure 失败时是否继续 + * @param debug_level 调试级别 + * @param max_retries 最大重试次数 + * @param retry_delay 重试延迟 * @return int 成功返回1,失败返回0 */ int perform_tls_version_test(const char* hostname, int port, const char* cert_file, const char* key_file, const char* ca_file, int verify_peer, - int test_count, int interval, int continue_on_failure, int debug_level) { + int test_count, int interval, int continue_on_failure, + int debug_level, int max_retries, int retry_delay) { int test_num = 0; int success_count = 0; int total_tests = 0; @@ -704,7 +868,7 @@ int perform_tls_version_test(const char* hostname, int port, const char* cert_fi // 测试TLS 1.2 printf("\n--- 第 %d 次测试 - TLS 1.2 ---\n", test_num); - if (perform_tls_test(hostname, port, cert_file, key_file, ca_file, verify_peer, 1, debug_level)) { + if (perform_tls_test(hostname, port, cert_file, key_file, ca_file, verify_peer, 1, debug_level, max_retries, retry_delay)) { printf("✓ TLS 1.2 测试成功\n"); success_count++; } else { @@ -724,7 +888,7 @@ int perform_tls_version_test(const char* hostname, int port, const char* cert_fi // 测试TLS 1.3 printf("\n--- 第 %d 次测试 - TLS 1.3 ---\n", test_num); - if (perform_tls_test(hostname, port, cert_file, key_file, ca_file, verify_peer, 2, debug_level)) { + if (perform_tls_test(hostname, port, cert_file, key_file, ca_file, verify_peer, 2, debug_level, max_retries, retry_delay)) { printf("✓ TLS 1.3 测试成功\n"); success_count++; } else { @@ -778,11 +942,14 @@ void print_usage(const char* program_name) { printf(" -t TLS版本 (1=TLS1.2, 2=TLS1.3, 3=循环测试1.2和1.3)\n"); printf(" -f 失败时继续测试(默认:失败时退出)\n"); printf(" -d OpenSSL调试级别 (0=无, 1=基本, 2=详细, 3=完整)\n"); + printf(" -r 握手重试次数 (默认: 3)\n"); + printf(" -w 重试基础延迟秒数 (默认: 2)\n"); printf(" --no-verify 禁用服务器证书验证\n"); printf(" --help 显示此帮助信息\n"); printf("\n示例:\n"); printf(" %s -h 192.168.1.100 -p 8443 -c client.crt -k client.key\n", program_name); printf(" %s -h example.com -p 443 -c client.crt -k client.key -a ca.crt -n 10\n", program_name); + printf(" %s -h server.com -c client.crt -k client.key -r 5 -w 3\n", program_name); } int main(int argc, char *argv[]) { @@ -798,6 +965,8 @@ int main(int argc, char *argv[]) { int tls_version = 3; // 默认循环测试TLS 1.2和1.3 int continue_on_failure = 0; // 失败时是否继续测试 int debug_level = 0; // OpenSSL调试级别 + int max_retries = 3; // 默认重试次数 + int retry_delay = 2; // 默认重试延迟 int opt; int test_num = 0; int success_count = 0; @@ -821,7 +990,7 @@ int main(int argc, char *argv[]) { } // 解析命令行参数 - while ((opt = getopt(argc, argv, "h:p:c:k:a:n:i:vxt:fd:")) != -1) { + while ((opt = getopt(argc, argv, "h:p:c:k:a:n:i:vxt:fd:r:w:")) != -1) { switch (opt) { case 'h': strncpy(hostname, optarg, sizeof(hostname) - 1); @@ -869,6 +1038,22 @@ int main(int argc, char *argv[]) { return 1; } break; + case 'r': + max_retries = atoi(optarg); + if (max_retries < 0 || max_retries > 10) { + fprintf(stderr, "错误: 重试次数必须是0-10\n"); + print_usage(argv[0]); + return 1; + } + break; + case 'w': + retry_delay = atoi(optarg); + if (retry_delay < 1 || retry_delay > 60) { + fprintf(stderr, "错误: 重试延迟必须是1-60秒\n"); + print_usage(argv[0]); + return 1; + } + break; default: print_usage(argv[0]); return 1; @@ -890,7 +1075,7 @@ int main(int argc, char *argv[]) { // 循环测试TLS 1.2和1.3 return perform_tls_version_test(hostname, port, cert_file, key_file, ca_file[0] ? ca_file : NULL, !no_verify, - test_count, interval, continue_on_failure, debug_level); + test_count, interval, continue_on_failure, debug_level, max_retries, retry_delay); } else { // 单版本测试 // 创建SSL上下文 @@ -930,7 +1115,7 @@ int main(int argc, char *argv[]) { } // 执行TLS测试 - if (perform_tls_test(hostname, port, cert_file, key_file, ca_file, !no_verify, tls_version, debug_level)) { + if (perform_tls_test(hostname, port, cert_file, key_file, ca_file, !no_verify, tls_version, debug_level, max_retries, retry_delay)) { printf("✓ 第 %d 次测试成功\n", test_num); success_count++; } else { diff --git a/tls_server.cpp b/tls_server.cpp index 5b0c732..1930a92 100644 --- a/tls_server.cpp +++ b/tls_server.cpp @@ -11,25 +11,204 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include -const int PORT = 7271; +const int DEFAULT_PORT = 7271; const char* SERVER_CERT_FILE = "server.crt"; const char* SERVER_KEY_FILE = "server.key"; const char* CA_CERT_FILE = "ca.crt"; volatile sig_atomic_t server_running = 1; +std::atomic connection_count(0); +std::atomic successful_connections(0); +std::atomic failed_connections(0); +std::mutex log_mutex; void signal_handler(int sig) { std::cout << "\n收到信号 " << sig << ",正在关闭服务器..." << std::endl; server_running = 0; } +/** + * @brief 获取当前时间戳字符串 + * @return std::string 格式化的时间戳 + */ +std::string get_current_time() { + auto now = std::chrono::system_clock::now(); + auto time_t = std::chrono::system_clock::to_time_t(now); + auto ms = std::chrono::duration_cast( + now.time_since_epoch()) % 1000; + + std::stringstream ss; + ss << std::put_time(std::localtime(&time_t), "%Y-%m-%d %H:%M:%S"); + ss << '.' << std::setfill('0') << std::setw(3) << ms.count(); + return ss.str(); +} + +/** + * @brief 线程安全的日志输出 + * @param message 日志消息 + */ +void log_message(const std::string& message) { + std::lock_guard lock(log_mutex); + std::cout << "[" << get_current_time() << "] " << message << std::endl; +} + +/** + * @brief 打印连接统计信息 + */ +void print_connection_stats() { + std::lock_guard lock(log_mutex); + std::cout << "\n=== 连接统计信息 ===" << std::endl; + std::cout << "总连接次数: " << connection_count.load() << std::endl; + std::cout << "成功连接次数: " << successful_connections.load() << std::endl; + std::cout << "失败连接次数: " << failed_connections.load() << std::endl; + if (connection_count.load() > 0) { + double success_rate = (double)successful_connections.load() / connection_count.load() * 100; + std::cout << "成功率: " << std::fixed << std::setprecision(2) << success_rate << "%" << std::endl; + } + std::cout << "===================" << std::endl; +} + +/** + * @brief 打印使用说明 + */ +void print_usage(const char* program_name) { + std::cout << "用法: " << program_name << " [选项]" << std::endl; + std::cout << "选项:" << std::endl; + std::cout << " -p 服务器端口 (默认: " << DEFAULT_PORT << ")" << std::endl; + std::cout << " -c 服务器证书文件 (默认: " << SERVER_CERT_FILE << ")" << std::endl; + std::cout << " -k 服务器私钥文件 (默认: " << SERVER_KEY_FILE << ")" << std::endl; + std::cout << " -a CA证书文件 (默认: " << CA_CERT_FILE << ")" << std::endl; + std::cout << " -h 显示此帮助信息" << std::endl; + std::cout << std::endl; + std::cout << "示例:" << std::endl; + std::cout << " " << program_name << " -p 8443" << std::endl; + std::cout << " " << program_name << " -p 443 -c my_server.crt -k my_server.key" << std::endl; + std::cout << " " << program_name << " -p 8443 -c server.crt -k server.key -a ca.crt" << std::endl; +} + +/** + * @brief 解析命令行参数 + * @param argc 参数个数 + * @param argv 参数数组 + * @param port 输出端口 + * @param cert_file 输出证书文件 + * @param key_file 输出私钥文件 + * @param ca_file 输出CA证书文件 + * @return bool 解析成功返回true,失败返回false + */ +bool parse_arguments(int argc, char* argv[], int& port, std::string& cert_file, + std::string& key_file, std::string& ca_file) { + port = DEFAULT_PORT; + cert_file = SERVER_CERT_FILE; + key_file = SERVER_KEY_FILE; + ca_file = CA_CERT_FILE; + + int opt; + while ((opt = getopt(argc, argv, "p:c:k:a:h")) != -1) { + switch (opt) { + case 'p': + port = std::atoi(optarg); + if (port <= 0 || port > 65535) { + std::cerr << "错误: 端口号必须在1-65535之间" << std::endl; + return false; + } + break; + case 'c': + cert_file = optarg; + break; + case 'k': + key_file = optarg; + break; + case 'a': + ca_file = optarg; + break; + case 'h': + print_usage(argv[0]); + return false; + default: + print_usage(argv[0]); + return false; + } + } + + return true; +} + void print_openssl_errors() { BIO* bio = BIO_new_fp(stderr, BIO_NOCLOSE); ERR_print_errors(bio); BIO_free(bio); } +/** + * @brief 分析SSL错误并返回详细错误信息 + * @param ssl SSL连接对象 + * @param ret SSL函数返回值 + * @return std::string 详细错误信息 + */ +std::string analyze_ssl_error(SSL* ssl, int ret) { + std::stringstream error_info; + int err = SSL_get_error(ssl, ret); + + error_info << "SSL错误代码: " << err << " ("; + + switch (err) { + case SSL_ERROR_NONE: + error_info << "SSL_ERROR_NONE"; + break; + case SSL_ERROR_SSL: + error_info << "SSL_ERROR_SSL - SSL协议错误"; + break; + case SSL_ERROR_WANT_READ: + error_info << "SSL_ERROR_WANT_READ - 需要读取更多数据"; + break; + case SSL_ERROR_WANT_WRITE: + error_info << "SSL_ERROR_WANT_WRITE - 需要写入更多数据"; + break; + case SSL_ERROR_WANT_X509_LOOKUP: + error_info << "SSL_ERROR_WANT_X509_LOOKUP - 需要X509查找"; + break; + case SSL_ERROR_SYSCALL: + error_info << "SSL_ERROR_SYSCALL - 系统调用错误"; + break; + case SSL_ERROR_ZERO_RETURN: + error_info << "SSL_ERROR_ZERO_RETURN - 连接被关闭"; + break; + case SSL_ERROR_WANT_CONNECT: + error_info << "SSL_ERROR_WANT_CONNECT - 需要连接"; + break; + case SSL_ERROR_WANT_ACCEPT: + error_info << "SSL_ERROR_WANT_ACCEPT - 需要接受连接"; + break; + default: + error_info << "未知SSL错误"; + break; + } + error_info << ")"; + + // 如果是系统调用错误,获取系统错误信息 + if (err == SSL_ERROR_SYSCALL) { + int sys_err = errno; + if (sys_err != 0) { + error_info << " | 系统错误: " << sys_err << " (" << strerror(sys_err) << ")"; + } + } + + // 获取SSL状态信息 + int state = SSL_get_state(ssl); + error_info << " | SSL状态: " << SSL_state_string_long(ssl); + + return error_info.str(); +} + void init_openssl() { SSL_load_error_strings(); OpenSSL_add_ssl_algorithms(); @@ -67,29 +246,37 @@ int verify_callback(int preverify_ok, X509_STORE_CTX* ctx) { return preverify_ok; } -void configure_context(SSL_CTX* ctx) { - if (SSL_CTX_use_certificate_file(ctx, SERVER_CERT_FILE, SSL_FILETYPE_PEM) <= 0) { - std::cerr << "无法加载服务器证书" << std::endl; +void configure_context(SSL_CTX* ctx, const std::string& cert_file, const std::string& key_file, const std::string& ca_file) { + log_message("加载服务器证书: " + cert_file); + if (SSL_CTX_use_certificate_file(ctx, cert_file.c_str(), SSL_FILETYPE_PEM) <= 0) { + log_message("错误: 无法加载服务器证书 " + cert_file); print_openssl_errors(); exit(EXIT_FAILURE); } + log_message("服务器证书加载成功"); - if (SSL_CTX_use_PrivateKey_file(ctx, SERVER_KEY_FILE, SSL_FILETYPE_PEM) <= 0) { - std::cerr << "无法加载服务器私钥" << std::endl; + log_message("加载服务器私钥: " + key_file); + if (SSL_CTX_use_PrivateKey_file(ctx, key_file.c_str(), SSL_FILETYPE_PEM) <= 0) { + log_message("错误: 无法加载服务器私钥 " + key_file); print_openssl_errors(); exit(EXIT_FAILURE); } + log_message("服务器私钥加载成功"); + log_message("验证证书和私钥匹配..."); if (!SSL_CTX_check_private_key(ctx)) { - std::cerr << "证书和私钥不匹配" << std::endl; + log_message("错误: 证书和私钥不匹配"); exit(EXIT_FAILURE); } + log_message("证书和私钥匹配验证成功"); - if (SSL_CTX_load_verify_locations(ctx, CA_CERT_FILE, nullptr) <= 0) { - std::cerr << "无法加载CA证书" << std::endl; + log_message("加载CA证书: " + ca_file); + if (SSL_CTX_load_verify_locations(ctx, ca_file.c_str(), nullptr) <= 0) { + log_message("错误: 无法加载CA证书 " + ca_file); print_openssl_errors(); exit(EXIT_FAILURE); } + log_message("CA证书加载成功"); SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verify_callback); SSL_CTX_set_verify_depth(ctx, 4); @@ -97,6 +284,8 @@ void configure_context(SSL_CTX* ctx) { // 关键优化:简化SSL选项 SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION); SSL_CTX_set_cipher_list(ctx, "ECDHE-RSA-AES128-GCM-SHA256"); + + log_message("SSL上下文配置完成"); } void graceful_ssl_close(SSL* ssl, int fd) { @@ -109,16 +298,27 @@ void graceful_ssl_close(SSL* ssl, int fd) { } void handle_connection(SSL* ssl, int client_fd, const char* client_ip, uint16_t client_port) { - std::cout << "\n处理连接 " << client_ip << ":" << client_port << std::endl; - std::cout << "协议: " << SSL_get_version(ssl) << std::endl; + log_message("处理连接 " + std::string(client_ip) + ":" + std::to_string(client_port)); + log_message("协议: " + std::string(SSL_get_version(ssl))); + log_message("密码套件: " + std::string(SSL_get_cipher(ssl))); // 验证客户端证书 X509* client_cert = SSL_get_peer_certificate(ssl); if (!client_cert) { - std::cerr << "客户端未提供证书" << std::endl; + log_message("错误: 客户端未提供证书"); + failed_connections++; graceful_ssl_close(ssl, client_fd); return; } + + // 获取证书信息 + char* subject = X509_NAME_oneline(X509_get_subject_name(client_cert), 0, 0); + char* issuer = X509_NAME_oneline(X509_get_issuer_name(client_cert), 0, 0); + log_message("客户端证书主题: " + std::string(subject ? subject : "未知")); + log_message("客户端证书颁发者: " + std::string(issuer ? issuer : "未知")); + + if (subject) OPENSSL_free(subject); + if (issuer) OPENSSL_free(issuer); X509_free(client_cert); // 设置TCP_NODELAY @@ -129,14 +329,14 @@ void handle_connection(SSL* ssl, int client_fd, const char* client_ip, uint16_t struct timeval timeout = {60, 0}; setsockopt(client_fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); - std::cout << "等待客户端数据..." << std::endl; + log_message("等待客户端数据..."); // 读取客户端数据 char buffer[4096]; int bytes = SSL_read(ssl, buffer, sizeof(buffer)); if (bytes > 0) { - std::cout << "收到数据: " << bytes << "字节" << std::endl; + log_message("收到数据: " + std::to_string(bytes) + "字节"); // 发送响应 const char* response = @@ -146,27 +346,44 @@ void handle_connection(SSL* ssl, int client_fd, const char* client_ip, uint16_t "\r\n" "Hello from TLS server!"; SSL_write(ssl, response, strlen(response)); - std::cout << "已发送响应" << std::endl; + log_message("已发送响应"); + successful_connections++; } else if (bytes == 0) { - std::cout << "客户端关闭连接" << std::endl; + log_message("客户端关闭连接"); } else { - std::cout << "客户端未发送数据(超时)" << std::endl; + int ssl_err = SSL_get_error(ssl, bytes); + log_message("SSL读取错误: " + analyze_ssl_error(ssl, bytes)); } graceful_ssl_close(ssl, client_fd); } -int main() { +int main(int argc, char* argv[]) { + // 解析命令行参数 + int port; + std::string cert_file, key_file, ca_file; + + if (!parse_arguments(argc, argv, port, cert_file, key_file, ca_file)) { + return 1; + } + signal(SIGINT, signal_handler); signal(SIGTERM, signal_handler); + log_message("=== TLS服务器启动 ==="); + log_message("端口: " + std::to_string(port)); + log_message("证书文件: " + cert_file); + log_message("私钥文件: " + key_file); + log_message("CA证书文件: " + ca_file); + log_message("=================="); + init_openssl(); SSL_CTX* ctx = create_context(); - configure_context(ctx); + configure_context(ctx, cert_file, key_file, ca_file); int sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) { - perror("socket"); + log_message("错误: 创建套接字失败 - " + std::string(strerror(errno))); exit(EXIT_FAILURE); } @@ -175,20 +392,21 @@ int main() { sockaddr_in addr{}; addr.sin_family = AF_INET; - addr.sin_port = htons(PORT); + addr.sin_port = htons(port); addr.sin_addr.s_addr = INADDR_ANY; if (bind(sockfd, (sockaddr*)&addr, sizeof(addr)) < 0) { - perror("bind"); + log_message("错误: 绑定端口失败 - " + std::string(strerror(errno))); exit(EXIT_FAILURE); } if (listen(sockfd, 10) < 0) { - perror("listen"); + log_message("错误: 监听失败 - " + std::string(strerror(errno))); exit(EXIT_FAILURE); } - std::cout << "服务器监听端口 " << PORT << std::endl; + log_message("服务器启动,监听端口 " + std::to_string(port)); + log_message("等待客户端连接..."); while (server_running) { sockaddr_in client_addr{}; @@ -196,28 +414,57 @@ int main() { int client_fd = accept(sockfd, (sockaddr*)&client_addr, &client_len); if (client_fd < 0) { - if (server_running) perror("accept"); + if (server_running) { + log_message("接受连接失败: " + std::string(strerror(errno))); + } continue; } + // 增加连接计数 + connection_count++; + int current_conn = connection_count.load(); + char client_ip[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &client_addr.sin_addr, client_ip, INET_ADDRSTRLEN); uint16_t client_port = ntohs(client_addr.sin_port); + log_message("================"); + log_message("新连接 #" + std::to_string(current_conn) + " 来自 " + + std::string(client_ip) + ":" + std::to_string(client_port)); + SSL* ssl = SSL_new(ctx); SSL_set_fd(ssl, client_fd); - if (SSL_accept(ssl) <= 0) { - std::cerr << "SSL握手失败: "; + log_message("开始SSL握手..."); + int ssl_ret = SSL_accept(ssl); + + if (ssl_ret <= 0) { + std::string error_msg = "SSL握手失败 #" + std::to_string(current_conn) + ": " + + analyze_ssl_error(ssl, ssl_ret); + log_message(error_msg); + + // 打印详细的OpenSSL错误 + log_message("OpenSSL错误详情:"); print_openssl_errors(); + + failed_connections++; SSL_free(ssl); close(client_fd); continue; } + log_message("SSL握手成功 #" + std::to_string(current_conn)); handle_connection(ssl, client_fd, client_ip, client_port); + + // 每10个连接显示一次统计信息 + if (current_conn % 10 == 0) { + print_connection_stats(); + } } + log_message("服务器关闭中..."); + print_connection_stats(); + close(sockfd); SSL_CTX_free(ctx); cleanup_openssl();