在SSH 文档,对于远程端口转发,它说:
如果端口参数为“0”,则侦听端口将在服务器上动态分配并在运行时报告给客户端。与一起使用时
-O forward
,分配的端口将打印到标准输出。
我如何获取/使用这个端口号?
我可以看到它打印在标准输出上,但我想将它记录在文件中。
我有几台计算机位于 NAT 防火墙后面,它们都连接到中央服务器,并设置了一条隧道,以便我可以通过 SSH 返回到它们。
我当前指定我自己的端口号(例如 12345)来执行此操作:
ssh -R 12345:localhost:22 1.2.3.4
这很有效,因为我可以连接到1.2.3.4
并使用:
ssh -p 12345 localhost
但我不想为每台计算机硬编码一个端口号,因为保留记录很痛苦;当连接最终失败时,重新连接有时不起作用(因为该端口仍在“使用中”)。
相反,我可以使用:
ssh -R 0:localhost:22 1.2.3.4
它报告的地方:
Allocated port 41191 for remote forward to localhost:22
但是我如何记录该端口号呢?
我假设我错过了一些关于如何访问它的明显内容。
我可以在 shell 脚本中执行一些操作,将端口号写入文件吗?
一种选择是检查侦听端口,当您有多个服务器执行此操作时,该选项不起作用:
sudo netstat -tpln | grep "127.0.0.1" | grep sshd
虽然这看起来有点浪费,但我可以先获取端口号,断开连接,然后使用它:
port=`ssh -R 0:localhost:22 1.2.3.4 exit 2>&1 | grep 'Allocated port' | awk '/port/ { print $3 }'`;
ssh 1.2.3.4 record-port.sh "my-name" "${port}";
ssh -NTC -o ConnectTimeout=10 -o ServerAliveInterval=30 -o ExitOnForwardFailure=yes -R "${port}:localhost:22" 1.2.3.4;
另一个选择(可能更糟糕)是我自己随机选择端口,并在尝试使用它之前记录下来:
while true; do
port=$(((RANDOM %= 1000) + 2000));
ssh 1.2.3.4 record-port.sh "my-name" "${port}";
ssh -NTC -o ConnectTimeout=10 -o ServerAliveInterval=30 -o ExitOnForwardFailure=yes -R "${port}:localhost:22" 1.2.3.4;
sleep 3;
done
答案1
首先连接主连接而不使用端口转发:
ssh -NMS /path/to/socket user@server
/path/to/socket
你决定。将在那里创建一个套接字。在您想要使用的脚本中-f
。
然后你用它-S /path/to/socket -O …
来控制主连接。例如,您可以检查它是否仍然有效:
ssh -S /path/to/socket -O check placeholder
placeholder
没关系,它是/path/to/socket
标识您要控制的主连接的内容。
现在您可以请求端口转发:
ssh -S /path/to/socket -O forward -R 0:localhost:22 placeholder
该命令会告诉您端口。它将立即退出,这意味着您能够捕获输出。什么都没有丢失。重复该命令,它会再次告诉您相同的端口,而不是将第二个端口转发到相同的目的地。因此,让我们将输出保存到变量中:
port="$(ssh -S /path/to/socket -O forward -R 0:localhost:22 placeholder)"
就是这样,现在您可以使用该变量了。
为了完整起见,取消转发的方法如下:
ssh -S /path/to/socket -O cancel -R 0:localhost:22 placeholder
尽管您不需要在终止主连接之前显式取消。你可以像这样终止它:
ssh -S /path/to/socket -O exit placeholder
在最基本的脚本中,并非所有上述命令都是必需的。您需要这些:
ssh -fNMS /path/to/socket user@server
port="$(ssh -S /path/to/socket -O forward -R 0:localhost:22 placeholder)"
# anything you want, now you know the port
ssh -S /path/to/socket -O exit placeholder
可能有一些逻辑来处理connection refused
等。
答案2
您无需在远程服务器上执行脚本或创建套接字锁即可获取分配的端口,通过有一个-o ExitOnForwardFailure=yes
选项。
它等待建立隧道,因此您可以"Allocated port ..."
在该命令完成后立即收到消息。
请阅读更多相关内容roaima对类似问题的回答。