基于openssl v3搭建ssl安全加固的c++ tcpserver

这篇具有很好参考价值的文章主要介绍了基于openssl v3搭建ssl安全加固的c++ tcpserver。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1 概述

tcp server和tcp client同时使用openssl库,可对通信双方流通的字节序列进行加解密,保障通信的安全。本文以c++编写的tcp server和tcp client为例子,openssl的版本为v3。

2 安装openssl v3

2.1 安装 perl-IPC-Cmd

openssl项目中的config脚本需要用到perl-IPC-Cmd工具。

yum -y install perl-IPC-Cmd

2.2 安装openssl v3

安装的结果放在目录/opt/openssl中。

mkdir -p /opt
cd /opt
wget --no-check-certificate https://www.openssl.org/source/openssl-3.1.0.tar.gz
tar xf openssl-3.1.0.tar.gz
cd openssl-3.1.0
./config --prefix=/opt/openssl
make -j8
make install

安装完毕后,结果如下图所示:
基于openssl v3搭建ssl安全加固的c++ tcpserver,c++,ssl,安全,c++,openssl


3 生成SSL私钥和证书

3.1 创建自签CA:

以下将生成一个名称为ca.key的key文件和一个名称为ca.crt的证书文件,CA的common name叫EXAMPLE Cert Authority。

openssl req -x509 -sha256 -newkey rsa:4096 -keyout ca.key -out ca.crt \
-days 3650 \
-nodes -subj '/CN=EXAMPLE Cert Authority'

3.2 生成key文件和csr文件

key文件名称为server.key,csr文件名称为server.csr,common name为apigateway.example.com。

openssl req -new -newkey rsa:4096 -keyout server.key -out server.csr -nodes \
-subj '/CN=apigateway.example.com'

3.2 编写csr扩展文件extfile

SAN就在subjectAltName字段中指定,可以写多个域名和IP,例如域名为apigateway,IP为192.168.16.128。

cat > extfile.cnf << EOF
[ v3_req ]
# Extensions to add to a certificate request
extendedKeyUsage = serverAuth,clientAuth
subjectAltName = DNS:apigateway.example.com,DNS:localhost,IP:192.168.16.128,IP:127.0.0.1
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
EOF

3.3 生成证书文件

依据key文件、csr文件和csr扩展文件,生成证书文件(名称为server.crt)

openssl x509 -req -sha256 -days 3650 \
-extfile extfile.cnf \
-extensions v3_req \
-in server.csr \
-CA ca.crt \
-CAkey ca.key \
-out server.crt \
-CAcreateserial

3.4 检验证书文件是否由指定CA签署

openssl verify -CAfile ca.crt -verbose server.crt

基于openssl v3搭建ssl安全加固的c++ tcpserver,c++,ssl,安全,c++,openssl


4 编写服务端代码

代码来自博客:https://blog.csdn.net/lf940841989/article/details/16881331

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

#define MAXBUF 1024

