使用JSCH实现SSH端口转发:预期方案失效,可行方案逻辑存疑
JSCH端口转发逻辑解析:为什么绑定回环地址能成功?
核心误解:你搞混了端口转发的监听位置
你之前的SSH命令测试和JSCH代码的执行场景完全不同:
- 测试时,你是在跳板机上执行
ssh -L *:34567:RemoteServer.com:22 [user]@JumpServer.com,这是让跳板机监听自身的34567端口(*表示绑定所有网卡),所以Java服务器能通过连接跳板机的34567端口走隧道到远程服务器。 - 但你的JSCH代码是在Java服务器上运行的,JSCH的
setPortForwardingL是本地端口转发——意思是在**运行JSCH的机器(即Java服务器)**上监听一个端口,所有发往这个端口的请求,会通过Java服务器和跳板机之间的SSH会话,转发到远程服务器的22端口。
你的代码为什么报错?
你调用setPortForwardingL("*",0,remoteServerAddress,22)后,错误地去连接跳板机的转发端口,但实际上这个转发端口是在Java服务器本地监听的,跳板机上根本没有开启这个端口,所以必然出现“Connection Refused”。
同事的代码逻辑是什么?
同事的代码做了两件正确的事:
setPortForwardingL(0,remoteServerAddress,22)省略了绑定地址参数,JSCH默认会把监听端口绑定到回环地址(127.0.0.1)——这意味着只有Java服务器本机才能访问这个转发端口,安全性更高。其中0表示让系统随机分配一个可用的本地端口。- 之后连接
127.0.0.1的转发端口,就是直接访问Java服务器本地的监听端口,请求通过已建立的SSH隧道(Java服务器 ↔ 跳板机)转发到远程服务器的22端口,自然能成功建立连接。
额外说明
如果你一定要让转发端口允许其他机器访问(类似测试时的*),可以用setPortForwardingL("0.0.0.0",0,remoteServerAddress,22)(0.0.0.0表示绑定所有网卡),但此时你需要连接的是Java服务器自身的那个随机端口,而不是跳板机的端口,这样也能成功。不过生产环境不建议这么做,回环地址的绑定更安全。
内容的提问来源于stack exchange,提问作者Raddaya
相关产品推荐
相关产品推荐

