基于frp实现内网穿透

    20

一、前言

最近在家里的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

31696258e7686bbe4538eb5be9577afa.png

(六)安全配置

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

生成如下文件:
d7c65530776dc3d528435788da4e193b.png

配置文件中添加如下内容,即可使能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/

消息盒子

# 暂无消息 #

只显示最新10条未读和已读信息