JSch 多个隧道/跳转主机

Posted

技术标签:

【中文标题】JSch 多个隧道/跳转主机【英文标题】:JSch multiple tunnels/jumphosts 【发布时间】:2019-05-03 01:11:07 【问题描述】:

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

我需要将本地端口 3308 一直转发到我的 SQL DB 3306。

我可以在本地的终端中一起运行这样的事情

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

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

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

线程“main”com.jcraft.jsch.JSchException 中的异常:java.net.ConnectException:操作超时(连接超时)

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

【问题讨论】:

【参考方案1】:

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

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

    在 Java 中做同样的事情,即使用session 在“跳转框”上运行ssh -L 3307:mysqlDB:3306 username@server

    见Executing a command using JSch。

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

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

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

    另见Does OpenSSH support multihop login?

    我更喜欢这种方法。


实现后一种方法:

你必须将一些本地端口转发到server:22,这样你才能打开到server的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();

然后你通过server将另一个本地端口转发到MySQL端口:

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

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


强制警告:不要使用StrictHostKeyChecking=no 盲目接受所有主机密钥。那是一个安全漏洞。你失去了对MITM attacks的保护。

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

【讨论】:

以上是关于JSch 多个隧道/跳转主机的主要内容,如果未能解决你的问题,请参考以下文章

通过 JSch 建立 SSH 隧道

使用 JSch 通过 SSH 隧道访问生产环境中的 JMX

基于 JSCH (SSH) 和 HTTPS 的反向隧道

使用 JSch 创建一个通过 SSH 隧道化的 SOCKS 代理

使用 JSCH Java 反向 SSH 隧道 [关闭]

在具有特定 mysql 主机的远程主机上使用 SSH 隧道连接到 MySql 数据库