将简单的套接字转换为SSL套接字


115

我编写了简单的C程序,这些程序使用套接字(“客户端”和“服务器”)。(UNIX / Linux使用)

服务器端只是创建一个套接字:

sockfd = socket(AF_INET, SOCK_STREAM, 0);

然后将其绑定到sockaddr:

bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));

并收听(并接受和读取):

listen(sockfd,5);
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
read(newsockfd,buffer,255);

客户端创建套接字,然后对其进行写入。

现在,我想以最简单,最田园,最整洁和最快的方式将这个简单的连接转换为SSL连接。

我试图将OpenSSL添加到我的项目中,但是找不到实现我想要的东西的简单方法。


如果您正在寻找“安全连接”而不是SSL,则可以查看位于应用程序外部的诸如proxychains.sourceforge.net之类的内容,并将其设置为通过SSH连接发送流量。对于应用程序内SSL,如果您了解SSL / TLS应该如何工作,则OpenSSL非常简单。如果您想要替代方法,请尝试使用yaSSL或gnuTLS。
Borealid 2011年

3
定义“简便方法”。OpenSSl是C程序员的标准。如果您遇到困难,应该询问一下。
洛恩侯爵,

选中“ OpenSSL编程简介”(第一部分)。第二部分对我来说太高级和困难了。但是part2值得一看。
里克

还要检查使用OpenSSL API的安全编程。但是我只是听到有关Openssl有多糟糕的观点,还有其他值得一试的替代方案。
瑞克

另一个选择是使用外部SSL包装工具,例如stunnel,该stunnel4软件包位于基于Debian的发行版中,并且易于使用。与在服务器中添加适当的SSL支持相比,存在一些限制,但是这对于快速解决方案可能会有所帮助。我喜欢stunnel,因为它似乎适合UNIX软件工具方法。
山姆·沃特金斯

Answers:


150

使用OpenSSL时需要执行几个步骤。必须制作一个SSL证书,其中可以包含带有私钥的证书,请确保指定证书的确切位置(此示例在根目录中)。有很多很好的教程。

其中包括:

#include <openssl/applink.c>
#include <openssl/bio.h>
#include <openssl/ssl.h>
#include <openssl/err.h>

您将需要初始化OpenSSL:

void InitializeSSL()
{
    SSL_load_error_strings();
    SSL_library_init();
    OpenSSL_add_all_algorithms();
}

void DestroySSL()
{
    ERR_free_strings();
    EVP_cleanup();
}

void ShutdownSSL()
{
    SSL_shutdown(cSSL);
    SSL_free(cSSL);
}

现在了解大部分功能。您可能要在连接上添加一个while循环。

int sockfd, newsockfd;
SSL_CTX *sslctx;
SSL *cSSL;

InitializeSSL();
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd< 0)
{
    //Log and Error
    return;
}
struct sockaddr_in saiServerAddress;
bzero((char *) &saiServerAddress, sizeof(saiServerAddress));
saiServerAddress.sin_family = AF_INET;
saiServerAddress.sin_addr.s_addr = serv_addr;
saiServerAddress.sin_port = htons(aPortNumber);

bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));

listen(sockfd,5);
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);

sslctx = SSL_CTX_new( SSLv23_server_method());
SSL_CTX_set_options(sslctx, SSL_OP_SINGLE_DH_USE);
int use_cert = SSL_CTX_use_certificate_file(sslctx, "/serverCertificate.pem" , SSL_FILETYPE_PEM);

int use_prv = SSL_CTX_use_PrivateKey_file(sslctx, "/serverCertificate.pem", SSL_FILETYPE_PEM);

cSSL = SSL_new(sslctx);
SSL_set_fd(cSSL, newsockfd );
//Here is the SSL Accept portion.  Now all reads and writes must use SSL
ssl_err = SSL_accept(cSSL);
if(ssl_err <= 0)
{
    //Error occurred, log and close down ssl
    ShutdownSSL();
}

然后,您可以使用以下方法进行读取或写入:

SSL_read(cSSL, (char *)charBuffer, nBytesToRead);
SSL_write(cSSL, "Hi :3\n", 6);

更新SSL_CTX_new应用TLS方法最适合于您的订单需要支持,而不是安全的新版本,被称为SSLv23_server_method()。请参阅: OpenSSL SSL_CTX_new说明

TLS_method(),TLS_server_method(),TLS_client_method()。 这些是通用版本灵活的 SSL / TLS方法。实际使用的协议版本将协商为客户端和服务器相互支持的最高版本。支持的协议为SSLv3,TLSv1,TLSv1.1,TLSv1.2和TLSv1.3。


9
并不是我想的那么“简单”,但是最后(感谢上帝!)我看到了一些代码。这是跨平台的还是仅用于Unix / Unix类的系统?
juliomalegria

3
我在多个平台上使用过类似的代码:arm,linux和Windows。
CaptainBli 2013年

2
最后if是错误的。它应该是if (ssl_err <= 0) {唯一的,然后它是一个错误。SSL_accept()收益1上的成功,0在“控制失灵”和-1关于“致命故障”。请参见手册页。
Jite 2014年

2
同样,如果SSL_CTX_set_tmp_dh[_callback]()不调用,DH密码将不起作用。刚发现硬盘的方式,A零位的密码将没有它不工作,产生警报号40
罗马Dmitrienko

5
@DevNull SSLv23_server_method()状态,表明服务器可以理解SSLv2和v3,现在已弃用。要支持TLS 1.1和1.2,请用替换该方法 TLS_server_method()来源
ezPaint

17

OpenSSL相当困难。如果不正确地进行协商,很容易意外地放弃所有安全性。(哎呀,我个人被bug咬伤了,其中curl不能完全正确地读取OpenSSL警报,并且无法与某些站点进行通信。)

如果您真的想快速简单,请将螺柱放在程序的前面,每天调用它。在不同的过程中使用SSL不会降低您的速度:http : //vincent.bernat.im/en/blog/2011-ssl-benchmark.html


11
这是一个实际的答案,但并不能真正回答问题。
瑞士

4
STUD于2016年被放弃。自述文件建议:github.com/varnish/hitch
Charles

7

对于像我这样的人:

目录中的SSL源中曾经有一个demos/ssl/带有C ++示例代码的示例。现在只能通过历史记录使用:https : //github.com/openssl/openssl/tree/691064c47fd6a7d11189df00a0d1b94d8051cbe0/demos/ssl

您可能必须找到一个工作版本,我最初在2015年11月6日发布了此答案。我不得不编辑源代码-数量不多。

证书:.pem demos/certs/apps/https//github.com/openssl/openssl/tree/master/demos/certs/apps


-1

这是我的示例ssl套接字服务器线程(多个连接)https://github.com/breakermind/CppLinux/blob/master/QtSslServerThreads/breakermindsslserver.cpp

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <unistd.h>
#include <iostream>

#include <breakermindsslserver.h>

using namespace std;

int main(int argc, char *argv[])
{
    BreakermindSslServer boom;
    boom.Start(123,"/home/user/c++/qt/BreakermindServer/certificate.crt", "/home/user/c++/qt/BreakermindServer/private.key");
    return 0;
}

请直接在您的SO帖子中包含解决方案。
Maciej Jureczko
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.