frp 是一個(gè)可用于內(nèi)網(wǎng)穿透的高性能的反向代理應(yīng)用,支持 tcp, udp 協(xié)議,為 http 和 https 應(yīng)用協(xié)議提供了額外的能力,且嘗試性支持了點(diǎn)對(duì)點(diǎn)穿透。可以用它進(jìn)行小程序開(kāi)發(fā)。
將 frps 及 frps.ini 放到具有公網(wǎng) IP 的機(jī)器上。
將 frpc 及 frpc.ini 放到處于內(nèi)網(wǎng)環(huán)境的機(jī)器上。
通過(guò) ssh 訪問(wèn)公司內(nèi)網(wǎng)機(jī)器
- 修改 frps.ini 文件,這里使用了最簡(jiǎn)化的配置,設(shè)置了 frp 服務(wù)器端接收客戶端流量的端口:
# frps.ini
[common]
bind_port = 7000
- 啟動(dòng) frps:
./frps -c ./frps.ini
- 修改 frpc.ini 文件,假設(shè) frps 所在服務(wù)器的公網(wǎng) IP 為 x.x.x.x:
# frpc.ini
[common]
server_addr = x.x.x.x
server_port = 7000
[ssh]
type = tcp
local_ip = 127.0.0.1
local_port = 22
remote_port = 6000
注意,local_port(客戶端偵聽(tīng))和 remote_port(服務(wù)器端暴露)是用來(lái)出入 frp 系統(tǒng)的兩端,server_port 則是服務(wù)器用來(lái)與客戶端通訊的。
- 啟動(dòng) frpc:
./frpc -c ./frpc.ini
- 通過(guò) ssh 訪問(wèn)內(nèi)網(wǎng)機(jī)器,假設(shè)用戶名為 test:
ssh -oPort=6000 [email protected]
通過(guò)自定義域名訪問(wèn)部署于內(nèi)網(wǎng)的 web 服務(wù)
有時(shí)想要讓其他人通過(guò)域名訪問(wèn)或者測(cè)試我們?cè)诒镜卮罱ǖ?web 服務(wù),但是由于本地機(jī)器沒(méi)有公網(wǎng) IP,無(wú)法將域名解析到本地的機(jī)器,通過(guò) frp 就可以實(shí)現(xiàn)這一功能,以下示例為 http 服務(wù),https 服務(wù)配置方法相同, vhost_http_port 替換為 vhost_https_port, type 設(shè)置為 https 即可。
- 修改 frps.ini 文件,設(shè)置 http 訪問(wèn)端口為 8080:
# frps.ini
[common]
bind_port = 7000
vhost_http_port = 8080
- 啟動(dòng) frps:
./frps -c ./frps.ini
- 修改 frpc.ini 文件,假設(shè) frps 所在的服務(wù)器的 IP 為 x.x.x.x,local_port 為本地機(jī)器上 web 服務(wù)對(duì)應(yīng)的端口, 綁定自定義域名 www.yourdomain.com:
# frpc.ini
[common]
server_addr = x.x.x.x
server_port = 7000
[web]
type = http
local_port = 80
custom_domains = www.yourdomain.com
- 啟動(dòng) frpc:
./frpc -c ./frpc.ini
- 將 www.yourdomain.com 的域名 A 記錄解析到 IP x.x.x.x,如果服務(wù)器已經(jīng)有對(duì)應(yīng)的域名,也可以將 CNAME 記錄解析到服務(wù)器原先的域名。
- 通過(guò)瀏覽器訪問(wèn) http://www.yourdomain.com:8080 即可訪問(wèn)到處于內(nèi)網(wǎng)機(jī)器上的 web 服務(wù)。
對(duì)外提供簡(jiǎn)單的文件訪問(wèn)服務(wù)
通過(guò) static_file 插件可以對(duì)外提供一個(gè)簡(jiǎn)單的基于 HTTP 的文件訪問(wèn)服務(wù)。
frps 的部署步驟同上。
- 啟動(dòng) frpc,啟用 static_file 插件,配置如下:
# frpc.ini
[common]
server_addr = x.x.x.x
server_port = 7000
[test_static_file]
type = tcp
remote_port = 6000
plugin = static_file
# 要對(duì)外暴露的文件目錄
plugin_local_path = /tmp/file
# 訪問(wèn) url 中會(huì)被去除的前綴,保留的內(nèi)容即為要訪問(wèn)的文件路徑
plugin_strip_prefix = static
plugin_http_user = abc
plugin_http_passwd = abc
- 通過(guò)瀏覽器訪問(wèn) http://x.x.x.x:6000/static/ 來(lái)查看位于 /tmp/file 目錄下的文件,會(huì)要求輸入已設(shè)置好的用戶名和密碼。
為本地 HTTP 服務(wù)啟用 HTTPS
通過(guò) https2http 插件可以讓本地 HTTP 服務(wù)轉(zhuǎn)換成 HTTPS 服務(wù)對(duì)外提供。
- 啟用 frpc,啟用 https2http 插件,配置如下:
# frpc.ini
[common]
server_addr = x.x.x.x
server_port = 7000
[test_htts2http]
type = https
custom_domains = test.yourdomain.com
plugin = https2http
plugin_local_addr = 127.0.0.1:80
# HTTPS 證書(shū)相關(guān)的配置
plugin_crt_path = ./server.crt
plugin_key_path = ./server.key
plugin_host_header_rewrite = 127.0.0.1
plugin_header_X-From-Where = frp
- 通過(guò)瀏覽器訪問(wèn) https://test.yourdomain.com 即可。
安全地暴露內(nèi)網(wǎng)服務(wù)
對(duì)于某些服務(wù)來(lái)說(shuō)如果直接暴露于公網(wǎng)上將會(huì)存在安全隱患。
使用 stcp(secret tcp) 類型的代理可以避免讓任何人都能訪問(wèn)到要穿透的服務(wù),但是訪問(wèn)者也需要運(yùn)行另外一個(gè) frpc。
以下示例將會(huì)創(chuàng)建一個(gè)只有自己能訪問(wèn)到的 ssh 服務(wù)代理。
frps 的部署步驟同上。
- 啟動(dòng) frpc,轉(zhuǎn)發(fā)內(nèi)網(wǎng)的 ssh 服務(wù),配置如下,不需要指定遠(yuǎn)程端口:
# frpc.ini
[common]
server_addr = x.x.x.x
server_port = 7000
[secret_ssh]
type = stcp
# 只有 sk 一致的用戶才能訪問(wèn)到此服務(wù)
sk = abcdefg
local_ip = 127.0.0.1
local_port = 22
- 在要訪問(wèn)這個(gè)服務(wù)的機(jī)器上啟動(dòng)另外一個(gè) frpc,配置如下:
# frpc.ini
[common]
server_addr = x.x.x.x
server_port = 7000
[secret_ssh_visitor]
type = stcp
# stcp 的訪問(wèn)者
role = visitor
# 要訪問(wèn)的 stcp 代理的名字
server_name = secret_ssh
sk = abcdefg
# 綁定本地端口用于訪問(wèn) ssh 服務(wù)
bind_addr = 127.0.0.1
bind_port = 6000
- 通過(guò) ssh 訪問(wèn)內(nèi)網(wǎng)機(jī)器,假設(shè)用戶名為 test:
ssh -oPort=6000 [email protected]
點(diǎn)對(duì)點(diǎn)內(nèi)網(wǎng)穿透
frp 提供了一種新的代理類型 xtcp 用于應(yīng)對(duì)在希望傳輸大量數(shù)據(jù)且流量不經(jīng)過(guò)服務(wù)器的場(chǎng)景。
使用方式同 stcp 類似,需要在兩邊都部署上 frpc 用于建立直接的連接。
目前處于開(kāi)發(fā)的初級(jí)階段,并不能穿透所有類型的 NAT 設(shè)備,所以穿透成功率較低。穿透失敗時(shí)可以嘗試 stcp 的方式。
- frps 除正常配置外需要額外配置一個(gè) udp 端口用于支持該類型的客戶端:
bind_udp_port = 7001
- 啟動(dòng) frpc,轉(zhuǎn)發(fā)內(nèi)網(wǎng)的 ssh 服務(wù),配置如下,不需要指定遠(yuǎn)程端口:
# frpc.ini
[common]
server_addr = x.x.x.x
server_port = 7000
[p2p_ssh]
type = xtcp
# 只有 sk 一致的用戶才能訪問(wèn)到此服務(wù)
sk = abcdefg
local_ip = 127.0.0.1
local_port = 22
- 在要訪問(wèn)這個(gè)服務(wù)的機(jī)器上啟動(dòng)另外一個(gè) frpc,配置如下:
# frpc.ini
[common]
server_addr = x.x.x.x
server_port = 7000
[p2p_ssh_visitor]
type = xtcp
# xtcp 的訪問(wèn)者
role = visitor
# 要訪問(wèn)的 xtcp 代理的名字
server_name = p2p_ssh
sk = abcdefg
# 綁定本地端口用于訪問(wèn) ssh 服務(wù)
bind_addr = 127.0.0.1
bind_port = 6000
- 通過(guò) ssh 訪問(wèn)內(nèi)網(wǎng)機(jī)器,假設(shè)用戶名為 test:
ssh -oPort=6000 [email protected]
Dashboard
通過(guò)瀏覽器查看 frp 的狀態(tài)以及代理統(tǒng)計(jì)信息展示。
注:Dashboard 尚未針對(duì)大量的 proxy 數(shù)據(jù)展示做優(yōu)化,如果出現(xiàn) Dashboard 訪問(wèn)較慢的情況,請(qǐng)不要啟用此功能。
需要在 frps.ini 中指定 dashboard 服務(wù)使用的端口,即可開(kāi)啟此功能:
[common]
dashboard_port = 7500
# dashboard 用戶名密碼,默認(rèn)都為 admin
dashboard_user = admin
dashboard_pwd = admin
打開(kāi)瀏覽器通過(guò) http://[server_addr]:7500 訪問(wèn) dashboard 界面,用戶名密碼默認(rèn)為 admin。
Admin UI
Admin UI 可以幫助用戶通過(guò)瀏覽器來(lái)查詢和管理客戶端的 proxy 狀態(tài)和配置。
需要在 frpc.ini 中指定 admin 服務(wù)使用的端口,即可開(kāi)啟此功能:
[common]
admin_addr = 127.0.0.1
admin_port = 7400
admin_user = admin
admin_pwd = admin
打開(kāi)瀏覽器通過(guò) http://127.0.0.1:7400 訪問(wèn) Admin UI,用戶名密碼默認(rèn)為 admin。
如果想要在外網(wǎng)環(huán)境訪問(wèn) Admin UI,將 7400 端口映射出去即可,但需要重視安全風(fēng)險(xiǎn)。
監(jiān)控
frps 當(dāng)啟用 Dashboard 后,會(huì)默認(rèn)開(kāi)啟內(nèi)部的監(jiān)控,數(shù)據(jù)存放在內(nèi)存中,每次重啟進(jìn)程后會(huì)清空,監(jiān)控?cái)?shù)據(jù)可以通過(guò) dashboard 的地址發(fā)送 HTTP 請(qǐng)求獲取。
目前還支持 Prometheus 作為可選的監(jiān)控系統(tǒng)。
Prometheus
在 frps.ini 中啟用 Dashboard,并且設(shè)置 enable_prometheus = true,則通過(guò) http://{dashboard_addr}/metrics 可以獲取到 Prometheus 的監(jiān)控?cái)?shù)據(jù)。
客戶端身份驗(yàn)證
目前 frpc 和 frps 之間支持兩種身份驗(yàn)證方式,token 和 oidc。
通過(guò) frpc.ini 和 frps.ini 中 [common] section 的 authentication_method 參數(shù)配置需要使用的驗(yàn)證方法。
authenticate_heartbeats = true 將會(huì)在每一個(gè)心跳包中附加上鑒權(quán)信息。
authenticate_new_work_conns = true 將會(huì)在每次建立新的工作連接時(shí)附加上鑒權(quán)信息。
Token
當(dāng) authentication_method = token,將會(huì)啟用基于 token 的驗(yàn)證方式。
需要在 frpc.ini 和 frps.ini 的 [common] section 中設(shè)置相同的 token。
OIDC
當(dāng) authentication_method = oidc,將會(huì)啟用基于 OIDC 的身份驗(yàn)證。
驗(yàn)證流程參考 Client Credentials Grant
啟用這一驗(yàn)證方式,配置 frpc.ini 和 frps.ini 如下:
# frps.ini
[common]
authentication_method = oidc
oidc_issuer = https://example-oidc-issuer.com/
oidc_audience = https://oidc-audience.com/.default
[common]
authentication_method = oidc
oidc_client_id = 98692467-37de-409a-9fac-bb2585826f18 # Replace with OIDC client ID
oidc_client_secret = oidc_secret
oidc_audience = https://oidc-audience.com/.default
oidc_token_endpoint_url = https://example-oidc-endpoint.com/oauth2/v2.0/token
加密與壓縮
這兩個(gè)功能默認(rèn)是不開(kāi)啟的,需要在 frpc.ini 中通過(guò)配置來(lái)為指定的代理啟用加密與壓縮的功能,壓縮算法使用 snAppy:
# frpc.ini
[ssh]
type = tcp
local_port = 22
remote_port = 6000
use_encryption = true
use_compression = true
如果公司內(nèi)網(wǎng)防火墻對(duì)外網(wǎng)訪問(wèn)進(jìn)行了流量識(shí)別與屏蔽,例如禁止了 ssh 協(xié)議等,通過(guò)設(shè)置 use_encryption = true,將 frpc 與 frps 之間的通信內(nèi)容加密傳輸,將會(huì)有效防止流量被攔截。
如果傳輸?shù)膱?bào)文長(zhǎng)度較長(zhǎng),通過(guò)設(shè)置 use_compression = true 對(duì)傳輸內(nèi)容進(jìn)行壓縮,可以有效減小 frpc 與 frps 之間的網(wǎng)絡(luò)流量,加快流量轉(zhuǎn)發(fā)速度,但是會(huì)額外消耗一些 cpu 資源。
TLS
從 v0.25.0 版本開(kāi)始 frpc 和 frps 之間支持通過(guò) TLS 協(xié)議加密傳輸。通過(guò)在 frpc.ini 的 common 中配置 tls_enable = true 來(lái)啟用此功能,安全性更高。
為了端口復(fù)用,frp 建立 TLS 連接的第一個(gè)字節(jié)為 0x17。
通過(guò)將 frps.ini 的 [common] 中 tls_only 設(shè)置為 true,可以強(qiáng)制 frps 只接受 TLS 連接。
注意: 啟用此功能后除 xtcp 外,不需要再設(shè)置 use_encryption。
客戶端熱加載配置文件
當(dāng)修改了 frpc 中的代理配置,可以通過(guò) frpc reload 命令來(lái)動(dòng)態(tài)加載配置文件,通常會(huì)在 10 秒內(nèi)完成代理的更新。
啟用此功能需要在 frpc 中啟用 admin 端口,用于提供 API 服務(wù)。配置如下:
# frpc.ini
[common]
admin_addr = 127.0.0.1
admin_port = 7400
之后執(zhí)行重啟命令:
frpc reload -c ./frpc.ini
等待一段時(shí)間后客戶端會(huì)根據(jù)新的配置文件創(chuàng)建、更新、刪除代理。
需要注意的是,[common] 中的參數(shù)除了 start 外目前無(wú)法被修改。
通過(guò)密碼保護(hù)你的 web 服務(wù)
由于所有客戶端共用一個(gè) frps 的 http 服務(wù)端口,任何知道你的域名和 url 的人都能訪問(wèn)到你部署在內(nèi)網(wǎng)的 web 服務(wù),但是在某些場(chǎng)景下需要確保只有限定的用戶才能訪問(wèn)。
frp 支持通過(guò) HTTP Basic Auth 來(lái)保護(hù)你的 web 服務(wù),使用戶需要通過(guò)用戶名和密碼才能訪問(wèn)到你的服務(wù)。
該功能目前僅限于 http 類型的代理,需要在 frpc 的代理配置中添加用戶名和密碼的設(shè)置。
# frpc.ini
[web]
type = http
local_port = 80
custom_domains = test.yourdomain.com
http_user = abc
http_pwd = abc
通過(guò)瀏覽器訪問(wèn) http://test.yourdomain.com,需要輸入配置的用戶名和密碼才能訪問(wèn)。