反向 SSH 隧道所需的資訊/協助(命名約定等)
我有多個執行 Arch Linux(無 GUI)的樹莓派,我需要在其中訪問。這些 pi 位於每個唯一位置的防火牆後面。目前我使用 openvpn 連接到這些系統,但是每個許可證的系統成本很高。我使用他們的訪問伺服器。
因此,我正在嘗試設計和設置一個系統,使我能夠登錄到我的 VPN 伺服器 (vps) 並執行命令來搜尋特定名稱 (OfficeDevice1991),例如:
customcommandsearch "OfficeDevice1991"
然後它返回 IP機器的地址或我可以用來 SSH 的東西。我也在尋找執行命令以列出每個活動連接設備的能力。它列出了 IP、名稱以及它可能活動了多長時間。為此,我當然需要創建包含設備名稱的內容(在本例中為 OfficeDevice1991),然後該 pi 將能夠連接到我的 vps 公共伺服器。從公共伺服器,我可以登錄並蒐索連接到它的每個設備,並返回 ssh 所需的資訊。
我一直在研究反向 SSH,到目前為止,我使用以下命令從我的 vps 連接並訪問了我的一個測試 pi:
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 的每個埠。我寫這篇文章是為了提供資訊/幫助,了解我的目標應該做什麼。
誰能給我一個合適的解決方案?
這是使用 OpenSSH >= 6.7 + socat的解決方案:
- OpenSSH >= 6.7 可以使用Unix 域套接字轉發
這意味著反向隧道端點將是一個UNIX 監聽套接字,而不是傳統的 TCP 監聽套接字。然後,您可以使用簡單的命名方案更輕鬆地管理 RPI 的艦隊:套接字的名稱將是 RPI 選擇(和固定)的名稱,例如
OfficeDevice1991
. 只要它是有效的文件名,它甚至可以是 RPI 的一個獨特屬性(因為 unix 套接字名稱遵守文件名約定)。例如它的主機名、它的乙太網或 wifi 卡的 MAC 地址……SSH 可以處理用於隧道的 unix 套接字,而不是用於連接自身。它將需要 a 的幫助
ProxyCommand
才能作為 unix-socket 客戶端工作。socat可以處理多種連接,包括 unix 套接字。更新:
還有一個特定的問題需要處理:unix 套接字文件不會在乾淨退出時被刪除,也不會被刪除,例如在崩潰後。這需要選項
StreamLocalBindUnlink=yes
。我最初並沒有發現,正如名稱可能暗示的那樣,必須在創建 unix 套接字的節點上設置此選項。-L
所以最後它是用本地轉發( )設置在客戶端上,或者sshd_config
用遠端轉發( )在伺服器(in )上設置-R
。OP在那裡找到它。此解決方案使用遠端轉發。VPS上的配置:
mkdir /rpi-access
(以 root 身份)編輯
sshd_config
文件 (/etc/ssh/sshd_config
)。它需要這個附加選項:StreamLocalBindUnlink yes
根據預設選項,它可能還需要
AllowStreamLocalForwarding yes
UPDATE2:
也在
sshd_config
參數中設置ClientAliveInterval
andClientAliveCountMax
,從而允許在合理的時間內檢測到斷開連接,例如: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 的名稱都以OfficeDevice 開頭:
Host OfficeDevice* User rpiuseraccount ProxyCommand socat UNIX:/rpi-access/%h -
- 要保留連結,只需使用循環
每當連接結束時,RPI 可以執行一個循環,將 ssh 重新連接到 VPS。為此,它不能使用後台模式(否
-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 套接字刷新到新連接。 3. 它已經由 1 處理。沒有
customcommandsearch
必要。在1中設置正確的設置。只需使用ssh OfficeDevice1991
將連接到OfficeDevice1991。如果在 VPS 上需要,
root
僅作為使用者,此命令:fuser /rpi-access/*
可以顯示目前連接了哪些 RPI(當然除了那些最近在檢測之前失去連接的 RPI)。它不會顯示陳舊的 unix 套接字文件,因為沒有與它們相關聯的程序。