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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7698488/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 06:33:27  来源:igfitidea点击:

Turn a simple socket into an SSL socket

clinuxsocketsunixssl

提问by David Mape

I wrote simple C programs, which are using sockets ('client' and 'server'). (UNIX/Linux usage)

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

The server side simply creates a socket:

服务器端简单地创建一个套接字:

sockfd = socket(AF_INET, SOCK_STREAM, 0);

And then binds it to sockaddr:

然后将其绑定到 sockaddr:

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

And listens (and accepts and reads):

并聆听(并接受并阅读):

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

The client creates the socket, and then writes to it.

客户端创建套接字,然后写入它。

Now, I want to convert this simple connection into an SSL connection, in the plainest, most idyllic, neatest and quickest way.

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

I've tried to add OpenSSLto my project, but I can't find an easy way to implement what I want.

我已经尝试将OpenSSL添加到我的项目中,但是我找不到一种简单的方法来实现我想要的。

回答by BraveNewCurrency

OpenSSL is quite difficult. It's easy to accidentally throw away all your security by not doing negotiation exactly right. (Heck, I've been personally bitten by a bug where curl wasn't reading the OpenSSL alerts exactly right, and couldn't talk to some sites.)

OpenSSL 相当困难。如果协商不完全正确,很容易不小心丢掉所有安全措施。(哎呀,我个人被一个 bug 给咬了,curl 没有完全正确地读取 OpenSSL 警报,并且无法与某些站点通信。)

If you really want quick and simple, put studin front of your program an call it a day. Having SSL in a different process won't slow you down: http://vincent.bernat.im/en/blog/2011-ssl-benchmark.html

如果你真的想要快速和简单,把螺柱放在你的程序前面,就这样吧。在不同的过程中使用 SSL 不会减慢你的速度:http: //vincent.bernat.im/en/blog/2011-ssl-benchmark.html

回答by CaptainBli

There are several steps when using OpenSSL. You must have an SSL certificate made which can contain the certificate with the private key be sure to specify the exact location of the certificate (this example has it in the root). There are a lot of good tutorials out there.

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

Some includes:

一些包括:

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

You will need to initialize OpenSSL:

您将需要初始化 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);
}

Now for the bulk of the functionality. You may want to add a while loop on connections.

现在是大部分功能。您可能希望在连接上添加一个 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();
}

You are then able read or write using:

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

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

UpdateThe SSL_CTX_newshould be called with the TLS method that best fits your needs in order to support the newer versions of security, instead of SSLv23_server_method(). See: OpenSSL SSL_CTX_new description

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

TLS_method(), TLS_server_method(), TLS_client_method().These are the general-purpose version-flexibleSSL/TLS methods. The actual protocol version used will be negotiated to the highest version mutually supported by the client and the server. The supported protocols are SSLv3, TLSv1, TLSv1.1, TLSv1.2 and TLSv1.3.

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

回答by 18446744073709551615

For others like me:

对于像我这样的其他人:

There was once an example in the SSL source in the directory demos/ssl/with example code in C++. Now it's available only via the history: https://github.com/openssl/openssl/tree/691064c47fd6a7d11189df00a0d1b94d8051cbe0/demos/ssl

目录中的 SSL 源demos/ssl/代码中曾经有一个示例,其中包含 C++ 示例代码。现在只能通过历史获取:https: //github.com/openssl/openssl/tree/691064c47fd6a7d11189df00a0d1b94d8051cbe0/demos/ssl

You probably will have to find a working version, I originally posted this answer at Nov 6 2015. And I had to edit the source -- not much.

您可能需要找到一个工作版本,我最初在 2015 年 11 月 6 日发布了这个答案。我不得不编辑源代码——不多。

Certificates: .pem in demos/certs/apps/: https://github.com/openssl/openssl/tree/master/demos/certs/apps

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

回答by Fanex

Here my example ssl socket server threads (multiple connection) https://github.com/breakermind/CppLinux/blob/master/QtSslServerThreads/breakermindsslserver.cpp

这是我的示例 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;
}