基于frp实现内网穿透
一、前言
最近在家里的NAS服务器上部署了一些应用(比如PhotoPrism照片管理、Joplin个人笔记),但是没有公网ip,所以在外面是无法访问这些服务的。这个时候,就需要一些工具将内网的服务暴露在公网上。由于自己已经有一台腾讯云服务器,所以就直接使用开源工具FRP实现内网穿透。
FRP是一款高性能的反向代理应用,专注于内网穿透。它支持多种协议,包括 TCP、UDP、HTTP、HTTPS 等,并且具备 P2P 通信功能。其部署非常简单,安装部署只需要一个执行文件加对应的配置文件。
二、安装
官方中文部署文档:https://gofrp.org/zh-cn/docs/setup/
(一)下载
直接github的releases页面下载release包,解压出客户端frpc和服务器frps文件。https://github.com/fatedier/frp/releases
(二)部署
(1) 解压下载的压缩包。
(2) 将 frpc 复制到内网服务所在的机器上。
(3) 将 frps 复制到拥有公网 IP 地址的机器上。
(三)使用
编写配置文件,然后在服务端和客户端分别启动frp,就可以使用对应的服务;如果需要后台长期运行,可以使用systemd或者其他工具实现。
使用以下命令启动服务器:./frps -c ./frps.toml
。
使用以下命令启动客户端:./frpc -c ./frpc.toml
。
官方介绍:
(1) 编写配置文件,目前支持的文件格式包括 TOML/YAML/JSON,旧的 INI 格式仍然支持,但已经不再推荐。
(2) 使用以下命令启动服务器:./frps -c ./frps.toml。
(3) 使用以下命令启动客户端:./frpc -c ./frpc.toml。
(4) 如果需要在后台长期运行,建议结合其他工具,如 systemd 和 supervisor。
(四)配置文件
从v0.52.0版本开始,配置文件已不推荐使用INI格式,可以使用TOML/YAML/JSON。官方推荐使用TOML格式。
TMOL介绍:
TMOL
A config file format for humans.
TOML aims to be a minimal configuration file format that's easy to read due to obvious semantics. TOML is designed to map unambiguously to a hash table. TOML should be easy to parse into data structures in a wide variety of languages.
一般用户较为常用的为SSH和WEB服务,所以先只介绍这两种配置。
1. SSH
# frps.toml
bindPort = 7000
# frpc.toml
serverAddr = "x.x.x.x"
serverPort = 7000
[[proxies]]
name = "ssh"
type = "tcp"
localIP = "127.0.0.1"
localPort = 22
remotePort = 6000
配置文件中,需要对以下配置项进行修改:
- serverAddr:服务端的公网IP
- localIP和localPort:内网服务的IP地址和端口。
- remotePort:服务端监听的端口,访问服务端此端口的流量将被转发到本地服务的相应端口。
启动 frps 和 frpc后,就可以通过6000端口访问内网机器,假设用户名为 test:
ssh -o Port=6000 test@x.x.x.x
2. WEB服务
WEB服务有IP访问和域名访问两种方式。如果是IP访问,其配置其实和SSH的完全相同(SSH也是基于TCP协议);如果是域名访问,当前我的服务端已经部署了nginx,在nginx层就可以将域名转发到对应的端口,所以不需要在FRP中设置域名访问了,如果有需要可以参考官方文档配置。
(1)使用IP方式访问
# frps.toml
bindPort = 7000
# frpc.toml
serverAddr = "x.x.x.x"
serverPort = 7000
[[proxies]]
name = "web"
type = "tcp"
localIP = "127.0.0.1"
localPort = 8080
remotePort = 8080
启动 frps 和 frpc后,使用浏览器访问 x.x.x.x:8080 即可访问内网机器上的 80 端口服务。
(2)使用域名方式
https://gofrp.org/zh-cn/docs/examples/vhost-http/
3. 配置拆分
当配置较多时,例如有很多个服务,可以将配置拆分为多个文件,在主配置文件中通过includes方式包含其他配置文件。
需要注意的是 includes 指定的文件中只能包含代理配置,通用参数的配置只能放在主配置文件中。通用配置可以参考官方文档:https://gofrp.org/zh-cn/docs/features/common/。
includes = ["./confd/*.toml"]
(五)设置后台运行
如果需要设置后台运行、开启启动等功能,需要配合systemd实现。
使用文本编辑器 (如 vim) 在 /etc/systemd/system 目录下创建一个 frps.service 文件,用于配置 frps 服务。
sudo vim /etc/systemd/system/frps.service
写入内容
[Unit]
# 服务名称,可自定义
Description = frp server
After = network.target syslog.target
Wants = network.target
[Service]
Type = simple
# 启动frps的命令,需修改为您的frps的安装路径
ExecStart = /path/to/frps -c /path/to/frps.toml
[Install]
WantedBy = multi-user.target
启动服务
sudo systemctl daemon-reload
sudo systemctl start frps
设置开机自启动
sudo systemctl enable frps
查询服务状态
sudo systemctl status frps
(六)安全配置
1. 身份认证
目前 frpc 和 frps 之间支持两种身份验证方式,token 和 oidc,默认为 token。这些认证方式允许您验证客户端与服务端之间的通信,并确保只有授权用户能够建立连接。oidc方式设置较为复杂,故使用token方式。
Token 身份认证是一种简单的身份认证方式,只需要在 frp 的客户端 frpc 和服务端 frps 配置文件中配置相同的 token 即可。
配置示例
# frps.toml
bindPort = 7000
auth.token = "abc"
# frpc.toml
auth.token = "abc"
2.自定义的TLS协议加密
除了可以通过设置transport.useEncryption = true
,也可以配置自定义证书来加密通信。
注意:以下生成证书方法仅为流程展示,如果需要生产有效的证书,需要对配置进行一定的修改。
1、使用OpenSSL生成证书
生成默认ca:
openssl genrsa -out ca.key 2048
openssl req -x509 -new -nodes -key ca.key -subj "/CN=example.ca.com" -days 5000 -out ca.crt
生成 frps 证书:
openssl genrsa -out server.key 2048
openssl req -new -sha256 -key server.key \
-subj "/C=XX/ST=DEFAULT/L=DEFAULT/O=DEFAULT/CN=server.com" \
-reqexts SAN \
-config <(cat my-openssl.cnf <(printf "\n[SAN]\nsubjectAltName=DNS:localhost,IP:127.0.0.1,DNS:example.server.com")) \
-out server.csr
openssl x509 -req -days 365 -sha256 \
-in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
-extfile <(printf "subjectAltName=DNS:localhost,IP:127.0.0.1,DNS:example.server.com") \
-out server.crt
生成 frpc 的证书:
openssl genrsa -out client.key 2048
openssl req -new -sha256 -key client.key \
-subj "/C=XX/ST=DEFAULT/L=DEFAULT/O=DEFAULT/CN=client.com" \
-reqexts SAN \
-config <(cat my-openssl.cnf <(printf "\n[SAN]\nsubjectAltName=DNS:client.com,DNS:example.client.com")) \
-out client.csr
openssl x509 -req -days 365 -sha256 \
-in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
-extfile <(printf "subjectAltName=DNS:client.com,DNS:example.client.com") \
-out client.crt
生成如下文件:
配置文件中添加如下内容,即可使能TLS加密认证。
# frpc.toml
transport.tls.certFile = "./cert/client.crt"
transport.tls.keyFile = "./cert/client.key"
transport.tls.trustedCaFile = "./cert/ca.crt"
# frps.toml
transport.tls.certFile = "./cert/server.crt"
transport.tls.keyFile = "./cert/server.key"
transport.tls.trustedCaFile = "./cert/ca.crt"
三、总结
以上就是我使用到的FRP配置。个人认为以上配置已经基本满足使用和安全要求,当然如果有其他诉求,可以阅读官方配置文档,上面有详尽的配置信息,可以实现各种定制化配置。
四、相关资料
官方中文资料:https://gofrp.org/zh-cn/docs/setup/
加密通信:https://gofrp.org/zh-cn/docs/examples/stcp/