first commit

This commit is contained in:
huanglinhuan
2025-10-09 10:05:40 +08:00
commit 63273630b3
12 changed files with 1395 additions and 0 deletions

225
tls_server.cpp Normal file
View File

@@ -0,0 +1,225 @@
#include <iostream>
#include <string>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/select.h>
#include <vector>
#include <netinet/tcp.h>
const int 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;
void signal_handler(int sig) {
std::cout << "\n收到信号 " << sig << ",正在关闭服务器..." << std::endl;
server_running = 0;
}
void print_openssl_errors() {
BIO* bio = BIO_new_fp(stderr, BIO_NOCLOSE);
ERR_print_errors(bio);
BIO_free(bio);
}
void init_openssl() {
SSL_load_error_strings();
OpenSSL_add_ssl_algorithms();
}
void cleanup_openssl() {
#if OPENSSL_VERSION_NUMBER < 0x10100000L
EVP_cleanup();
#endif
}
SSL_CTX* create_context() {
const SSL_METHOD* method = TLS_server_method();
SSL_CTX* ctx = SSL_CTX_new(method);
if (!ctx) {
std::cerr << "无法创建SSL上下文" << std::endl;
print_openssl_errors();
exit(EXIT_FAILURE);
}
SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION);
return ctx;
}
int verify_callback(int preverify_ok, X509_STORE_CTX* ctx) {
if (!preverify_ok) {
int err = X509_STORE_CTX_get_error(ctx);
if (err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) {
return 1;
}
}
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;
print_openssl_errors();
exit(EXIT_FAILURE);
}
if (SSL_CTX_use_PrivateKey_file(ctx, SERVER_KEY_FILE, SSL_FILETYPE_PEM) <= 0) {
std::cerr << "无法加载服务器私钥" << std::endl;
print_openssl_errors();
exit(EXIT_FAILURE);
}
if (!SSL_CTX_check_private_key(ctx)) {
std::cerr << "证书和私钥不匹配" << std::endl;
exit(EXIT_FAILURE);
}
if (SSL_CTX_load_verify_locations(ctx, CA_CERT_FILE, nullptr) <= 0) {
std::cerr << "无法加载CA证书" << std::endl;
print_openssl_errors();
exit(EXIT_FAILURE);
}
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verify_callback);
SSL_CTX_set_verify_depth(ctx, 4);
// 关键优化简化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");
}
void graceful_ssl_close(SSL* ssl, int fd) {
if (!ssl || fd < 0) return;
// 简化的关闭逻辑
SSL_shutdown(ssl);
SSL_free(ssl);
close(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;
// 验证客户端证书
X509* client_cert = SSL_get_peer_certificate(ssl);
if (!client_cert) {
std::cerr << "客户端未提供证书" << std::endl;
graceful_ssl_close(ssl, client_fd);
return;
}
X509_free(client_cert);
// 设置TCP_NODELAY
int optval = 1;
setsockopt(client_fd, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(optval));
// 设置60秒读取超时
struct timeval timeout = {60, 0};
setsockopt(client_fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
std::cout << "等待客户端数据..." << std::endl;
// 读取客户端数据
char buffer[4096];
int bytes = SSL_read(ssl, buffer, sizeof(buffer));
if (bytes > 0) {
std::cout << "收到数据: " << bytes << "字节" << std::endl;
// 发送响应
const char* response =
"HTTP/1.1 200 OK\r\n"
"Content-Type: text/plain\r\n"
"Connection: close\r\n"
"\r\n"
"Hello from TLS server!";
SSL_write(ssl, response, strlen(response));
std::cout << "已发送响应" << std::endl;
} else if (bytes == 0) {
std::cout << "客户端关闭连接" << std::endl;
} else {
std::cout << "客户端未发送数据(超时)" << std::endl;
}
graceful_ssl_close(ssl, client_fd);
}
int main() {
signal(SIGINT, signal_handler);
signal(SIGTERM, signal_handler);
init_openssl();
SSL_CTX* ctx = create_context();
configure_context(ctx);
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("socket");
exit(EXIT_FAILURE);
}
int optval = 1;
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
sockaddr_in addr{};
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
addr.sin_addr.s_addr = INADDR_ANY;
if (bind(sockfd, (sockaddr*)&addr, sizeof(addr)) < 0) {
perror("bind");
exit(EXIT_FAILURE);
}
if (listen(sockfd, 10) < 0) {
perror("listen");
exit(EXIT_FAILURE);
}
std::cout << "服务器监听端口 " << PORT << std::endl;
while (server_running) {
sockaddr_in client_addr{};
socklen_t client_len = sizeof(client_addr);
int client_fd = accept(sockfd, (sockaddr*)&client_addr, &client_len);
if (client_fd < 0) {
if (server_running) perror("accept");
continue;
}
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);
SSL* ssl = SSL_new(ctx);
SSL_set_fd(ssl, client_fd);
if (SSL_accept(ssl) <= 0) {
std::cerr << "SSL握手失败: ";
print_openssl_errors();
SSL_free(ssl);
close(client_fd);
continue;
}
handle_connection(ssl, client_fd, client_ip, client_port);
}
close(sockfd);
SSL_CTX_free(ctx);
cleanup_openssl();
return 0;
}