Существует множество способов решить данную проблему, и один из них - создание SSH-туннеля между сервером и клиентом.
картинки взяты с какой-то статьи о remote-debugging'е ZendFramework и немного подправлены
Под *nix системами решение простое:
$ ssh -f -N -L 5432:localhost:5432 username@host- -f
- оставить соединение в фоне
- -N
- не выполнять никаких команд
- -L
- выполнить "проброс" портов в формате port:host:hostport
Для удалённого SSH-соединения во все времена выручал пресловутый PuTTY. Он же и умеет делать SSH-туннели.
Но поставлять стороннее приложение, хоть оно и opensource, с продуктом, только для создания SSH-туннеля и проброски портов - “не спортивно”. Нужно научить наше приложение самому поднимать SSH соединение.
Известно, что в составе библиотек .NET Framework нет инструментов для работы с SSH-протоколом.
После непродолжительного "гугления" можно обнаружить две разработки, которые не требуют от вас много денежных знаков: Granados и SharpSSH.
Что касается первого, то меня огорчило три вещи:
- совсем невменяемая документация;
- запутанная структура проекта;
- возраст (последние изменения датированы апрелем 2004 года);
Второй же, в отмену, имеет и хорошую документацию (+ блог автора, Тамир Гал) и внятную структуру проекта. Хоть новизной так же не блещет. Помимо этого у проекта есть форк SharpSSH2. Отличия от "папки":
- переведён на .NET Framework 3.5;
- дополнительные настройки компрессии;
- дополнительные опции шифрования AES;
- пачка мелких "энхансов".
 
Для начала работы, нам необходимо подключить библиотеку SharpSSH и её namespace.
using SharpSsh;
Также необходимо будет реализовать простенький интерфейс:
public interface UserInfo
{
    /// <summary>
    /// Returns the user passphrase (passwd for the private key file)
    /// </summary>
    String getPassphrase();
    /// <summary>
    /// Returns the user password
    /// </summary>
    String getPassword();
    /// <summary>
    /// Prompt the user for a password
    /// </summary>
    bool promptPassword(String message);
    /// <summary>
    /// Prompt the user for a passphrase (passwd for the private key file)
    /// </summary>
    bool promptPassphrase(String message);
    /// <summary>
    /// Prompt the user for a Yes/No input
    /// </summary>
    bool promptYesNo(String message);
    /// <summary>
    /// Show messages
    /// </summary>
    void showMessage(String message);
}
Примерно вот так:
public class MyUserInfo : UserInfo
{
    private String passphrase;
    public MyUserInfo (String Passphrase)
    {
        passphrase = Passphrase;
    }
    public String getPassword()
    {
        return null;
    }
    public bool promptYesNo(String str)
    {
        return true;
    }
    public String getPassphrase()
    {
        return passphrase;
    }
    public bool promptPassphrase(String message)
    {
        return true;
    }
    public bool promptPassword(String message)
    {
        return true;
    }
    public void showMessage(String message)
    {
        // MessageBox.Show(message);
        // Console.WriteLine(message);
    }
}ненужные методы я грубо закрыл return true;
Далее в коде создадим
Session session;
Channel channel;
JSch jsch;
jsch = new JSch();
const String PrivateKeyFile = "id_dsa";
jsch.addIdentity(PrivateKeyFile);
const String host = "host.com";
const String user = "user";
const String passphrase = "Passphrase";
//Create a new SSH session
session = jsch.getSession(user, host, 22);
session.setPortForwardingL(5432, "localhost", 5432);
//Username and password will be given via UserInfo interface.
UserInfo ui = new MyUserInfo(passphrase);
session.setUserInfo(ui);
//Connect to remote SSH server
session.connect();
//Open a new Shell channel on the SSH session
channel = session.openChannel("shell");
//Connect the channel
channel.connect();
//Wait till channel is closed
while (!channel.isClosed())
{
  System.Threading.Thread.Sleep(500);
}Ну а дальше "причёсываем" код, добавляем try-catch, где надо и т.п.
Получаем малой кровью, очень даже неплохой SSH-туннель, средствами C#.




 

Комментариев нет:
Отправить комментарий