简体   繁体   English

用于本地(非远程)命令执行的ssh隧道

[英]ssh tunnel for local (not remote) command execution

I want to create a Linux shell (bash-) script which creates an SSH tunnel, runs a local command which uses that tunnel and finally closes the tunnel and the surrounding SSH connection. 我想创建一个Linux shell(bash-)脚本,它创建一个SSH隧道,运行一个使用该隧道的本地命令,最后关闭隧道和周围的SSH连接。

To make this less difficult to explain consider there is a local SSH configuration to a host called 'remoteserver' containing a local private key without a password, so 为了减少解释难度,可以考虑一个名为“remoteserver”的主机的本地SSH配置,其中包含一个没有密码的本地私钥,所以

ssh remoteserver -L 4444:targetserver:5555

would directly open a connection to the remote server and create a tunnel from the local port 4444 to a target server. 将直接打开与远程服务器的连接,并创建从本地端口4444到目标服务器的隧道。 And consider the local command would be localclient --port 4444 , how would a script look like that opens the tunnel, executes the local command and closes the tunnel after the local client application is finished? 并且考虑本地命令是localclient --port 4444 ,脚本看起来如何打开隧道,执行本地命令并在本地客户端应用程序完成后关闭隧道?

As it should be possible to keep other parallel ongoing SSH connections, I don't want something like sudo killall ssh . 由于应该可以保持其他并行正在进行的SSH连接,我不想要像sudo killall ssh这样的东西。

You can try something like 你可以尝试类似的东西

TIMEOUT=60 # seconds
ssh remoteserver -L 4444:targetserver:5555 sleep $TIMEOUT &
localclient --port 4444

The tunnel will close itself automatically after $TIMEOUT seconds. $ TIMEOUT秒后隧道将自动关闭。 Note that using the & is only valid with passwordless connections. 请注意,使用&仅对无密码连接有效。 Otherwise you need to use the -f flag of SSH. 否则,您需要使用SSH的-f标志。

Alternatively, 或者,

ssh -N remoteserver -L 4444:targetserver:5555 &
sshpid=$!
localclient --port 4444
kill $sshpid

will kill the tunnel just after localclient executes. localclient执行后会杀死隧道。 Note that this will not work with the -f flag because the process double forks. 请注意,这不适用于-f标志,因为进程双叉。

An ssh -only solution (does not work for me) 一个ssh -only解决方案(对我不起作用)

The second suggestion of @damienfrancois is adquate, but for some reason I did not like the idea of having to kill something. @damienfrancois的第二个建议是适当的,但由于某种原因,我不喜欢不得不kill一些东西的想法。

Also, I could not believe ssh has no built-in mechanism for this. 另外,我无法相信ssh没有内置机制。 And indeed it has. 确实如此。 This is how things should work: 事情应该如何运作:

ssh remoteserver -o "PermitLocalCommand yes" -o "LocalCommand localclient --port 4444" \
    -L 4444:targetserver:5555 -N

But for some reason, this did not work as expected for me: I first tried with something simple like w for the LocalCommand but the -N made the command hang, so I used sleep 0 instead, which appeared to work. 但由于某些原因,这对我来说没有预期的效果:我首先尝试使用像w这样简单的东西用于LocalCommand但是-N使命令挂起,所以我使用了sleep 0来代替,这似乎有效。

But when I inserted my actual network command, the result ran extremely slowly. 但是当我插入我的实际网络命令时,结果运行得非常慢。 Instead of finishing in less than one second, it took 40 seconds before even the start message appeared. 而不是在不到一秒的时间内完成,甚至在开始消息出现之前花了40秒。 I terminated the command after 20 minutes. 我在20分钟后终止了命令。

A pipe solution (works for me) 管道解决方案(适合我)

After some experimentation, this is what I now use: 经过一些实验,这就是我现在使用的:

ssh remoteserver -L 4444:targetserver:5555 keepalive.sh \
  | (sleep 0.5; localclient --port 4444)

where keepalive.sh on the remote side is this: 其中远程端的keepalive.sh是这样的:

while true; do
   sleep 1
   echo "keepalive"
done

The sleep 0.5 is needed to make (sort of) sure the tunnel is set up before localclient starts (and for a far-away or slow remoteserver , you may need a longer wait). 需要sleep 0.5才能确保在localclient启动之前设置隧道(对于远程或慢速remoteserver ,您可能需要更长的等待时间)。 The tunnel is terminated as soon as localclient finishes because the shell terminates the pipe as soon as the second command closes its standard input. 一旦localclient完成,隧道就会终止,因为一旦第二个命令关闭其标准输入,shell就会终止管道。

Is this better than @damienfrancois's solution? 这比@ damienfrancois的解决方案更好吗? Depends. 要看。

The need for keepalive.sh is a clear drawback, but the way in which the tunnel is cleared away no matter how and why localclient terminates is cleaner. keepalive.sh的需求是一个明显的缺点,但无论localclient如何以及为何终止,隧道被清除的方式都更加清晰。

I need this in a Makefile context and like the fact it fits on a single line. 我在Makefile上下文中需要这个,就像它适合单行一样。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM