反向 SSH 隧道

3

我有一个嵌入式设备放在外面的领域里,通过USB手机卡连接到互联网。为了能够访问它,我在端口19996上建立了一个反向ssh隧道到我的家用电脑。

现在我每10分钟重新建立一次该隧道(通过cron),以确保我几乎可以不间断地访问它,即使提供商决定更改我的IP。

现在我意识到我的进程列表已经满了

"4383 root     ssh -R 19996:localhost:22 -f -N user@host"

netstat也有很多连接。我该如何确保这不会发生?我只需要一个隧道处于打开状态,而不是100个。


Burrow.io 是一个很酷的工具,如果你需要使用 HTTP 或 HTTPS 的话。免费账户可以让你创建一个隧道(HTTP),而你只需要在你的设备中运行一个 curl 命令就行了。它甚至会验证连接始终保持打开状态,省去了 Cron job 的需求。 - Paulo Arruda
5个回答

2
我编写了以下Shell脚本,似乎运行良好!
#!/bin/sh
RETVAL=`netstat | grep 'S0106b0487afe2a57'| grep -c 'ssh ESTABLISHED'`
echo "${RETVAL} open tunnel(s)"
if [ "$RETVAL" -lt "1" ]
  then
        echo "starting reverse ssh tunnel"
        `ssh -R 19999:localhost:22 -f -N user@host`
        echo "done"
fi

我使用了RETVAL=netstat | grep '<hostname>:ssh' | grep -c 'ssh ESTABLISHED',看起来运行良好。 - MitchBroadhead

1

使用autossh代替,如果连接断开,它将重新建立连接。首先在您的发行版存储库中搜索,如果找不到,请在网络上搜索。


问题是我的发行版是使用Buildroot(带有Busybox)自己组装的。我需要重新编译整个系统......如果可以的话,我更喜欢其他方法......但是好建议,谢谢! :) - stdcerr

1
我编写了以下脚本,cron每5分钟运行一次。 虽然我希望它能正常工作,但我仍然发现有时远程端不允许我进入。 回答上面的评论-它似乎没有从netstat中消失。 我检查netstat,它仍会显示连接的“ssh ESTABLISHED”,因此当我的脚本运行时,我得到“sockets appear connected. assuming reverse ssh tunnel is running fine.”的结果。 必须有更好的方法来测试远程端并获得一个可以表明它正在工作的结果吗?
#!/bin/bash

#$Id: ssh_reverse_tunnel.sh 14 2012-10-13 22:53:21Z root $

REMOTE_USER="user"
REMOTE_DOMAIN="domain"
SOCKETS_USED=`netstat -p ssh | grep 'ssh ESTABLISHED' | grep -c $(host $REMOTE_DOMAIN | awk {'print $NF'})`

establish_connecton() {
  echo "establishing reverse ssh tunnel connection..."
  ssh -R 12222:localhost:22 -R12223:localhost:5901 -f -N -T ${REMOTE_USER}@${REMOTE_DOMAIN} &
  echo "done."
  echo
  exit
}

if [ $(ps -ef | grep "ssh -R 12222" | grep -v grep | wc -l) == 0 ]; then
  echo "no reverse ssh tunnel connection exists."
  establish_connecton
fi

if [ "$SOCKETS_USED" -lt 1 ]; then
  echo "no reverse ssh tunnel sockets are connected. nuking stale pids and re-establishing connection"
  # check for stale pids and kill them if found.
  if [ $(ps -ef | grep "ssh -R 12222" | grep -v grep | wc -l) -gt 0 ]; then
    # stale pids exist, kill them...
    ps -ef | grep "ssh -R 12222" | grep -v grep | awk {'print $2'} | \
      while read PID; do
        echo "kill -9 $PID"
      done
  fi
  establish_connecton
else
  echo "sockets appear connected. assuming reverse ssh tunnel is running fine."
fi

希望有人会发现上述内容有用,并且能够告诉我在哪里可以增加更多的检查。

0

启动新进程后,只需通过ID结束先前的进程。您可以通过ps命令获取进程ID。


但是如果我杀死现有的会话,当前的SSH会话会被终止,对吧?如果每10分钟就掉线,这样并不方便... - stdcerr
是的,但从技术上讲还有另一个问题。一个进程不应该能够在你已经有一个正在运行中的本地端口之后绑定到相同的本地端口,因此只有一个进程应该在结束之前运行。如果您连续运行这些命令,其中一个应该会生成错误并立即终止...因此多个进程的问题似乎不应该出现。也许这里发生了其他事情。尝试从该框内本地连续运行它们并查看输出结果。 - Robert
实际上,我正在办公室的电脑上执行相同的操作(建立到我的家用电脑的反向隧道),并且我得到了完全相同的结果。在这里,我正在运行Kubuntu 12.04,所以是一个顶级发行版,完全相同... :o 但是当建立隧道时,我会收到“警告:远程端口转发失败,侦听端口19999”错误,但是我在我的小型嵌入式设备上也遇到了这个问题...但它仍然会将进程添加到进程列表中...这就是错的... :( - stdcerr
有没有办法检查命令是否无法绑定到端口,并在失败时终止挂起的进程?这样,实际上保持端口打开的进程将保持打开状态,您不会失去连接。类似于这里:http://www.cyberciti.biz/faq/what-are-the-exit-statuses-of-ssh-command/(echo $?,然后根据返回代码/状态执行某些操作) - Robert
同时,我编写了一个小的bash脚本,用于搜索特定的外部地址和“ssh ESTABLISHED”,如果连接数少于1,则重新打开它。但是,我不知道在动态IP更改的情况下,它是否会从netstat中消失...我假设至少状态会改变,对吗? - stdcerr

0
您可以使用ssh命令套接字来检查连接是否仍处于活动状态。它应该是这个样子的:
#!/bin/bash
if ! ssh -S mysocket -O check user@host ; then
    ssh -M -S mysocket -R 19996:localhost:22 -f -N user@host
fi

然后,您可以使用以下方法关闭特定的连接:

ssh -S mysocket -O exit user@host

也许将ServerAliveInterval设置为大于0的值,使用-o ServerAliveInterval=N会更有价值。因为如果连接丢失,它将终止您的隧道。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接