我写了一个小 bash 脚本,它需要一个 ssh 隧道来从远程服务器中提取数据,所以它会提示用户:
echo "Please open an ssh tunnel using 'ssh -L 6000:localhost:5432 example.com'"
我想检查用户是否打开了此隧道,如果不存在隧道,则退出并显示错误消息。有没有办法查询ssh
隧道,即检查本地端口 6000 是否真的通过隧道连接到该服务器?
我写了一个小 bash 脚本,它需要一个 ssh 隧道来从远程服务器中提取数据,所以它会提示用户:
echo "Please open an ssh tunnel using 'ssh -L 6000:localhost:5432 example.com'"
我想检查用户是否打开了此隧道,如果不存在隧道,则退出并显示错误消息。有没有办法查询ssh
隧道,即检查本地端口 6000 是否真的通过隧道连接到该服务器?
Netcat 是你的朋友:
nc -z localhost 6000 || echo "no tunnel open"
这是我的测试。希望它是有用的。
# $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
Autossh 是最佳选择 - 检查进程并非在所有情况下都有效(例如僵尸进程、网络相关问题)
例子:
autossh -M 2323 -c arcfour -f -N -L 8088:localhost:80 host2
这实际上更像是一个 serverfault 类型的问题,但您可以使用 netstat。
就像是:
# netstat -lpnt | grep 6000 | grep ssh
这将告诉您是否有 ssh 进程正在侦听指定端口。它还会告诉你进程的PID。
如果您真的想仔细检查 ssh 进程是否使用正确的选项启动,则可以通过 PID 查找该进程,例如
# ps aux | grep PID
使用autossh。这是用于监视 ssh 连接的工具。
这些是测试或排除 SSH 隧道故障的更详细步骤。您可以在脚本中使用其中的一些。我添加这个答案是因为我必须在两个应用程序停止工作后对它们之间的链接进行故障排除。仅仅 grepping ssh 进程是不够的,因为它仍然存在。而且我无法使用nc -z
,因为我的 netcat 咒语中没有该选项。
让我们从头开始。假设有一台机器,它将被称为本地,IP 地址为 10.0.0.1,而另一台机器,称为远程,位于 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 然后运行您的应用程序。您可以使用以下命令检查它是否正在侦听正确的端口:
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。
#!/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 < '
我们可以使用 ps 命令检查
# ps -aux | grep ssh
将显示所有正在运行的 shh 服务,我们可以找到列出的隧道服务
stunnel 是在主机之间建立半永久连接的好工具。
如果您在后台使用 ssh,请使用以下命令:
sudo lsof -i -n | egrep '\<ssh\>'