相信你們在支付寶、微信、釘釘等各類小程序或支付對接的開發中,常常會遇到服務端回調的問題,至少要求接收回調請求的服務器有公網IP,以便能收到請求,微信的開發甚至要求回調接口必須是https
,而本地開發環境每每都是內網環境,甚至連固定ip都沒有,難道每次測試回調內容只能發佈到測試環境中去測試,有沒有簡單的方法呢?nginx
固然有!答案就是使用SSH代理(或其餘相似的proxy代理)。假定發佈應用給公網用戶,確定得有一臺固定ip的公網服務器吧,甚至還有固定ip的測試環境,利用這臺服務器作ssh server實現代理(Linux服務器自帶ssh server,windows環境能夠安裝ssh server,這裏不贅述了)。shell
以前我寫過一篇利用SSH代理訪問內網資源的文章,若是以前的文章對運維比較有用,那麼本篇的內容體現了ssh對開發的價值。以前的文章-R
參數不是重點,那麼本篇則是詳解-R
參數。-L
參數表明在本地監聽端口,將請求轉發到遠程,而-R
參數正好相反,在遠程監聽一個端口,將請求轉發到本地。小程序
本地必須有openssh client(Linux和Mac OS自帶,windows 10系統目前也自帶,windows低版本操做系統須要本身單獨下載openssh client安裝),一臺遠程服務器,有公網ip,開啓ssh server,用做回調服務器。segmentfault
本地須要經過ssh鏈接遠程服務器,在遠程服務器上監聽一個端口,將此端口的數據轉發到本地的某個應用端口上,實現將遠程數據代理到本地的做用,大概的示意圖像這樣:windows
request ----> | remote server | <------------> | local client | ^ ssh通道
這樣的話本地客戶端不須要有固定ip,只要能ssh鏈接到remote server,就可讓remote server將request轉發過來,而openssh剛好就提供了這樣的功能,對應的是-R
參數:api
-R [bind_address:]port:host:hostport -R [bind_address:]port:local_socket -R remote_socket:host:hostport -R remote_socket:local_socket -R [bind_address:]port
按照官方man手冊的敘述,-R
參數的做用是在遠程服務器bind一個ip:port(或unix domain socket),監聽請求,並將請求轉發到本地的ip:port(或unix domain socket)上,本質上仍是一個反向代理。安全
所以這個命令就很是容易寫出來(如下命令在本地執行):服務器
ssh -R 9999:127.0.0.1:9999 user@remote
和常見的ssh user@remote
這種直接鏈接ssh shell的命令相比,添加了一個-R
參數,表明ssh鏈接成功以後,在遠程服務器上監聽127.0.0.1:9999
(注意省略bind_address表明bind環回口),將請求轉發到127.0.0.1:9999
上(相對於本機的Ip),所以就等於訪問了本機127.0.0.1:9999
上監聽的應用程序。若是不想登陸到遠程shell,能夠追加-N
參數,若是不想掛起在前臺,能夠追加-f
參數,若是想啓用傳輸壓縮(gzip),還能夠追加-C
參數。更多有用的參數能夠參見man手冊微信
須要注意下-R
的幾個限制:網絡
port
參數設置爲0
,表示隨機監聽一個可用的端口bind_address
默認爲localhost
,若是爲空
或*
或0.0.0.0
則表示bind全部可用ip,可是注意遠程服務器的sshd_config
必須啓用GatewayPorts
選項纔有權限這麼作TCP
協議,所以這個代理也只是TCP
四層反向代理,不能實現UDP
的反向代理明白這個原理以後,咱們就能夠在實際應用中實現咱們的需求了。因爲微信、支付寶、釘釘等絕大多數回調請求都使用HTTP
協議,這個協議自己是工做在TCP
協議之上的,所以能夠用ssh代理實現代理HTTP
協議。
對於http請求,其實咱們只要在sshd_config
啓用GatewayPorts
選項,去bind 0.0.0.0
就能夠將回調請求轉發到本地了,可是考慮到https反向代理,以及其餘的一些http預處理需求,實際使用的時候建議前面放一個Nginx
或其餘http proxy server作反向代理,這樣的話就不須要配置sshd_config
,只bind 127.0.0.1就夠了。
以咱們剛纔的配置爲例,監聽遠程服務器的127.0.0.1:9999
端口,所以很容易寫出Nginx的反向代理配置:
server { listen 80; server_name api.example.com; location / { proxy_pass http://127.0.0.1:9999; } }
把域名A記錄指向remote server就好了(好比api.example.com),這樣回調請求到http://api.example.com/callback
就會轉發到本地的http://127.0.0.1:9999/callback
,因而乎在本地開發環境就能夠愉快的調試回調請求了,不再用反覆發佈到測試環境調試那麼麻煩了。
微信端回調要求https,那麼也簡單,使用免費的Let's encrypt證書,或者其餘已有的安全證書,配置到Nginx就好了,使得https://api.example.com
可使用就好了,這裏就再也不贅述了。
ssh直接作可能會由於網絡閃斷致使代理失效,若是但願ssh自動重連,可使用autossh這個小工具,幫咱們在ssh斷掉以後自動重連,維持代理隧道的穩定。
autossh的使用也十分簡單,基本兼容絕大多數ssh參數,像ssh同樣用就行,好比:
autossh -M 0 -R 9999:192.168.1.10:9999 -C -N
更詳細的用法參考官方文檔或者man手冊便可。
本篇文章咱們介紹了ssh的-R
代理在實際開發過程當中的用途,結合以前利用SSH代理訪問內網資源這篇文章,SSH的代理功能就所有講解完畢了。可能會有人要問,ssh功能如此強大,爲了防止ssh被濫用,我如何限制ssh的權限呢?對於這個問題,我將在後續的分享中詳解一下ssh的各類權限。