文章

如何用frp实现内网穿透

写在前面

众所周知的原因,运营商一般不会为每个接入用户单独分配IPv4公网地址。而大多数本地服务都有公网访问的需求,像是RDP、个人流媒体服务、家庭网盘。

我所在学校网络拓扑大致如下,AP隔离的情况使得校园局域网内设备之间无法直接访问,通过内网穿透能基本解决这一痛点。

拓扑图

frp 是什么?

frp 是一款高性能的反向代理应用,专注于内网穿透。它支持多种协议,包括 TCP、UDP、HTTP、HTTPS 等,并且具备 P2P 通信功能。使用 frp,您可以安全、便捷地将内网服务暴露到公网,通过拥有公网 IP 的节点进行中转。

架构

frp架构如下,只需在用户端和服务端分别配置frp。

为什么选择 frp?

通过在具有公网 IP 的节点上部署 frp 服务端,您可以轻松地将内网服务穿透到公网,并享受以下专业特性:

  • 多种协议支持:客户端服务端通信支持 TCP、QUIC、KCP 和 Websocket 等多种协议。

  • TCP 连接流式复用:在单个连接上承载多个请求,减少连接建立时间,降低请求延迟。

  • 代理组间的负载均衡。

  • 端口复用:多个服务可以通过同一个服务端端口暴露。

  • P2P 通信:流量不必经过服务器中转,充分利用带宽资源。

  • 客户端插件:提供多个原生支持的客户端插件,如静态文件查看、HTTPS/HTTP 协议转换、HTTP、SOCKS5 代理等,以便满足各种需求。

  • 服务端插件系统:高度可扩展的服务端插件系统,便于根据自身需求进行功能扩展。

  • 用户友好的 UI 页面:提供服务端和客户端的用户界面,使配置和监控变得更加方便。

二、配置要求

  • 一台带公网的服务器(或者是frp服务提供商)

  • 需要内网穿透的设备

三、服务端frps配置

frp分为服务端和客户端部分。本部分先讲如何配置frps(即frp的服务端部分)

如果使用frp服务商则可以略过这一步。

以下示例均为个人使用实际需求,并未涵盖全部场景。

确保云服务器安全组中开放了对应端口

Linux服务实现

以Ubuntu系统(Debian系)为例。

从github上根据自己的系统和架构选择合适的文件下载

下载地址:https://github.com/fatedier/frp/releases

新建配置文件

新建一个文件夹用来存放配置文件

mkdir frps

用vim新建一个文件frps.toml用来存放配置

vim frps.toml

键入入下列配置

# frps.toml
bindPort = 7000	# 此处填写你监听的端口

保存配置

启动frps

启动frps用frps.toml作为配置文件

./frps -c ./frps.toml

可以看到输出日志为

2024-06-01 22:45:51.214 [I] [frps/root.go:105] frps uses config file: frps.toml
2024-06-01 22:45:51.331 [I] [server/service.go:237] frps tcp listen on 0.0.0.0:7000
2024-06-01 22:45:51.331 [I] [frps/root.go:114] frps started successfully

表示启动成功,frps使用frps.toml作为配置文件并监听7000端口

将frps作为服务启动

将frps作为服务启动,使得其在后台仍能继续执行并随系统启动。

1.创建Unit配置文件
vim /usr/lib/systemd/system/frps.service

编写配置文件

[Unit]
# 服务名称,可自定义
Description= frps
After = network.target syslog.target
Wants = network.target
[Service]
# 启动frps的命令,需修改为您的frps的安装路径
ExecStart=/opt/frps/frps.sh
Type=simple
[Install]
WantedBy=multi-user.target
Alias=frp
2.创建并编写sh脚本文件
vim /opt/frps/frps.sh
#!/bin/sh

/opt/frps/frps -c /opt/frps/frps.toml
3.服务配置

设置服务开机启动

systemctl enable frps

启动服务

systemctl start frps

查看服务状态

systemctl status frps

日志如下

 frps.service - frps
     Loaded: loaded (/lib/systemd/system/frps.service; enabled; vendor preset: enabled)
     Active: active (running) since Sat 2024-06-01 23:16:07 CST; 4s ago
   Main PID: 19697 (frps.sh)
      Tasks: 7 (limit: 1989)
     Memory: 8.2M
        CPU: 401ms
     CGroup: /system.slice/frps.service
             ├─19697 /bin/sh /opt/frps/frps.sh
             └─19698 /opt/frps/frps -c /opt/frps/frps.toml

Jun 01 23:16:07 hcss-ecs-f19a systemd[1]: Started frps.
Jun 01 23:16:07 hcss-ecs-f19a frps.sh[19698]: 2024-06-01 23:16:07.889 [I] [frps/root.go:105] frps uses config file: /opt/frps/frps.toml
Jun 01 23:16:08 hcss-ecs-f19a frps.sh[19698]: 2024-06-01 23:16:08.280 [I] [server/service.go:237] frps tcp listen on 0.0.0.0:7000
Jun 01 23:16:08 hcss-ecs-f19a frps.sh[19698]: 2024-06-01 23:16:08.281 [I] [frps/root.go:114] frps started successfully