int main(int argc, char **argv)
{
    int sockfd, new_fd;
    socklen_t len;
    struct sockaddr_in my_addr, their_addr;
    unsigned int myport, lisnum;
    char buf[MAXBUF + 1];
    SSL_CTX *ctx;

        printf("Usage: %s port listenno(1) ip publickey privaterkey\n", argv[0]);

        if(argc != 6) {
                printf("parameter error\n");
                exit(0);
        }

    if (argv[1])
        myport = atoi(argv[1]);
    else
        myport = 7838;
    if (argv[2])
        lisnum = atoi(argv[2]);
    else
        lisnum = 2;

    /* SSL 库初始化*/
    SSL_library_init();

    /* 载入所有SSL 算法*/
    OpenSSL_add_all_algorithms();

    /* 载入所有SSL 错误消息*/
    SSL_load_error_strings();

    /* 以SSL V2 和V3 标准兼容方式产生一个SSL_CTX ,即SSL Content Text */
    ctx = SSL_CTX_new(SSLv23_server_method());
    //ctx = SSL_CTX_new(SSLv3_server_method());

    /* 也可以用SSLv2_server_method() 或SSLv3_server_method() 单独表示V2 或V3
     * 标准*/
    if (ctx == NULL) {
        ERR_print_errors_fp(stdout);
        exit(1);
    }

    /* 载入用户的数字证书, 此证书用来发送给客户端。证书里包含有公钥*/
    if (SSL_CTX_use_certificate_file(ctx, argv[4], SSL_FILETYPE_PEM) <= 0) {
        ERR_print_errors_fp(stdout);
        exit(1);
    }

    /* 载入用户私钥*/
    if (SSL_CTX_use_PrivateKey_file(ctx, argv[5], SSL_FILETYPE_PEM) <= 0) {
        ERR_print_errors_fp(stdout);
        exit(1);
    }

    /* 检查用户私钥是否正确*/
    if (!SSL_CTX_check_private_key(ctx)) {
        ERR_print_errors_fp(stdout);
        exit(1);
    }

    /* 开启一个socket 监听*/
    if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
        perror("socket");
        exit(1);
    } else
        printf("socket created\n");

    bzero(&my_addr, sizeof(my_addr));
    my_addr.sin_family = PF_INET;
    my_addr.sin_port = htons(myport);

    if (argv[3])
        my_addr.sin_addr.s_addr = inet_addr(argv[3]);
    else
        my_addr.sin_addr.s_addr = INADDR_ANY;

    if (bind(sockfd, (struct sockaddr *) &my_addr, sizeof(struct sockaddr))
            == -1) {
        perror("bind");
        exit(1);
    } else
        printf("binded\n");

    if (listen(sockfd, lisnum) == -1) {
        perror("listen");
        exit(1);
    } else
        printf("begin listen\n");

    while (1) {
        SSL *ssl;
        len = sizeof(struct sockaddr);

        /* 等待客户端连上来*/
        if ((new_fd =
                    accept(sockfd, (struct sockaddr *) &their_addr,
                           &len)) == -1) {
            perror("accept");
            exit(errno);
        } else
            printf("server: got connection from %s, port %d, socket %d\n",
                   inet_ntoa(their_addr.sin_addr),
                   ntohs(their_addr.sin_port), new_fd);

        /* 基于ctx 产生一个新的SSL */
        ssl = SSL_new(ctx);

        /* 将连接用户的socket 加入到SSL */
        SSL_set_fd(ssl, new_fd);

        /* 建立SSL 连接*/
        if (SSL_accept(ssl) == -1) {
            perror("accept");
            close(new_fd);
            break;
        }

        /* 开始处理每个新连接上的数据收发*/
        bzero(buf, MAXBUF + 1);
        strcpy(buf, "server->client");

        /* 发消息给客户端*/
        len = SSL_write(ssl, buf, strlen(buf));
        if (len <= 0) {
            printf
            ("消息'%s'发送失败!错误代码是%d,错误信息是'%s'\n",
             buf, errno, strerror(errno));
            goto finish;
        } else
            printf("消息'%s'发送成功,共发送了%d 个字节!\n",
                   buf, len);
        bzero(buf, MAXBUF + 1);

        /* 接收客户端的消息*/
        len = SSL_read(ssl, buf, MAXBUF);
        if (len > 0)
            printf("接收消息成功:'%s',共%d 个字节的数据\n",
                   buf, len);
        else
            printf
            ("消息接收失败!错误代码是%d,错误信息是'%s'\n",
             errno, strerror(errno));
        /* 处理每个新连接上的数据收发结束*/

finish:
        /* 关闭SSL 连接*/
        SSL_shutdown(ssl);

        /* 释放SSL */
        SSL_free(ssl);

        /* 关闭socket */
        close(new_fd);
    }

    /* 关闭监听的socket */
    close(sockfd);

    /* 释放CTX */
    SSL_CTX_free(ctx);

    return 0;
}

5 编写客户端代码

代码来自博客:https://blog.csdn.net/lf940841989/article/details/16881331

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

#define MAXBUF 1024

void ShowCerts(SSL * ssl)
{
    X509 *cert;
    char *line;
    cert = SSL_get_peer_certificate(ssl);
    if (cert != NULL) {
        printf("数字证书信息:\n");
        line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
        printf("证书: %s\n", line);
        free(line);
        line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
        printf("颁发者: %s\n", line);
        free(line);
        X509_free(cert);
    } else
        printf("无证书信息!\n");
}

