實戰 SSH 端口轉發
通過本文的介紹,讀者可以從中了解到如何應用 SSH 端口轉發機制來解決日常工作 /
生活中的一些問題。學會在非安全環境下使用端口轉發來加密網絡應用,保護個人隐私以及重要商業資訊。同時也能夠用此技術解決工作中一些常見問題,例如解決防火牆及網絡應用本身帶來的一些限制。
轉載:http://www.ibm.com/developerworks/cn/linux/l-cn-sshforward/index.html
當你在咖啡館享受免費 WiFi 的時候,有沒有想到可能有人正在竊取你的密碼及隐私資訊?當你發現實驗室的防火牆阻止了你的網絡應用端口,是不是有苦難言?來看看 SSH 的端口轉發功能能給我們帶來什麼好處吧!
讓我們先來了解一下端口轉發的概念吧。我們知道,SSH
會自動加密和解密所有 SSH 用戶端與服務端之間的網絡資料。但是,SSH 還同時提供了一個非常有用的功能,這就是端口轉發。它能夠将其他 TCP
端口的網絡資料通過 SSH 連結來轉發,并且自動提供了相應的加密及解密服務。這一過程有時也被叫做“隧道”(tunneling),這是因為
SSH 為其他 TCP 連結提供了一個安全的通道來進行傳輸而得名。例如,Telnet,SMTP,LDAP 這些 TCP
應用均能夠從中得益,避免了使用者名,密碼以及隐私資訊的明文傳輸。而與此同時,如果您工作環境中的防火牆限制了一些網絡端口的使用,但是允許 SSH
的連接配接,那麼也是能夠通過将 TCP 端口轉發來使用 SSH 進行通訊。總的來說 SSH 端口轉發能夠提供兩大功能:
加密 SSH Client 端至 SSH Server 端之間的通訊資料。
突破防火牆的限制完成一些之前無法建立的 TCP 連接配接。
如上圖所示,使用了端口轉發之後,TCP 端口 A 與 B 之間現在并不直接通訊,而是轉發到了 SSH 用戶端及服務端來通訊,進而自動實作了資料加密并同時繞過了防火牆的限制。
回頁首
我們先來看第一個例子,在實驗室裡有一台
LDAP 伺服器(LdapServerHost),但是限制了隻有本機上部署的應用才能直接連接配接此 LDAP
伺服器。如果我們由于調試或者測試的需要想臨時從遠端機器(LdapClientHost)直接連接配接到這個 LDAP 伺服器 ,
有什麼方法能夠實作呢?
答案無疑是本地端口轉發了,它的指令格式是:
在 LdapClientHost 上執行如下指令即可建立一個 SSH 的本地端口轉發,例如:
這裡需要注意的是本例中我們選擇了 7001 端口作為本地的監聽端口,在選擇端口号時要注意非管理者帳号是無權綁定 1-1023 端口的,是以一般是選用一個 1024-65535 之間的并且尚未使用的端口号即可。
然後我們可以将遠端機器(LdapClientHost)上的應用直接配置到本機的 7001 端口上(而不是 LDAP 伺服器的 389 端口上)。之後的資料流将會是下面這個樣子:
我們在 LdapClientHost 上的應用将資料發送到本機的 7001 端口上,
而本機的 SSH Client 會将 7001 端口收到的資料加密并轉發到 LdapServertHost 的 SSH Server 上。
SSH Server 會解密收到的資料并将之轉發到監聽的 LDAP 389 端口上,
最後再将從 LDAP 傳回的資料原路傳回以完成整個流程。
我們可以看到,這整個流程應用并沒有直接連接配接 LDAP 伺服器,而是連接配接到了本地的一個監聽端口,但是 SSH 端口轉發完成了剩下的所有事情,加密,轉發,解密,通訊。
這裡有幾個地方需要注意:
SSH 端口轉發是通過 SSH 連接配接建立起來的,我們必須保持這個 SSH 連接配接以使端口轉發保持生效。一旦關閉了此連接配接,相應的端口轉發也會随之關閉。
我們隻能在建立 SSH 連接配接的同時建立端口轉發,而不能給一個已經存在的 SSH 連接配接增加端口轉發。
你可能會疑惑上面指令中的
<remote host> 為什麼用 localhost,它指向的是哪台機器呢?在本例中,它指向 LdapServertHost
。我們為什麼用 localhost 而不是 IP 位址或者主機名呢?其實這個取決于我們之前是如何限制 LDAP 隻有本機才能通路。如果隻允許
lookback 接口通路的話,那麼自然就隻有 localhost 或者 IP 為 127.0.0.1 才能通路了,而不能用真實 IP
或者主機名。
指令中的 <remote host> 和 <SSH hostname> 必須是同一台機器麼?其實是不一定的,它們可以是兩台不同的機器。我們在後面的例子裡會詳細闡述這點。
好了,我們已經在
LdapClientHost 建立了端口轉發,那麼這個端口轉發可以被其他機器使用麼?比如能否新增加一台 LdapClientHost2
來直接連接配接 LdapClientHost 的 7001 端口?答案是不行的,在主流 SSH 實作中,本地端口轉發綁定的是 lookback
接口,這意味着隻有 localhost 或者 127.0.0.1 才能使用本機的端口轉發 , 其他機器發起的連接配接隻會得到“ connection
refused. ”。好在 SSH 同時提供了 GatewayPorts 關鍵字,我們可以通過指定它與其他機器共享這個本地端口轉發。
<code>ssh -g -L <local port>:<remote host>:<remote port> <SSH hostname></code>
我們來看第二個例子,這次假設由于網絡或防火牆的原因我們不能用 SSH 直接從 LdapClientHost 連接配接到 LDAP 伺服器(LdapServertHost),但是反向連接配接卻是被允許的。那此時我們的選擇自然就是遠端端口轉發了。
它的指令格式是:
例如在 LDAP 伺服器(LdapServertHost)端執行如下指令:
和本地端口轉發相比,這次的圖裡,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> 可以是不同的機器麼?
答案是可以的!讓我們來看一個涉及到四台機器 (A,B,C,D) 的例子。
在 SSH Client(C) 執行下列指令來建立 SSH 連接配接以及端口轉發:
然後在我們的應用用戶端(A)上配置連接配接機器(C
)的 7001 端口即可。注意我們在指令中指定了“ -g
”參數以保證機器(A)能夠使用機器(C)建立的本地端口轉發。而另一個值得注意的地方是,在上述連接配接中,(A)<-> (C) 以及
(B)<->(D) 之間的連接配接并不是安全連接配接,它們之間沒有經過 SSH
的加密及解密。如果他們之間的網絡并不是值得信賴的網絡連接配接,我們就需要謹慎使用這種連接配接方式了。
恩,動态轉發,聽上去很酷。當你看到這裡時,有沒有想過我們已經讨論過了本地轉發,遠端轉發,但是前提都是要求有一個固定的應用服務端的端口号,例如前面例子中的
LDAP 服務端的 389 端口。那如果沒有這個端口号怎麼辦?等等,什麼樣的應用會沒有這個端口号呢?嗯,比如說用浏覽器進行 Web
浏覽,比如說 MSN 等等。
當我們在一個不安全的 WiFi 環境下上網,用 SSH 動态轉發來保護我們的網頁浏覽及 MSN 資訊無疑是十分必要的。讓我們先來看一下動态轉發的指令格式:
例如:
似乎很簡單,我們依然選擇了 7001 作為本地的端口号,其實在這裡 SSH 是建立了一個 SOCKS 代理服務。來看看幫助文檔中對 -D 參數的描述:
之後的使用就簡單了,我們可以直接使用
localhost:7001 來作為正常的 SOCKS 代理來使用,直接在浏覽器或 MSN 上設定即可。在 SSH Client
端無法通路的網站現在也都可以正常浏覽。而這裡需要值得注意的是,此時 SSH 所包護的範圍隻包括從浏覽器端(SSH Client 端)到 SSH
Server 端的連接配接,并不包含從 SSH Server 端
到目标網站的連接配接。如果後半截連接配接的安全不能得到充分的保證的話,這種方式仍不是合适的解決方案。
好了,讓我們來看最後一個例子 - 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 的位置,指令格式如下:
然後直接運作 X 應用即可,X 視窗就會自動在我們的本地端打開。
一切運作正常,但是,這時候
IT 部門突然在遠端 Linux/Unix/Solaris/HP 前面加了一道防火牆。非常不幸的是,X
協定并不在允許通過的清單之内。怎麼辦?隻能使用 VNC 了麼?不,其實隻要使用了 SSH 端口轉發即可通過,同時也對 X
通訊資料做了加密,真是一舉兩得。(當然,使用此方法前最好先咨詢相關 IT 部門是否符合相應的安全條例,以免造成違規操作。)
建立指令也很簡單,直接從本地機器(X Server 端)發起一個如下的 SSH 連接配接即可:
建立連接配接之後就可以直接運作遠端的 X 應用。注意建立 X 轉發之後會自動設定 DISPLAY 環境變量,通常會被設定成<code>localhost:10.0</code>,我們無需也不應該在連接配接之後再進行修改此環境變量。
一個比較常見的場景是,我們的本地機器是 Windows 作業系統,這時可以選擇開源的 XMing 來作為我們的 XServer,而 SSH Client 則可以任意選擇了,例如 PuTTY,Cygwin 均可以配置 通路 SSH 的同時建立 X 轉發。
至此,我們已經完成了本地端口轉發,遠端端口轉發,動态端口轉發以及
X 轉發的介紹。回顧起來,總的思路是通過将 TCP 連接配接轉發到 SSH
通道上以解決資料加密以及突破防火牆的種種限制。對一些已知端口号的應用,例如
Telnet/LDAP/SMTP,我們可以使用本地端口轉發或者遠端端口轉發來達到目的。動态端口轉發則可以實作 SOCKS
代理進而加密以及突破防火牆對 Web 浏覽的限制。對于 X 應用,無疑是 X
轉發最為适用了。雖然每一部分我們都隻是簡單的介紹了一下,但如果能靈活應用這些技巧,相信對我們的日常生活 / 工作也是會有所幫助的。