如何通過反向 SSH 隧道訪問 NAT 后面的 Linux 服務器

jopen 9年前發布 | 16K 次閱讀 SSH Linux

你在家里運行著一臺 Linux 服務器,它放在一個 NAT 路由器或者限制性防火墻后面。現在你想在外出時用 SSH 登錄到這臺服務器。你如何才能做到呢?SSH 端口轉發當然是一種選擇。但是,如果你需要處理多級嵌套的 NAT 環境,端口轉發可能會變得非常棘手。另外,在多種 ISP 特定條件下可能會受到干擾,例如阻塞轉發端口的限制性 ISP 防火墻、或者在用戶間共享 IPv4 地址的運營商級 NAT。

什么是反向 SSH 隧道?

SSH 端口轉發的一種替代方案是 反向 SSH 隧道。反向 SSH 隧道的概念非常簡單。使用這種方案,在你的受限的家庭網絡之外你需要另一臺主機(所謂的“中繼主機”),你能從當前所在地通過 SSH 登錄到它。你可以用有公網 IP 地址的 VPS 實例 配置一個中繼主機。然后要做的就是從你的家庭網絡服務器中建立一個到公網中繼主機的永久 SSH 隧道。有了這個隧道,你就可以從中繼主機中連接“回”家庭服務器(這就是為什么稱之為 “反向” 隧道)。不管你在哪里、你的家庭網絡中的 NAT 或 防火墻限制多么嚴格,只要你可以訪問中繼主機,你就可以連接到家庭服務器。

如何通過反向 SSH 隧道訪問 NAT 后面的 Linux 服務器

在 Linux 上設置反向 SSH 隧道

讓我們來看看怎樣創建和使用反向 SSH 隧道。我們做如下假設:我們會設置一個從家庭服務器(homeserver)到中繼服務器(relayserver)的反向 SSH 隧道,然后我們可以通過中繼服務器從客戶端計算機(clientcomputer) SSH 登錄到家庭服務器。本例中的中繼服務器 的公網 IP 地址是 1.1.1.1。

在家庭服務器上,按照以下方式打開一個到中繼服務器的 SSH 連接。

homeserver~$ ssh -fN -R 10022:localhost:22 relayserver_user@1.1.1.1

這里端口 10022 是任何你可以使用的端口數字。只需要確保中繼服務器上不會有其它程序使用這個端口。

“-R 10022:localhost:22” 選項定義了一個反向隧道。它轉發中繼服務器 10022 端口的流量到家庭服務器的 22 號端口。

用 “-fN” 選項,當你成功通過 SSH 服務器驗證時 SSH 會進入后臺運行。當你不想在遠程 SSH 服務器執行任何命令,就像我們的例子中只想轉發端口的時候非常有用。

運行上面的命令之后,你就會回到家庭主機的命令行提示框中。

登錄到中繼服務器,確認其 127.0.0.1:10022 綁定到了 sshd。如果是的話就表示已經正確設置了反向隧道。

relayserver~$ sudo netstat -nap | grep 10022

tcp      0    0 127.0.0.1:10022          0.0.0.0:*               LISTEN      8493/sshd

現在就可以從任何其它計算機(客戶端計算機)登錄到中繼服務器,然后按照下面的方法訪問家庭服務器。

relayserver~$ ssh -p 10022 homeserver_user@localhost

需要注意的一點是你在上面為localhost輸入的 SSH 登錄/密碼應該是家庭服務器的,而不是中繼服務器的,因為你是通過隧道的本地端點登錄到家庭服務器,因此不要錯誤輸入中繼服務器的登錄/密碼。成功登錄后,你就在家庭服務器上了。

通過反向 SSH 隧道直接連接到網絡地址變換后的服務器

上面的方法允許你訪問 NAT 后面的 家庭服務器,但你需要登錄兩次:首先登錄到 中繼服務器,然后再登錄到家庭服務器。這是因為中繼服務器上 SSH 隧道的端點綁定到了回環地址(127.0.0.1)。

事實上,有一種方法可以只需要登錄到中繼服務器就能直接訪問NAT之后的家庭服務器。要做到這點,你需要讓中繼服務器上的 sshd 不僅轉發回環地址上的端口,還要轉發外部主機的端口。這通過指定中繼服務器上運行的 sshd 的 GatewayPorts 實現。

打開中繼服務器的 /etc/ssh/sshd_conf 并添加下面的行。

