首頁 > 軟體

實戰 SSH 埠轉發

2020-06-16 17:48:45

通過本文的介紹,讀者可以從中了解到如何應用 SSH 埠轉發機制來解決日常工作 / 生活中的一些問題。學會在非安全環境下使用埠轉發來加密網路應用,保護個人隱私以及重要商業資訊。同時也能夠用此技術解決工作中一些常見問題,例如解決防火牆及網路應用本身帶來的一些限制。

第一部分 概述

當你在咖啡館享受免費 WiFi 的時候,有沒有想到可能有人正在竊取你的密碼及隱私資訊?當你發現實驗室的防火牆阻止了你的網路應用埠,是不是有苦難言?來看看 SSH 的埠轉發功能能給我們帶來什麼好處吧!

埠轉發概述

讓我們先來了解一下埠轉發的概念吧。我們知道,SSH 會自動加密和解密所有 SSH 用戶端與伺服器端之間的網路資料。但是,SSH 還同時提供了一個非常有用的功能,這就是埠轉發。它能夠將其他 TCP 埠的網路資料通過 SSH 連結來轉發,並且自動提供了相應的加密及解密服務。這一過程有時也被叫做“隧道”(tunneling),這是因為 SSH 為其他 TCP 連結提供了一個安全的通道來進行傳輸而得名。例如,Telnet,SMTP,LDAP 這些 TCP 應用均能夠從中得益,避免了使用者名稱,密碼以及隱私資訊的明文傳輸。而與此同時,如果您工作環境中的防火牆限制了一些網路埠的使用,但是允許 SSH 的連線,那麼也是能夠通過將 TCP 埠轉發來使用 SSH 進行通訊。總的來說 SSH 埠轉發能夠提供兩大功能:

  1. 加密 SSH Client 端至 SSH Server 端之間的通訊資料。
  2. 突破防火牆的限制完成一些之前無法建立的 TCP 連線。
圖 1. SSH 埠轉發

如上圖所示,使用了埠轉發之後,TCP 埠 A 與 B 之間現在並不直接通訊,而是轉發到了 SSH 用戶端及伺服器端來通訊,從而自動實現了資料加密並同時繞過了防火牆的限制。

第二部分 本地轉發與遠端轉發

本地轉發範例分析

我們先來看第一個例子,在實驗室裡有一台 LDAP 伺服器(LdapServerHost),但是限制了只有本機上部署的應用才能直接連線此 LDAP 伺服器。如果我們由於偵錯或者測試的需要想臨時從遠端機器(LdapClientHost)直接連線到這個 LDAP 伺服器 , 有什麼方法能夠實現呢?

答案無疑是本地埠轉發了,它的命令格式是:

ssh -L <local port>:<remote host>:<remote port> <SSH hostname>

在 LdapClientHost 上執行如下命令即可建立一個 SSH 的本地埠轉發,例如:

$ ssh -L 7001:localhost:389 LdapServerHost
圖 2. 本地埠轉發

這裡需要注意的是本例中我們選擇了 7001 埠作為原生的監聽埠,在選擇埠號時要注意非管理員帳號是無權系結 1-1023 埠的,所以一般是選用一個 1024-65535 之間的並且尚未使用的埠號即可。

然後我們可以將遠端機器(LdapClientHost)上的應用直接設定到本機的 7001 埠上(而不是 LDAP 伺服器的 389 埠上)。之後的資料流將會是下面這個樣子:

  • 我們在 LdapClientHost 上的應用將資料傳送到本機的 7001 埠上,
  • 而本機的 SSH Client 會將 7001 埠收到的資料加密並轉發到 LdapServertHost 的 SSH Server 上。
  • SSH Server 會解密收到的資料並將之轉發到監聽的 LDAP 389 埠上,
  • 最後再將從 LDAP 返回的資料原路返回以完成整個流程。

我們可以看到,這整個流程應用並沒有直接連線 LDAP 伺服器,而是連線到了原生的一個監聽埠,但是 SSH 埠轉發完成了剩下的所有事情,加密,轉發,解密,通訊。

