JSch несколько туннелей/jumphosts

avatar
Fangming
30 ноября 2018 в 21:13
1698
1
6

Я не уверен, что это вызвано использованием закрытого ключа вместо пароля для переадресации портов, но вот что я пытаюсь сделать

enter image description here

Мне нужно перенаправить локальный порт 3308 на всю базу данных SQL по адресу 3306.

Я могу запускать такие вещи все вместе в терминале на моем локальном компьютере

ssh -L 3308:localhost:3307 username@jumpbox "ssh -L 3307:mysqlDB:3306 username@server"

Или запустите первую часть на моем локальном компьютере, а затем вторую часть на панели перехода. Оба работают нормально, и я могу подключиться к моему локальному хосту: 3308.

Проблема возникает, когда я начинаю использовать JSch. Вот мой код

JSch jsch = new JSch();
jsch.addIdentity("~/.ssh/id_rsa");

Session session = jsch.getSession("username", "jumpbox");
session.setConfig("StrictHostKeyChecking", "no");
session.connect();

int assinged_port = session.setPortForwardingL(3308, "localhost", 3307);
Session mysqlSession = jsch.getSession("username", "server", assinged_port);
mysqlSession.setConfig("StrictHostKeyChecking", "no");
mysqlSession.connect(); // Connection timed out here
mysqlSession.setPortForwardingL(3307, "mysqlDB", 3306);

Первое соединение установлено, но время ожидания второго истекло.

Исключение в потоке "main" com.jcraft.jsch.JSchException: java.net.ConnectException: время ожидания операции истекло (время ожидания соединения истекло)

Я делаю что-то не так с JSch или переадресацией портов?

Источник

Ответы (1)

avatar
Martin Prikryl
1 декабря 2018 в 07:46
5

Ваша команда ssh использует SSH-клиент (еще один ssh), работающий на "переходнике".

Если вы хотите реализовать то же самое с помощью Java, у вас есть два варианта:

  1. Сделайте то же самое в Java, т.е. используйте session для запуска ssh -L 3307:mysqlDB:3306 username@server на "переходнике".

    См. Выполнение команды с помощью JSch.

    Хотя я не думаю, что вы должны полагаться на программу ssh для второго перехода, по той же причине вы используете Java/JSch для первого перехода (а не программу ssh).

  2. Избегайте использования отдельного инструмента ssh и вместо этого откройте другой сеанс SSH локально через еще один перенаправленный порт. Фактически вы можете сделать то же самое, используя последние версии ssh с -J (переход) переключателем (поддерживается начиная с OpenSSH 7.3):

    ssh -L 3308:mysqlDB:3306 -J username@jumpbox username@server
    

    См. также Поддерживает ли OpenSSH вход в систему с несколькими переходами?

    Я предпочитаю этот подход.


Для реализации последнего подхода:

  • Вы должны перенаправить некоторый локальный порт на server:22, чтобы вы могли открыть SSH-соединение с server:

    JSch jsch = new JSch();
    jsch.addIdentity("~/.ssh/id_rsa");
    
    Session jumpboxSession = jsch.getSession("username", "jumpbox");
    jumpboxSession.connect();
    
    int serverSshPort = jumpboxSession.setPortForwardingL(0, "server", 22);
    Session serverSession = jsch.getSession("username", "localhost", serverSshPort);
    serverSession.connect();
    
  • Затем вы перенаправляете другой локальный порт через server на порт MySQL:

    int mysqlPort = serverSession.setPortForwardingL(0, "mysqlDB", 3306);
    

    Теперь вы сможете подключиться к localhost:mysqlPort с помощью клиента MySQL.


Обязательное предупреждение: не используйте StrictHostKeyChecking=no для слепого принятия всех ключей хоста. Это недостаток безопасности. Вы теряете защиту от MITM-атак.

Для правильного (и безопасного) подхода см.:
Как разрешить Java UnknownHostKey при использовании библиотеки JSch SFTP?
<82853047