基于OpenSSL的多客户端加密通信系统

基于OpenSSL的多客户端加密通信系统

1. 系统概述

本系统实现了一个基于OpenSSL的多客户端加密通信系统,具有以下特点:

  • 使用SSL/TLS进行加密通信
  • 支持多客户端并发连接
  • 使用多线程处理客户端请求
  • 提供安全的握手过程和数据传输

2. 系统架构

2.1 文件结构

03.加密通信系统/
├── SSLServer.h          # 服务器类声明
├── SSLServer.cpp        # 服务器类实现
├── SSLClient.h          # 客户端类声明
├── SSLClient.cpp        # 客户端类实现
├── server_main.cpp      # 服务器主程序
├── client_main.cpp      # 客户端主程序
├── Makefile            # 编译配置文件
├── server.crt          # 服务器证书
└── server.key          # 服务器私钥

2.2 主要类设计

SSLServer类
  • 功能:处理多客户端连接和SSL通信
  • 主要方法:
    • start(): 启动服务器
    • stop(): 停止服务器
    • handleClient(): 处理客户端连接
    • initSSL(): 初始化SSL上下文
SSLClient类
  • 功能:实现客户端SSL通信
  • 主要方法:
    • connect(): 连接到服务器
    • send(): 发送数据
    • receive(): 接收数据
    • disconnect(): 断开连接

2.2 代码实现

SSLServer.h
#ifndef SSL_SERVER_H
#define SSL_SERVER_H

#include <string>
#include <vector>
#include <thread>
#include <mutex>
#include <memory>
#include <openssl/ssl.h>
#include <openssl/err.h>

class SSLServer {
public:
    // 构造函数,初始化端口号
    SSLServer(int port);
    // 析构函数,确保资源正确释放
    ~SSLServer();

    // 启动服务器
    bool start();
    // 停止服务器
    void stop();

private:
    // 初始化SSL上下文
    bool initSSL();
    // 处理客户端连接
    void handleClient(int clientSocket);
    // 清理SSL资源
    void cleanupSSL();

    int port_;                    // 服务器端口
    int serverSocket_;           // 服务器socket
    bool running_;               // 服务器运行状态
    SSL_CTX* ctx_;              // SSL上下文
    std::vector<std::thread> clientThreads_;  // 客户端线程列表
    std::mutex mutex_;          // 互斥锁,保护共享资源
};

#endif // SSL_SERVER_H
SSLServer.cpp
#include "SSLServer.h"
#include <iostream>
#include <cstring>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

// 构造函数:初始化OpenSSL库和成员变量
SSLServer::SSLServer(int port) : port_(port), serverSocket_(-1), running_(false), ctx_(nullptr) {
    // 初始化OpenSSL库
    SSL_library_init();
    OpenSSL_add_all_algorithms();
    SSL_load_error_strings();
}

// 析构函数:确保资源正确释放
SSLServer::~SSLServer() {
    stop();
    cleanupSSL();
}

// 初始化SSL上下文
bool SSLServer::initSSL() {
    // 创建SSL上下文,使用TLS服务器方法
    ctx_ = SSL_CTX_new(TLS_server_method());
    if (!ctx_) {
        std::cerr << "Error creating SSL context" << std::endl;
        return false;
    }

    // 加载服务器证书
    if (SSL_CTX_use_certificate_file(ctx_, "server.crt", SSL_FILETYPE_PEM) <= 0) {
        std::cerr << "Error loading certificate" << std::endl;
        return false;
    }

    // 加载服务器私钥
    if (SSL_CTX_use_PrivateKey_file(ctx_, "server.key", SSL_FILETYPE_PEM) <= 0) {
        std::cerr << "Error loading private key" << std::endl;
        return false;
    }

    return true;
}

