連結兩個 ssh portforwards

連結兩個 ssh portforwards

我一直在瀏覽超級用戶的答案,但是我發現沒有任何答案可以解決我的用例。

我想連結我使用的兩個命令,讓我穿過隧道:

ssh -L 22:hostB:22 user@hostA

ssh -L 10002:localhost:10001 user@localhost

現在我要做的就是輸入第一個命令,打開另一個終端,然後輸入第二個命令。如果我做類似的事情

ssh … && ssh …

第二個命令僅在我從第一個連線「退出」後執行。

由於 hostA 上的伺服器配置,更高級的 ssh 選項(如 Jumphost)無法運作,因此我很確定這是可以像這樣存取 10001 連接埠的唯一選項。

有沒有一種方法可以將這兩個命令連結到一個別名中,或者使用一些帶有超時的簡單 bash 腳本等?

答案1

我認為你不能僅僅ssh -L 10002:hostB:10001 user@hostA因為

  • 監聽 B 的任何內容10001都只綁定到本地接口,
  • 或 B 上的防火牆不允許hostB:10001從 A 進行連接,
  • 管他呢。

ssh … && ssh …

第二個命令僅在我從第一個連線「退出」後執行。

是的,這是正常的。前面的部分&&必須在下一個命令運行之前終止並返回退出狀態(或不終止,取決於狀態)。

這幾乎會立即運行第二個,ssh但它有缺陷:

( ssh … & ) && ssh …

它是有缺陷的,因為第一個ssh對第二個沒有影響。第二個可能會在第一個建立隧道之前運行。詢問密碼也可能會出現問題。

對於這個用例ssh-f選項。從man 1 ssh:

-f
請求ssh在命令執行之前進入後台。 […]

所以基本指令可能是:

ssh -fNL 22:hostB:22 user@hostA && ssh -NL 10002:localhost:10001 user@localhost

-N是否要與第二個一起使用取決於您ssh。現在的技巧是ssh在詢問密碼(如果適用)和建立第一個隧道後第一個分叉到後台,因此暫時有兩個「第一個」ssh進程。後台的人開始處理隧道;前台的退出,這允許&&工作。

你可能想要-o ExitOnForwardFailure=yes。如果第一個隧道無法建立,第一個隧道ssh將無法成功退出,第二個隧道也不會運作。改進後的命令為:

ssh -fNL 22:hostB:22 \
    -o ExitOnForwardFailure=yes \
    user@hostA &&
ssh -NL 10002:localhost:10001 user@localhost

請注意,當第二個ssh退出時,第一個(在後台)仍然存在。好處是你可以ssh稍後運行唯一的第二秒。缺點是如果您不想保留第一個,則需要手動殺死它。考慮到這一點,請考慮以下方法:

ssh -fNL 22:hostB:22 \
    -o ExitOnForwardFailure=yes \
    user@hostA
ssh -NL 10002:localhost:10001 user@localhost

注意沒有&&.現在,如果舊的第一個ssh仍在運行,那麼新的將失敗,因為它無法綁定到連接埠。無論如何,第二個隧道ssh都會運行,它將使用第一個隧道,並且無論隧道有多舊。

可能會發生沒有舊的ssh並且第一個ssh由於某種原因而失敗的情況。如果是這樣,第二個將運行,但它可能會失敗(連接被拒絕),因為連接埠上沒有任何監聽22

您仍然可能不想離開「空閒」ssh進程,您可能希望在第二次ssh退出後自動終止它。顯然killall ssh可能會造成附帶損害。讓我們找到更微妙的東西:

-M
ssh客戶端置於「主」模式以進行連線共享。 […]

[…]

-O ctl_cmd
控制活動連線復用主進程。 […]

[…]

-S ctl_path
指定用於連接共享的控制套接字的位置[...]

#!/bin/sh

socket=/tmp/hostA.socket

ssh -fNL 22:hostB:22 \
    -o ExitOnForwardFailure=yes \
    -MS "$socket"
    user@hostA &&
{
ssh -NL 10002:localhost:10001 user@localhost
ssh -S "$socket" -O exit dummy
}

第二個ssh終止後,第三個將告訴第一個退出。在第三個ssh命令中,重要的是套接字,而不是主機名稱;您仍然需要提供一些主機名,因此dummy.第一個ssh將在退出之前刪除套接字,不應該留下任何垃圾。

仍然存在一些擔憂:

  • 如果腳本被中斷,第一個腳本ssh將保留。要么在最開始就刪除&&或發送,-O exit以防萬一(這將是第零個ssh)。
  • 如果第一個ssh突然死亡,插座可能會保留。這將使任何新的第一次ssh失敗。一個好主意可能是ssh像這樣擴展第零個:

    ssh -S "$socket" -O exit dummy || rm "$socket"
    
  • /tmp/hostA.socket可能不是插座的最佳位置。相當於命令列選項ssh_config是.看什麼-SControlPathman 5 ssh_config對此說:

    建議ControlPath用於機會性連結共享的任何內容至少包括%h%p、 和%r(或%C) 並放置在其他使用者不可寫入的目錄中。

    /run/user/$UID如果您的作業系統支援的話,「其他使用者不可寫入的目錄」可能是(我相信這是systemd事實)。

相關內容