int main(int argc, char **argv)
{
    int sockfd, len;
    struct sockaddr_in dest;
    char buffer[MAXBUF + 1];
    SSL_CTX *ctx;
    SSL *ssl;

        printf("Usage: %s server_ip server_port\n", argv[0]);

    if (argc != 3) {

        printf("参数格式错误!正确用法,比如: %s 127.0.0.1 80\n"
                 "此程序用来从某个IP 地址的服务器某个端口接收最多MAXBUF 个字节的消息\n",
         argv[0]);

        exit(0);
    }

    /* SSL 库初始化,参看ssl-server.c 代码*/
    SSL_library_init();
    OpenSSL_add_all_algorithms();
    SSL_load_error_strings();
    ctx = SSL_CTX_new(SSLv23_client_method());
    // ctx = SSL_CTX_new(SSLv3_client_method());
    if (ctx == NULL) {
        ERR_print_errors_fp(stdout);
        exit(1);
    }

    /* 创建一个socket 用于tcp 通信*/
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        perror("Socket");
        exit(errno);
    }
    printf("socket created\n");

    /* 初始化服务器端(对方)的地址和端口信息*/
    bzero(&dest, sizeof(dest));
    dest.sin_family = AF_INET;
    dest.sin_port = htons(atoi(argv[2]));
    if (inet_aton(argv[1], (struct in_addr *) &dest.sin_addr.s_addr) == 0) {
        perror(argv[1]);
        exit(errno);
    }
    printf("address created\n");

    /* 连接服务器*/
    if (connect(sockfd, (struct sockaddr *) &dest, sizeof(dest)) != 0) {
        perror("Connect ");
        exit(errno);
    }
    printf("server connected\n");

    /* 基于ctx 产生一个新的SSL */
    ssl = SSL_new(ctx);
    SSL_set_fd(ssl, sockfd);

    /* 建立SSL 连接*/
    if (SSL_connect(ssl) == -1)
        ERR_print_errors_fp(stderr);
    else {
        printf("Connected with %s encryption\n", SSL_get_cipher(ssl));
        ShowCerts(ssl);
    }
    /* 接收对方发过来的消息,最多接收MAXBUF 个字节*/
    bzero(buffer, MAXBUF + 1);

    /* 接收服务器来的消息*/
    len = SSL_read(ssl, buffer, MAXBUF);
    if (len > 0)
        printf("接收消息成功:'%s',共%d 个字节的数据\n",
               buffer, len);
    else {
        printf
        ("消息接收失败!错误代码是%d,错误信息是'%s'\n",
         errno, strerror(errno));
        goto finish;
    }
    bzero(buffer, MAXBUF + 1);
    strcpy(buffer, "from client->server");

    /* 发消息给服务器*/
    len = SSL_write(ssl, buffer, strlen(buffer));
    if (len < 0)
        printf
        ("消息'%s'发送失败!错误代码是%d,错误信息是'%s'\n",
         buffer, errno, strerror(errno));
    else
        printf("消息'%s'发送成功,共发送了%d 个字节!\n",
               buffer, len);

finish:
    /* 关闭连接*/
    SSL_shutdown(ssl);
    SSL_free(ssl);
    close(sockfd);
    SSL_CTX_free(ctx);

    return 0;
}


6 编译服务端代码并运行

g++ -o server server_ssl.c -Wl,-rpath,/opt/openssl/lib64 -L/opt/openssl/lib64 -lssl -lcrypto -I/opt/openssl/include
./server 8888 1 127.0.0.1 server.crt server.key

基于openssl v3搭建ssl安全加固的c++ tcpserver,c++,ssl,安全,c++,openssl


7 编译客户端代码

g++ -o client client_ssl.c -L/opt/openssl/lib64 -lssl -lcrypto -I/opt/openssl/include -Wl,-rpath,/opt/openssl/lib64

基于openssl v3搭建ssl安全加固的c++ tcpserver,c++,ssl,安全,c++,openssl


8 运行客户端

./client 127.0.0.1 8888

客户端的输出如下图:
基于openssl v3搭建ssl安全加固的c++ tcpserver,c++,ssl,安全,c++,openssl

客户端会打印服务端传输过来的ssl证书,CA和CN正是本文在创建证书阶段所填写的信息,说明在TCP握手之后,进行SSL握手也是成功的。握手成功后,往服务端发送信息"from client->server"。

此时服务端的输出如下图:
基于openssl v3搭建ssl安全加固的c++ tcpserver,c++,ssl,安全,c++,openssl
服务端在SSL握手成功后,通过SSL_read()方法接收来自客户端发送过来的加密信息并自动解密(明文信息为"from client->server")。


9 小结

tcp握手成功后,服务端和客户端代码使用openssl库能加解密tcp中传输的字节序列,保障通信的安全。在代码编写套路上,服务端和客户端代码在拿到fd之后,将fd塞进ssl上下文对象中,使用格式如SSL_XXX的方法来进行SSL握手、读写数据。文章来源地址https://www.toymoban.com/news/detail-823730.html

