序言
当我们需要将内网服务器暴露到公网上时,一种简单有效的方法是使用内网穿透工具。
使用内网穿透工具时,大多需要我们在公网上拥有一台自己的服务器,因为我们需要在云厂商服务器的管理界面分配一个唯一的域名或 IP 地址,并通过对安装的内网穿透工具进行配置,以把公网和内网绑定起来,最终实现将来自互联网的请求通过自己的服务器转发到内网服务器的目的。
目前市面上的内网穿透工具五花八门,其中比较流行的是 Frp(Fast Reverse Proxy)。
Frp 是一款开源的反向代理软件,它可以帮助你快速搭建内网穿透服务,支持多种协议和加密方式,并且非常易于部署和使用。
在本文中,我们将介绍如何使用 Frp 来实现内网穿透,并通过具体的案例来演示其使用方法。我们将从安装和配置开始,了解 Frp 的核心概念和组件,以及如何使用 Frp 快速搭建内网穿透服务。
简介
frp 是一个专注于内网穿透的高性能的反向代理应用,支持 TCP、UDP、HTTP、HTTPS 等多种协议。可以将内网服务以安全、便捷的方式通过具有公网 IP 节点的中转暴露到公网。
为什么使用 frp?
通过在具有公网 IP 的节点上部署 frp 服务端,可以轻松地将内网服务穿透到公网,同时提供诸多专业的功能特性,这包括:
- 客户端服务端通信支持 TCP、KCP 以及 Websocket 等多种协议。
- 采用 TCP 连接流式复用,在单个连接间承载更多请求,节省连接建立时间。
- 代理组间的负载均衡。
- 端口复用,多个服务通过同一个服务端端口暴露。
- 多个原生支持的客户端插件(静态文件查看,HTTP、SOCK5 代理等),便于独立使用 frp 客户端完成某些工作。
- 高度扩展性的服务端插件系统,方便结合自身需求进行功能扩展。
- 服务端和客户端 UI 页面
安装
关于如何安装 frp 的说明。
frp 采用 Golang 编写,支持跨平台,仅需下载对应平台的二进制文件即可执行,没有额外依赖。
系统需求
由于采用 Golang 编写,所以系统需求和最新的 Golang 对系统和平台的要求一致,具体可以参考 Golang System requirements。
下载
目前可以在 Github 的 Release 页面中下载到最新版本的客户端和服务端二进制文件,所有文件被打包在一个压缩包中。
部署
解压缩下载的压缩包,将其中的 frpc 拷贝到内网服务所在的机器上,将 frps 拷贝到具有公网 IP 的机器上,放置在任意目录。
开始使用!
编写配置文件,先通过 ./frps -c ./frps.ini
启动服务端,再通过 ./frpc -c ./frpc.ini
启动客户端。如果需要在后台长期运行,建议结合其他工具使用,例如 systemd 和 supervisor
。
如果是 Windows 用户,需要在 cmd 终端中执行命令。
概念
一些概念,理解它们有助于您更好地了解和使用 frp。
原理
frp 主要由 客户端(frpc) 和 服务端(frps) 组成,服务端通常部署在具有公网 IP 的机器上,客户端通常部署在需要穿透的内网服务所在的机器上。
内网服务由于没有公网 IP,不能被非局域网内的其他用户访问。
用户通过访问服务端的 frps,由 frp 负责根据请求的端口或其他信息将请求路由到对应的内网机器,从而实现通信。
代理
在 frp 中一个代理对应一个需要暴露的内网服务。一个客户端支持同时配置多个代理。
代理类型
frp 支持多种代理类型来适配不同的使用场景:
类型 | 描述 |
---|---|
tcp | 单纯的 TCP 端口映射,服务端会根据不同的端口路由到不同的内网服务 |
udp | 单纯的 UDP 端口映射,服务端会根据不同的端口路由到不同的内网服务 |
http | 针对 HTTP 应用定制了一些额外的功能,例如修改 Host Header,增加鉴权 |
https | 针对 HTTPS 应用定制了一些额外的功能 |
stcp | 安全的 TCP 内网代理,需要在被访问者和访问者的机器上都部署 frpc,不需要在服务端暴露端口 |
sudp | 安全的 UDP 内网代理,需要在被访问者和访问者的机器上都部署 frpc,不需要在服务端暴露端口 |
xtcp | 点对点内网穿透代理,功能同 stcp,但是流量不需要经过服务器中转 |
tcpmux | 支持服务端 TCP 端口的多路复用,通过同一个端口访问不同的内网服务 |
快速入门
这里包括多个常见的使用场景和配置示例,你可以用来亲自部署和体验这些示例。
- 通过 SSH 访问内网机器
- 自定义域名访问内网 Web 服务
- 转发 DNS 查询请求
- 转发 Unix 域套接字
- 对外提供简单的文件访问服务
- 为本地 HTTP 服务启用 HTTPS
- 安全地暴露内网服务
- 点对点内网穿透
SSH 访问内网机器
这个示例通过简单配置 TCP 类型的代理让用户访问到内网的服务器。
① 在具有公网 IP 的机器上部署 frps,修改frps.ini
文件,这里使用了最简化的配置,设置了 frp 服务器用户接收客户端连接的端口:
1 | [common] |
② 在需要被访问的内网机器上(SSH 服务通常监听在 22 端口)部署 frpc,修改frpc.ini
文件,假设 frps 所在服务器的公网 IP 为 42.192.83.41:
1 | [common] |
其中:
local_ip
:本地需要暴露到公网的服务地址local_port
:本地需要暴露到公网和端口remote_port
:在 frp 服务端监听的端口,访问此端口的流量将会被转发到本地服务对应的端口
③ 分别启动 frps 和 frpc。1
2
3
4# 启动服务端
./frps -c ./frps.ini
# 启动客户端
./frpc -c ./frpc.ini
④ 通过 SSH 访问内网机器,假设用户名为 test:1
ssh -oPort=6000 test@42.192.83.41
frp 会将请求 42.192.83.41:6000
的流量转发到内网机器的 22 端口。
自定义域名访问内网 Web 服务
这个示例通过简单配置 HTTP 类型的代理让用户访问到内网的 Web 服务。
HTTP 类型的代理相比于 TCP 类型,不仅在服务端只需要监听一个额外的端口 vhost_http_port
用于接收 HTTP 请求,还额外提供了基于 HTTP 协议的诸多功能。
① 修改frps.ini
文件,设置监听 HTTP 请求端口为 7080:
1 | [common] |
② 修改frpc.ini
文件,假设 frps 所在的服务器的 IP 为 42.192.83.41,local_port
为本地机器上 Web 服务监听的端口, 绑定自定义域名为 custom_domains
。
1 | [common] |
③ 分别启动 frps 和 frpc。1
2
3
4# 启动服务端
./frps -c ./frps.ini
# 启动客户端
./frpc -c ./frpc.ini
④ 将 www.yourdomain.com
和 www.yourdomain2.com
的域名 A 记录解析到 IP 42.192.83.41
,如果服务器已经有对应的域名,也可以将 CNAME 记录解析到服务器原先的域名。或者可以通过修改 HTTP 请求的 Host 字段来实现同样的效果。
⑤ 通过浏览器访问 http://www.yourdomain.com:7080
即可访问到处于内网机器上 80 端口的服务,访问 http://www.yourdomain2.com:7080
则访问到内网机器上 8080 端口的服务。
扩展
如果访问时不想在域名额外加 7080 端口访问,可以通过 Nginx 配置再转发一次,这样就可以直接通过域名访问:1
2
3
4
5
6
7
8
9server {
listen 80;
server_name www.yourdomain.com;
location / {
proxy_pass http://www.yourdomain.com:7080;
}
}
转发 DNS 查询请求
这个示例通过简单配置 UDP 类型的代理转发 DNS 查询请求。
DNS 查询请求通常使用 UDP 协议,frp 支持对内网 UDP 服务的穿透,配置方式和 TCP 基本一致。
① frps.ini
内容如下:
1 | [common] |
② frpc.ini 内容如下:
1 | [common] |
这里反代了 Google 的 DNS 查询服务器的地址,仅仅用于测试 UDP 代理,并无实际意义。
③ 分别启动 frps 和 frpc。1
2
3
4# 启动服务端
./frps -c ./frps.ini
# 启动客户端
./frpc -c ./frpc.ini
④ 通过 dig (挖) 测试 UDP 包转发是否成功,预期会返回 www.baidu.com
域名的解析结果。
dig @42.192.83.41 -p 6000 www.baidu.com
转发 Unix 域套接字
这个示例通过配置 Unix域套接字客户端插件来通过 TCP 端口访问内网的 Unix域套接字服务,例如 Docker Daemon。
① frps.ini
内容如下:
1 | [common] |
② frpc.ini 内容如下:
1 | [common] |
③ 分别启动 frps 和 frpc。1
2
3
4# 启动服务端
./frps -c ./frps.ini
# 启动客户端
./frpc -c ./frpc.ini
④ 通过 curl 命令查看 docker 版本信息
curl http://42.192.83.41:6000/version
对外提供简单的文件访问服务
这个示例通过配置 static_file
客户端插件来将本地文件暴露在公网上供其他人访问。
通过 static_file
插件可以对外提供一个简单的基于 HTTP 的文件访问服务。
① frps.ini
内容如下:
1 | [common] |
② frpc.ini 内容如下:
1 | [common] |
③ 分别启动 frps 和 frpc。1
2
3
4# 启动服务端
./frps -c ./frps.ini
# 启动客户端
./frpc -c ./frpc.ini
④ 通过浏览器访问 http://42.192.83.41:6000/static/
来查看位于 /tmp/file
目录下的文件,会要求输入已设置好的用户名和密码。
为本地 HTTP 服务启用 HTTPS
通过 https2http
插件可以让本地 HTTP 服务转换成 HTTPS 服务对外提供。
① frps.ini
内容如下:
1 | [common] |
② frpc.ini
内容如下:
1 | [common] |
③ 分别启动 frps 和 frpc。1
2
3
4# 启动服务端
./frps -c ./frps.ini
# 启动客户端
./frpc -c ./frpc.ini
④ 通过浏览器访问 https://test.yourdomain.com
。
安全地暴露内网服务
这个示例将会创建一个只有自己能访问到的 SSH 服务代理。
对于某些服务来说如果直接暴露于公网上将会存在安全隐患。
使用 stcp(secret tcp)
类型的代理可以避免让任何人都能访问到要穿透的服务,但是访问者也需要运行另外一个 frpc 客户端。
①frps.ini
内容如下:
1 | [common] |
② 在需要暴露到外网的机器上部署 frpc,且配置如下:
1 | [common] |
③ 在想要访问内网服务的机器上也部署 frpc,且配置如下:
1 | [common] |
④ 通过 SSH 访问内网机器,假设用户名为 test:
ssh -oPort=6000 test@127.0.0.1
点对点内网穿透
这个示例将会演示一种不通过服务器中转流量的方式来访问内网服务。
frp 提供了一种新的代理类型 xtcp
用于应对在希望传输大量数据且流量不经过服务器的场景。
使用方式同 stcp
类似,需要在两边都部署上 frpc 用于建立直接的连接。
目前处于开发的初级阶段,并不能穿透所有类型的 NAT 设备,所以穿透成功率较低。穿透失败时可以尝试 stcp
的方式。
①frps.ini
内容如下,需要额外配置监听一个 UDP 端口用于支持该类型的客户端:
1 | [common] |
② 在需要暴露到外网的机器上部署 frpc,且配置如下:
1 | [common] |
③ 在想要访问内网服务的机器上也部署 frpc,且配置如下:
1 | [common] |
④ 通过 SSH 访问内网机器,假设用户名为 test:1
ssh -oPort=6000 test@127.0.0.1
功能特性
通用功能
身份认证
目前 frpc 和 frps 之间支持两种身份验证方式,token 和 oidc,默认为 token。
通过 frpc.ini 和 frps.ini 的 [common] 段落中配置 authentication_method 来指定要使用的身份验证方式。
只有通过身份验证的客户端(frpc)才能成功连接 frps。
Token
基于 Token 的身份验证方式比较简单,需要在 frpc 和 frps 的 [common]
段落中配置上相同的 token 参数即可。
frps 服务端配置
1 | [common] |
frpc 客户端配置
1 | [common] |
参考
文章信息
时间 | 说明 |
---|---|
2023-02-25 | 初稿 |