使用 Frp 爲你的 Web 服務添加 https 支持

frp 是一個可用於內網穿透的高性能的反向代理應用,支持 tcp, udp 協議,爲 http 和 https 應用協議提供了額外的能力,且嘗試性支持了點對點穿透。

在衆多反向代理應用中,frp 的最大特點就在於內網穿透。所以,如果你有將內網對外提供 Web 服務的需求,就可以考慮使用 frp 爲你的 Web 服務提供 https 支持。


下載 frp

前往 GitHub 下載 frp:

有適用於各種不同操作系統的 frp,如果你對外提供的公網服務器和實際提供 Web 服務的服務器不是同一臺機器的話,需要爲各自機器下載對應版本的 frp。

準備好 Web 服務和 SSL 證書

你可以用任何方式開發你的 Web 服務,注意你的 Web 服務需要監聽一個本機端口。

對於準備 SSL 證書,你可以參考我的另一篇博客:

對於本文的後續內容,你需要將證書導出成 Nginx 格式,即一個 crt 文件和一個 key 文件。

配置 frp

你需要準備運行一個 frp 服務端和一個 frp 客戶端。它們可以運行在不同的機器上,也可以運行在同一臺機器上。

鑑於 frp 的內網穿透的優勢,如果你將這兩個端部署在不同的機器上,就能夠實現 https 支持的同時也做到內網穿透——即你可以將 NAT 網絡中的一臺電腦對全球公開的互聯網提供服務。

當然,你也可以部署到同一臺機器上,這樣的優勢就是一個端口可以服務很多的 Web 服務,同時支持 https。

接下來的描述中,我用 A 機器表示 frp 服務端(也就是對公衆開放服務的一端),B 機器表示 frp 客戶端(提供 Web 服務的一端)。它們可以是同一臺機器,也可以是不同的機器。

反向代理服務端

A 機器需要修改 frps.ini 文件:

[common]
bind_port = 7000
vhost_http_port = 80
vhost_https_port = 443

▲ bind_port 是 frp 服務端口,客戶端如果要使用 frp 服務則連接這個端口;vhost_http_port 是代理 http 的端口;vhost_https_port 是代理 https 的端口

配置完成之後,運行 frp 程序:

./frps -c ./frps.ini

▲ 對於 Linux 系統

./frps.exe -c ./frps.ini

▲ 對於 Windows 系統

於是,A 機器就配置好了。

反向代理客戶端

B 機器的配置將是 https 支持的重點:

[common]
# 這裏填寫 A 機器的 IP 或者域名
server_addr = 100.13.*.*
# 填寫 A 機器開放的 frp 服務端口,也就是 frps.ini 配置文件中 bind_port 的值
server_port = 7000

[walterlv_example_http]
# 依然支持 http 訪問
type = http
# 本地 Web 服務的端口
local_port = 10000
# 需要反向代理的域名(當訪客通過此域名訪問 A 機器時,纔會將請求反向代理到此 Web 服務)
custom_domains = example.walterlv.com

[walterlv_example]
# 配置 https 訪問
type = https
# 本地 Web 服務的端口(與前面的配置一樣,都對應同一個 Web 服務)
local_port = 10000
# 需要反向代理的域名(當訪客通過此域名訪問 A 機器時,纔會將請求反向代理到此 Web 服務)
custom_domains = example.walterlv.com

# 接下來的配置是支持 https 的重點配置
# 配置插件,將 https 請求轉換成 http 請求後再發送給本地 Web 服務程序
plugin = https2http
# 轉換成 http 後,發送到本機的 10000 端口
plugin_local_addr = 127.0.0.1:10000
# 可能是 frp 的 Bug?這裏必須寫成 127.0.0.1,稍後解釋
plugin_host_header_rewrite = 127.0.0.1
# 指定代理方式爲 frp
plugin_header_X-From-Where = frp
# 指定成你在前面部分導出的證書的路徑
plugin_crt_path = C:/Samples/_.walterlv.com_chain.crt
plugin_key_path = C:/Samples/_.walterlv.com_key.key

這就是 frp 的特色,重點配置都放到了反向代理的客戶端中。這樣的配置方式安全性自然成了問題,但也正因爲如此,纔可以真正實現帶有內網穿透的反向代理。

接下來介紹以下這個文件裏面爲什麼是這樣配置的。