到了这里,关于基于openssl v3搭建ssl安全加固的c++ tcpserver的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • linux系统openssl的C++开发环境搭建

    在Linux上进行OpenSSL的C++开发,你需要安装OpenSSL库并且在编译时链接该库。以下是在Linux环境中搭建基础开发环境的步骤: 在终端中执行以下命令来安装OpenSSL开发包: 这将会安装OpenSSL的开发头文件和库文件,使你能够在C++程序中使用OpenSSL功能。 创建一个新的C++源代码文件,

    2024年02月06日
    浏览(33)
  • 基于Linux对MySQL数据库的安全加固指南(超实用--实战版)

    👨‍🎓 博主简介   🏅云计算领域优质创作者   🏅华为云开发者社区专家博主   🏅阿里云开发者社区专家博主 💊 交流社区: 运维交流社区 欢迎大家的加入! 🐋 希望大家多多支持,我们一起进步!😄 🎉如果文章对你有帮助的话,欢迎 点赞 👍🏻 评论 💬 收藏

    2024年02月07日
    浏览(44)
  • 基于FiscoBcos v3.0.1 pro版的host网络模式集群环境搭建

    更新 最新版本系统软件 yum update -y 安装docker yum install -y yum-utils device-mapper-persistent-data lvm2 设置yum源 yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo 可以查看所有仓库中所有docker版本,并选择特定版本安装 yum list docker-ce --showduplicates | sort -r 安装 yum install

    2024年02月03日
    浏览(24)
  • 【使用openssl生成https v3版本证书】

    HTTPS是在HTTP的基础上通过传输加密和身份认证保证了传输过程的安全性,安全基础为SSL(安全套接字协议),或者叫TLS。 总的来说, 先通过非对称加密传输密钥,之后用该密钥对数据进行对称加密。 客户端向服务器发起HTTPS请求,连接到服务器的443端口 服务器端有一个密钥对

    2024年01月17日
    浏览(27)
  • 基于Ubuntu20.04搭建OpenHarmony v3.0.6的qemu仿真环境

    出于个人兴趣,也出于对国产操作系统的好奇,想尝试一下以LiteOS为内核的Openharmony。但过程相当不顺利,主要原因是官方文档内容组织的不敢恭维。挺好的东西,不把说明书写好,让用户怎么用?我研究的核心问题就一个:如何在基于Qemu仿真的Openharmony中输出一个hello worl

    2024年02月09日
    浏览(30)
  • SpringCloud微服务实战——搭建企业级开发框架:微服务安全加固—自定义Gateway拦截器实现防止SQL注入/XSS攻击

     SQL注入是常见的系统安全问题之一,用户通过特定方式向系统发送SQL脚本,可直接自定义操作系统数据库,如果系统没有对SQL注入进行拦截,那么用户甚至可以直接对数据库进行增删改查等操作。   XSS全称为Cross Site Script跨站点脚本攻击,和SQL注入类似,都是通过特定方

    2024年02月03日
    浏览(52)
  • OpenSSL v3.0.1版本安装及遇到的坑

    环境:CentOS 7.6,腾讯云轻量应用服务器 最近在折腾Python的flask框架,但是在请求HTTPS连接时遇到了下面这个报错: 一番搜索,认为是SSL版本过低的问题,不适配当前的Python版本,于是决定升级OpenSSL。 首先安装相关依赖: 官网下载OpenSSL的新版本、解压并进入安装目录 配置安

    2024年02月17日
    浏览(27)
  • 基于OpenSSL的安全Web Server实现

    目录 一、实验目的 二、实验软硬件要求 三、实验预习 四、实验内容(实验步骤、测试数据等) 实验步骤 1编辑代码 2解决报错 3准备网页 五、实验体会(遇到的问题及解决方法) 六、服务器代码 七、测试网页代码 熟悉软件安全需求分析方法,掌握软件安全分析技术。 1、

    2024年02月02日
    浏览(23)
  • 开源CA搭建-基于openssl实现数字证书的生成与分发

    目录 一、前言 二、openssl介绍 三、openssl的常用用法 (一)单向加密 (二)生成随机数 (三)生成公钥,私钥 1.生成私钥 2.提取公钥 四、搭建CA (一)创建根CA私钥: (二)生成自签名证书 (三)创建数据库以及新颁发证书数字 (四)设置证书的起始编号 (五)创建文件

    2024年02月06日
    浏览(32)
  • 基于openssl国密算法SM2搭建CA及颁发证书

    一、环境说明: 1.操作系统:CentOS 7.9 2.openssl : OpenSSL 1.1.1q  5 Jul 2022 二、搭建私有CA 1. 创建CA目录,在目录下创建相关目录如下: 在CA下生成证书索引库文件: 指定颁发第一个证书的序列号: 2. 生成SM2私钥 生成证书: 3.ca自签名证书生成完毕。将该证书后缀改为crt,导入到

    2024年02月12日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包