frp內(nèi)網(wǎng)穿透工具
內(nèi)網(wǎng)穿透,也即 NAT 穿透,進(jìn)行 NAT 穿透是為了使具有某一個特定源 IP 地址和源端口號的數(shù)據(jù)包不被 NAT 設(shè)備屏蔽而正確路由到內(nèi)網(wǎng)主機(jī)。下面就相互通信的主機(jī)在網(wǎng)絡(luò)中與 NAT 設(shè)備的相對位置介紹內(nèi)網(wǎng)穿透方法。目前較為成熟穩(wěn)定的是花生殼和神卓互聯(lián),花生殼的技術(shù)是PHtunnel,神卓互聯(lián)使用的是WanGooe tunnel,和nginx架構(gòu)一樣都是采用C語言編寫,性能上是比較優(yōu)異的,適合很多嵌入式的設(shè)備搭載使用,而frp采用的是Go語言。
UDP 內(nèi)網(wǎng)穿透的實質(zhì)是利用路由器上的NAT 系統(tǒng)。NAT 是一種將私有(保留)地址轉(zhuǎn)化為合法IP地址的轉(zhuǎn)換技術(shù),它被廣泛應(yīng)用于各種類型 Internet 接入方式和各種類型的網(wǎng)絡(luò)中。NAT可以完成重用地址,并且對于內(nèi)部的網(wǎng)絡(luò)結(jié)構(gòu)可以實現(xiàn)對外隱蔽。
網(wǎng)絡(luò)地址轉(zhuǎn)換(Network Address Translation,NAT)機(jī)制的問題在于,NAT設(shè)備自動屏蔽了非內(nèi)網(wǎng)主機(jī)主動發(fā)起的連接,也就是說,從外網(wǎng)發(fā)往內(nèi)網(wǎng)的數(shù)據(jù)包將被NAT設(shè)備丟棄,這使得位于不同NAT設(shè)備之后的主機(jī)之間無法直接交換信息。這一方面保護(hù)了內(nèi)網(wǎng)主機(jī)免于來自外部網(wǎng)絡(luò)的攻擊,另一方面也為P2P通信帶來了一定困難。Internet上的NAT設(shè)備大多是地址限制圓錐形NAT或端口限制圓錐形 NAT,外部主機(jī)要與內(nèi)網(wǎng)主機(jī)相互通信,必須由內(nèi)網(wǎng)主機(jī)主動發(fā)起連接,使 NAT設(shè)備產(chǎn)生一個映射條目,這就有必要研究一下內(nèi)網(wǎng)穿透技術(shù)。
使用示例
根據(jù)對應(yīng)的操作系統(tǒng)及架構(gòu),從 Release 頁面下載最新版本的程序。
將 frps 及 frps.ini 放到具有公網(wǎng) IP 的機(jī)器上。
將 frpc 及 frpc.ini 放到處于內(nèi)網(wǎng)環(huán)境的機(jī)器上。
通過訪問公司內(nèi)網(wǎng)機(jī)器
- 修改 frps.ini 文件,這里使用了最簡化的配置:
# frps.ini
[common]
bind_port = 1000
- 啟動 frps:
./frps -c ./frps.ini
- 修改 frpc.ini 文件,假設(shè) frps 所在服務(wù)器的公網(wǎng) IP 為 x.x.x.x;
# frps.ini
[common]
server_addr = x.x.x.x
server_port = 1000
[ssh]
type = tcp
local_ip = 127.0.0.1
local_port = 22
remote_port = 6000
- 啟動 frpc:
./frpc -c ./frpc.ini
- 通過 ssh 訪問內(nèi)網(wǎng)機(jī)器,假設(shè)用戶名為 test:
ssh -oPort=6000 [email protected]
# frps.ini
[common]
bind_port = 1000
vhost_http_port = 8080
- 啟動 frps;
./frps -c ./frps.ini
- 修改 frpc.ini 文件,假設(shè) frps 所在的服務(wù)器的 IP 為 x.x.x.x,local_port 為本地機(jī)器上 web 服務(wù)對應(yīng)的端口, 綁定自定義域名
www.yourdomain.com:
# frpc.ini
[common]
server_addr = x.x.x.x
server_port = 1000
[web]
type = http
local_port = 80
custom_domains = www.yourdomain.com
- 啟動 frpc:
./frpc -c ./frpc.ini
-
將
www.yourdomain.com的域名 A 記錄解析到 IPx.x.x.x,如果服務(wù)器已經(jīng)有對應(yīng)的域名,也可以將 CNAME 記錄解析到服務(wù)器原先的域名。 -
通過瀏覽器訪問
http://www.yourdomain.com:8080即可訪問到處于內(nèi)網(wǎng)機(jī)器上的 web 服務(wù)。
# frps.ini
[common]
server_addr = x.x.x.x
server_port = 7000
[test_static_file]
type = tcp
remote_port = 6000
plugin = static_file
# 要對外暴露的文件目錄
plugin_local_path = /tmp/file
# 訪問 url 中會被去除的前綴,保留的內(nèi)容即為要訪問的文件路徑
plugin_strip_prefix = static
plugin_http_user = abc
plugin_http_passwd = abc
- 通過瀏覽器訪問
http://x.x.x.x:6000/static/來查看位于/tmp/file目錄下的文件,會要求輸入已設(shè)置好的用戶名和密碼。
為本地 HTTP 服務(wù)啟用 HTTPS
通過 https2http 插件可以讓本地 HTTP 服務(wù)轉(zhuǎn)換成 HTTPS 服務(wù)對外提供。
# frps.ini
[common]
server_addr = x.x.x.x
server_port = 6000
[test_htts2http]
type = https
custom_domains = test.yourdomain.com
plugin = https2http
plugin_local_addr = 127.0.0.1:80
# HTTPS 證書相關(guān)的配置
plugin_crt_path = ./server.crt
plugin_key_path = ./server.key
plugin_host_header_rewrite = 127.0.0.1
- 通過瀏覽器訪問
https://test.yourdomain.com即可。
# frps.ini
[common]
server_addr = x.x.x.x
server_port = 6000
[secret_ssh]
type = stcp
# 只有 sk 一致的用戶才能訪問到此服務(wù)
sk = abcdefg
local_ip = 127.0.0.1
local_port = 22
- 在要訪問這個服務(wù)的機(jī)器上啟動另外一個 frpc,配置如下:
# frps.ini
[common]
server_addr = x.x.x.x
server_port = 6000
[secret_ssh_visitor]
type = stcp
# stcp 的訪問者
role = visitor
# 要訪問的 stcp 代理的名字
server_name = secret_ssh
sk = abcdefg
# 綁定本地端口用于訪問 ssh 服務(wù)
bind_addr = 127.0.0.1
bind_port = 6000
- 通過 ssh 訪問內(nèi)網(wǎng)機(jī)器,假設(shè)用戶名為 test:
ssh -oPort=6000 [email protected]
網(wǎng)絡(luò)安全的屏障
強(qiáng)化網(wǎng)絡(luò)安全策略
# frps.ini
[common]
server_addr = x.x.x.x
server_port = 6000
[secret_ssh_visitor]
type = stcp
# stcp 的訪問者
role = visitor
# 要訪問的 stcp 代理的名字
server_name = secret_ssh
sk = abcdefg
# 綁定本地端口用于訪問 ssh 服務(wù)
bind_addr = 127.0.0.1
bind_port = 6000
監(jiān)控審計
防止內(nèi)部信息的外泄
點對點內(nèi)網(wǎng)穿透
frp 提供了一種新的代理類型 xtcp 用于應(yīng)對在希望傳輸大量數(shù)據(jù)且流量不經(jīng)過服務(wù)器的場景。
使用方式同 stcp 類似,需要在兩邊都部署上 frpc 用于建立直接的連接。
目前處于開發(fā)的初級階段,并不能穿透所有類型的 NAT 設(shè)備,所以穿透成功率較低。穿透失敗時可以嘗試 stcp 的方式。
- frps 除正常配置外需要額外配置一個 udp 端口用于支持該類型的客戶端:
bind_udp_port = 7001
- 啟動 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ù)
sk = abcdefg
local_ip = 127.0.0.1
local_port = 22
- 在要訪問這個服務(wù)的機(jī)器上啟動另外一個 frpc,配置如下:
# frpc.ini
[common]
server_addr = x.x.x.x
server_port = 7000
[p2p_ssh_visitor]
type = xtcp
# xtcp 的訪問者
role = visitor
# 要訪問的 xtcp 代理的名字
server_name = p2p_ssh
sk = abcdefg
# 綁定本地端口用于訪問 ssh 服務(wù)
bind_addr = 127.0.0.1
bind_port = 6000
- 通過 ssh 訪問內(nèi)網(wǎng)機(jī)器,假設(shè)用戶名為 test:
ssh -oPort=6000 [email protected]
功能說明
配置文件
由于 frp 目前支持的功能和配置項較多,未在文檔中列出的功能可以從完整的示例配置文件中發(fā)現(xiàn)。
frps 完整配置文件
frpc 完整配置文件
export FRP_SERVER_ADDR="x.x.x.x"
export FRP_SSH_REMOTE_PORT="6000"
./frpc -c ./frpc.ini
frpc 會自動使用環(huán)境變量渲染配置文件模版,所有環(huán)境變量需要以 .Envs 為前綴。
數(shù)據(jù)必經(jīng)之地
網(wǎng)絡(luò)流量的合法性
抗攻擊免疫力
frp 支持根據(jù)請求的 URL 路徑路由轉(zhuǎn)發(fā)到不同的后端服務(wù)。
通過配置文件中的 locations 字段指定一個或多個 proxy 能夠匹配的 URL 前綴(目前僅支持最大前綴匹配,之后會考慮正則匹配)。例如指定 locations = /news,則所有 URL 以 /news 開頭的請求都會被轉(zhuǎn)發(fā)到這個服務(wù)。
# frpc.ini
[web01]
type = http
local_port = 80
custom_domains = web.yourdomain.com
locations = /
[web02]
type = http
local_port = 81
custom_domains = web.yourdomain.com
locations = /news,/about
按照上述的示例配置后,web.yourdomain.com 這個域名下所有以 /news 以及 /about 作為前綴的 URL 請求都會被轉(zhuǎn)發(fā)到 web02,其余的請求會被轉(zhuǎn)發(fā)到 web01。
通過代理連接 frp
在只能通過代理訪問外網(wǎng)的環(huán)境內(nèi),frpc 支持通過 HTTP PROXY 和 frps 進(jìn)行通信。
可以通過設(shè)置 HTTP_PROXY 系統(tǒng)環(huán)境變量或者通過在 frpc 的配置文件中設(shè)置 http_proxy 參數(shù)來使用此功能。
僅在 protocol = tcp 時生效。
# frpc.ini
[common]
server_addr = x.x.x.x
server_port = 7000
http_proxy = http://user:[email protected]:8080
端口映射
在 frpc 的配置文件中可以指定映射多個端口,目前只支持 tcp 和 udp 的類型。
這一功能通過 range: 段落標(biāo)記來實現(xiàn),客戶端會解析這個標(biāo)記中的配置,將其拆分成多個 proxy,每一個 proxy 以數(shù)字為后綴命名。
例如要映射本地 6000-6005, 6007 這6個端口,主要配置如下:
# frpc.ini
[range:test_tcp]
type = tcp
local_ip = 127.0.0.1
local_port = 6000-6006,6007
remote_port = 6000-6006,6007
實際連接成功后會創(chuàng)建 8 個 proxy,命名為 test_tcp_0, test_tcp_1 ... test_tcp_7。
插件
默認(rèn)情況下,frpc 只會轉(zhuǎn)發(fā)請求到本地 tcp 或 udp 端口。
插件模式是為了在客戶端提供更加豐富的功能,目前內(nèi)置的插件有 unix_domain_socket、http_proxy、socks5、static_file。具體使用方式請查看使用示例。
通過 plugin 指定需要使用的插件,插件的配置參數(shù)都以 plugin_ 開頭。使用插件后 local_ip 和 local_port 不再需要配置。
