【问题标题】:ssh: check if a tunnel is alivessh:检查隧道是否存在
【发布时间】:2011-01-01 04:22:03
【问题描述】:

我写了一个small bash script,它需要一个ssh隧道从远程服务器提取数据,所以它提示用户:

echo "Please open an ssh tunnel using 'ssh -L 6000:localhost:5432 example.com'"

我想检查用户是否打开了此隧道,如果不存在隧道,则退出并显示错误消息。有没有办法查询ssh隧道,即检查本地端口6000是否真的通过隧道连接到该服务器?

【问题讨论】:

  • 这可能会部分帮助“lsof -i | grep ssh”

标签: ssh tunneling ssh-tunnel


【解决方案1】:

Netcat 是你的朋友:

nc -z localhost 6000 || echo "no tunnel open"

【讨论】:

  • 哇,这该死的有用。我正在制作一个脚本,首先创建一个 ssh 隧道,现在我正在使用 netcat 来了解它何时准备好接受连接。像魅力一样工作。
【解决方案2】:

如果您在后台使用 ssh,请使用:

sudo lsof -i -n | egrep '\<ssh\>'

【讨论】:

    【解决方案3】:

    这实际上更像是一个服务器故障类型的问题,但您可以使用 netstat。

    类似:

     # netstat -lpnt | grep 6000 | grep ssh
    

    这会告诉你是否有一个 ssh 进程在监听指定的端口。它还会告诉你进程的PID。

    如果您真的想仔细检查 ssh 进程是否使用正确的选项启动,则可以通过 PID 查找进程,例如

    # ps aux | grep PID
    

    【讨论】:

    • 请注意,此解决方案不适用于 OS X,因为 OS X 上的 netstat 不同。
    【解决方案4】:

    我们可以用ps命令检查

    # ps -aux | grep ssh
    

    将显示所有正在运行的 shh 服务,我们可以找到列出的隧道服务

    【讨论】:

      【解决方案5】:

      这些是测试 SSH 隧道或排除故障的更详细步骤。您可以在脚本中使用其中的一些。我添加这个答案是因为我必须在两个应用程序停止工作后对它们之间的链接进行故障排除。仅仅 grepping ssh 进程是不够的,因为它仍然存在。而且我不能使用nc -z,因为我的netcat咒语中没有该选项。

      让我们从头开始。假设有一台名为 local 的机器,IP 地址为 10.0.0.1,另一台名为 remote,位于 10.0.3.12。我会将这些主机名添加到下面的命令中,这样它们的执行位置就很明显了。

      目标是创建一个隧道,将 TCP 流量从远程机器上的端口 123 上的环回地址转发到本地机器上的端口 456。这可以在本地机器上使用以下命令完成:

      local:~# ssh -N -R 123:127.0.0.1:456 10.0.3.12
      

      要检查进程是否正在运行,我们可以这样做:

      local:~# ps aux | grep ssh
      

      如果您在输出中看到该命令,我们可以继续。否则,请检查 SSH 密钥是否安装在遥控器中。请注意,排除远程 IP 之前的用户名,使 ssh 使用当前用户名。

      接下来,我们要检查隧道是否在远程打开:

      remote:~# netstat | grep 10.0.0.1
      

      我们应该得到类似这样的输出:

      tcp  0  0  10.0.3.12:ssh  10.0.0.1:45988  ESTABLISHED
      

      如果能真正看到一些从远程到主机的数据,那就太好了。这就是 netcat 的用武之地。在 CentOS 上可以使用yum install nc 安装它。

      首先,在本地机器上打开一个监听端口:

      local:~# nc -l 127.0.0.1:456
      

      然后在遥控器上建立连接:

      remote:~# nc 127.0.0.1 123
      

      如果您打开本地计算机的第二个终端,您可以看到连接。像这样的:

      local:~# netstat | grep 456
      tcp  0  0 localhost.localdom:456 localhost.localdo:33826 ESTABLISHED
      tcp  0  0 localhost.localdo:33826 localhost.localdom:456 ESTABLISHED
      

      更好的是,继续在遥控器上输入一些内容:

      remote:~# nc 127.0.0.1 8888
      Hallo?
      anyone there?
      

      您应该会在本地终端上看到它的镜像:

      local:~# nc -l 127.0.0.1:456
      Hallo?
      anyone there?
      

      隧道正在工作!但是,如果您有一个名为 appname 的应用程序,它应该监听本地机器上的 456 端口,该怎么办?在两侧终止 nc 然后运行您的应用程序。您可以使用this 来检查它是否在正确端口上侦听:

      local:~# netstat -tulpn | grep LISTEN | grep appname
      tcp  0  0  127.0.0.1:456  0.0.0.0:* LISTEN  2964/appname
      

      顺便说一句,在遥控器上运行相同的命令应该会显示 sshd 正在侦听端口 127.0.0.1:123。

      【讨论】:

        【解决方案6】:
        #!/bin/bash
        
        # Check do we have tunnel to example.com server
        lsof -i tcp@localhost:6000 > /dev/null
        
        # If exit code wasn't 0 then tunnel doesn't exist.
        if [ $? -eq 1 ]
        then
          echo ' > You missing ssh tunnel. Creating one..'
          ssh -L 6000:localhost:5432 example.com
        fi
        
        echo ' > DO YOUR STUFF < '
        

        【讨论】:

          【解决方案7】:

          Autossh 是最佳选择 - 检查进程并非在所有情况下都有效(例如僵尸进程、网络相关问题)

          示例:

          autossh -M 2323 -c arcfour -f -N -L 8088:localhost:80 host2
          

          【讨论】:

            【解决方案8】:

            stunnel 是在主机之间建立半永久连接的好工具。

            http://www.stunnel.org/

            【讨论】:

              【解决方案9】:

              这是我的测试。希望有用。

              # $COMMAND is the command used to create the reverse ssh tunnel
              COMMAND="ssh -p $SSH_PORT -q -N -R $REMOTE_HOST:$REMOTE_HTTP_PORT:localhost:80 $USER_NAME@$REMOTE_HOST"
              
              # Is the tunnel up? Perform two tests:
              
              # 1. Check for relevant process ($COMMAND)
              pgrep -f -x "$COMMAND" > /dev/null 2>&1 || $COMMAND
              
              # 2. Test tunnel by looking at "netstat" output on $REMOTE_HOST
              ssh -p $SSH_PORT $USER_NAME@$REMOTE_HOST netstat -an | egrep "tcp.*:$REMOTE_HTTP_PORT.*LISTEN" \
                 > /dev/null 2>&1
              if [ $? -ne 0 ] ; then
                 pkill -f -x "$COMMAND"
                 $COMMAND
              fi
              

              【讨论】:

              • 上面的代码好像有bug。如果 [ $? -ne 0 ],0 应该是 1。远程 egrep 将设置 $?如果成功找到匹配项,则为 0。无论如何,每次运行命令时,我都需要使用 1 来获取此命令以停止杀死现有隧道。
              【解决方案10】:

              使用autossh。它是用于监控 ssh 连接的工具。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2020-09-11
                • 2012-09-18
                • 1970-01-01
                • 2022-12-23
                • 1970-01-01
                • 2020-07-31
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多