[Website] Tunneling/Proxy 實作方法

工作上遇到要將某個 localhost 的 port 轉到 public 的區域的需求,查了很多關於 Tunneling/Proxy 實作方法,整理在這邊各種方法的優缺點,以下條列各種方法方法一:Tunneling, 方法二:proxy 代理主機, 方法三:使用商用或是開源的 local server exposure 的服務, 方法四:利用 Nginx 進行 Proxy 的服務。

方法一:Tunneling 

使用 Tunneling 的方法可以執行以下的指令參考,利用 tunneling 用戶可以在 client 端將某個特定的 port 接到遠端的伺服器上面,這個方法安全可靠,但是用戶要自己下這個 ssh 的指令,如果要方便用戶的話比較不會採用!

ssh -N -f -L localhost:8888:localhost:8889 remote_user@remote_host

其他參考連結

方法二:proxy 代理主機

這邊我們參考了 Django 的以下兩個專案,他們的目標都是利用 Proxy 去代理 localhost 的服務:

https://pypi.org/project/djproxy/
https://github.com/mjumbewu/django-proxy

但是缺點是這兩個專案實作的 proxy 並沒有辦法去支援有利用 WebSocket 的服務,所以如果 localhost 端運行的服務有利用到 WS 的話就會無法完全套用,利用 Django 要能夠支援 WebSocket 的服務需要用到像是 Django-Channels 的套件。

這邊主要是遇到 Missing “Upgrade” header 的問題,牽扯到 HTTP 1.1  有所謂的 hop-by-hop  Header,以上實作的兩個 Proxy 會把 Hop-by-hop  的標頭檔濾掉,使得 WS 無法建立!

Traceback (most recent call last):
  File "/usr/lib64/python3.6/wsgiref/handlers.py", line 137, in run
    self.result = application(self.environ, self.start_response)
  File "/home/***/.local/lib/python3.6/site-packages/django/contrib/staticfiles/handlers.py", line 65, in __call__
    return self.application(environ, start_response)
  File "/home/***/.local/lib/python3.6/site-packages/django/core/handlers/wsgi.py", line 150, in __call__
    start_response(status, response_headers)
  File "/usr/lib64/python3.6/wsgiref/handlers.py", line 236, in start_response
    assert not is_hop_by_hop(name),"Hop-by-hop headers not allowed"
AssertionError: Hop-by-hop headers not allowed
[19/Jun/2020 23:10:03] "GET /api/kernels/5a5da918-f5d3-4f5a-b9db-b4bdba265dd2/channels?session_id=7e74df521faa45f6ad7aae8b2fa05d80 HTTP/1.1" 500 59

 

方法三:使用商用或是開源的 local server exposure 的服務

將 localhost 的服務公開到 public 算是蠻有需求的,因為這樣可以大幅度地加快開發的流程,直接給客戶 Demo 之類等等,所以有一些開源或是商用的套件已經可以支援這樣的功能,筆者嘗試了 ngroklocaltunnel 這兩個服務,ngrok 是需要付費的方法,免費可以使用,但是有限發布的數量,另外 localtunnel 如何部署在以下的連結裡面講解得非常清楚!

部署 localtunnel 可以使用以下指令啟動:

node -r esm bin/server --secure true --domain test.domain --port 80

部署完 localtunnel 之後只需要執行指令就可以把自己的 localhost 透過 URL 發佈出去!

lt --host http://test.domain --port [your-local-port] -s name

 

方法四:利用 Nginx 進行 Proxy 的服務

這邊提到的 Proxy 與方法二提到的代理主機功能類似,但是利用 Nginx 可以對 WebSocket 的服務進行支援,可以參考另一篇文章教你如何把 Jupyter Notebook 部署在 Nginx 服務器之後。關於 Jupyter Notebook 可以查看

備註:也可以利用 Apache2 進行 Proxy 的服務

參考這兩個:網頁一網頁二 需要先安裝 Apache 的某些特定的 module:

proxy proxy_http proxy_https proxy_wstunnel ssl headers rewrite