java - JSch 多个隧道/跳跃站

标签 java ssh jsch portforwarding ssh-tunnel

我不确定这是否是由于使用私钥而不是密码进行端口转发引起的,但这就是我正在尝试做的

enter image description here

我需要将本地端口 3308 一直转发到位于 3306 的 SQL 数据库。

我可以在本地终端上运行这样的事情

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

或者在我的本地运行第一部分,然后在跳转盒上运行第二部分。两者都工作正常,我可以连接到我的 localhost: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);

第一个连接已完成,但第二个连接超时。

Exception in thread "main" com.jcraft.jsch.JSchException: java.net.ConnectException: Operation timed out (Connection timed out)

我在 JSch 或端口转发方面做错了什么吗?

最佳答案

您的 ssh 命令正在使用在“jump box”上运行的 SSH 客户端(另一个 ssh)。

当您想使用 Java 实现相同的功能时,您有两种选择:

  1. 在 Java 中执行相同操作,即使用 session 在“跳转框”上运行 ssh -L 3307:mysqlDB:3306 username@server

    参见Executing a command using JSch .

    不过,我认为您不应该依赖 ssh 程序进行第二次跳转,这与您使用 Java/JSch 进行第一次跳转的原因相同(而不是 ssh > 程序)。

  2. 避免使用单独的 ssh 工具,而是通过另一个转发端口在本地打开另一个 SSH session 。实际上,您可以使用最新版本的 ssh 执行相同的操作,即 -J (jump) switch (自 OpenSSH 7.3 起支持):

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

    另请参阅Does OpenSSH support multihop login?

    我更喜欢这种方法。

<小时/>

要实现后一种方法:

  • 您必须将一些本地端口转发到server:22,以便您可以打开与服务器的SSH连接:

    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();
    
  • 然后通过服务器将另一个本地端口转发到MySQL端口:

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

    现在您应该能够使用 MySQL 客户端连接到 localhost:mysqlPort

<小时/>

强制警告:请勿使用 StrictHostKeyChecking=no 盲目接受所有主机 key 。这是一个安全缺陷。您失去了针对 MITM attacks 的保护.

有关正确(且安全)的方法,请参阅:
How to resolve Java UnknownHostKey, while using JSch SFTP library?

关于java - JSch 多个隧道/跳跃站,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35208180/

相关文章:

java - 如何使用一个 session 同时使用 JSch 中的 'exec' 和 'sftp' channel

java - 向 Cloud Endpoint 添加参数会导致 404 GoogleJsonResponseException

java - JAXB 2.x : Marshalling puts element value twice into the XML

java - 如何在JSch中设置Java home来执行命令?

linux - 如何与连接到一台计算机的两个 beaglebone black 进行交互

java - 将绑定(bind)地址与 Jsch session 结合使用

java - Spring 与 JMS + ActiveMQ 集成 : Messages remain in JDBC Message Store after reconnect

java - 将 JSON unicode 字符转换为 unicode 值

ssh - 使用 ssh 隧道从远程服务器复制到本地计算机的 shell 脚本 - scp

java - 连接池 MySQL 连接与 SSH(JSch)