這裡有幾個地方需要注意:

  1. SSH 埠轉發是通過 SSH 連線建立起來的,我們必須保持這個 SSH 連線以使埠轉發保持生效。一旦關閉了此連線,相應的埠轉發也會隨之關閉。
  2. 我們只能在建立 SSH 連線的同時建立埠轉發,而不能給一個已經存在的 SSH 連線增加埠轉發。
  3. 你可能會疑惑上面命令中的 <remote host> 為什麼用 localhost,它指向的是哪台機器呢?在本例中,它指向 LdapServertHost 。我們為什麼用 localhost 而不是 IP 地址或者主機名呢?其實這個取決於我們之前是如何限制 LDAP 只有本機才能存取。如果只允許 lookback 介面存取的話,那麼自然就只有 localhost 或者 IP 為 127.0.0.1 才能存取了,而不能用真實 IP 或者主機名。
  4. 命令中的 <remote host> 和 <SSH hostname> 必須是同一台機器麼?其實是不一定的,它們可以是兩台不同的機器。我們在後面的例子裡會詳細闡述這點。
  5. 好了,我們已經在 LdapClientHost 建立了埠轉發,那麼這個埠轉發可以被其他機器使用麼?比如能否新增加一台 LdapClientHost2 來直接連線 LdapClientHost 的 7001 埠?答案是不行的,在主流 SSH 實現中,本地埠轉發系結的是 lookback 介面,這意味著只有 localhost 或者 127.0.0.1 才能使用本機的埠轉發 , 其他機器發起的連線只會得到“ connection refused. ”。好在 SSH 同時提供了 GatewayPorts 關鍵字,我們可以通過指定它與其他機器共用這個本地埠轉發。
    ssh -g -L <local port>:<remote host>:<remote port> <SSH hostname>

遠端轉發範例分析

我們來看第二個例子,這次假設由於網路或防火牆的原因我們不能用 SSH 直接從 LdapClientHost 連線到 LDAP 伺服器(LdapServertHost),但是反向連線卻是被允許的。那此時我們的選擇自然就是遠端埠轉發了。

它的命令格式是:

ssh -R <local port>:<remote host>:<remote port> <SSH hostname>

例如在 LDAP 伺服器(LdapServertHost)端執行如下命令:

$ ssh -R 7001:localhost:389 LdapClientHost
圖 3. 遠端埠轉發

和本地埠轉發相比,這次的圖裡,SSH Server 和 SSH Client 的位置對調了一下,但是資料流依然是一樣的。我們在 LdapClientHost 上的應用將資料傳送到本機的 7001 埠上,而本機的 SSH Server 會將 7001 埠收到的資料加密並轉發到 LdapServertHost 的 SSH Client 上。 SSH Client 會解密收到的資料並將之轉發到監聽的 LDAP 389 埠上,最後再將從 LDAP 返回的資料原路返回以完成整個流程。

看到這裡,你是不是會有點糊塗了麼?為什麼叫本地轉發,而有時又叫遠端轉發?這兩者有什麼區別?

本地轉發與遠端轉發的對比與分析

不錯,SSH Server,SSH Client,LdapServertHost,LdapClientHost,本地轉發,遠端轉發,這麼多的名詞的確容易讓人糊塗。讓我們來分析一下其中的結構吧。首先,SSH 埠轉發自然需要 SSH 連線,而 SSH 連線是有方向的,從 SSH Client 到 SSH Server 。而我們的應用也是有方向的,比如需要連線 LDAP Server 時,LDAP Server 自然就是 Server 端,我們應用連線的方向也是從應用的 Client 端連線到應用的 Server 端。如果這兩個連線的方向一致,那我們就說它是本地轉發。而如果兩個方向不一致,我們就說它是遠端轉發。

我們可以回憶上面的兩個例子來做個對照。

本地轉發時:

LdapClientHost 同時是應用的用戶端,也是 SSH Client,這兩個連線都從它指向 LdapServertHost(既是 LDAP 伺服器端,也是 SSH Server)。

遠端轉發時:

LdapClientHost 是應用的用戶端,但卻是 SSH Server ;而 LdapServertHost 是 LDAP 的伺服器端,但卻是 SSH Client 。這樣兩個連線的方向剛好相反。

