内网穿透工具 frp 使用教程

525 阅读16分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第18天,点击查看活动详情


title: 内网穿透工具 frp 使用教程

tags: [Environment, Nas] categories: [Environment, Nas]

为了让家中的NAS 可以为不在局域网范围内的我提供服务,而家里又没有公网IP,需要进行内网穿透,frp是一款优秀好用的工具,本文介绍 ssh, http 内网穿透方法与示例。

frp 简介

  • frp 是一个可用于内网穿透的高性能的反向代理应用,支持 tcp, udp, http, https 协议。

  • frp目前最新版本为0.38.0,frp目前仍然处于前期开发阶段,未经充分测试与验证,不推荐用于生产环境。

  • 本文记录快速搭建 frp 并使用的方法,更多细节请参考官方文档

  • 官方 github: github.com/fatedier/fr…

背景

frp 适用于有公网IP需求的用户,如果有需要在互联网中找到自己的电脑,但是电脑又没有公网IPv4地址,又不想用IPv6地址,恰好还有一个空闲的拥有IPv4公网地址的云服务器,那么frp 是使用你需要的工具。

使用条件

  • 内网计算机有在公网 IP 提供服务的需求
  • 有拥有公网 IP 的计算机(可以是云服务器,别人家的电脑等)
  • 如果有http / https 服务需求还要有备案的域名
  • 没有域名也可以配置 tcp 映射完成网站穿透

使用教程

安装

以我的安装了Ubuntu 20.04 的 x86_64 cpu 主机为例,我需要下载 frp版本 _ Linux _ amd64 的安装包:

  • 下载安装包:
wget https://github.91chi.fun//https://github.com//fatedier/frp/releases/download/v0.38.0/frp_0.38.0_linux_amd64.tar.gz
  • 解压
$ tar -axvf frp_0.38.0_linux_amd64.tar.gz 

frp_0.38.0_linux_amd64/
frp_0.38.0_linux_amd64/frpc_full.ini
frp_0.38.0_linux_amd64/frps.ini
frp_0.38.0_linux_amd64/frps_full.ini
frp_0.38.0_linux_amd64/LICENSE
frp_0.38.0_linux_amd64/frpc
frp_0.38.0_linux_amd64/systemd/
frp_0.38.0_linux_amd64/systemd/frps@.service
frp_0.38.0_linux_amd64/systemd/frpc.service
frp_0.38.0_linux_amd64/systemd/frps.service
frp_0.38.0_linux_amd64/systemd/frpc@.service
frp_0.38.0_linux_amd64/frpc.ini
frp_0.38.0_linux_amd64/frps

  • 得到这样的文件结构
frp_0.38.0_linux_amd64$ ls
frpc  frpc_full.ini  frpc.ini  frps  frps_full.ini  frps.ini  LICENSE  systemd

其中 frpc 开头的是客户端(client) 的核心文件

其中 frps 开头的是服务器端(server) 的核心文件

systemd 文件夹是建立 systemctl 的示例文件

服务器端

  • 服务器可以购买服务商的云服务主机,最便宜的就行,但是必须有公网IP
配置
  • 此处关心的核心文件为 frpsfrps.ini
  • frps复制到 /usr/bin 目录下(也可以按照个人习惯放置)
sudo cp frps /usr/bin
  • frps.ini放到 /etc/frp 目录下
