起因
最近碰到一件事:B同學在他電腦的Ubuntu
虛擬機中學習搭建服務器碰到了問題,要我幫他看下。我總不能一個QQ遠程桌面連過去,那樣操作會卡到崩潰。ssh
過去是最好的方法,不過他的電腦跟我不在一個局域網,又是虛擬機,要怎么連過去呢?
怎么解決?
有兩種方法:
- 通過一台公網服務器,通過
ssh
命令建立反向隧道 - 通過第三方的
ngrok
服務建立tcp
反向隧道
它們的原理都是使用了反向隧道,原理見下圖:
正向與反向的區別在於正向連接是使用者通過自己的客戶端操作服務器資源;反向連接是使用者通過服務器操作客戶端資源。結合上圖理解:
- 客戶端1
ssh
連接公網服務器時,所有的操作都在服務器上,所以稱為正向隧道
; - 客戶端2
ssh
連接公網服務器的2244
端口時,公網服務器全部轉發客戶端1,使用者通過公網服務器操作客戶端1,所以公網服務器到客戶端1的連接稱為反向隧道
。
第一種方法
在客戶端1
執行一條命令即可建立反向隧道:
$ssh -N -f -R *:2244:localhost:22 106.10.10.xxx
其中-N
表示不執行命令,只轉發;-f
表示后台運行;-R
表示反向隧道;*:2244:localhost:22
表示監聽服務器的2244
端口,所有包轉發到本地的22
端口;106.10.10.xxx
為服務器IP
。
我只要在客戶端2
執行ssh -p 2244 xxx@106.10.10.xxx
就能連接客戶端1
的電腦了。
實際使用中會發現,該通道會經常自動斷開,這是正常現象。可通過autossh
實現斷開重連。使用autossh
之前,必須確保該客戶端與服務器連接使用了無密碼的密鑰對登陸。
$autossh -M 5678 -N -f -R *:2244:localhost:22 106.10.10.xxx
其中-M 5678
表示通過5678
端口監聽連接狀態,有問題就重連。
第二種
使用ngrok
(1.x版本)就簡單多了,一條命令搞定,也不需要知道服務器的密碼或傳公鑰,適合第三方服務器提供跳板服務。
$ngrok -proto=tcp 22
ngrok (Ctrl+C to quit)
Tunnel Status online
Version 1.7/1.7
Forwarding tcp://106.10.10.xxx:2244 -> 127.0.0.1:22
Web Interface 127.0.0.1:4040
# Conn 0
Avg Conn Time 0.00ms
根據上面的輸出,我只要在客戶端2執行ssh -p 2244 xxx@106.10.10.xxx
就能連接客戶端1
的電腦了。
默認情況下,ngrok
的轉發端口是隨機的,如果要固定,編輯~/.ngrok
,按如下添加通道:
server_addr: 106.10.10.xxx:4443
trust_host_root_certs: false
tunnels:
ssh:
proto:
tcp: "22"
remote_port: 2244
然后通過以下命令啟動:
ngrok start ssh