另一個方便記憶的方法是,Server 端的埠都是預定義的固定埠(SSH Server 的埠 22,LDAP 的埠 389),而 Client 端的埠都是動態可供我們選擇的埠(如上述例子中選用的 7001 埠)。如果 Server 端的兩個埠都在同一台機器,Client 端的兩個埠都在另一台機器上,那麼這就是本地連線;如果這四個埠交叉分布在兩個機器上,每台機器各有一個 Server 端埠,一個 Client 端埠,那就是遠端連線。

弄清楚了兩者的區別之後,再來看看兩者的相同之處。如果你所在的環境下,既允許 LdapClientHost 發起 SSH 連線到 LdapServerHost,也允許 LdapServerHost 發起 SSH 連線到 LdapClientHost 。那麼這時我們選擇本地轉發或遠端轉發都是可以的,能完成一樣的功能。

接著讓我們來看個進階版的埠轉發。我們之前涉及到的各種連線 / 轉發都只涉及到了兩台機器,還記得我們在本地轉發中提到的一個問題麼?本地轉發命令中的 <remote host> 和 <SSH hostname> 可以是不同的機器麼?

ssh -L <local port>:<remote host>:<remote port> <SSH hostname>

答案是可以的!讓我們來看一個涉及到四台機器 (A,B,C,D) 的例子。

圖 4. 多主機轉發應用

在 SSH Client(C) 執行下列命令來建立 SSH 連線以及埠轉發:

$ ssh -g -L 7001:<B>:389 <D>

然後在我們的應用用戶端(A)上設定連線機器(C )的 7001 埠即可。注意我們在命令中指定了“ -g ”引數以保證機器(A)能夠使用機器(C)建立的本地埠轉發。而另一個值得注意的地方是,在上述連線中,(A)<-> (C) 以及 (B)<->(D) 之間的連線並不是安全連線,它們之間沒有經過 SSH 的加密及解密。如果他們之間的網路並不是值得信賴的網路連線,我們就需要謹慎使用這種連線方式了。

第三部分 其他型別的轉發

動態轉發範例分析

恩,動態轉發,聽上去很酷。當你看到這裡時,有沒有想過我們已經討論過了本地轉發,遠端轉發,但是前提都是要求有一個固定的應用伺服器端的埠號,例如前面???子中的 LDAP 伺服器端的 389 埠。那如果沒有這個埠號怎麼辦?等等,什麼樣的應用會沒有這個埠號呢?嗯,比如說用瀏覽器進行 Web 瀏覽,比如說 MSN 等等。

當我們在一個不安全的 WiFi 環境下上網,用 SSH 動態轉發來保護我們的網頁瀏覽及 MSN 資訊無疑是十分必要的。讓我們先來看一下動態轉發的命令格式:

$ ssh -D <local port> <SSH Server>

例如:

$ ssh -D 7001 <SSH Server>
圖 5. 動態埠轉發

似乎很簡單,我們依然選擇了 7001 作為原生的埠號,其實在這裡 SSH 是建立了一個 SOCKS 代理服務。來看看幫助文件中對 -D 引數的描述:

-D port 
 This works by allocating a socket to listen to port on the local 
 side, and whenever a connection is made to this port, the con- 
 nection is forwarded over the secure channel, and the applica- 
 tion protocol is then used to determine where to connect to from 
 the remote machine.  Currently the SOCKS4 and SOCKS5 protocols 
 are supported, and ssh will act as a SOCKS server.  Only root 
 can forward privileged ports.  Dynamic port forwardings can also 
 be specified in the configuration file.

之後的使用就簡單了,我們可以直接使用 localhost:7001 來作為正常的 SOCKS 代理來使用,直接在瀏覽器或 MSN 上設定即可。在 SSH Client 端無法存取的網站現在也都可以正常瀏覽。而這裡需要值得注意的是,此時 SSH 所包護的範圍只包括從瀏覽器端(SSH Client 端)到 SSH Server 端的連線,並不包含從 SSH Server 端 到目標網站的連線。如果後半截連線的安全不能得到充分的保證的話,這種方式仍不是合適的解決方案。

X 協定轉發範例分析

好了,讓我們來看最後一個例子 - X 協定轉發。

