c - libssh2 channel SSL BIO 使用

标签 c ssl openssl libssh

我正在为自己的娱乐编写一个小型 ftp 项目,它应该能够做 4 件事:

  1. 直接连接到 ftp
  2. 使用 SSL(包装器)直接连接到 ftp
  3. 通过 ssh 隧道连接到 ftp
  4. 使用 SSL 通过 ssh 隧道连接到 ftp。

我正在用纯 C(unix,在这种情况下无关紧要)编写我的程序,使用 1 和 2 的标准库,除了 2 和 4 的 OpenSSL 之外,还使用 ​​libssh2 3 和 4。

我可以让 1-3 人工作,但不能让 4 人工作。这就是我所在的位置:

  1. 通过打开到 host:port 的套接字、连接、从套接字写入/读取来完成。
  2. 通过打开到主机的套接字:端口、连接、写入“AUTH SSL”、使用来自先前套接字的 BIO 启动 SSL 对象来完成 -> SSL_connect()、SSL_read()、SSL_write()。
  3. 通过在目标和本地主机之间打开一个隧道来完成(虽然我不确定我在我的方法中使用本地主机绑定(bind)的目的:)

类似于:

test_ssh_channel = libssh2_channel_direct_tcpip_ex(test_ssh_session, "100.100.100.100", 21, "127.0.0.1", 21);

然后我写入/读取该 channel (libssh2_channel_read()) - 在我看来,它提供了以下流程: 纯文本 -> 通过 ssh 发送 -> 从 ssh 主机向目标发送纯文本。 出于 3. 的目的,这很好并且可以完成工作。

现在,对于 4。我被卡住了,因为我(尽量保持简单)需要以某种方式将这个 channel 变成一个套接字。所以在我看来,我有两个选择:

  • 一个。制作一个伪套接字和每个 我需要读/写的时候,我 从 channel 读/写, 将其发送/检索到套接字中, 并让 SSL_connect(pseudo_socket) 与我的伪套接字通信, 每次服用什么 ssl_write 发送,发送到 channel ,反之亦然。

  • b。设置一个 BIO 缓冲区(有 比我能做的更多的生物功能 绕过我的头;这 文档还没有完全 有帮助)并以某种方式读/写

理想情况下,我会选择 2,原因如下:由于我的项目是用 C 编写的,因此在执行其他代码的同时维护套接字读/写会变得比我希望的要复杂一些。

但是,b。给出一个问题:我担心握手将如何工作;特别是我担心我最终会与本地主机而不是远程主机握手。

总结一下我的问题:我可以通过 channel 在 SSL 中读/写(在其周围放置一个包装器),以便 4. 的流程变为:纯文本 -> SSL(plaintext) ->通过 ssh -> 从 ssh 主机向目标主机传送 SSL(明文)?

有点长,但我希望它是可以理解的。如果没有,请告诉我,我会澄清。从谷歌搜索/搜索 stackoverflow 看来,是我和一个使用 mysql 的人遇到了同样的问题,而且答案有限。

非常感谢任何输入!

  • 詹姆斯

最佳答案

是的,选项 2 是正确的方法。使用 BIO_make_bio_pair() 创建 BIO 对,并使用 SSL_set_bio() 将它们分配给 SSL 对象.

然后,您使用 BIO_read() 读取加密端 SSL 数据并将其写入 libssh 隧道,然后使用 BIO_write() 从 libssh 隧道读取并写入它>.


附录:

当您使用此方法时,您的 SSL 对象没有它自己的文件描述符 - BIO 替换了文件描述符/套接字。 OpenSSL 将从您提供的 BIO 中读取和写入,而不是从文件描述符读取和写入。

BIO 只是位于 OpenSSL 库和您自己的代码之间的接口(interface)。它们是您实现加密端 SSL 数据与另一端之间实际传输的一种方式(而不是直接使用套接字的 OpenSSL)。

当您对作为 wbio 提供给 SSL_set_bio() 的 BIO 执行 BIO_read() 时,您将读取加密端SSL 数据,然后您必须自己将其发送到另一端(大概使用一些 libssh2 函数)。类似地,当您从另一端接收到加密端 SSL 数据时(同样,来自某些 libssh2 函数),您可以通过在 BIO 上使用 BIO_write() 将其泵入 SSL您作为 rbio 提供。

也许这个插图会有所帮助。当您从 SSL 对象读取和写入时,OpenSSL 将只从底层 BIO 读取和写入,将数据留在那里供您稍后处理:

+------+               +-----+               +-----+
| Your | SSL_write()   | SSL | BIO_read()    | BIO |
| code | ------------> |     | <------------ |     |
|      |               |     |               |     |
|      |               |     | BIO_write()   |     |
|      |               |     | ------------> |     |
+------+               +-----+               +-----+

+------+              +-----+               +-----+
| Your | SSL_read()   | SSL | BIO_read()    | BIO |
| code | <----------- |     | <------------ |     |
|      |              |     |               |     |
|      |              |     | BIO_write()   |     |
|      |              |     | ------------> |     |
+------+              +-----+               +-----+

(但请注意,SSL_write() 可能会导致从底层 BIO 进行读取,反之亦然)。

wbio中有数据时,必须读取并发送给对方:

+------+              +-----+
| Your | BIO_read()   | BIO |
| code | <----------- |     |
|      |              +-----+
|      |                           +---------+
|      | libssh2_channel_write()   | libssh2 |
|      | ------------------------> |         | -> (... to other side)
|      |                           +---------+
+------+

反之,当对方有可用数据时,你应该读取它并将其传递给rbio:

+------+
| Your |                          +---------+
| code | libssh2_channel_read()   | libssh2 |
|      | <----------------------- |         | -> (... from other side)
|      |                          +---------+
|      |              +-----+
|      | BIO_write()  | BIO |
|      | -----------> |     |
|      |              +-----+
+------+

关于c - libssh2 channel SSL BIO 使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3069876/

相关文章:

php - 客户端证书和 PHP 入门

c++ - 用 C++ 解密文件,用 openssl -aes-128-cbc 加密

c - 运行到在线编译器但在终端上出现段错误(Ubuntu)

c - main() 和 int main() 有什么区别?

ssl - Safari 在使用 HTTP/2 时无法给出响应

javascript - 套接字.IO 和 SSL

c - 迭代C中未初始化的数组

c - 致力于对链表进行排序,用 c 编写,然后为内核输出

ruby - 如何在 Ruby 的 SSLServer 中实现 SSL 证书的自定义验证?

ssl - 在 Windows 上安装 cassandra(DataStax 社区版)时启用 SSL 时出错