Существует множество способов решить данную проблему, и один из них - создание 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#.
Комментариев нет:
Отправить комментарий