我有多个运行 Arch Linux(无 GUI)的树莓派,我需要访问它们。这些 pi 位于每个独特位置的防火墙后面。目前我使用 openvpn 来连接到这些,但该系统的每个许可证的成本都很昂贵。我使用他们的访问服务器。
因此,我正在尝试设计和设置一个系统,使我能够登录到我的 VPN 服务器(vps)并运行命令来搜索特定名称(OfficeDevice1991),例如:customcommandsearch "OfficeDevice1991"
然后返回 IP机器的地址或者我可以用来通过 SSH 连接的东西。我还在寻找运行命令来列出每个活动连接设备的能力。它会列出 IP、名称以及可能的活跃时间。
为了这个目标,我当然需要创建一些包含设备名称(在本例中为 OfficeDevice1991)的内容,然后该 pi 将能够连接到我的 vps 公共服务器。我可以从公共服务器登录并搜索连接到它的每个设备,并返回 ssh 所需的信息。
我一直在研究反向 SSH,到目前为止,我已经连接了一个测试 pi,并使用以下命令从我的 vps 进行访问:
PI:
ssh -fN -R 12345:localhost:22 -i /publickeyfile useraccount@ip //Pi's command to connect to vpn
虚拟专用服务器:
ssh -p 12345 useraccount@localhost //command for vpn to connect to pi
这很有效,但是使用这种方法,如果我要实现它,我会遇到一些问题:
- 我需要设置独特的未使用端口
- 保持这些端口/隧道打开的某种方法
- 我需要想出一个系统来识别每个设备。我可以将每个端口记录为本地文本文件中的名称吗?如果可能的话,能够将其包含在每个设备的 ssh 设置中将是有益的。我仍然需要确保我使用的端口没有被任何其他程序或已有的任何设备使用。
我不想做的事
检查每个 RPI 可以免费使用哪些端口
必须手动编辑
.ssh/config
以添加名称来代表上面第 1 部分中分配给 RPI 的每个端口。
我写这篇文章是为了获得有关如何实现我的目标的信息/帮助。
有人能为我提供合适的解决方案吗?
答案1
这是使用 OpenSSH >= 6.7 + 的解决方案索卡特:
OpenSSH >= 6.7 可以使用Unix 域套接字转发
这意味着反向隧道端点将是UNIX 监听套接字而不是传统的 TCP 监听套接字。然后,您可以使用简单的命名方案更轻松地管理 RPI 群:套接字的名称将是 RPI 选择(和固定)的名称,例如
OfficeDevice1991
。只要它是有效的文件名,它甚至可以是 RPI 的唯一属性(因为 unix 套接字名称遵循文件名约定)。例如它的主机名、以太网或 wifi 卡的 MAC 地址......SSH 可以处理用于隧道的 unix 套接字,而不是用于连接本身。它将需要 a 的帮助
ProxyCommand
才能作为 unix-socket 客户端工作。索卡特可以处理多种连接,包括unix套接字。更新:
还有一个需要处理的具体问题:unix 套接字文件在干净退出时不会被删除,也不会被删除,例如在崩溃后。这需要选项StreamLocalBindUnlink=yes
。我最初并没有发现,正如名称所暗示的那样,必须在创建 unix 套接字的节点上设置此选项。所以最后是在客户端设置了本地转发(-L
)要不然sshd_config
在具有远程转发 ( )的服务器 (in ) 上-R
。奥普找到了那里。该解决方案使用远程转发。VPS上的配置:
mkdir /rpi-access
(以 root 身份)编辑
sshd_config
文件 (/etc/ssh/sshd_config
)。它需要这个附加选项:StreamLocalBindUnlink yes
根据默认选项,它可能还需要
AllowStreamLocalForwarding yes
UPDATE2:
也在sshd_config
参数ClientAliveInterval
和中进行设置ClientAliveCountMax
,从而允许在合理的时间内检测到断开连接,例如:ClientAliveInterval 300 ClientAliveCountMax 2
然后,应尽早在 VPS 上检测到过时的 ssh 连接(示例中约为 1000 万个),然后相应的 sshd 进程将退出。
RPI 上的用法:
ssh -fN -R /rpi-access/OfficeDevice1991:localhost:22 -i /privatekeyfile useraccount@ip
在配置文件中,这将类似于:
Host ip User useraccount RemoteForward /rpi-access/OfficeDevice1991:localhost:22 IdentityFile /privatekeyfile
再次重复一遍:
StreamLocalBindUnlink yes
sshd
在VPS端设置选项很重要:即使正常退出,刚刚创建的套接字也不会被删除。此选项可确保在使用之前删除套接字(如果存在),从而允许重新使用以进行进一步的重新连接。这也意味着不能仅将套接字的存在视为 RPI 已连接(但请参阅下文)。现在可以在 VPS 上执行以下操作:
ssh -o 'ProxyCommand=socat UNIX:/rpi-access/%h -' rpiuseraccount@OfficeDevice1991
作为配置文件,考虑到例如 RPI 的名称均以办公设备:
Host OfficeDevice* User rpiuseraccount ProxyCommand socat UNIX:/rpi-access/%h -
要保留链接,只需使用循环
无论何时连接结束,RPI 都可以运行循环将 ssh 重新连接到 VPS。为此,它不能使用后台模式( no
-f
)。还应该使用保活机制。 TCPKeepAlive(系统级别)或 ServerAliveInterval(应用程序级别)可用。我认为 TCPKeepAlive 仅在服务器(接收连接的一侧)上有用,所以我们宁愿使用 ServerAliveInterval。它的值(以及 ServerAliveCountMax)可能应该根据各种标准进行调整:防火墙在一定时间后丢弃不活动的连接,希望的恢复延迟,不生成无用的流量,......这里假设 300 秒。
OfficeDevice1991 RPI:
#!/bin/sh while : ; do ssh -N -o ConnectTimeout=30 -o ServerAliveInterval=300 -R /rpi-access/OfficeDevice1991:localhost:22 -i /privatekeyfile useraccount@ip sleep 5 # avoid flood/DDoS in case of really unexpected issues done
即使远程端尚未检测到先前的连接故障,并且旧的 ssh 连接仍在运行一段时间,
StreamLocalBindUnlink yes
无论如何都会强制将 unix 套接字刷新到新连接。它已经被 1 处理了。
没有
customcommandsearch
必要啊在 1. 中设置正确的设置后,只需使用ssh OfficeDevice1991
即可连接到 OfficeDevice1991。如果需要在 VPS 上,
root
仅以用户身份执行以下命令:fuser /rpi-access/*
可以显示当前有哪些RPI已连接(当然除了那些最近在检测前失去连接的RPI)。它不会显示过时的 unix 套接字文件,因为没有进程与它们绑定。
答案2
这是对这种情况的几种不同看法。我在这里省略了一些细节,因为没有什么可以阻止你提出进一步的问题如果您尝试其中任何一种路线,请了解具体信息。
1.更换OpenVPN接入服务器
如果 OpenVPN 访问服务器的成本是一个令人望而却步的问题,请考虑部署您自己的 OpenVPN 服务器。该软件免费使用;您只需要一个服务器端点(如果本地没有任何东西,则需要一个 VPS 或同等设备)和设置它的技能。有许多教程可用于此目的,因此您无需从零开始。
设置完成后,您可以使用 DNS 或/etc/hosts
定义主机名(例如您的主机名)OfficeDevice1991
来指向服务器上相应的 VPN 端点地址。
2. 使用autossh
而不是OpenVPN
一旦您拥有了自己的端点,您就可以autossh
在每个 Pi 系统上使用类似于ssh
启动时的“众所周知”端点(VPS 或同等设备,如果您本地没有任何端点)。
每个 Pi 上都带有反向隧道 ( ssh -R
),这样每个 Pi 都会呈现服务器的不同端口号,映射回其自己的ssh
端口 22。
明智地使用 中的条目~/.ssh/config
可以让您运行ssh OfficeDevice1991
并自动映射到类似 的内容ssh -p 12345 localhost
,这反过来又对应于ssh
与代表 OfficeDevice1991 的 Pi 的正常连接。
回答您在编辑中添加的一组问题,
who
或者finger
会给你每个树莓派的连接时间。
- 端口 49152 至 65535是你的
- 这就是
autossh
做的事 - 主机名
和
- 如上面#1
- 一个短
for x ... do ... done
循环可以为您自动生成文件。我也不想手动创建 1000 个条目。