使用SSH代理在本地開發環境調試各類回調

前言背景

相信你們在支付寶、微信、釘釘等各類小程序或支付對接的開發中,常常會遇到服務端回調的問題,至少要求接收回調請求的服務器有公網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的幾個限制:網絡

  • 想bind權限端口(1024之內的端口號),必須以root身份鏈接,普通用戶無權限
  • port參數設置爲0,表示隨機監聽一個可用的端口
  • bind_address默認爲localhost,若是爲*0.0.0.0則表示bind全部可用ip,可是注意遠程服務器的sshd_config必須啓用GatewayPorts選項纔有權限這麼作
  • 因爲ssh是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的各類權限。

相關文章
相關標籤/搜索