我正在为自己的娱乐编写一个小型 ftp 项目,它应该能够做 4 件事:
- 直接连接到 ftp
- 使用 SSL(包装器)直接连接到 ftp
- 通过 ssh 隧道连接到 ftp
- 使用 SSL 通过 ssh 隧道连接到 ftp。
我正在用纯 C(unix,在这种情况下无关紧要)编写我的程序,使用 1 和 2 的标准库,除了 2 和 4 的 OpenSSL 之外,还使用 libssh2 3 和 4。
我可以让 1-3 人工作,但不能让 4 人工作。这就是我所在的位置:
- 通过打开到 host:port 的套接字、连接、从套接字写入/读取来完成。
- 通过打开到主机的套接字:端口、连接、写入“AUTH SSL”、使用来自先前套接字的 BIO 启动 SSL 对象来完成 -> SSL_connect()、SSL_read()、SSL_write()。
- 通过在目标和本地主机之间打开一个隧道来完成(虽然我不确定我在我的方法中使用本地主机绑定(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/