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