sudo mkdir /etc/frp
sudo cp frps.ini /etc/frp
  • 修改 frps.ini 文件 (核心步骤
sudo vim /etc/frp/frps.ini
[common]
bind_port = 7000

vhost_http_port = 6988
vhost_https_port = 6989

token=yourtoken

# dashboard 用户名密码,默认都为 admin

dashboard_port = 6999
dashboard_user = admin
dashboard_pwd = admin

log_file = ./frps.log
log_level = info
log_max_days = 3

heartbeat_timeout = 90

privilege_allow_ports = 6000-7000, 3001

max_pool_count = 100

max_ports_per_client = 0

authentication_timeout = 900

tcp_mux = true

其中:

参数含义
bind_port表示内网计算机和服务器计算机的通信端口,需要打开外网计算机的端口防火墙限制
vhost_http_porthttp 服务映射端口,需要打开外网计算机的端口防火墙限制
vhost_https_porthttps 服务映射端口,需要打开外网计算机的端口防火墙限制
token协商令牌,客户端和服务器需要一致才可以生效
dashboard_portfrp 管理端口,需要打开外网计算机的端口防火墙限制
dashboard_user管理端口用户名
dashboard_pwd管理端口密码
log_file日志文件位置
log_level日志级别,分为debug, info, warn, error四级
log_max_days日志保存的天数
heartbeat_timeout心跳配置
privilege_allow_portsfrp内网穿透服务端监听的端口,如果不设置的话,所有端口都可以连接使用,但为为了不占用系统使用的端口号,建议设置允许的监听端口,比如www.chuantou.org提供的内网穿透服务器就是开放50000-60000端口
max_pool_count连接池的数量,如果frp内网穿透客户端设置的连接池的数量大于下面的数值,就会修改frp客户端的连接池为下面的数值
max_ports_per_client每个客户端最大可以使用的端口,0表示无限制
authentication_timeoutfrp内网穿透服务端frps和frp内网穿透的客户端frpc两台电脑的时间差,如果设置为0的话,不校验时间差异,默认校验时间差为900秒。
tcp_mux是否使用tcp复用,默认为true, frp只对同意客户端的连接进行复用
开启服务
  • 之后我们执行命令:
/usr/bin/frps -c /etc/frp/frps.ini

便可以开启服务了

测试
  • 开启后可以访问公网IP:6999查看 frp 的工作状态,也说明我们成功开启了服务器端 frp 服务

开机启动
  • 接下来关闭服务,我们设置服务器端 frps 服务开机启动
  • 将解压的压缩包中systemd文件夹中的 frps.service文件复制到 /usr/lib/systemd/system 文件夹中
  • 如果你的 frps 文件和配置文件都按照我上述步骤完成的不需要修改 frps.service文件,否则需要将文件中 ExecStart 值更改为你执行命令时的指令
[Unit]
Description=Frp Server Service
After=network.target

[Service]
Type=simple
User=nobody
Restart=on-failure
RestartSec=5s
ExecStart=/usr/bin/frps -c /etc/frp/frps.ini
LimitNOFILE=1048576

[Install]
WantedBy=multi-user.target
  • 重新加载 systemd 并开启服务,设置开机启动:

相关 systemd 知识可以参考 Linux Systemd 实战

# 重新加载 systemd 配置
sudo systemctl daemon-reload
# 开启服务
sudo systemctl start frps
# 设置开启启动
sudo systemctl enable frps
  • 至此我们的服务端彻底设置完成

客户端

  • 客户端也需要下载 frp 安装包并解压
配置
  • 将 frpc 文件复制到 /usr/bin
sudo cp frpc /usr/bin
  • frpc.ini 文件放到 /etc/frp 文件夹中
sudo mkdir /etc/frp
sudo cp frpc.ini /etc/frp
  • 修改 frpc.ini 文件 (核心步骤
[common]
server_addr=23.23.23.23
server_port=7000
token=yourtoken

[ssh]
type = tcp
local_ip =127.0.0.1
local_port = 22
remote_port = 6987

[http]
type=http
local_port=4000
custom_domains=test.zywvvd.com

[web]
type = tcp
local_ip = 127.0.0.1
local_port = 80
remote_port = 80

该配置文件主要绑定了两个业务——ssh 和网站服务,其中http为http模式的网页,需要域名,如果没有域名可以直接使用80端口tcp映射完成无域名网页穿透

server_addr公网服务器的公网IP
server_port和服务器端配置一致
token和服务器端配置一致
[ssh] / [http]服务名称,根据个人情况设置
type服务类型,包含 tcp, udp, http, https 等,ssh 使用 tcp即可
local_ip本机IP,建议设置127.0.0.1 ,就不用来回改了
local_port本地映射端口,其实本质为本地端口数据映射到服务器端端口
remote_port服务器端端口
custom_domainshttp 类型必填,需要域名解析到该公网IP上(http 类型服务需要)
域名解析
  • 对于http服务需要域名解析
  • 以我的百度智能云域名为例

  • 将自己的公网 IP 解析到一个 A 记录上即可
开启服务
  • 执行命令
/usr/bin/frpc -c /etc/frp/frpc.ini

即可开启客户端服务

ssh 测试
  • 此时 ssh 服务已经可用了
# Windows
ssh user_name@公网IP:6987 
# linux
ssh user_name@公网IP -p 6987 

输入密码即可远程公网ssh访问自己的电脑

http 测试
  • 此时我把我的个人网站挂载在我本机的 4000 端口上
  • 公网访问 test.zywvvd.com:6988 即可看到我本地的网站,说明我们的http穿透成功

web 测试
  • 公网访问公网IP,可以直接访问本地映射到80端口的网页

注意:一个 frp 服务器只可以同一时间有一个 http 服务,有一个绑定 http 服务的客户机后,其余http服务不会被支持

开机启动
  • 接下来关闭服务,我们设置服务器端 frpc 服务开机启动
  • 将解压的压缩包中systemd文件夹中的 frpc.service文件复制到 /usr/lib/systemd/system 文件夹中
  • 如果你的 frpc 文件和配置文件都按照我上述步骤完成的不需要修改 frpc.service文件,否则需要将文件中 ExecStartExecReload值更改为你执行命令时的指令
[Unit]
Description=Frp Client Service
After=network.target

[Service]
Type=simple
User=nobody
Restart=on-failure
RestartSec=5s
ExecStart=/etc/frp/frpc -c /etc/frp/frpc.ini
ExecReload=/etc/frp/frpc reload -c /etc/frp/frpc.ini
LimitNOFILE=1048576

[Install]
WantedBy=multi-user.target
  • 重新加载 systemd 并开启服务,设置开机启动:
# 重新加载 systemd 配置
sudo systemctl daemon-reload
# 开启服务
sudo systemctl start frpc
# 设置开启启动
sudo systemctl enable frpc
  • 至此我们的客户端彻底设置完成,也就完成了 ssh 和 http 的内网穿透

服务端配置详细信息

frp 服务端详细配置说明,官方的极简设置只要设置红色 bind_port即可。

稍微复杂点可以选择紫色的条目

基础配置

参数类型说明默认值可选值备注
bind_addrstring服务端监听地址0.0.0.0
bind_portint服务端监听端口7000接收 frpc 的连接
bind_udp_portint服务端监听 UDP 端口0用于辅助创建 P2P 连接
kcp_bind_portint服务端监听 KCP 协议端口0用于接收采用 KCP 连接的 frpc
proxy_bind_addrstring代理监听地址同 bind_addr可以使代理监听在不同的网卡地址
log_filestring日志文件地址./frps.log如果设置为 console,会将日志打印在标准输出中
log_levelstring日志等级infotrace, debug, info, warn, error
log_max_daysint日志文件保留天数3
disable_log_colorbool禁用标准输出中的日志颜色false
detailed_errors_to_clientbool禁用服务端返回详细错误信息给客户端true
heart_beat_timeoutint服务端和客户端心跳连接的超时时间90单位:秒
user_conn_timeoutint用户建立连接后等待客户端响应的超时时间10单位:秒

权限验证

参数类型说明默认值可选值备注
authentication_methodstring鉴权方式tokentoken, oidc
authenticate_heartbeatsbool开启心跳消息鉴权false
authenticate_new_work_connsbool开启建立工作连接的鉴权false
tokenstring鉴权使用的 token 值客户端需要设置一样的值才能鉴权通过
oidc_issuerstringoidc_issuer
oidc_audiencestringoidc_audience
oidc_skip_expiry_checkbooloidc_skip_expiry_check
oidc_skip_issuer_checkbooloidc_skip_issuer_check

管理配置

参数类型说明默认值可选值备注
allow_portsstring允许代理绑定的服务端端口格式为 1000-2000,2001,3000-4000
max_pool_countint最大连接池大小5
max_ports_per_clientint限制单个客户端最大同时存在的代理数00 表示没有限制
tls_onlybool只接受启用了 TLS 的客户端连接false

Dashboard, 监控

参数类型说明默认值可选值备注
dashboard_addrstring启用 Dashboard 监听的本地地址0.0.0.0
dashboard_portint启用 Dashboard 监听的本地端口0
dashboard_userstringHTTP BasicAuth 用户名admin
dashboard_pwdstringHTTP BasicAuth 密码admin
enable_prometheusbool是否提供 Prometheus 监控接口false需要同时启用了 Dashboard 才会生效
asserts_dirstring静态资源目录Dashboard 使用的资源默认打包在二进制文件中,通过指定此参数使用自定义的静态资源

HTTP & HTTPS

参数类型说明默认值可选值备注
vhost_http_portint为 HTTP 类型代理监听的端口0启用后才支持 HTTP 类型的代理,默认不启用
vhost_https_portint为 HTTPS 类型代理监听的端口0启用后才支持 HTTPS 类型的代理,默认不启用
vhost_http_timeoutintHTTP 类型代理在服务端的 ResponseHeader 超时时间60
subdomain_hoststring二级域名后缀
custom_404_pagestring自定义 404 错误页面地址

TCPMUX

参数类型说明默认值可选值备注
tcpmux_httpconnect_portint为 TCPMUX 类型代理监听的端口0启用后才支持 TCPMUX 类型的代理,默认不启用

客户端配置详细信息

基础配置

参数类型说明默认值可选值备注
server_addrstring连接服务端的地址0.0.0.0
server_portint连接服务端的端口7000
http_proxystring连接服务端使用的代理地址格式为 {protocol}://user:passwd@192.168.1.128:8080 protocol 目前支持 http 和 socks5
log_filestring日志文件地址./frpc.log如果设置为 console,会将日志打印在标准输出中
log_levelstring日志等级infotrace, debug, info, warn, error
log_max_daysint日志文件保留天数3
disable_log_colorbool禁用标准输出中的日志颜色false
pool_countint连接池大小0
userstring用户名设置此参数后,代理名称会被修改为 {user}.{proxyName},避免代理名称和其他用户冲突
dns_serverstring使用 DNS 服务器地址默认使用系统配置的 DNS 服务器,指定此参数可以强制替换为自定义的 DNS 服务器地址
login_fail_exitbool第一次登陆失败后是否退出true
protocolstring连接服务端的通信协议tcptcp, kcp, websocket
tls_enablebool启用 TLS 协议加密连接false
heartbeat_intervalint向服务端发送心跳包的间隔时间30
heartbeat_timeoutint和服务端心跳的超时时间90
startstring指定启用部分代理当配置了较多代理,但是只希望启用其中部分时可以通过此参数指定,默认为全部启用

权限验证

参数类型说明默认值可选值备注
authentication_methodstring鉴权方式tokentoken, oidc需要和服务端一致
authenticate_heartbeatsbool开启心跳消息鉴权false需要和服务端一致
authenticate_new_work_connsbool开启建立工作连接的鉴权false需要和服务端一致
tokenstring鉴权使用的 token 值需要和服务端设置一样的值才能鉴权通过
oidc_client_idstringoidc_client_id
oidc_client_secretstringoidc_client_secret
oidc_audiencestringoidc_audience
oidc_token_endpoint_urlstringoidc_token_endpoint_url

UI

参数类型说明默认值可选值备注
admin_addrstring启用 AdminUI 监听的本地地址0.0.0.0
admin_portint启用 AdminUI 监听的本地端口0
admin_userstringHTTP BasicAuth 用户名admin
admin_pwdstringHTTP BasicAuth 密码admin
asserts_dirstring静态资源目录AdminUI 使用的资源默认打包在二进制文件中,通过指定此参数使用自定义的静态资源
参数类型说明是否必须默认值可选值备注
typestring代理类型tcptcp, udp, http, https, stcp, sudp, xtcp, tcpmux
use_encryptionbool是否启用加密功能false启用后该代理和服务端之间的通信内容都会被加密传输
use_compressionbool是否启用压缩功能false启用后该代理和服务端之间的通信内容都会被压缩传输
proxy_protocol_versionstring启用 proxy protocol 协议的版本v1, v2如果启用,则 frpc 和本地服务建立连接后会发送 proxy protocol 的协议,包含了原请求的 IP 地址和端口等内容
bandwidth_limitstring设置单个 proxy 的带宽限流单位为 MB 或 KB,0 表示不限制,如果启用,会作用于对应的 frpc

本地服务配置

local_ipplugin 的配置必须配置一个,且只能生效一个,如果配置了 plugin,则 local_ip 配置无效。

参数类型说明是否必须默认值可选值备注
local_ipstring本地服务 IP127.0.0.1需要被代理的本地服务的 IP 地址,可以为所在 frpc 能访问到的任意 IP 地址
local_portint本地服务端口xxxx配合 local_ip
pluginstring客户端插件名称见客户端插件的功能说明用于扩展 frpc 的能力,能够提供一些简单的本地服务,如果配置了 plugin,则 local_ip 和 local_port 无效,两者只能配置一个
plugin_paramsmap客户端插件参数map 结构,key 需要都以 “plugin_” 开头,每一个 plugin 需要的参数也不一样,具体见客户端插件参数中的内容

负载均衡和健康检查

参数类型说明是否必须默认值可选值备注
groupstring负载均衡分组名称用户请求会以轮询的方式发送给同一个 group 中的代理
group_keystring负载均衡分组密钥用于对负载均衡分组进行鉴权,group_key 相同的代理才会被加入到同一个分组中
health_check_typestring健康检查类型tcp,http配置后启用健康检查功能,tcp 是连接成功则认为服务健康,http 要求接口返回 2xx 的状态码则认为服务健康
health_check_timeout_sint健康检查超时时间(秒)3执行检查任务的超时时间
health_check_max_failedint健康检查连续错误次数1连续检查错误多少次认为服务不健康
health_check_interval_sint健康检查周期(秒)10每隔多长时间进行一次健康检查
health_check_urlstring健康检查的 HTTP 接口如果 health_check_type 类型是 http,则需要配置此参数,指定发送 http 请求的 url,例如 “/health”

TCP

参数类型说明是否必须默认值可选值备注
remote_portint服务端绑定的端口用户访问此端口的请求会被转发到 local_ip:local_port 当type=tcp时,此项必选

UDP

参数类型说明是否必须默认值可选值备注
remote_portint服务端绑定的端口用户访问此端口的请求会被转发到 local_ip:local_port

HTTP

custom_domainssubdomain 必须要配置其中一个,两者可以同时生效。

参数类型说明是否必须默认值可选值备注
custom_domains[]string服务器绑定自定义域名是(和 sub_domain 两者必须配置一个)用户通过 vhost_http_port 访问的 HTTP 请求如果 Host 在 custom_domains 配置的域名中,则会被路由到此代理配置的本地服务
subdomainstring自定义子域名是(和 custom_domains 两者必须配置一个)和 custom_domains 作用相同,但是只需要指定子域名前缀,会结合服务端的 subdomain_host 生成最终绑定的域名
locations[]stringURL 路由配置采用最大前缀匹配的规则,用户请求匹配响应的 location 配置,则会被路由到此代理
http_userstring用户名如果配置此参数,暴露出去的 HTTP 服务需要采用 Basic Auth 的鉴权才能访问
http_pwdstring密码结合 http_user 使用
host_header_rewritestring替换 Host header替换发送到本地服务 HTTP 请求中的 Host 字段
headersmap替换 headermap 中的 key 是要替换的 header 的 key,value 是替换后的内容

HTTPS

custom_domainssub_domain 必须要配置其中一个,两者可以同时生效。

参数类型说明是否必须默认值可选值备注
custom_domains[]string服务器绑定自定义域名是(和 sub_domain 两者必须配置一个)用户通过 vhost_http_port 访问的 HTTP 请求如果 Host 在 custom_domains 配置的域名中,则会被路由到此代理配置的本地服务
sub_domainstring自定义子域名是(和 custom_domains 两者必须配置一个)和 custom_domains 作用相同,但是只需要指定子域名前缀,会结合服务端的 subdomain_host 生成最终绑定的域名

STCP

参数类型说明是否必须默认值可选值备注
rolestring角色serverserver,visitorserver 表示服务端,visitor 表示访问端
skstring密钥服务端和访问端的密钥需要一致,访问端才能访问到服务端

SUDP

参数类型说明是否必须默认值可选值备注
rolestring角色serverserver,visitorserver 表示服务端,visitor 表示访问端
skstring密钥服务端和访问端的密钥需要一致,访问端才能访问到服务端

XTCP

参数类型说明是否必须默认值可选值备注
rolestring角色serverserver,visitorserver 表示服务端,visitor 表示访问端
skstring密钥服务端和访问端的密钥需要一致,访问端才能访问到服务端

参考资料