Ru-Board.club
← Вернуться в раздел «Прикладное программирование»

» Реализация SSH протокола из под Delphi

Автор: Delphi6
Дата сообщения: 03.03.2007 14:15
Swappp
Самое интересное что консольный аналог putty - plink не ожидает когда закончится получение результата команды, а продолжает отсылать все команды из файла. Я это заметил когда распаковывал до 10 tar файлов, часто было что лог распаковки первого архива отображался в конце, что доказывает что пакеты даже в plink приходят хаотично и программа не следит за этим. Вот идея на счет "приветствия" пока не была опробована, работаю над реализацией.

Что касается OpenSSH, я к сожалению не нашел исходных кодов Или их и ни надо искать? и вы подразумевали что-то другое?

idiMAN

Цитата:
Ещё бы предусмотреть таймаут

Это само собой как же без него
Автор: Delphi6
Дата сообщения: 03.03.2007 17:13
И снова плохая новость, при первом же тесте произошел сбой на одном из моих серверов приветствие Shell-а выглядит очень коротко "$" когда зашел юзером. А при подключении реально что в информации, которую выдает сервер при первом коннекте, будет содержать данный символ Получается нет возможности определить, как выглядит приветствие ($ или server-name#).

Вопрос остается открытым, принимаются любые предложения.

Добавлено:
Класс на уровне TIdTelnet готов, что означает что есть ивент OnData который возникает когда на сокете прибыли данные. Даже уже сделал маленький клиент на подобие Putty, НО проблема в том что приходится до сих пор следить визуально, когда ответ на команду уже пришел. Каждая команда действительно заканчивается приветствием Shell но, как его определить? На каждой системе оно индивидуально, можно конечно создать свойство куда его надо ввести вручную, типа каждый раз подтачивать компонент под определенный сервер (для моей конкретной задачи хватает) но хотелось бы сделать не на конкретный случай.

А вот пример имени файла который собьет с толку выше указанный алгоритм на моем сервере

Цитата:
$ touch $
$ ls -al
total 8
drwxr-xr-x 2 gesoft gesoft 4096 Mar 4 04:11 ./
drwxr-xr-x 13 gesoft gesoft 4096 Mar 4 04:09 ../
-rw-r--r-- 1 gesoft gesoft 0 Mar 4 04:11 $
Автор: Delphi6
Дата сообщения: 04.03.2007 15:59
Только сегодня вспомнил про РНР класс в котором тоже реализовано SSH (пока его не добавили сами разработчики). Вот пример считывания данных:

Код: $ssh->write("ls -al\n");
$cycle = true;
while ($cycle) {
    $data = $ssh->read();
    echo $data;
    if (ereg('\$',$data)) {
        $cycle = false;
    }
}
Автор: Delphi6
Дата сообщения: 05.03.2007 11:50
Ну кажется бета версия класса уже готова, скачивать можно отсюда
http://proxy-list.org/ru-board/SSHClient.rar

Все сделано на интуитивном уровне, поддерживается как ивент OnData так и метод ReadData, первый возникает как только информация прибыла, а второй имеет собственный буфер, и в нем инфа храниться до того момента пока объект на класс существует либо инфа не считается, это я делала специально для любителей все делать в ручную.

Данные серверу можно переслать двумя способами:

1) Execute и тогда метод ждет определенное timeOut время пока не придет ответ (ответ определяется наличием в пакете символа $ либо #), если за это время ответ не пришел то возвращается пустая строка.
2) WriteData, который действует как принято в SSH протоколе, просто передает данные и забывает.

Ивент OnLog используется больше для дебагинга чем для практических задач.

В архиве есть пример простого SSHClient-а на уровне Putty, подключается к серверу, отсылает команды и получает ответы, на его базе можно вести тестирования. Любые ошибки или пожелания пожалуйста пишите здесь или на присылайте на мыло administrator[ a t ]gesoft.org.

