我正在通过 SSH 进行永久端口转发。基本上是
while true; do
ssh <somewhere> \
-R <dst-port>:localhost:<src-port> \
-N -n -o ExitOnForwardFailure=yes
sleep 10
done
但是,这种方式不太可靠。有时,端口根本无法转发(我不确定连接是否正确处于活动状态,但我可以在客户端上看到该过程,并且它已经运行了几个小时),有时连接肯定不再处于活动状态(因为网络接口已关闭),但超时需要很长时间(有时长达 30-60 分钟)。
我怎样才能让它更可靠?我希望超时时间大约为一分钟。
我刚刚发现这个非常相关/相似的问题。但是,第一个答案表明ExitOnForwardFailure
应该可以解决它,但是我已经有了它,但是却没有(我现在可以使用ssh
此选项看到正在运行的进程,但端口没有转发)。
答案1
我将这些放在 SSH 客户端config
文件中:
ServerAliveInterval = 60
ServerAliveCountMax = 3
ssh
或者,可以通过命令行传递这些选项-o
。
某些客户端可能没有这种配置控制,例如各种移动设备的微不足道的客户端。在这种情况下,仍然可以在连接到的每个服务器上进行全局配置,这当然需要服务器计算机上的权限。OpenSSHD 实现似乎没有让用户自定义服务器参数的方法(没有~/.ssh/sshd_config
读取文件,可以从服务器端自定义所选参数)。
答案2
我在我的工作机器上使用 autossh 来设置远程 Web 开发:
autossh -M0 -N -R \*:8080:localhost:80 -R \*:5051:localhost:22 home
autossh 是一个程序,如果 ssh 因除“kill -9”之外的任何原因崩溃或停止,它会不断重新启动 ssh。上述命令设置了两个隧道:一个用于将我工作机器上的端口 80 转发到我家用机器上的 8080,另一个将我工作机器上的 ssh 服务器隧道传输到我家用机器。端口前面的 * 使它适用于任何主机名,而不仅仅是 localhost。不过,您可能需要在 sshd_config 上设置“GatewayPorts yes”才能使其正常工作。我的家用机器上的 ~/.ssh/config 和 /etc/hosts 中有主机,以使它更加透明。对于其他系统,需要使用 ProxyCommand (http://sshmenu.sourceforge.net/articles/transparent-mulithop.html),但是我此刻没有启动使用此命令的主机来抓取它。
〜/.ssh /配置:
Host work
hostname localhost
port 5051
那么就只是
autossh -M0 -t home 'ssh work'
从任何主机进行连接。
答案3
此版本会频繁向服务器发送一些数据。如果连接断开,管道迟早会断开。
while true; do
{ while true; do echo echo ping; sleep 10; done } | \
ssh <somewhere> \
-R <something> \
-o ExitOnForwardFailure=yes \
>/dev/null
sleep 10
done
答案4
正如 Kaz 先前所引用的,该连接似乎不需要任何显式流量来保持活动状态。例如:
ssh you@there 'read ANYTHING' < $PIPE
就可以了。$PIPE 是一个命名管道,当您完成后,您将写入该管道。
好吧,让我们明确一点——$PIPE 比“读取任何内容”更复杂,值得举一个详细的例子。这是我用来在无法直接访问的网络中 rdesktop 一台机器的代码:
p_user=myself
p_bridge=me@there
p_host=192.168.xxx.yyy
p_port=9999
p_size=100% # or: p_size=1280x1024
p_trace=stderr # or: p_trace=null
s_trace() { echo "$*" > /dev/$p_trace; }
PIPE=$TEMP/${0##*/}.$$
mkfifo $PIPE.0
mkfifo $PIPE.1
trap 'rm $PIPE.0 $PIPE.1' 0
# ----------------------------------------------------
ssh $p_bridge \
-L $p_port:$p_host:3389 \
'read CONNECT; date; read QUIT' \
< $PIPE.1 \
> $PIPE.0 \
&
# ----------------------------------------------------
# note: "type -p" is somehow required with xinit
# note: "-p -" reads password from stdin
DESKCMD="$(type -p rdesktop) -P -z -u $p_user -p - -g $p_size localhost:$p_port"
{
echo connect >&3; read CONNECT <&4; s_trace "CONNECTED: $CONNECT"
$DESKCMD -f # or: xinit $DESKCMD -- :1
echo quit >&3
} \
3> $PIPE.1 \
4< $PIPE.0
wait