我试图在JSch
中以编程方式完成在Bash中工作良好的工作。我建立了一个SSH隧道,然后通过隧道进行通信。我应该每隔10秒左右发送一个身份验证字符串,作为回报,我将从远程主机获得稳定的行流。在JSch
中,我已经建立了到远程主机的连接,但是当我尝试使用direct-tcpip
选项设置通道,阅读和写入通道的getInputStream
和getOutputStream
时,它抛出了一个异常failed to initialize the channel
。在阅读了人们在其他SO回答中关于JSch
的内容后,我在尝试写入outputStream之前做了channel.connect()
。这就是Bash的工作原理:
在一个shell中:
ssh -l username -L LOCALPORT:127.0.0.1:REMOTEPORT REMOTEHOST
另一个shell:
ID='{ "id": 1234, "auth": "abcdefhijklmnopqrstuvwxyz" }'
while true; do echo $ID; sleep 10; done | nc localhost LOCALPORT
下面是一些Scala调用JSch的测试代码。我知道这很艰难。我只是想让JSch为我工作
import com.jcraft.jsch._
object Main extends Log4JLogging {
def main(args: Array[String]): Unit = {
// $ ssh -l username -L LOCALPORT:127.0.0.1:REMOTEPORT REMOTEHOST
// $ ID='{ "id": 1234, "auth": "abcdefghijklmnopqrstuvwxyz" }'
// $ while true; do echo $ID; sleep 10; done | nc localhost LOCALPORT
val remoteIpaddr = "123.45.54.321"
val localhost = "127.0.0.1"
val sshPort = 22
val tunnelLocalPort = LOCALPORT
val tunnelRemotePort = REMOTEPORT
val usernameAtRemoteHost = "username"
val privateKeyForRemoteHost = "ssh/for-remotehost/id_rsa"
val auth = "{ \"id\": 1234, \"auth\": \"abcdefghijklmnopqrstuvwxyz\" }\n"
try {
val currentWorkingDirectory: String = System.getProperty("user.dir")
val pathPrivateKeyForRemoteHost: String = s"$currentWorkingDirectory/$privateKeyForRemoteHost"
JSch.setConfig("server_host_key", JSch.getConfig("server_host_key") + ",ssh-rsa")
JSch.setConfig("PubkeyAcceptedAlgorithms", JSch.getConfig("PubkeyAcceptedAlgorithms") + ",ssh-rsa")
val tunnelJSch = new JSch()
tunnelJSch.addIdentity(pathPrivateKeyForRemoteHost)
val tunnelSessionPort = sshPort
val tunnelSession = tunnelJSch.getSession(usernameAtRemoteHost, remoteIpaddr, tunnelSessionPort)
tunnelSession.setConfig("StrictHostKeyChecking", "no") // yes I know this is bad, will change once things work
tunnelSession.setPortForwardingL(tunnelLocalPort, localhost, tunnelRemotePort)
tunnelSession.connect()
val tunnelChannel = tunnelSession.openChannel("direct-tcpip")
val input = tunnelChannel.getInputStream()
val output = tunnelChannel.getOutputStream()
tunnelChannel.connect()
// tunnelChannel.setInputStream(System.in)
// tunnelChannel.setOutputStream(System.out)
output.write(auth.getBytes(StandardCharsets.UTF_8))
val buffer = new Array[Byte](1024)
var n = input.read(buffer)
while (n > 0) {
n = input.read(buffer)
}
// val dataJsch = new JSch()
// dataJsch.addIdentity(pathPrivateKeyForRemoteHost)
// val dataSession = dataJsch.getSession(usernameAtRemoteHost, localhost, tunnelLocalPort)
// dataSession.setConfig("StrictHostKeyChecking", "no") // yes I know this is bad, will change once things work
//
// val dataChannel = dataSession.openChannel("forwarded-tcpip")
// dataChannel.setInputStream(System.in)
// dataChannel.setOutputStream(System.out)
// dataChannel.connect()
//
// val input = dataChannel.getInputStream()
// val output = dataChannel.getOutputStream()
// output.write(auth.getBytes(StandardCharsets.UTF_8))
// val buffer = new Array[Byte](1024)
// var n = input.read(buffer)
// while (n > 0) {
// n = input.read(buffer)
// }
// dataChannel.disconnect()
tunnelSession.disconnect()
} catch {
case e: Exception =>
logStackTrace(e)
System.exit(1)
}
}
}
1条答案
按热度按时间643ylb081#
看起来您希望
direct-tcpip
以某种方式神奇地连接到setPortForwardingL
。我很确定不会的。你基本上是在尝试两次同样的事情,但在这两种情况下,你都做了所有需要做的事情。或者:
Socket
连接到localhost:tunnelLocalPort
,并通过它与远程端通话。这有点夸张,但也许更容易实现。tunnelChannel
(通过调用setHost
和setPort
)。或者更确切地说,使用Session.getStreamForwarder
就可以做到这一点。