Теперь немного инфы для того кто в будущем зайдет в этот топик и будет ломать голову, как же это возможно определить конец команды. Я специально отослал письма разработчикам Putty и библиотеки DelphiCryptLib. Вот что я получил в ответ:


Цитата:
Ben Harris
>The project is open source. The class almost finished. As a sample I
>have created Putty like program, of course not with all Putty
>functionalities but: it could connect to SSH server, send commands and
>receive answers.
...
>Question: I am pushing data =91ls#13=92, and after I am popping first
>package successfully. Now, how I should determine that there is still 4
>answer packages for my command (ls)?
...
>How this problem is solved in Putty?

It isn't. PuTTY doesn't know about commands or prompts or anything like
that; it just takes keypresses from the user and sends them to the
server, and takes characters from the server and displays them to the
user. It's up to the user to notice when their shell prompt returns and
start typing again.


Для тех у кого проблемы с английским, в двух словах, даже Putty не определяет конец команды, а из ответа на мой вопрос в comp.security.ssh, я получил:


Цитата:
Steven Mocking
> Now, how I should determine that there is still 4 answer packages for
> my command (ls)?

You can't. Even the server can't know that a command is finished.

The good news is that you don't need to, as long as you multiplex
between the file descriptors. That way you don't block your program if
there are no "packets" in the stack.

I'm not sure about a Delphi implementation, but POSIX has the select()
and poll() system calls for that, which you might want to read up on.

> The first idea which came to us (some other developers taking part in
> implementing
> this class) is to wait until 'shell prompt' line will not occur in
> package (server-name#
> or u...@name.com$). Later after many tests, we discover that some
> server's 'shell prompt'
> line could be just one symbol '$'. As you know symbol '$' could be
> used in file name,
> so that make possible to false 'answer end' determination.

Never rely on such things. For example, any user can set his prompt to
an arbitrary string!


Откуда ясно что в протоколе SSH вообще не предусмотрено определение конца команды. Дословно перевожу одну строку: "Определить конец ты не можешь Даже серверу не известно когда будет завершена команда" а также "Никогда не полагайся на эти веши (речь идет о символах $ и #). Например, любой пользователь может установить произвольную строку как приветствие Shell".
Автор: idiMAN
Дата сообщения: 05.03.2007 17:49
Delphi6, спасибо!
Завтра обязательно потестирую.
Автор: Delphi6
Дата сообщения: 06.03.2007 11:05
idiMAN
Спасибо. Буду признателен за любое замечание

Найдены и исправлены две маленькие не доработки, при дисконекте рекурсивный поток останавливается только в том случае если только был удачный коннект. Изменилась конструкция уничтожения класса на кнопке Disconnect.

Нужно добавить проверку на наличие имени и пароля, без них коннект не произойдет, а при попытке сгенерируется ошибка.

Код: procedure TSSHClient.Connect();
begin
if (Assigned(fOnConnect)) then
fOnConnect();
if (fUserName = '')or(fPassword = '') then
exit;
...
end;
Автор: Swappp
Дата сообщения: 09.03.2007 17:55
Delphi6

Цитата:
Что касается OpenSSH, я к сожалению не нашел исходных кодов Или их и ни надо искать? и вы подразумевали что-то другое?

Хм, я понял, если бы не нашел бинарок под вин, но вот не найти исходники... http://www.openssh.com/ http://www.openssh.com/portable.html
Автор: Delphi6
Дата сообщения: 09.03.2007 20:46
Swappp
Когда десять дней с утра до вечера пытаешься решить одну задачу, то не такое бывает Спасибо, посмотрю обязательно, хотя получив ответы от разработчиков Putty и CryptLib я понял что то что я хочу сделать почти мечта, если только не делать часть CryptLib с самого начала (то что касается SSH)
Автор: Delphi6
Дата сообщения: 10.03.2007 11:48
Уважаемый Wolfgang Gothier (автор DelphiCryptLib) посоветовал воспользоваться командой SP1 и SP2 с помощью которой можно задать собственный Shell prompt, что дает возможность 90% повысить стабильность. Для этого надо просто сгенерировать 64 байтную строку из случайных цифр и букв алфавита и ее использовать как Shell promt. На днях пофиксю TSSHClietn и перевыложу
Автор: idiMAN
Дата сообщения: 11.03.2007 18:30
Delphi6

