你可能已經熟悉使用 ssh 命令存取遠端系統。ssh
命令背後所使用的協定允許終端的輸入和輸出流經安全通道。但是你知道也可以使用 ssh
來安全地傳送和接收其他資料嗎?一種方法是使用“埠轉發”,它允許你在進行 ssh
對談時安全地連線網路埠。本文向你展示了它是如何工作的。
標準 Linux 系統已分配了一組網路埠,範圍是 0 - 65535。系統會保留 0 - 1023 的埠以供系統使用。在許多系統中,你不能選擇使用這些低埠號。通常有幾個埠用於執行特定的服務。你可以在系統的 /etc/services
檔案中找到這些定義。
你可以認為網路埠是類似的物理埠或可以連線到電纜的插孔。埠可以連線到系統上的某種服務,類似物理插孔後面的接線。一個例子是 Apache Web 伺服器(也稱為 httpd
)。對於 HTTP 非安全連線,Web 伺服器通常要求在主機系統上使用埠 80,對於 HTTPS 安全連線通常要求使用 443。
當你連線到遠端系統(例如,使用 Web 瀏覽器)時,你是將瀏覽器“連線”到你的主機上的埠。這通常是一個隨機的高階口號,例如 54001。你的主機上的埠連線到遠端主機上的埠(例如 443)來存取其安全的 Web 伺服器。
那麼,當你有這麼多可用埠時,為什麼還要使用埠轉發呢?這是 Web 開發人員生活中的幾種常見情況。
想象一下,你正在名為 remote.example.com
的遠端系統上進行 Web 開發。通常,你是通過 ssh
進入此系統的,但是它位於防火牆後面,而且該防火牆很少允許其他型別的存取,並且會阻塞大多數其他埠。要嘗試你的網路應用,能夠使用瀏覽器存取遠端系統會很有幫助。但是,由於使用了討厭的防火牆,你無法通過在瀏覽器中輸入 URL 的常規方法來存取它。
本地轉發使你可以通過 ssh
連線來建立可通過遠端系統存取的埠。該埠在系統上顯示為本地埠(因而稱為“本地轉發”)。
假設你的網路應用在 remote.example.com
的 8000 埠上執行。要將那個系統的 8000 埠本地轉發到你系統上的 8000 埠,請在開始對談時將 -L
選項與 ssh
結合使用:
$ ssh -L 8000:localhost:8000 remote.example.com
等等,為什麼我們使用 localhost
作為轉發目標?這是因為從 remote.example.com
的角度來看,你是在要求主機使用其自己的埠 8000。(回想一下,任何主機通常可以通過網路連線 localhost
而連線到自身。)現在那個埠連線到你系統的 8000 埠了。ssh
對談準備就緒後,將其保持開啟狀態,然後可以在瀏覽器中鍵入 http://localhost:8000
來檢視你的 Web 應用。現在,系統之間的流量可以通過 ssh
隧道安全地傳輸!
如果你有敏銳的眼睛,你可能已經注意到了一些東西。如果我們要 remote.example.com
轉發到與 localhost
不同的主機名怎麼辦?如果它可以存取該網路上另一個系統上的埠,那麼通常可以同樣輕鬆地轉發該埠。例如,假設你想存取也在該遠端網路中的 db.example.com
的 MariaDB 或 MySQL 服務。該服務通常在埠 3306 上執行。因此,即使你無法 ssh
到實際的 db.example.com
主機,你也可以使用此命令將其轉發:
$ ssh -L 3306:db.example.com:3306 remote.example.com
現在,你可以在 localhost
上執行 MariaDB 命令,而實際上是在使用 db.example.com
主機。
遠端轉發讓你可以進行相反操作。想象一下,你正在為辦公室的朋友設計一個 Web 應用,並想向他們展示你的工作。不過,不幸的是,你在咖啡店裡工作,並且由於網路設定,他們無法通過網路連線存取你的筆記型電腦。但是,你同時使用著辦公室的 remote.example.com
系統,並且仍然可在這裡登入。你的 Web 應用似乎在本地 5000 埠上執行良好。
遠端埠轉發使你可以通過 ssh
連線從本地系統建立埠的隧道,並使該埠在遠端系統上可用。在開始 ssh
對談時,只需使用 -R
選項:
$ ssh -R 6000:localhost:5000 remote.example.com
現在,當在公司防火牆內的朋友開啟瀏覽器時,他們可以進入 http://remote.example.com:6000
檢視你的工作。就像在本地埠轉發範例中一樣,通訊通過 ssh
對談安全地進行。
預設情況下,sshd
守護行程執行在設定的主機上,因此只有該主機可以連線它的遠端轉發埠。假設你的朋友希望能夠讓其他 example.com
公司主機上的人看到你的工作,而他們不在 remote.example.com
上。你需要讓 remote.example.com
主機的所有者將以下選項之一新增到 /etc/ssh/sshd_config
中:
GatewayPorts yes # 或GatewayPorts clientspecified
第一個選項意味著 remote.example.com
上的所有網路介面都可以使用遠端轉發的埠。第二個意味著建立隧道的用戶端可以選擇地址。預設情況下,此選項設定為 no
。
使用此選項,你作為 ssh
用戶端仍必須指定可以共用你這邊轉發埠的介面。通過在本地埠之前新增網路地址範圍來進行此操作。有幾種方法可以做到,包括:
$ ssh -R *:6000:localhost:5000 # 所有網路$ ssh -R 0.0.0.0:6000:localhost:5000 # 所有網路$ ssh -R 192.168.1.15:6000:localhost:5000 # 單個網路$ ssh -R remote.example.com:6000:localhost:5000 # 單個網路
請注意,本地和遠端系統上的埠號不必相同。實際上,有時你甚至可能無法使用相同的埠。例如,普通使用者可能不會在預設設定中轉發到系統埠。
另外,可以限制主機上的轉發。如果你需要在聯網主機上更嚴格的安全性,那麼這你來說可能很重要。 sshd
守護程進程的 PermitOpen
選項控制是否以及哪些埠可用於 TCP 轉發。預設設定為 any
,這讓上面的所有範例都能正常工作。要禁止任何埠轉發,請選擇 none
,或僅允許的特定的“主機:埠”。有關更多資訊,請在手冊頁中搜尋 PermitOpen
來設定 sshd
守護行程:
$ man sshd_config
最後,請記住,只有在 ssh
對談處於開啟狀態時才會埠轉發。如果需要長時間保持轉發活動,請嘗試使用 -N
選項在後台執行對談。確保控制台已鎖定,以防止在你離開控制台時其被篡奪。