将简单套接字变成 SSL 套接字

发布于 2024-12-09 08:33:16 字数 635 浏览 0 评论 0原文

我编写了简单的 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 添加到我的项目中,但我找不到一种简单的方法实现我想要的。

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

The server side simply creates a socket:

sockfd = socket(AF_INET, SOCK_STREAM, 0);

And then binds it to 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.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

长途伴 2024-12-16 08:33:16

使用 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);

更新
应使用最适合您需求的 TLS 方法调用 SSL_CTX_new,以支持较新版本的安全性,而不是 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。

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.

Some includes:

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

You will need to initialize 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.

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);

Update
The SSL_CTX_new should 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

TLS_method(), TLS_server_method(), TLS_client_method().
These are the general-purpose version-flexible SSL/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.

小清晰的声音 2024-12-16 08:33:16

OpenSSL 相当困难。如果谈判不正确,很容易意外地放弃所有的安全性。 (哎呀,我个人就遇到过一个错误,curl 无法完全正确地读取 OpenSSL 警报,并且无法与某些网站通信。)

如果您确实想要快速而简单,请输入 stud 在你的程序前面,今天就到此为止了。在不同的进程中使用 SSL 不会减慢您的速度:http:// vincent.bernat.im/en/blog/2011-ssl-benchmark.html

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.)

If you really want quick and simple, put stud in 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

你又不是我 2024-12-16 08:33:16

对于像我这样的人:

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

你可能必须找到一个工作版本,我最初于 2015 年 11 月 6 日发布了这个答案。编辑源代码——不多。

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

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

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.

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

半衾梦 2024-12-16 08:33:16

就像你看到的那样,它毛茸茸的。但“简单”的部分是,在使用 OpenSSL 设置 SSL/TLS 会话后,在 HTTPS 套接字上读/写所遵循的模式与 HTTP 所遵循的模式相同。

不同之处在于您使用SSL_read/SSL_write 函数,而不是read/write 函数。 SSL_read/SSL_write 函数采用 SSL 指针而不是文件描述符作为其第一个参数。

无论如何,这里是一个适用于 Unix 环境的完整工作 OpenSSL 示例,其中包含编译/运行指令、APT 依赖项和参考。这只是一些更多的工作代码,供您练习。

成功编译后,您将看到一条有关已弃用的 OpenSSL 函数的警告。

成功运行后,您将看到 example.com 的 TLS 证书主题打印到标准输出,后面是 example.com 的 HTML 内容。

https://github.com/angstyloop/c- web/blob/main/openssl-fetch-example.c

在 Ubuntu 22.04 上测试。

Like you've seen it's pretty hairy. But the "easy" part is, after you've set up your SSL/TLS session with OpenSSL, the pattern you follow to read/write on a socket for HTTPS is the same as the one you follow for HTTP.

The difference is you use the SSL_read/SSL_write functions, instead of the read/write functions. The SSL_read/SSL_write functions take an SSL pointer as their first argument instead of a file descriptor.

Anyways, here is a full working OpenSSL example for a Unix environment, with compile/run instructions, APT dependencies, and references. It's just some more working code for you to cut your teeth on.

On successful compilation, you will see one warning about a deprecated OpenSSL function.

On successful run, you will see example.com's TLS certificate subject printed to standard output, followed by the HTML content of example.com.

https://github.com/angstyloop/c-web/blob/main/openssl-fetch-example.c

Tested on Ubuntu 22.04.

等数载,海棠开 2024-12-16 08:33:16

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

Here my example ssl socket server threads (multiple connection) 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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文