我們日常工作當中,可能會經常會遠端登入到 Linux/Unix/Solaris/HP 等機器上去做一些開發或者維護,也經常需要以 GUI 方式執行一些程式,比如要求圖形化介面來安裝 DB2/WebSphere 等等。這時候通常有兩種選擇來實現:VNC 或者 X 視窗,讓我們來看看後者。

使用 X 視窗通常需要分別安裝:X Client 和 X Server 。在本例中我們的 X Client 就是所存取的遠端 Linux/Unix/Solaris/HP,而我們的 X Server 則是發起存取的本地機器(例如你面前正在使用的筆電或桌上型電腦)。把 X Client 端的 X 視窗顯示在 X Server 端需要先行在 X Client 端指定 X Server 的位置,命令格式如下:

export DISPLAY=<X Server IP>:<display #>.<virtual #>

例如:

export DISPLAY=myDesktop:1.0

然後直接執行 X 應用即可,X 視窗就會自動在我們的本地端開啟。

一切執行正常,但是,這時候 IT 部門突然在遠端 Linux/Unix/Solaris/HP 前面加了一道防火牆。非常不幸的是,X 協定並不在允許通過的列表之內。怎麼辦?只能使用 VNC 了麼?不,其實只要使用了 SSH 埠轉發即可通過,同時也對 X 通訊資料做了加密,真是一舉兩得。(當然,使用此方法前最好先咨詢相關 IT 部門是否符合相應的安全條例,以免造成違規操作。)

建立命令也很簡單,直接從本地機器(X Server 端)發起一個如下的 SSH 連線即可:

$ ssh -X <SSH Server>
圖 5. X 轉發

建立連線之後就可以直接執行遠端的 X 應用。注意建立 X 轉發之後會自動設定 DISPLAY 環境變數,通常會被設定成localhost:10.0,我們無需也不應該在連線之後再進行修改此環境變數。

一個比較常見的場景是,我們的本地機器是 Windows 作業系統,這時可以選擇開源的 XMing 來作為我們的 XServer,而 SSH Client 則可以任意選擇了,例如 PuTTY,Cygwin 均可以設定 存取 SSH 的同時建立 X 轉發。

第四部分 總結

至此,我們已經完成了本地埠轉發,遠端埠轉發,動態埠轉發以及 X 轉發的介紹。回顧起來,總的思路是通過將 TCP 連線轉發到 SSH 通道上以解決資料加密以及突破防火牆的種種限制。對一些已知埠號的應用,例如 Telnet/LDAP/SMTP,我們可以使用本地埠轉發或者遠端埠轉發來達到目的。動態埠轉發則可以實現 SOCKS 代理從而加密以及突破防火牆對 Web 瀏覽的限制。對於 X 應用,無疑是 X 轉發最為適用了。雖然每一部分我們都只是簡單的介紹了一下,但如果能靈活應用這些技巧,相信對我們的日常生活 / 工作也是會有所幫助的。

參考資料

下面關於SSH相關的文章您也可能喜歡,不妨參考下:

Ubuntu 下設定 SSH服務全過程及問題解決 http://www.linuxidc.com/Linux/2011-09/42775.htm

Ubuntu 14.04 下安裝Samba 及SSH 伺服器端的方法 http://www.linuxidc.com/Linux/2015-01/111971.htm

SSH服務遠端存取Linux伺服器登陸慢 http://www.linuxidc.com/Linux/2011-08/39742.htm

提高Ubuntu的SSH登陸認證速度的辦法 http://www.linuxidc.com/Linux/2014-09/106810.htm

開啟SSH服務讓Android手機遠端存取 Ubuntu 14.04  http://www.linuxidc.com/Linux/2014-09/106809.htm

如何為Linux系統中的SSH新增雙重認證 http://www.linuxidc.com/Linux/2014-08/105998.htm

在 Linux 中為非 SSH 使用者設定 SFTP 環境 http://www.linuxidc.com/Linux/2014-08/105865.htm

Linux 上SSH 服務的設定和管理 http://www.linuxidc.com/Linux/2014-06/103627.htm

本文永久更新連結地址http://www.linuxidc.com/Linux/2015-12/126309.htm


IT145.com E-mail:sddin#qq.com