社区网站建设资金申请,海曙网站制作,专业网站定制报价,dw如何制作表格网页数据安全的需求如今越来越重要#xff0c;本篇简单举例给日常的TCP/UDP通信加密#xff0c;至少能让想干坏事的崽犯罪的成本更高一些#xff08;如果会一些BPF的#xff0c;可能难不住这些崽#xff09;#xff0c;能让我们的数据更安全一点。
经典TCP socket编程
下面… 数据安全的需求如今越来越重要本篇简单举例给日常的TCP/UDP通信加密至少能让想干坏事的崽犯罪的成本更高一些如果会一些BPF的可能难不住这些崽能让我们的数据更安全一点。
经典TCP socket编程
下面为大家常见的TCP socket编程示例
客户端
/* client.c */
#include stdio.h
#include stdlib.h
#include string.h
#include unistd.h
#include arpa/inet.h
#include sys/types.h
#include sys/socket.h
#include netinet/in.h
#include errno.h
//#include myssl.hint main(int argc, char *argv[])
{// 定义相关变量int sockfd;struct sockaddr_in serv_addr;char buf[1024] {0};const char *greeting Hello from client;if(argc 2){printf(please input the ip of the server..\n);return -1;}//获取并初始化服务端地址serv_addr.sin_family AF_INET;serv_addr.sin_port htons(8080);if(inet_pton(AF_INET, argv[1], serv_addr.sin_addr) 0){fprintf(stderr, inet_pton failed[%d].\n, errno);return -1;}// 创建socketif((sockfd socket(AF_INET, SOCK_STREAM, 0)) 0){fprintf(stderr, create socket failed[%d].\n, errno);return -1;}// 连接到服务器if(connect(sockfd, (struct sockaddr *)serv_addr, sizeof(serv_addr)) 0){fprintf(stderr, connect failed[%d].\n, errno);return -1;}// 发送数据if(write(sockfd, greeting, strlen(greeting)) 0){fprintf(stderr, write failed[%d].\n, errno);return -1;}// 接收数据if(read(sockfd, buf, 1024) 0){fprintf(stderr, read failed[%d].\n, errno);return -1;}printf(received message:%s\n, buf);close(sockfd);
}
服务端
/* server.c */
#include stdio.h
#include stdlib.h
#include string.h
#include unistd.h
#include arpa/inet.h
#include sys/types.h
#include sys/socket.h
#include netinet/in.h
#include errno.h
//#include myssl.h#define MAX_CNT 5int main(int argc, char *argv[])
{// 定义相关变量int server_fd, new_socket;int opt 1; struct sockaddr_in serv_addr, cli_addr;socklen_t cli_addr_len;char buf[1024] {0};const char *greeting Hello from server;// 创建socket文件描述符if((server_fd socket(AF_INET, SOCK_STREAM, 0)) 0){fprintf(stderr, create socket failed[%d].\n, errno);return -1;}// 设置socket选项if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, opt, sizeof(opt))) { fprintf(stderr, set socket failed[%d].\n, errno);return -1; }// 绑定socket到指定端口和地址memset(serv_addr, 0, sizeof(serv_addr));serv_addr.sin_family AF_INET;serv_addr.sin_addr.s_addr htonl(INADDR_ANY);serv_addr.sin_port htons(8080);if(bind(server_fd, (struct sockaddr *)serv_addr, sizeof(serv_addr)) 0){fprintf(stderr, create bind failed[%d].\n, errno);return -1;}// 监听if(listen(server_fd, MAX_CNT) 0){fprintf(stderr, listen failed[%d].\n, errno);return -1;}// 接受客户端连接请求memset(cli_addr, 0, sizeof(cli_addr));cli_addr_len sizeof(cli_addr);if((new_socket accept(server_fd, (struct sockaddr *)cli_addr, (socklen_t *)cli_addr_len)) 0 ){fprintf(stderr, accept failed[%d].\n, errno);return -1;}printf(Client [%s-%d] connected.\n, inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port));// 接收数据if(read(new_socket, buf, 1024) 0){fprintf(stderr, read failed[%d].\n, errno);return -1;}printf(received message:%s\n, buf);// 发送数据if(write(new_socket, greeting, strlen(greeting)) 0){fprintf(stderr, write failed[%d].\n, errno);return -1;}// 关闭socketclose(new_socket);close(server_fd);printf(server closed.\n);return 0;
}
开启两个终端运行结果如下 数据加密方式TCP socket编程
封装加密初始化程序 我们创建两个文件一个为myssl.h一个为对应的实现文件myssl.c,如下
/* myssl.h */#ifndef __MYSSL_H_
#define __MYSSL_H_#include openssl/ssl.htypedef enum{SSL_MODE_SERVER,SSL_MODE_CLIENT
}SSL_MODE;//对象方法枚举SSL *init_ssl(char *cert_path, char *key_path, SSL_MODE mode, int fd);//初始化函数#endif
/* myssl.c */
#include openssl/ssl.h
#include stdio.h
#include stdlib.h
#include myssl.hSSL *init_ssl(char * cert_path, char * key_path, SSL_MODE mode, int fd)
{// 声明套件变量const SSL_METHOD *method;SSL_CTX *ctx;SSL *ssl NULL;// 添加支持的算法加载错误信息OpenSSL_add_all_algorithms();SSL_load_error_strings();// 获取对象方法// 不同版本的openssl对应的API也是有区别的需要注意if(mode SSL_MODE_SERVER){method SSLv23_server_method();}else if(mode SSL_MODE_CLIENT){method SSLv23_client_method();}else{printf(unkown method\n);return NULL;}// 创建CTXctx SSL_CTX_new(method);if(!ctx){printf(create SSL CTX failed.\n);return NULL;}// 读取证书公钥和密钥私钥if((SSL_CTX_use_certificate_file(ctx, cert_path, SSL_FILETYPE_PEM) 0)||(SSL_CTX_use_PrivateKey_file(ctx, key_path, SSL_FILETYPE_PEM) 0)){printf(not found file\n);return NULL;}// 创建SSLssl SSL_new(ctx);if(!ssl){printf(failed create SSL.\n);return NULL;}// 绑定套接字的文件描述符到SSL中if(SSL_set_fd(ssl, fd) 0){printf(SSL set fd failed.\n);return NULL;}// 连接套接字if((mode SSL_MODE_SERVER SSL_connect(ssl) 0)||(mode SSL_MODE_CLIENT SSL_connect(ssl) 0)){printf(failed handshake with ssl.\n);return NULL;}return ssl;
} 修改经典socket编程代码 我们来对上面的客户端和服务端程序做些修改以期使得变成加密的套接字通信。
客户端
/* client.c */
#include stdio.h
#include stdlib.h
#include string.h
#include unistd.h
#include arpa/inet.h
#include sys/types.h
#include sys/socket.h
#include netinet/in.h
#include errno.h
#include myssl.hint main(int argc, char *argv[])
{// 定义相关变量int sockfd;struct sockaddr_in serv_addr;char buf[1024] {0};const char *greeting Hello from client;if(argc 2){printf(please input the ip of the server..\n);return -1;}//获取并初始化服务端地址serv_addr.sin_family AF_INET;serv_addr.sin_port htons(8080);if(inet_pton(AF_INET, argv[1], serv_addr.sin_addr) 0){fprintf(stderr, inet_pton failed[%d].\n, errno);return -1;}// 创建socketif((sockfd socket(AF_INET, SOCK_STREAM, 0)) 0){fprintf(stderr, create socket failed[%d].\n, errno);return -1;}// 连接到服务器if(connect(sockfd, (struct sockaddr *)serv_addr, sizeof(serv_addr)) 0){fprintf(stderr, connect failed[%d].\n, errno);return -1;}// 初始化加密函数SSL *ssl init_ssl(./cert.pem, ./key.pem, SSL_MODE_CLIENT, sockfd);// 发送数据if(SSL_write(ssl, greeting, strlen(greeting)) 0) //if(write(sockfd, greeting, strlen(greeting)) 0){fprintf(stderr, write failed[%d].\n, errno);return -1;}// 接收数据if(SSL_read(ssl, buf, 1024) 0) //if(read(sockfd, buf, 1024) 0){fprintf(stderr, read failed[%d].\n, errno);return -1;}printf(received message:%s\n, buf);close(sockfd);SSL_shutdown(ssl);SSL_free(ssl);
}
服务端
/* server.c */#include stdio.h
#include stdlib.h
#include string.h
#include unistd.h
#include arpa/inet.h
#include sys/types.h
#include sys/socket.h
#include netinet/in.h
#include errno.h
//#include myssl.h#define MAX_CNT 5int main(int argc, char *argv[])
{// 定义相关变量int server_fd, new_socket;int opt 1;struct sockaddr_in serv_addr, cli_addr;socklen_t cli_addr_len;char buf[1024] {0};const char *greeting Hello from server;// 创建socket文件描述符if((server_fd socket(AF_INET, SOCK_STREAM, 0)) 0){fprintf(stderr, create socket failed[%d].\n, errno);return -1;}// 设置socket选项if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, opt, sizeof(opt))) { fprintf(stderr, set socket failed[%d].\n, errno);return -1; } // 绑定socket到指定端口和地址memset(serv_addr, 0, sizeof(serv_addr));serv_addr.sin_family AF_INET;serv_addr.sin_addr.s_addr htonl(INADDR_ANY);serv_addr.sin_port htons(8080);if(bind(server_fd, (struct sockaddr *)serv_addr, sizeof(serv_addr)) 0){fprintf(stderr, create bind failed[%d].\n, errno);return -1;}// 监听if(listen(server_fd, MAX_CNT) 0){fprintf(stderr, listen failed[%d].\n, errno);return -1;}// 接受客户端连接请求memset(cli_addr, 0, sizeof(cli_addr));cli_addr_len sizeof(cli_addr);if((new_socket accept(server_fd, (struct sockaddr *)cli_addr, (socklen_t *)cli_addr_len)) 0 ){fprintf(stderr, accept failed[%d].\n, errno);return -1;} printf(Client [%s-%d] connected.\n, inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port));// 初始化加密函数SSL *ssl init_ssl(./cert.pem, ./key.pem, SSL_MODE_SERVER, new_socket);// 接收数据if(SSL_read(ssl, buf, 1024) 0) //if(read(new_socket, buf, 1024) 0){fprintf(stderr, read failed[%d].\n, errno);return -1;}printf(received message:%s\n, buf);// 发送数据if(SSL_write(ssl, greeting, strlen(greeting)) 0) //if(write(new_socket, greeting, strlen(greeting)) 0){fprintf(stderr, write failed[%d].\n, errno);return -1;}// 关闭socketclose(new_socket);close(server_fd);SSL_shutdown(ssl);SSL_free(ssl);printf(server closed.\n);return 0;
}Makefile 为了方便总体编译我们创建一个Makefile,内容如下
LIBS-lssl -lcrypto
all:gcc -o server server.c myssl.c $(LIBS)gcc -o client client.c myssl.c $(LIBS)
clean:rm -rf server client
证书、密钥 为方便测试我们利用openssl生成密钥key.pem及公钥文件cert.pem命令如下
密钥
$openssl genpkey -algorithm RSA -out key.pem
公钥(利用密钥生成生成之前需要根据提示输入一些地址公司等信息)
$sudo openssl req -new -x509 -key key.pem -out cert.pem -days 3650
注意openssl的版本程序中用到的和命令行的这个要保持一致结果如下 编译问题 在终端执行make命令如果出现找不到openssl/ssl.h那么你的系统环境可能没有安装openssl开发库我们可以通过下面命令安装
sudo apt-get update
sudo apt-get install libssl-dev
安装完毕后openssl/ssl.h应该可以在/usr/include/openssl/目录中找到。
如果安装成功之后还是报找不到头文件的错误通过下面命令检查定位头文件所在位置
dpkg -L libssl-dev | grep ssl.h
如果你确定环境中有这个头文件而其他方法都不行的话可以试试手动添加路径指定如下
gcc -o myprogram myprogram.c -I/usr/include/openssl -lssl -lcrypto
如果方法都试遍了我们只能尝试卸掉重新安装。
sudo apt-get remove --purge libssl-dev
sudo apt-get update
sudo apt-get install libssl-dev
如果报找不到openssl的某些API 或相关问题此时则需参考下面的流程对源码做出修改。
补充 因为openssl每个跨级的版本0.9/1.0/3.0API的变动较大有些遗弃有些修改兼容性不好我们编写的应用源代码可能会需要做些修改如果使用的openssl变动了版本。如果没有openssl的源码系统中只有库文件我们可以通过objdump命令来检索其用的哪些API方便我们替换修改举例
$objdump -Tt libxxx.so | grep SSL*类似返回如下结果 参考
B站爱吃甜食的老猫的视频