本文作者:ivweb 吳浩麟 原文出處:IVWEB社群 未經同意,禁止轉載
在開發微信公衆号或小程式的時候,由于微信平台規則的限制,部分接口需要通過線上域名才能正常通路。但我們一般都會在本地開發,因為這能快速的看到源碼修改後的運作結果。但當涉及到需要調用微信接口時,由于不和你在同一個區域網路中的使用者是無法通路你的本地開發機的,就必須把修改後的代碼重新釋出到線上域名所在的伺服器才能去驗證結果。每次修改都重新釋出很繁瑣也很浪費時間。
本文将教你如何通過 SSH 隧道把本地服務映射到外網,以友善調試,通常把這種方法叫内網穿透。
閱讀完本文後,你能解決以下常見問題:
開發微信公衆号等應用時把本地服務映射到外網,加速調試流程;
把你正在開發的本地服務分享給網際網路上其它人通路體驗;
在任何地方通過網際網路控制你家中在區域網路裡的電腦;

把運作在本地開發機上的 HTTP 服務映射到外網,讓全世界都能通過外網 IP 服務到你本地開發機上的 HTTP 服務。例如你本地的 HTTP 服務監聽在 127.0.0.1:8080,你有一台公網 IP 為 12.34.56.78 的伺服器,通過本文介紹的方法,可以讓全世界的使用者通過 http://12.34.56.78:8080 通路到你本地開發機上的 HTTP 服務。
總結成一句話就是:把内網端口映射到外網。
為了把内網服務映射到外網,以下資源為必須的:
一台有外網 IP 的伺服器;
能在本地開發機上通過 ssh 登入到外網伺服器。
要滿足以上條件很簡單:
對于條件1:購買一台低配 Linux 伺服器,推薦國外的 DigitalOcean;
對于條件2:對于 Mac、Linux 開發機是内置了 ssh 用戶端的,對于 Windows 可以安裝 Cygwin。
要實作把内網端口映射到外網,最簡單的方式就是通過 SSH 隧道。
SSH 隧道就像一根管道,能把任何2台機器連接配接在一起,把發送到其中一台機器的資料通過管道傳輸到另一台機器。假如已經通過 SSH 隧道把本地開發機和外網伺服器連接配接在了一起,外網伺服器端監聽在 12.34.56.78:8080,那麼所有發給 12.34.56.78:8080 的資料都會通過 SSH 隧道原封不動地傳輸給本地開發機的 127.0.0.1:8080,如圖所示:
也就是說,去通路 12.34.56.78:8080 就像是通路本地開發機的 127.0.0.1:8080,本地開發機上的 8080 端口被映射到了外網伺服器上的 8080 端口。
如果你的外網伺服器 IP 配置了域名解析,例如 yourdomin.com 會通過 DNS 解析為 12.34.56.78,那麼也可以通過 yourdomin.com:8080 去通路本地開發機上的服務。 這樣就做到了通路外網位址時其實是本地服務傳回的結果。
通過 SSH 隧道傳輸資料時,資料會被加密,就算中間被劫持,黑客也無法得到資料的原内容。 是以 SSH 隧道還有一個功能就是保證資料傳輸的安全性。
把本地開機和外網伺服器通過 SSH 隧道連接配接起來就和在本地開發機 SSH 登入遠端登入到外網伺服器一樣簡單。
先來回顧以下 SSH 遠端登入指令,假如想在本地遠端登入到 12.34.56.78,可以在本地開發機上執行以下指令:
而實作 SSH 隧道隻需在本地開發機上執行:
可以看出實作 SSH 隧道的指令相對于 SSH 登入多出來 -R 8080:127.0.0.1:8080,多出的這部分的含義是: 在遠端機器(12.34.56.78)上啟動 TCP 8080端口監聽着,再把遠端機器(12.34.56.78)上8080端口映射到本地的127.0.0.1:8080。 執行完以上指令後,就可以通過 12.34.56.78:8080 去通路本地的 127.0.0.1:8080 了。
通常把這種技術叫做 SSH 遠端端口轉發(remote forwarding)。
其實不限于隻能把本地開發機上運作的服務映射到外網伺服器上去,還可以把任何本地開發機可以通路的服務映射到外網伺服器上去。例如在本地開發機上能通路 github.com:80,在本地開發機上執行:
就能通過 12.34.56.78:8080 去通路 github.com:80 了。
在執行完上面介紹的 SSH 隧道指令後,你會發現登入到了外網伺服器上去了,如果你登出外網伺服器,就會發現 12.34.56.78:8080 無法通路了。導緻這個問題的原因是你登出外網伺服器時,在外網伺服器上本次操作對應的 SSH 程序也跟着退出了,而這個退出的程序曾負責監聽在 8080 端口進行轉發操作。
為了讓 SSH 隧道一直保持在背景執行,有以下方法。
通過 SSH 自帶的參數
SSH 還支援這些參數:
N參數:表示隻連接配接遠端主機,不打開遠端shell;
T參數:表示不為這個連接配接配置設定TTY;
f參數:表示連接配接成功後,轉入背景運作;
是以要讓 SSH 隧道一直保持在背景執行,可以通過以下指令:
通過 AutoSSH
SSH 隧道是不穩定的,在網絡惡劣的情況下可能随時斷開。如果斷開就需要手動去本地開發機再次向外網伺服器發起連接配接。 AutoSSH 能讓 SSH 隧道一直保持執行,他會啟動一個 SSH 程序,并監控該程序的健康狀況;當 SSH 程序崩潰或停止通信時,AutoSSH 将重新開機動 SSH 程序。
使用AutoSSH 隻需在本地開發機上安裝 AutoSSH ,方法如下:
Mac 系統:brew install autossh;
Linux 系統:apt-get install autossh;
安裝成功後,在本地開發機上執行:
就能完成和上面一樣的效果,但本方法能保持 SSH 隧道一直運作。 可以看出這行指令和上面的差別在于把 ssh 換成了 autossh,并且少了 -f 參數,原因是 autossh 預設會轉入背景運作。
如果你遇到通過以上方法成功啟動 SSH 隧道後,還是無法通路 12.34.56.78:8080,那麼很有可能是外網伺服器上的 SSH 沒有配置對。為此你需要去外網伺服器上修改 /etc/ssh/sshd_config 檔案如下:
這個選項的意思是,SSH 隧道監聽的服務的 IP 是對外開放的 0.0.0.0,而不是隻對本機的 127.0.0.1。不開 GatewayPorts 的後果是不能通過 12.34.56.78:8080 通路,隻能在外網伺服器上通過 127.0.0.1:8080 服務到本地開發機的服務。
修改好配置檔案後,你還需要重新開機 sshd 服務來加載新的配置,指令如下:
如果使用以上方法還是無法通路 12.34.56.78:8080,請檢查你外網伺服器的防火牆配置,確定 8080 端口是對外開放的。
除了 SSH 隧道能實作内網穿透外,還有以下常用方法。
frp
frp 是一個可用于内網穿透的高性能的反向代理應用,支援 tcp, udp, http, https 協定。 frp 有以下特性:
frp 比 SSH 隧道功能更多,配置項更多;
frp 也需要一台外網伺服器,并且需要在外網伺服器上安裝 frps,在本地開發機上安裝 frpc;
ngrok
ngrok 是一個商用的内網穿透工具,它有以下特點:
不需要有外網伺服器,因為 ngrok 會為你提供;
隻需要在本地開發機安裝 ngrok 用戶端,和注冊 ngrok 賬戶;
按照服務收費;
這些代替方案的缺點在于都需要再額外安裝其它工具,沒有 SSH 隧道來的直接。 想了解更多可以通路它們的首頁。