// 启动服务器
bool SSLServer::start() {
    if (!initSSL()) {
        return false;
    }

    // 创建服务器socket
    serverSocket_ = socket(AF_INET, SOCK_STREAM, 0);
    if (serverSocket_ < 0) {
        std::cerr << "Error creating socket" << std::endl;
        return false;
    }

    // 设置socket选项,允许地址重用
    int opt = 1;
    if (setsockopt(serverSocket_, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
        std::cerr << "Error setting socket options" << std::endl;
        return false;
    }

    // 绑定地址和端口
    struct sockaddr_in serverAddr;
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_addr.s_addr = INADDR_ANY;
    serverAddr.sin_port = htons(port_);

    if (bind(serverSocket_, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) < 0) {
        std::cerr << "Error binding socket" << std::endl;
        return false;
    }

    // 开始监听连接
    if (listen(serverSocket_, SOMAXCONN) < 0) {
        std::cerr << "Error listening on socket" << std::endl;
        return false;
    }

    running_ = true;
    std::cout << "Server started on port " << port_ << std::endl;

    // 主循环:接受客户端连接
    while (running_) {
        struct sockaddr_in clientAddr;
        socklen_t clientLen = sizeof(clientAddr);
        int clientSocket = accept(serverSocket_, (struct sockaddr*)&clientAddr, &clientLen);

        if (clientSocket < 0) {
            std::cerr << "Error accepting connection" << std::endl;
            continue;
        }

        std::cout << "New client connected from " << inet_ntoa(clientAddr.sin_addr) << std::endl;

        // 为每个客户端创建新线程
        std::lock_guard<std::mutex> lock(mutex_);
        clientThreads_.emplace_back(&SSLServer::handleClient, this, clientSocket);
    }

    return true;
}

// 处理客户端连接
void SSLServer::handleClient(int clientSocket) {
    // 创建SSL连接
    SSL* ssl = SSL_new(ctx_);
    SSL_set_fd(ssl, clientSocket);

    // 执行SSL握手
    if (SSL_accept(ssl) <= 0) {
        std::cerr << "SSL handshake failed" << std::endl;
        SSL_free(ssl);
        close(clientSocket);
        return;
    }

    std::cout << "SSL connection established" << std::endl;

    // 处理客户端数据
    char buffer[1024];
    while (running_) {
        int bytes = SSL_read(ssl, buffer, sizeof(buffer) - 1);
        if (bytes <= 0) {
            break;
        }

        buffer[bytes] = '\0';
        std::cout << "Received: " << buffer << std::endl;

        // 发送响应
        std::string response = "Server received: " + std::string(buffer);
        SSL_write(ssl, response.c_str(), response.length());
    }

    // 清理SSL连接
    SSL_shutdown(ssl);
    SSL_free(ssl);
    close(clientSocket);
}

// 停止服务器
void SSLServer::stop() {
    running_ = false;
    
    // 等待所有客户端线程结束
    for (auto& thread : clientThreads_) {
        if (thread.joinable()) {
            thread.join();
        }
    }
    clientThreads_.clear();

    if (serverSocket_ >= 0) {
        close(serverSocket_);
        serverSocket_ = -1;
    }
}

// 清理SSL资源
void SSLServer::cleanupSSL() {
    if (ctx_) {
        SSL_CTX_free(ctx_);
        ctx_ = nullptr;
    }
    EVP_cleanup();
}
SSLClient.h
#ifndef SSL_CLIENT_H
#define SSL_CLIENT_H

#include <string>
#include <openssl/ssl.h>
#include <openssl/err.h>

class SSLClient {
public:
    // 构造函数,初始化主机和端口
    SSLClient(const std::string& host, int port);
    // 析构函数,确保资源正确释放
    ~SSLClient();

    // 连接到服务器
    bool connect();
    // 发送数据
    bool send(const std::string& message);
    // 接收数据
    std::string receive();
    // 断开连接
    void disconnect();

private:
    // 初始化SSL
    bool initSSL();
    // 清理SSL资源
    void cleanupSSL();

    std::string host_;           // 服务器主机名
    int port_;                  // 服务器端口
    int socket_;               // 客户端socket
    SSL_CTX* ctx_;            // SSL上下文
    SSL* ssl_;               // SSL连接
    bool connected_;         // 连接状态
};

#endif // SSL_CLIENT_H
SSLClient.cpp
#include "SSLClient.h"
#include <iostream>
#include <cstring>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

// 构造函数:初始化OpenSSL库和成员变量
SSLClient::SSLClient(const std::string& host, int port)
    : host_(host), port_(port), socket_(-1), ctx_(nullptr), ssl_(nullptr), connected_(false) {
    // 初始化OpenSSL库
    SSL_library_init();
    OpenSSL_add_all_algorithms();
    SSL_load_error_strings();
}

// 析构函数:确保资源正确释放
SSLClient::~SSLClient() {
    disconnect();
    cleanupSSL();
}

// 初始化SSL
bool SSLClient::initSSL() {
    // 创建SSL上下文,使用TLS客户端方法
    ctx_ = SSL_CTX_new(TLS_client_method());
    if (!ctx_) {
        std::cerr << "Error creating SSL context" << std::endl;
        return false;
    }

    return true;
}

// 连接到服务器
bool SSLClient::connect() {
    if (!initSSL()) {
        return false;
    }

    // 创建socket
    socket_ = socket(AF_INET, SOCK_STREAM, 0);
    if (socket_ < 0) {
        std::cerr << "Error creating socket" << std::endl;
        return false;
    }

    // 解析主机名
    struct hostent* server = gethostbyname(host_.c_str());
    if (!server) {
        std::cerr << "Error resolving hostname" << std::endl;
        return false;
    }

    // 设置服务器地址
    struct sockaddr_in serverAddr;
    memset(&serverAddr, 0, sizeof(serverAddr));
    serverAddr.sin_family = AF_INET;
    memcpy(&serverAddr.sin_addr.s_addr, server->h_addr, server->h_length);
    serverAddr.sin_port = htons(port_);

    // 连接到服务器
    if (::connect(socket_, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) < 0) {
        std::cerr << "Error connecting to server" << std::endl;
        return false;
    }

    // 创建SSL连接
    ssl_ = SSL_new(ctx_);
    SSL_set_fd(ssl_, socket_);

    // 执行SSL握手
    if (SSL_connect(ssl_) != 1) {
        std::cerr << "SSL handshake failed" << std::endl;
        return false;
    }

    std::cout << "Connected to server with " << SSL_get_cipher(ssl_) << " encryption" << std::endl;
    connected_ = true;
    return true;
}

// 发送数据
bool SSLClient::send(const std::string& message) {
    if (!connected_) {
        return false;
    }

    int bytes = SSL_write(ssl_, message.c_str(), message.length());
    return bytes > 0;
}

// 接收数据
std::string SSLClient::receive() {
    if (!connected_) {
        return "";
    }

    char buffer[1024];
    int bytes = SSL_read(ssl_, buffer, sizeof(buffer) - 1);
    if (bytes <= 0) {
        return "";
    }

    buffer[bytes] = '\0';
    return std::string(buffer);
}

// 断开连接
void SSLClient::disconnect() {
    if (connected_) {
        SSL_shutdown(ssl_);
        SSL_free(ssl_);
        ssl_ = nullptr;
        close(socket_);
        socket_ = -1;
        connected_ = false;
    }
}

// 清理SSL资源
void SSLClient::cleanupSSL() {
    if (ctx_) {
        SSL_CTX_free(ctx_);
        ctx_ = nullptr;
    }
    EVP_cleanup();
}
server_main.cpp
#include "SSLServer.h"
#include <iostream>
#include <csignal>

// 全局服务器指针,用于信号处理
SSLServer* server = nullptr;

// 信号处理函数
void signalHandler(int signum) {
    if (server) {
        std::cout << "\nShutting down server..." << std::endl;
        server->stop();
    }
    exit(signum);
}

int main(int argc, char* argv[]) {
    // 检查命令行参数
    if (argc != 2) {
        std::cerr << "Usage: " << argv[0] << " <port>" << std::endl;
        return 1;
    }

    int port = std::stoi(argv[1]);

    // 注册信号处理函数
    signal(SIGINT, signalHandler);
    signal(SIGTERM, signalHandler);

    // 创建并启动服务器
    server = new SSLServer(port);
    if (!server->start()) {
        std::cerr << "Failed to start server" << std::endl;
        delete server;
        return 1;
    }

    // 等待服务器停止
    while (true) {
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }

    delete server;
    return 0;
}
client_main.cpp
#include "SSLClient.h"
#include <iostream>
#include <string>
#include <csignal>

// 全局客户端指针,用于信号处理
SSLClient* client = nullptr;

// 信号处理函数
void signalHandler(int signum) {
    if (client) {
        std::cout << "\nDisconnecting..." << std::endl;
        client->disconnect();
    }
    exit(signum);
}

int main(int argc, char* argv[]) {
    // 检查命令行参数
    if (argc != 3) {
        std::cerr << "Usage: " << argv[0] << " <host> <port>" << std::endl;
        return 1;
    }

    std::string host = argv[1];
    int port = std::stoi(argv[2]);

    // 注册信号处理函数
    signal(SIGINT, signalHandler);
    signal(SIGTERM, signalHandler);

    // 创建并连接客户端
    client = new SSLClient(host, port);
    if (!client->connect()) {
        std::cerr << "Failed to connect to server" << std::endl;
        delete client;
        return 1;
    }

    // 交互式发送消息
    std::string message;
    while (true) {
        std::cout << "Enter message (or 'quit' to exit): ";
        std::getline(std::cin, message);

        if (message == "quit") {
            break;
        }

        if (!client->send(message)) {
            std::cerr << "Failed to send message" << std::endl;
            break;
        }

        std::string response = client->receive();
        if (response.empty()) {
            std::cerr << "Failed to receive response" << std::endl;
            break;
        }

        std::cout << "Server response: " << response << std::endl;
    }

    client->disconnect();
    delete client;
    return 0;
}
Makefile
# 编译器设置
CXX = g++
CXXFLAGS = -std=c++17 -Wall -Wextra

# OpenSSL库
OPENSSL_LIBS = -lssl -lcrypto -lpthread

# 目标文件
SERVER_OBJS = server_main.o SSLServer.o
CLIENT_OBJS = client_main.o SSLClient.o

# 可执行文件
SERVER = ssl_server
CLIENT = ssl_client

# 默认目标
all: $(SERVER) $(CLIENT)

# 编译服务器
$(SERVER): $(SERVER_OBJS)
	$(CXX) $(CXXFLAGS) -o $@ $^ $(OPENSSL_LIBS)

# 编译客户端
$(CLIENT): $(CLIENT_OBJS)
	$(CXX) $(CXXFLAGS) -o $@ $^ $(OPENSSL_LIBS)

# 编译规则
%.o: %.cpp
	$(CXX) $(CXXFLAGS) -c $<

# 清理
clean:
	rm -f $(SERVER) $(CLIENT) *.o

# 重新编译
rebuild: clean all

.PHONY: all clean rebuild

3. 安全特性

  1. SSL/TLS加密

    • 使用TLS 1.2/1.3协议
    • 支持多种加密套件
    • 证书验证
    • 安全的密钥交换
  2. 证书管理

    • 使用自签名证书
    • 在生产环境中应使用CA签发的证书
  3. 多线程安全

    • 使用互斥锁保护共享资源
    • 线程安全的资源管理

4. 编译和运行

4.1 环境要求

  • Ubuntu系统
  • OpenSSL开发库
  • g++编译器

4.2 安装依赖

sudo apt-get update
sudo apt-get install libssl-dev g++

4.3 生成证书

openssl req -x509 -newkey rsa:2048 -keyout server.key -out server.crt -days 365 -nodes -subj "/CN=localhost"

4.4 编译程序

cd 03.加密通信系统
make

4.5 运行程序

  1. 启动服务器:
./ssl_server 8888
  1. 启动客户端:
./ssl_client localhost 8888

5. Makefile说明

5.1 主要配置

# 编译器设置
CXX = g++
CXXFLAGS = -std=c++17 -Wall -Wextra

# OpenSSL库
OPENSSL_LIBS = -lssl -lcrypto -lpthread

5.2 常用命令

  • make: 编译所有目标
  • make clean: 清理编译产生的文件
  • make rebuild: 清理后重新编译

6. 使用示例

  1. 服务器端输出:
Server started on port 8888
New client connected from 127.0.0.1
SSL connection established
Received: Hello, Server!
  1. 客户端输出:
Connected to server with TLS_AES_256_GCM_SHA384 encryption
Enter message (or 'quit' to exit): Hello, Server!
Server response: Server received: Hello, Server!

7. 扩展建议

  1. 功能扩展

    • 添加用户认证
    • 实现文件传输
    • 添加数据压缩
    • 实现心跳检测
    • 添加日志系统
  2. 安全增强

    • 使用CA签发的证书
    • 实现证书吊销检查
    • 添加双向认证
    • 实现会话恢复
  3. 性能优化

    • 使用线程池
    • 实现连接池
    • 添加数据缓存
    • 优化内存使用

8. 注意事项

  1. 安全考虑

    • 生产环境必须使用CA签发的证书
    • 定期更新证书
    • 注意保护私钥安全
    • 实现适当的访问控制
  2. 性能考虑

    • 合理设置线程数
    • 注意内存使用
    • 实现超时机制
    • 处理异常情况
  3. 维护建议

    • 定期检查日志
    • 监控系统资源
    • 及时更新依赖
    • 做好备份工作

声明

该文章为学习过程中的笔记,目的是防止自己忘记,并且可以随时随地查阅。其中大部分内容收集于互联网。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值