[Common] 節點是爲了與 frp 服務端取得聯繫的。所以 server_addrserver_port 自然成了必要,畢竟連接一個 Web 服務這是兩個必要的參數。如果你的兩個端部署在同一臺電腦上,那麼這裏可以填寫 127.0.0.1

[walterlv_example_http] 節點和 [walterlv_example] 兩個節點的名稱是隨便取的,不需要滿足什麼規律。唯一的要求是,連接到此 frp 服務端的所有客戶端之間,這個名稱都不能重複。frp 的服務端通過此名稱來區分不同的客戶端配置。因此,通常將這個名稱命名成域名或者功能名。

[walterlv_example_http] 節點配置來兼容 http 訪問。如果不配置這一個節點,那麼使用 http 訪問的訪客將得到 frp 服務器返回的 403 狀態碼。這裏的三項配置表示,如果使用 http 協議訪問此 frp 服務端,且訪問域名是 example.walterlv.com(http 頭裏寫的),那麼將此請求轉發到 frp 客戶端本機的 10000 端口。

[walterlv_example] 節點的前三項與 [walterlv_example_http] 一樣,含義也是一樣的。接下來就是啓用 https2http 插件,將訪問 frp 服務端的 https 流量全部轉換成 http 流量,然後轉發給本機的 http 服務。plugin_local_addr 就是指定轉發到本機的 10000 端口。當然你也可以寫成非本機的 http 服務,例如 walterlv.github.io:80,這樣,https 流量轉換成 http 流量後會發給對應的機器。plugin_host_header_rewrite 在目前(frp 0.31.1 版本),這個值必須寫成 127.0.0.1,否則會出現錯誤的重定向(例如,如果指定成 example.walterlv.com 會導致流量回流到 frp 服務端,這絕對是反向代理的一個 Bug!)這個值的含義是修改 http 的請求頭,將請求頭中的域名部分改寫成 127.0.0.1(在改寫之前,頭是 example.walterlv.com)。plugin_crt_pathplugin_key_path 指定爲 SSL 證書的路徑。plugin_header_X-From-Where 則不是必須的。

工作原理

使用 frp 讓 Web 服務支持 https 的流程是一個典型的反向代理服務器的工作流程。

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-6hMPGdXG-1588218788342)(https://blog.walterlv.com/static/posts/2020-01-12-19-15-53.png)]

訪客在瀏覽器中輸入網址 https://blog.walterlv.com 後,瀏覽器會查詢 <blog.walterlv.com> 的 IP,查詢到之後,向此 IP 的 443 端口發送 https 請求。frp 服務端收到此請求後檢查訪問的域名,發現曾經連接此 frp 服務端的一個客戶端配置了此域名的反向代理。於是將請求轉發給此客戶端。frp 客戶端在收到轉發的 https 請求後,使用 SSL 證書將 https 解密成 http 請求,然後修改 http 頭添加或修改額外的信息。最後,frp 客戶端將修改後的 http 請求轉發給本機的真正的 Web 服務程序。當 Web 服務程序處理完 Web 請求後,響應沿着原路返回。

這裏值得注意的是,由於 frp 反向代理系統中,使用 SSL 證書的一端在 frp 客戶端,這意味着 frp 服務端完全無法得知此 https 請求的內容。於是在轉發後也無法得知此請求的真實來源(訪客 IP),這樣,真實的 Web 服務將無法得知真實的訪客信息。這也是 frp 在此設計下必然出現的缺陷。

如果你希望你的 Web 服務在 https 下破除這些限制,那麼建議使用其他的反向代理服務器。關於其他配置 https 的方法,你可以閱讀:

除了 frp 以外的方法都可以獲得真實的訪客信息。


參考資料


我的博客會首發於 https://blog.walterlv.com/,而 CSDN 會從其中精選發佈,但是一旦發佈了就很少更新。

如果在博客看到有任何不懂的內容,歡迎交流。我搭建了 dotnet 職業技術學院 歡迎大家加入。

知識共享許可協議

本作品採用知識共享署名-非商業性使用-相同方式共享 4.0 國際許可協議進行許可。歡迎轉載、使用、重新發布,但務必保留文章署名呂毅(包含鏈接:https://walterlv.blog.csdn.net/),不得用於商業目的,基於本文修改後的作品務必以相同的許可發佈。如有任何疑問,請與我聯繫

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章