Цитата:
На днях пофиксю TSSHClietn и перевыложу

Хорошая новость!

От себя, как вариант, добавлю, что можно к любой отсылаемой на сервер команде добавить " && echo signature" и при получении ответа искать уникальную строку signature как признак завершения выполнения отправленной команды.
Автор: gerbirosius
Дата сообщения: 08.07.2009 12:00
И вот опять поднимаю эту тему,
так как все ссылки которые были выложены Delphi6 на его пример не рабочие.

Мне пришлось писать SSH клиент на Делфи своим путем.
Но вот тормознулся я на реализации туннеля , то есть перенаправление
удаленного 3306 порта на localhost у меня не получается.

Ради изучения этого процесса установил на шлюзовом компе
SSH сервер и Mysql сервер.

В исходнике моего клиента есть такие функции которые
я применил для перенаправления порта согласно инструкции
приложенной к cryptlib :


Цитата:


iResult:=cryptSetAttribute(cryptSession, CRYPT_SESSINFO_SSH_CHANNEL, CRYPT_UNUSED );

iResult:=cryptSetAttributeString(cryptSession,CRYPT_SESSINFO_SSH_CHANNEL_TYPE, pChar(MChannelType), length(MChannelType));
iResult:=cryptSetAttributeString( cryptSession,CRYPT_SESSINFO_SSH_CHANNEL_ARG1, pChar(MChannelArg1), length(MChannelArg1));
iResult:=cryptSetAttribute(cryptSession, CRYPT_SESSINFO_ACTIVE, 1);
if iResult<>0 then showmessage('False') else showmessage('Ok');


В результате перенаправление не происходит, пробовал и локальный тип(direct-tcpip) и удаленный (tcpip-forward).

вот значение переменных из этого исходника :

iResult - cryptInit
MChannelType - тип форвардинга
MChannelArg1- адрес с портом подключения

Выше этого исходника имеется алгоритм подключения по 22 порту,
но он мне кажется выполняет свою работу потому что
после подключения я проверял через netstat -an и видел 22 порт 192.168.0.1:22 ESTABLISHED то есть происходит подключение по ssh.
Тогда я начал копать и искать причину по которой не происходит перенаправление порта, запускал всем известный putty и он прекрасно конектица и осуществляет туннель, и тогда решил проверить форвардинг в ручную, то есть предварительно
подключится с putty и набрать команду перенаправления 3306 порта
-N -f -R 3306:localhost:3306 192.168.0.1
на что мне выходит обломное сообщение
Warning: remote port forwarding failed for listen port 3306
или на платном хосте
Permission denied (publickey, keyboard-interactive).

Помогите пожалуйста кто как говорится в этом профи,
что я делаю не так и как мне реализовать перенаправление
для работы с удаленной MYSQL базой ?


Автор: gerbirosius
Дата сообщения: 09.07.2009 13:10
Ну что нет что ли знатоков по этой теме ?
Автор: gerbirosius
Дата сообщения: 14.07.2009 07:32
Почему вы не кто не отвечаете ? Что секретная тема чтоли ?
Если я торможу , то подскажите в чем ?
Автор: atomic9
Дата сообщения: 09.09.2010 07:49
У кого-нибудь сохранился примерчик из данной темы?

Страницы: 12

Предыдущая тема: socket не компилируется :(


Форум Ru-Board.club — поднят 15-09-2016 числа. Цель - сохранить наследие старого Ru-Board, истории становления российского интернета. Сделано для людей.