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