使用 frp 实现内网穿透搭建内网服务

在工作和生活中,我们经常需要在外部访问我们家中的主机。然而,由于主机处于内网中,外部设备 (公网) 很难直接连接到主机以获取所需的资料。

本文将介绍一种通过内网穿透软件来搭建内网服务的方法,使得外部用户能够方便地访问和使用内网中的服务和资源。在这个过程中,将会涉及到内网穿透和反向代理的核心技术。

通过调研不同的 内网穿透工具,目前主要分为两种类型:

  • 一种是通过销售硬件设备和流量的方式实现,比如快解析、花生壳、神卓互联、NAT123 等。这些工具拥有自主研发的核心技术,可以在淘宝等平台直接购买和配置。然而,这种方式的缺点是需要付费购买硬件设备,并且免费流量有限制,适合一些专业用户或氪金用户。

  • 一种是使用免费开源软件(如 frp 和 nps)来搭建内网穿透,不需要额外购买硬件设备,但需要具备公网 IP 的条件。这种方式的优点在于可以根据自己的需求进行定制化配置,后续扩展性强, 但对于新手来说入门门槛较高。

考虑到使用开源软件的优点,我的本地主机没有敏感信息,流量不设限制, 所以我选择了免费开源软件 -- frp 来搭建内网穿透服务。请注意,虽然 frp 目前使用广泛,但是本身逻辑设计有先天性缺陷,网络安全性差, 非常容易造成网络堵塞,不能长时间连接使用,技术不够成熟.

我的应用场景

  • 在办公室或外出办公时,能够通过远程 ssh 控制家中的另一台电脑;
  • 家中电脑上运行了一个 web 服务,希望能够让非局域网的用户访问到这个服务。

工具和材料

  • 一个云服务器(包含公网 IP);
  • 本地电脑需要联网;
  • 一个域名(用于多个 web 服务,如果只有 ssh 访问则不需要)。

请注意,以下的教程适合具备一定计算机基础的开发者,对于新手来说可能存在一定的配置难度。

我的网络配置示意图

我进行了如下的网络配置,以实现通过 frp 在远程访问家中的主机和使用 web 服务的目标。比如,在 ipad 上就可以通过网页连接内网服务上的 stable diffusion 生成图片。具体示意图如下:

frp 是什么?

frp 是一个专注于内网穿透的高性能的反向代理应用,支持 TCP、UDP、HTTP、HTTPS 等多种协议,且支持 P2P 通信。可以将内网服务以安全、便捷的方式通过具有公网 IP 节点的中转暴露到公网。

内网穿透是什么?

内网穿透,即 NAT(Network Address Translator)穿透,是指计算机在内网(局域网)内使用私有 IP 地址,在连接外网(互联网)时使用全局 IP 地址的技术。简而言之,内网穿透可以将内网中的服务暴露到公网,使得这些服务可以通过公网访问。

反向代理是什么?

反向代理(reverse proxy)是指以代理服务器来接受 internet 上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给 internet 上请求连接的客户端,此时代理服务器对外就表现为一个反向代理服务器。

frp 安装

你可以参考 安装教程 中的详细步骤来下载、部署和配置 frp。该教程提供了安装和开机自启动的指导,具有很好的实用性。

我的配置环境

frp 服务端:

操作系统:Ubuntu 20.04

frp 客户端设备 #1:

操作系统:Ubuntu 20.04

frp 客户端设备 #2:

操作系统:Ubuntu 22.04

如何设置 frp 支持多个本地网页终端

在我本地的开发机器 #2 ,部署了 stable diffusion 和 Jupyter Notebook 两个 web 应用,它们通过指定的本地端口提供服务,例如通过 127.0.0.1:8080 可以访问 jupyter。由于这些应用都部署在本地,无法直接从公网访问,因此 #2 主机需要配置 frpc 服务来支持公网访问。

多 web 服务主机配置

在 #2 的 frp 的配置文件(frpc.ini)添加下面的内容

[frpc.ini]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

[common]
server_addr = 1.2.3.4 # 替换成公网 IP
server_port = 1234 # 替换成开放的 Port
# 此处省去 token 等配置

[web1] # 此处配置用于远程访问内网电脑上的 A 服务
type = http
local_ip = 127.0.0.1
local_port = port1
custom_domains = a.my_domain.com

[web2] # 此处配置用于远程访问内网电脑上的 B 服务
type = http
local_ip = 127.0.0.1
local_port = port2
custom_domains = b.my_domain.com

在上述配置中,我们使用不同的 custom_domains(例如 a.my_domain.comb.my_domain.com)以及不同的 local_port(例如 88889999)来区分两个本地网页终端。在实际应用中,通过 custom_domains:vhost_http_port 就可以访问内网的 web 项目.

VPS 服务器配置

在 frp 服务器上配置相应的转发规则,将请求转发到本地网页终端。你可以在 frps.ini 配置文件中进行设置。

[frps.ini]
1
2
3
4
5
6
7
8
[common]
bind_port = 1234
token = xxxx
vhost_http_port = 8888
dashboard_port = xxxx
dashboard_user = xxxx
dashboard_pwd = xxxx

通过以上配置,你可以通过 a.my_domain.com:8888 访问第一个本地网页终端,通过 b.my_domain.com:8888 访问第二个本地网页终端。

frp 如何支持多个服务端

如果你想要支持多个服务端,需要在每个客户端安装一个 frpc 服务,并根据每个设备的差异进行配置,确保每个设备的 remote_port 不重复即可。

上文提到,本地有两台主机,如果想让两台主机都可以远程访问, 需要在每个客户端安装一个 frpc 服务.

设备 #1

[frpc.ini]
1
2
3
4
5
6
7
8
9
10
11
12

[common]
server_addr = 1.2.3.4 # 替换成公网 IP
server_port = 1234 # 替换成开放的 Port
# 此处省去 token 等配置

[ssh1] # 若有多个客户端,名称不要重复。
type = tcp
local_ip = 127.0.0.1
local_port = 22
remote_port = 2345 # 远程连接端口不要重复

设备 #2

[frpc.ini]
1
2
3
4
5
6
7
8
9
10
11
12
13
14

[common]
server_addr = 1.2.3.4 # 替换成公网 IP
server_port = 1234 # 替换成开放的 Port
# 此处省去 token 等配置

[ssh2] # 若有多个客户端,名称不要重复。
type = tcp
local_ip = 127.0.0.1
local_port = 22
remote_port = 3456 # 远程连接端口不要重复

# 此处省去 web 等配置

VPS 服务器配置

[frps.ini]
1
2
3
4
5
6
7
8
[common]
bind_port = 1234
token = xxxx
vhost_http_port = 8080
dashboard_port = xxxx
dashboard_user = xxxx
dashboard_pwd = xxxx

根据提供的示例,两台机器都绑定服务器的 1234 端口,但是远程连接的端口不同,第一台机器的远程连接端口为 2345,第二台机器的远程连接端口为 3456。假设 #1 用户名为 test1, #2 用户名为 test2, 那么

[#1 机器连接]
1
ssh  -oPort=2345 test1@1.2.3.4
[#2 机器连接]
1
ssh  -oPort=3456 test2@1.2.3.4

安全性

参考资料