relayserver~$ vi /etc/ssh/sshd_conf

GatewayPorts clientspecified

重啟 sshd。

基于 Debian 的系統:

relayserver~$ sudo /etc/init.d/ssh restart

基于紅帽的系統:

relayserver~$ sudo systemctl restart sshd

現在在家庭服務器中按照下面方式初始化一個反向 SSH 隧道。

homeserver~$ ssh -fN -R 1.1.1.1:10022:localhost:22 relayserver_user@1.1.1.1

登錄到中繼服務器然后用 netstat 命令確認成功建立的一個反向 SSH 隧道。

relayserver~$ sudo netstat -nap | grep 10022

tcp      0      0 1.1.1.1:10022     0.0.0.0:*           LISTEN      1538/sshd: dev

不像之前的情況,現在隧道的端點是 1.1.1.1:10022(中繼服務器的公網 IP 地址),而不是 127.0.0.1:10022。這就意味著從外部主機可以訪問隧道的另一端。

現在在任何其它計算機(客戶端計算機),輸入以下命令訪問網絡地址變換之后的家庭服務器。

clientcomputer~$ ssh -p 10022 homeserver_user@1.1.1.1

在上面的命令中,1.1.1.1 是中繼服務器的公共 IP 地址,homeserver_user必須是家庭服務器上的用戶賬戶。這是因為你真正登錄到的主機是家庭服務器,而不是中繼服務器。后者只是中繼你的 SSH 流量到家庭服務器。

在 Linux 上設置一個永久反向 SSH 隧道

現在你已經明白了怎樣創建一個反向 SSH 隧道,然后把隧道設置為 “永久”,這樣隧道啟動后就會一直運行(不管臨時的網絡擁塞、SSH 超時、中繼主機重啟,等等)。畢竟,如果隧道不是一直有效,你就不能可靠的登錄到你的家庭服務器。

對于永久隧道,我打算使用一個叫 autossh 的工具。正如名字暗示的,這個程序可以讓你的 SSH 會話無論因為什么原因中斷都會自動重連。因此對于保持一個反向 SSH 隧道非常有用。

第一步,我們要設置從家庭服務器到中繼服務器的無密碼 SSH 登錄。這樣的話,autossh 可以不需要用戶干預就能重啟一個損壞的反向 SSH 隧道。

下一步,在建立隧道的家庭服務器上安裝 autossh

在家庭服務器上,用下面的參數運行 autossh 來創建一個連接到中繼服務器的永久 SSH 隧道。

    homeserver~$ autossh -M 10900 -fN -o "PubkeyAuthentication=yes" -o "StrictHostKeyChecking=false" -o "PasswordAuthentication=no" -o "ServerAliveInterval 60" -o "ServerAliveCountMax 3" -R 1.1.1.1:10022:localhost:22 relayserver_user@1.1.1.1

“-M 10900” 選項指定中繼服務器上的監視端口,用于交換監視 SSH 會話的測試數據。中繼服務器上的其它程序不能使用這個端口。

“-fN” 選項傳遞給 ssh 命令,讓 SSH 隧道在后臺運行。

“-o XXXX” 選項讓 ssh:

  • 使用密鑰驗證,而不是密碼驗證。
  • 自動接受(未知)SSH 主機密鑰。
  • 每 60 秒交換 keep-alive 消息。
  • 沒有收到任何響應時最多發送 3 條 keep-alive 消息。
  • </ul>

    其余 SSH 隧道相關的選項和之前介紹的一樣。

    如果你想系統啟動時自動運行 SSH 隧道,你可以將上面的 autossh 命令添加到 /etc/rc.local。

    總結

    在這篇博文中,我介紹了你如何能從外部通過反向 SSH 隧道訪問限制性防火墻或 NAT 網關之后的 Linux 服務器。這里我介紹了家庭網絡中的一個使用事例,但在企業網絡中使用時你尤其要小心。這樣的一個隧道可能被視為違反公司政策,因為它繞過了企業的防火墻并把企業網絡暴露給外部攻擊。這很可能被誤用或者濫用。因此在使用之前一定要記住它的作用。


    via: http://xmodulo.com/access-linux-server-behind-nat-reverse-ssh-tunnel.html

    作者:Dan Nanni 譯者:ictlyh 校對:wxy

    本文由 LCTT 原創翻譯,Linux中國 榮譽推出

    來源: https://linux.cn/article-5975-1.html

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!