1

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

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

我正在用普通 C(unix,在这种情况下并不重要)编写我的程序,使用标准库作为 1 和 2,使用 libssh2 作为 3 和 4,除了 OpenSSL 用于 2 和 4。

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

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

就像是:

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

然后我写入/读取该通道(libssh2_channel_read()) - 正如我所看到的,它给出了以下流程:纯文本 - > 通过 ssh 发送 - > 从 ssh 主机将纯文本传递到目标。出于 3. 的目的,这很好并且可以完成工作。

现在,对于 4。我被卡住了,因为我(试图保持简单)需要以某种方式将此通道变成一个套接字。所以我看到它的方式有两个选择:

  • 一个。制作一个伪套接字,每次我需要读/写时,我从通道读/写,将其发送/检索到套接字中,并让 SSL_connect(pseudo_socket) 与我的伪套接字通信,每次接收 ssl_write 发送的内容,将其发送到频道,反之亦然。

或者

  • 湾。设置一个 BIO 缓冲区(有更多的 BIO 功能,我无法理解;文档并没有完全有帮助)并以某种方式读/写它。

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

然而,B。给出一个问题:我担心握手会如何工作;特别是我担心我最终会与 localhost 而不是 remotehost 握手。

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

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

非常感谢任何输入!

  • 詹姆士
4

1 回答 1

2

Yes, option 2 is the right way to go. Create a BIO pair with BIO_make_bio_pair(), and assign them to the SSL object with SSL_set_bio().

You then read the encrypted-side SSL data with BIO_read() and write it to the libssh tunnel, and read from the libssh tunnel and write it with BIO_write().


Addendum:

When you use this method, your SSL object doesn't have a file descriptor of its own - the BIOs replace the file descriptor / socket. Instead of reading and writing from a file descriptor, OpenSSL will read and write from the BIOs you provided.

The BIOs are simply an interface that sit between the OpenSSL library and your own code. They're a way for you to implement the actual shipping of the encrypted-side SSL data to and from the other side (instead of OpenSSL directly using a socket).

When you do a BIO_read() on the BIO you provided as wbio to SSL_set_bio(), you will read the encrypted-side SSL data, and you must then send this on to the other side yourself (presumably using some libssh2 function). Similarly, when you recieve encrypted-side SSL data from the other side (again, from some libssh2 function), you pump it into SSL by using BIO_write() on the BIO you provided as the rbio.

Perhaps this illustration will help. When you read and write from the SSL object, OpenSSL will just read and write from the underlying BIO, leaving the data there for you to deal with later:

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

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

(Note, though, that an SSL_write() may cause a read from the underlying BIO, and vice-versa).

When there is data in the wbio, you must read it and ship it to the other side:

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

Conversely, when there is data available from the other side, you should read it and pass it into the rbio:

+------+
| Your |                          +---------+
| code | libssh2_channel_read()   | libssh2 |
|      | <----------------------- |         | -> (... from other side)
|      |                          +---------+
|      |              +-----+
|      | BIO_write()  | BIO |
|      | -----------> |     |
|      |              +-----+
+------+
于 2010-06-21T14:47:03.813 回答