一、前言
SSH 是一種建立在應(yīng)用層基礎(chǔ)上的安全協(xié)議,利用SSH進行數(shù)據(jù)傳輸時也是較為可靠和安全的。當(dāng)有明文數(shù)據(jù)傳輸時,為保障其安全,可以利用SSH隧道對其進行加密安全傳輸,本文中講到的SSH隧道用法均可以保障安全傳輸,文中不詳做介紹,本文著重講解除安全傳輸之外的其他使用場景,來分別分析三種SSH隧道的用法。
文中會用到以下SSH參數(shù),先看一下man文檔中對以下SSH參數(shù)的解釋:
-L port:host:hostport
將本地機(客戶機)的某個端口轉(zhuǎn)發(fā)到遠(yuǎn)端指定機器的指定端口. 工作原理是這樣的, 本地機器上分配了一個 socket 偵聽 port 端口, 一旦這個端口上有了連接, 該連接就經(jīng)過安全通道轉(zhuǎn)發(fā)出去, 同時遠(yuǎn)程主機和 host 的 hostport 端口建立連接. 可以在配置文件中指定端口的轉(zhuǎn)發(fā). 只有 root 才能轉(zhuǎn)發(fā)特權(quán)端口. IPv6 地址用另一種格式說明: port/host/hostport
-R port:host:hostport
將遠(yuǎn)程主機(服務(wù)器)的某個端口轉(zhuǎn)發(fā)到本地端指定機器的指定端口. 工作原理是這樣的, 遠(yuǎn)程主機上分配了一個 socket 偵聽 port 端口, 一旦這個端口上有了連接, 該連接就經(jīng)過安全通道轉(zhuǎn)向出去, 同時本地主機和 host 的 hostport 端口建立連接. 可以在配置文件中指定端口的轉(zhuǎn)發(fā). 只有用 root 登錄遠(yuǎn)程主機 才能轉(zhuǎn)發(fā)特權(quán)端口. IPv6 地址用另一種格式說明: port/host/hostport
-D port
指定一個本地機器 “動態(tài)的” 應(yīng)用程序端口轉(zhuǎn)發(fā). 工作原理是這樣的, 本地機器上分配了一個 socket 偵聽 port 端口, 一旦這個端口上有了連接, 該連接就經(jīng)過安全通道轉(zhuǎn)發(fā)出去,根據(jù)應(yīng)用程序的協(xié)議可以判斷出遠(yuǎn)程主機將和哪里連接. 目前支持 SOCKS4 協(xié)議, ssh 將充當(dāng) SOCKS4 服務(wù)器. 只有 root 才能轉(zhuǎn)發(fā)特權(quán)端口. 可以在配置文件中指定動態(tài)端口的轉(zhuǎn)發(fā).
-N
不執(zhí)行遠(yuǎn)程命令. 用于轉(zhuǎn)發(fā)端口. (僅限協(xié)議第二版)
-f
要求 ssh 在執(zhí)行命令前退至后臺. 它用于當(dāng) ssh 準(zhǔn)備詢問口令或密語, 但是用戶希望它在后臺進行. 該選項隱含了 -n 選項. 在遠(yuǎn)端機器上啟動 X11 程序的推薦手法就是類似于 ssh -f host xterm 的命令.
-g
允許遠(yuǎn)端主機連接本地轉(zhuǎn)發(fā)的端口.
二. 本地轉(zhuǎn)發(fā)
1.功能解釋
本地轉(zhuǎn)發(fā)即在A服務(wù)器執(zhí)行ssh命令登錄B服務(wù)器來啟用SSH隧道,以實現(xiàn)通過訪問A服務(wù)器的轉(zhuǎn)發(fā)端口,達到實際訪問為B服務(wù)器的目標(biāo)端口的目的。如下圖所示:
2. 使用場景
當(dāng)客戶端可以訪問主機A的任意端口,但由于網(wǎng)絡(luò)或安全的原因客戶端無法訪問到主機B的任意端口。如果現(xiàn)在客戶端想要訪問主機B的某個服務(wù)時(如MySQL數(shù)據(jù)庫),此時只要主機A可以訪問到主機B的SSH端口,這里就可以使用SSH隧道,實現(xiàn)客戶端訪問主機A的轉(zhuǎn)發(fā)端口即可訪問到主機B的mysql數(shù)據(jù)庫。
3. 命令示例
以下命令均在A主機執(zhí)行:
SSH登錄后啟用ssh隧道,但僅監(jiān)聽A主機127.0.0.1地址,退出ssh登錄后隧道斷開
ssh -L A轉(zhuǎn)發(fā)port:B主機IP:B目的端口 root@B主機
SSH命令后不登錄B主機,僅啟用ssh隧道,僅監(jiān)聽A主機127.0.0.1地址,關(guān)閉A主機終端后隧道斷開
ssh -N -L A轉(zhuǎn)發(fā)port:B主機IP:B目的端口 root@B主機
SSH命令后不登錄B主機,僅啟用ssh隧道,僅監(jiān)聽A主機127.0.0.1地址,關(guān)閉A主機終端后隧道不會斷開
ssh -f -N -L A轉(zhuǎn)發(fā)port:B主機IP:B目的端口 root@B主機
指定A主機中ssh隧道轉(zhuǎn)發(fā)端口綁定的網(wǎng)卡
ssh -f -N -L A主機IP:A轉(zhuǎn)發(fā)port:B主機IP:B目的端口 root@B主機
將轉(zhuǎn)發(fā)端口綁定至A主機所有網(wǎng)卡
ssh -g -f -N -L A轉(zhuǎn)發(fā)port:B主機:B目的端口 root@B主機
三、遠(yuǎn)程轉(zhuǎn)發(fā)
1. 功能解釋
上面我們知道了本地轉(zhuǎn)發(fā)是在A服務(wù)器執(zhí)行ssh命令后將轉(zhuǎn)發(fā)端口設(shè)置在A服務(wù)器本身,遠(yuǎn)程轉(zhuǎn)發(fā)則相反,是將轉(zhuǎn)發(fā)端口設(shè)置在ssh命令的目標(biāo)服務(wù)器上。
遠(yuǎn)程轉(zhuǎn)發(fā)即在B服務(wù)器執(zhí)行ssh命令登錄A服務(wù)器來啟用SSH隧道,以實現(xiàn)通過訪問A服務(wù)器的轉(zhuǎn)發(fā)端口,達到實際訪問為B服務(wù)器的目標(biāo)端口的目的。如下圖所示:
2. 使用場景
遠(yuǎn)程轉(zhuǎn)發(fā)使用場景較為廣泛且實用。
如果我們在家庭電腦上跑了一個Tomcat服務(wù)并想提供到互聯(lián)網(wǎng)訪問,由于家庭電腦一般是通過路由器來訪問互聯(lián)網(wǎng)的(即在nat網(wǎng)絡(luò)中),我們需要在家庭路由器中進行端口映射來實現(xiàn)。
如果我們是公共路由器沒有權(quán)限怎么辦?又或者在權(quán)限管控嚴(yán)格的公司中我們沒有權(quán)限怎么辦?
巧合的是,我們手上還有一臺擁有公網(wǎng)IP的主機(如阿里云主機等),我們的家庭電腦是可以訪問到互聯(lián)網(wǎng)的(即可以SSH訪問到擁有公網(wǎng)IP的主機),直接使用SSH隧道就可以解決以上問題。
3. 命令示例
以下命令均在B主機執(zhí)行:
SSH命令后不登錄A主機,僅啟用ssh隧道,僅監(jiān)聽A主機127.0.0.1地址,關(guān)閉B主機終端后隧道不會斷開
ssh -f -N -R A主機轉(zhuǎn)發(fā)端口:B主機IP:B目的端口 root@A主機
看到這里,你一定會聯(lián)想到以下兩條指令來實現(xiàn)綁定到非lookback地址:
ssh -f -N -R A主機IP:A主機轉(zhuǎn)發(fā)端口:B主機IP:B目的端口 root@A主機
ssh -g -f -N -R A主機轉(zhuǎn)發(fā)端口:B主機IP:B目的端口 root@A主機
不過當(dāng)你實驗時敲下以下指令,會發(fā)現(xiàn)A主機的SSH隧道監(jiān)聽地址仍然是127.0.0.1,這又是為什么呢?
4. 將遠(yuǎn)程轉(zhuǎn)發(fā)綁定到網(wǎng)卡
上一小節(jié)我們嘗試建立遠(yuǎn)程轉(zhuǎn)發(fā)隧道后,僅監(jiān)聽127.0.0.1地址,這是因為在SSH服務(wù)的配置文件/etc/ssh/sshd_config中有這樣一個配置
GatewayPorts 是否允許遠(yuǎn)程主機連接本地的轉(zhuǎn)發(fā)端口,默認(rèn)值為 no。
將此項配置為yes并重啟SSH服務(wù)后,再次執(zhí)行命令
ssh -f -N -R A主機轉(zhuǎn)發(fā)端口:B主機IP:B目的端口 root@A主機
這時遠(yuǎn)程轉(zhuǎn)發(fā)的轉(zhuǎn)發(fā)端口會設(shè)置在A主機的所有網(wǎng)卡上,即0.0.0.0
當(dāng)然除了這種方法,我們還可以使用其他技術(shù)手段來實現(xiàn)允許其他主機訪問A主機127.0.0.1地址的轉(zhuǎn)發(fā)端口,例如在A主機用其他程序去反向代理127.0.0.1的轉(zhuǎn)發(fā)端口,使用Nginx反代實現(xiàn)方式和配置可以點開我的主頁,查看《Nginx實現(xiàn)socket代理》這篇文章。
四、 動態(tài)轉(zhuǎn)發(fā)
1. 功能解釋
動態(tài)轉(zhuǎn)發(fā)即通過配置一個本地端口,將通過隧道的數(shù)據(jù)轉(zhuǎn)發(fā)到目標(biāo)端地址網(wǎng)絡(luò)。
如上圖所示,動態(tài)轉(zhuǎn)發(fā)不像本地轉(zhuǎn)發(fā)與遠(yuǎn)程轉(zhuǎn)發(fā)一樣轉(zhuǎn)發(fā)端口與目標(biāo)端口是一對一的,動態(tài)轉(zhuǎn)發(fā)中的轉(zhuǎn)發(fā)端口對應(yīng)的目標(biāo)是目標(biāo)主機所在的整個網(wǎng)絡(luò)。不過使用動態(tài)轉(zhuǎn)發(fā)訪問目標(biāo)主機所在網(wǎng)絡(luò)時需要應(yīng)用程序本身支持代理配置或者使用socket代理工具。
2. 使用場景
同樣如上圖所示,如果存在一個子網(wǎng)1與子網(wǎng)2之間設(shè)有防火墻,主機A只能訪問到主機B的ssh端口,這時如果主機A或者外部客戶端想要訪問子網(wǎng)2中的任意IP的任意端口時,可以使用動態(tài)轉(zhuǎn)發(fā)隧道實現(xiàn)。
3. 命令示例
以下命令均在A主機執(zhí)行:
SSH命令后不登錄B主機,僅啟用ssh隧道,僅監(jiān)聽A主機127.0.0.1地址,關(guān)閉A主機終端后隧道不會斷開
ssh -f -N -D A主機轉(zhuǎn)發(fā)端口 root@A主機
SSH命令后不登錄B主機,僅啟用ssh隧道,監(jiān)聽A主機指定網(wǎng)卡IP地址,關(guān)閉A主機終端后隧道不會斷開
ssh -f -N -D A主機IP地址:A主機轉(zhuǎn)發(fā)端口 root@A主機
4. 客戶端代理配置
當(dāng)隧道創(chuàng)建好之后我們需要通過代理客戶端進行設(shè)置之后才會使用隧道,如果應(yīng)用程序支持配置直接配置即可,如果是不支持配置代理的應(yīng)用程序可以使用到socket代理工具來搭配使用,我常用的客戶端代理工具是Proxifier,關(guān)于用法可以參考我主頁的另一篇文章《Socket代理神器客戶端Proxifier+服務(wù)端ss5》。
五、AutoSSH
在實際的使用過程中,如果使用遠(yuǎn)程轉(zhuǎn)發(fā)穿透到內(nèi)網(wǎng),ssh隧道將會非常不穩(wěn)定,隧道會莫名其妙的消失或者失效,特別是在沒有固定IP的網(wǎng)絡(luò)內(nèi),本章節(jié)講解使用AutoSSH進行穩(wěn)定的遠(yuǎn)程轉(zhuǎn)發(fā)。
1. 下載安裝
①下載地址
https://www.harding.motd.ca/autossh/autossh-1.4g.tgz
②解壓
tar zxvf autossh-1.4g.tgz
③預(yù)編譯
cd autossh-1.4g
./configure
④編譯
make
編譯完成后當(dāng)前目錄下會生成autossh這個文件。
⑤至此,autossh安裝完成,將authssh文件拷貝到任意目錄執(zhí)行即可使用。
也可以將autossh文件拷貝到環(huán)境變量$PATH中的目錄即可實現(xiàn)在任意目錄下直接訪問autossh。
2. 參數(shù)解釋
AuthSSH只有三個自己的參數(shù):
-M <port>[:echo_port] 指定要使用的基本監(jiān)控端口,或者指定要使用的監(jiān)控端口和回顯服務(wù)端口。
-f 使 autossh 在運行 ssh 之前進入后臺。注意在autossh中使用到此參數(shù)將不會提示輸入密碼,所以使用此參數(shù)需要先配置好公鑰登錄。
-V 查看版本號。
3. 配置公鑰登錄
若未配置過公鑰登錄的朋友可以點開我的主頁,參考《SSH登錄流程及配置公鑰登錄》這篇文章。
4. 使用autossh進行遠(yuǎn)程轉(zhuǎn)發(fā)
在B主機執(zhí)行命令
AutoSSH命令后不登錄A主機,關(guān)閉B主機終端后隧道不會斷開
autossh -M 10000 -f -N -R A主機轉(zhuǎn)發(fā)端口:B主機IP:B目的端口 root@A主機
5. 驗證穩(wěn)定性
使用autossh命令后,autossh會打開另一個ssh進程創(chuàng)建隧道,我們嘗試kill14837進程后,再次ps查看進程時發(fā)現(xiàn)autossh立即又打開了另一個ssh進程創(chuàng)建了隧道,并且測試隧道使用正常。
參考:
朱雙印個人日志《ssh端口轉(zhuǎn)發(fā):ssh隧道》
寫在最后:
如有錯誤,請評論告知,多多包涵,謝謝!