Использование SSL BIO на канале libssh2

Я пишу небольшой ftp-проект для своего собственного развлечения, который должен быть в состоянии сделать 4 вещи:

  1. подключиться напрямую к FTP
  2. подключиться напрямую к ftp через SSL (обертку)
  3. подключиться через туннель ssh к ftp
  4. подключиться через туннель SSH к FTP с SSL.

Я пишу свою программу на простом C (unix, в данном случае это не важно), используя стандартные библиотеки для 1 и 2, используя libssh2 для 3 и 4 в дополнение к OpenSSL для 2 и 4.

Я могу заставить работать 1-3, а не 4. Вот где я нахожусь:

  1. делается путем открытия сокета для хоста: порт, подключение, запись / чтение из сокета.
  2. выполняется путем открытия сокета для хоста: порт, подключение, запись "AUTH SSL", инициирование объекта SSL с BIO из предыдущего сокета -> SSL_connect(), SSL_read(), SSL_write().
  3. сделано путем открытия туннеля между целью и локальным хостом (хотя я не уверен, для чего я использую привязку локального хоста в моем подходе:)

что-то вроде:

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, поддержка чтения / записи в сокете при выполнении другого кода станет немного сложнее, чем я бы предпочел.

Тем не менее, б. дает проблему: я волнуюсь, как будет работать рукопожатие; в частности, я боюсь, что в итоге я получаю рукопожатие с localhost вместо удаленного хоста, так сказать.

Подводя итог, мой вопрос: могу ли я через канал читать / писать в SSL (обернуть его вокруг него), чтобы поток для 4. стал: обычный текст -> SSL(открытый текст) -> через ssh -> доставить SSL (открытый текст), чтобы нацелить хост с хоста ssh?

Это немного долго, но я надеюсь, что это было понятно. Если нет, пожалуйста, дайте мне знать, и я проясню. Из поиска в стеке и поиска в Google кажется, что я и парень, работающий с mysql, сталкиваемся с той же проблемой и ограниченными ответами.

ЛЮБОЙ вклад приветствуется!

  • Джеймс

1 ответ

Да, вариант 2 - правильный путь. Создайте БИО пару с BIO_make_bio_pair() и назначить их объекту SSL с SSL_set_bio(),

Затем вы читаете данные SSL зашифрованной стороны с BIO_read() и запишите его в туннель libssh, и прочитайте из туннеля libssh и запишите его BIO_write(),


Приложение:

Когда вы используете этот метод, ваш объект SSL не имеет собственного дескриптора файла - BIO заменяют дескриптор файла / сокет. Вместо чтения и записи из файлового дескриптора, OpenSSL будет читать и писать из предоставленных вами БИО.

BIO - это просто интерфейс, который находится между библиотекой OpenSSL и вашим собственным кодом. Это способ для вас реализовать фактическую доставку данных SSL с зашифрованной стороны на другую сторону (вместо OpenSSL, использующего сокет).

Когда вы делаете BIO_read() на био вы предоставили как wbio в SSL_set_bio() вы прочтете данные SSL зашифрованной стороны, а затем отправите их другой стороне самостоятельно (предположительно, используя некоторые libssh2 функция). Точно так же, когда вы получаете данные SSL зашифрованной стороны от другой стороны (опять же, от некоторых libssh2 функция), вы закачиваете его в SSL с помощью BIO_write() на био вы предоставили как 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 |
|      | -----------> |     |
|      |              +-----+
+------+
Другие вопросы по тегам