服务正常启动且配置完成

通过docker实现

前提

确保服务器环境安装有docker

liunx终端中输入

docker

若出现

Usage:  docker [OPTIONS] COMMAND

A self-sufficient runtime for containers

Common Commands:
  run         Create and run a new container from an image
  exec        Execute a command in a running container
  ps          List containers
  build       Build an image from a Dockerfile
  pull        Download an image from a registry
  push        Upload an image to a registry
  images      List images
  login       Log in to a registry
  logout      Log out from a registry
  search      Search Docker Hub for images
  version     Show the Docker version information
  info        Display system-wide information

Management Commands:
  builder     Manage builds

...

则表明docker环境正常

拉取docker镜像

这里选择snowdreamtech/frps

docker pull snowdreamtech/frps

启动容器

docker run --restart=always --network host -d -v /opt/frps/frps.toml:/etc/frp/frps.toml --name frps snowdreamtech/frps

启动容器前确保创建好了frp配置文件

查看容器日志

docker logs frps

输出log

2024-06-01 15:36:19.334 [I] [frps/root.go:105] frps uses config file: /etc/frp/frps.toml
2024-06-01 15:36:19.472 [I] [server/service.go:237] frps tcp listen on 0.0.0.0:7000
2024-06-01 15:36:19.472 [I] [frps/root.go:114] frps started successfully

表明容器创建成功

1Panel面板创建frp 服务端

1Panel只是一个Linux服务器面板,本质还是通过docker创建frps,故若通过docker创建frps 亦可在面板容器菜单找到并管理frp。下面使用gui面板创建frps.

在应用商场里检索frp并安装frp 服务端

打开frp管理面板

管理面板默认端口为7500,在浏览器中键入http://serverIP:5700进入管理面板

用户名和密码在参数中查看

管理面板

四、客户端配置

配置文件规则

serverAddr = "x.x.x.x" # 暴露在公网的服务器地址
serverPort = 7000	# 公网服务监听端口与服务端保持一致

[[proxies]]
name = "ssh"	# 隧道名称
type = "tcp"	# 穿透类型
localIP = "127.0.0.1"	# 本地地址
localPort = 22	# 本地端口
remotePort = 6000	# 远程端口

[[proxies]]
name = "web2"
type = "http"
localPort = 8080
customDomains = ["www.yourdomain2.com"] # 自定义端口名

[[proxies]]
name = "test_htts2http"
type = "https"
customDomains = ["test.yourdomain.com"]

[proxies.plugin] # 插件
type = "https2http" 
localAddr = "127.0.0.1:80"

# HTTPS 证书相关的配置
crtPath = "./server.crt"
keyPath = "./server.key"
hostHeaderRewrite = "127.0.0.1"
requestHeaders.set.x-from-where = "frp"

一个文件可以配置多个代理

Linux服务部署

此处以Debian为例

下载对应服务端

配置frpc文件

以https连接为例

serverAddr = "xxx.xxx.xxx.xxx" # 服务器地址
serverPort = 7000				
user = "填写从服务提供商获取的密钥" # 用户密钥

[auth]
method = "token"
token = "OpenFrpToken"

[transport]
protocol = "tcp"

[transport.tls]
enable = true
disableCustomTLSFirstByte = false

[[proxies]]
name = "alist"
type = "https"
localIP = "127.0.0.1"
localPort = 5244
customDomains = ["www.yourdomain.com"]

[proxies.plugin]
type = "https2http"
localAddr = "127.0.0.1"

# HTTPS 证书相关的配置
crtPath = "/opt/frpc/server.crt" 
keyPath = "/opt/frpc/server.key"
hostHeaderRewrite = "127.0.0.1"
requestHeaders.set.x-from-where = "frp"

保存为frpc.toml文件

新建服务文件

[Unit]
# 服务名称,可自定义
Description = frp client
After = network.target syslog.target
Wants = network.target

[Service]
Type = simple
# 启动frpc的命令,需修改为您的frpc的安装路径
ExecStart = /path/to/frpc -c /path/to/frpc.toml

[Install]
WantedBy = multi-user.target

保存到/usr/lib/systemd/system/路径下

开机自启动

systemctl enable frpc

使用docker安装

拉取镜像snowdreamtech/frpc

docker pull snowdreamtech/frpc

启动容器

docker run --restart=always --network host -d -v /opt/frpc/frpc.toml:/etc/frp/frpc.toml -v /opt/frpc/server.crt:/etc/frpc/server.crt -v /opt/frpc/server.key:/etc/frpc/server.key --name frpc snowdreamtech/frpc


五、最后

frp官方完整文档:https://github.com/fatedier/frp

frp docker文档:https://hub.docker.com/r/snowdreamtech/frpc

https://hub.docker.com/r/snowdreamtech/frps

License:  CC BY 4.0