Frp内网穿透工具的搭建和使用方法

frp 是一个可用于内网穿透的高性能的反向代理应用,支持 tcp, udp, http, https 协议。利用免费frp内网穿透服务实现处于内网或防火墙后的机器,对外网环境提供httphttps服务。对于 http 服务支持基于域名的虚拟主机,支持自定义域名绑定,使多个域名可以共用一个80端口,支持80端口穿透。利用处于内网或防火墙后的机器,对外网环境提供 tcp/udp 服务,例如在家里通过 ssh 访问处于公司内网环境内的主机,支持 Web 服务根据域名进行路由转发,支持kcp协议和点对点穿透。

FRP 的作用

利用处于内网或防火墙后的机器,对外网环境提供 HTTP 或 HTTPS 服务。

对于 HTTP, HTTPS 服务支持基于域名的虚拟主机,支持自定义域名绑定,使多个域名可以共用一个 80 端口。

利用处于内网或防火墙后的机器,对外网环境提供 TCP 和 UDP 服务,例如在家里通过 SSH 访问处于公司内网环境内的主机。

架构原理图

frp架构图

服务端 - frps

1. 下载程序

首先到 frp 的 releases 页面下载最新版的对应 VPS 的处理器架构的压缩包、地址:https://github.com/fatedier/frp/releases

如何知道 VPS 的处理器架构?在 VPS 上运行这个命令:

1
arch

如果输出x86_64那么就说明是arm64,即需要下载带linux_amd64的那个压缩包;如果输出的是其他的,则在文件列表中找 linux 的对应架构的压缩包
arm64架构举例(目前大多数都应该是这个架构),本文编写时 frp 最新版是v0.27.0

1
2
3
4
5
6
7
8
cd /home
wget --no-check-certificate https://github.com/fatedier/frp/releases/download/v0.27.0/frp_0.27.0_linux_amd64.tar.gz
tar -xzvf frp_0.27.0_linux_amd64.tar.gz
# 文件夹名改成 frp,不然目录太长了不方便
mv frp_0.27.0_linux_amd64 frp
cd frp
# 确保 frps 程序具有可执行权限
chmod +x frps

然后试着运行一下frps,看看是否能正常运行

1
./frps --help

正常情况下会输出如下一串帮助信息,那么就说明你下载了正确架构的版本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
frps is the server of frp (https://github.com/fatedier/frp)

Usage:
frps [flags]

Flags:
--allow_ports string allow ports
--bind_addr string bind address (default "0.0.0.0")
-p, --bind_port int bind port (default 7000)
--bind_udp_port int bind udp port
-c, --config string config file of frps
--dashboard_addr string dasboard address (default "0.0.0.0")
--dashboard_port int dashboard port
--dashboard_pwd string dashboard password (default "admin")
--dashboard_user string dashboard user (default "admin")
-h, --help help for frps
--kcp_bind_port int kcp bind udp port
--log_file string log file (default "console")
--log_level string log level (default "info")
--log_max_days int log_max_days (default 3)
--max_ports_per_client int max ports per client
--proxy_bind_addr string proxy bind address (default "0.0.0.0")
--subdomain_host string subdomain host
-t, --token string auth token
-v, --version version of frpc
--vhost_http_port int vhost http port
--vhost_http_timeout int vhost http response header timeout (default 60)
--vhost_https_port int vhost https port

如果提示-bash: ./frps: cannot execute binary file: Exec format error就说明你下错版本了

配置文件

文件介绍:

文件名 功能
frpc 客户端应用程序
frps 服务端应用程序
frpc.ini 客户端配置文件-精简版
frps.ini 服务端配置文件-精简版
frpc_full.ini 客户端配置文件-完整版
frps_full.ini 服务配置文件-完整版

这里进行配置时使用精简版的配置文件 frps.ini

2. 配置程序

参考以下配置说明来书写配置文件frps.ini,你可以先在电脑上打一份草稿,这里的port可以自己指定,比如我使用7000(默认)
此处只解释说明一些必要和常用的配置,如需研究完整配置说明请看目录下的frps_full.ini,以及参考frp中文说明

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 下面这句开头必须要有,表示配置的开始
[common]
# frp 服务端端口(必须)
bind_port = 7000
# frp 服务端密码(必须)
token = token_chenjh_2019
# 认证超时时间,由于时间戳会被用于加密认证,防止报文劫持后被他人利用
# 因此服务端与客户端所在机器的时间差不能超过这个时间(秒)
# 默认为900秒,即15分钟,如果设置成0就不会对报文时间戳进行超时验证
authentication_timeout = 900
# 仪表盘端口,只有设置了才能使用仪表盘(即后台)
dashboard_port = 7500
# 仪表盘访问的用户名密码,如果不设置,则默认都是 admin
dashboard_user = admin
dashboard_pwd = admin
# 如果你想要用 frp 穿透访问内网中的网站(例如路由器设置页面)
# 则必须要设置以下两个监听端口,不设置则不会开启这项功能
vhost_http_port = 10080
vhost_https_port = 10443
# 此设置需要配合客户端设置,仅在穿透到内网中的 http 或 https 时有用(可选)
# 假设此项设置为 example.com,客户端配置 http 时将 subdomain 设置为 test
# 则你将 test.example.com 解析到服务端后,可以使用此域名来访问客户端对应的 http
subdomain_host = example.com

然后把你的准备好的配置文件内容写入frps.ini

1
2
3
4
5
6
7
8
9
echo "[common]
bind_port = 7000
token = 12345678
dashboard_port = 7500
dashboard_user = admin
dashboard_pwd = admin
vhost_http_port = 10080
vhost_https_port = 10443
subdomain_host = example.com" > frps.ini

试着启动一下frps

1
2
# 使用 -c 参数指定配置文件
./frps -c frps.ini

如果没有出现错误提示就说明配置没有问题,可以正常使用

接着按下Ctrl + C终止程序运行

3. 后台运行

启动

直接使用前面的命令行来运行是不行的,因为在关掉 ssh 窗口后程序frps就会停止运行,因此要使用nohup [command] &这种操作来使其在后台运行

1
nohup /home/frp/frps -c /home/frp/frps.ini &

并且程序的所有输出(日志)会被写入nohup.out文件中,你可以使用cat命令查看其内容

停止

想停止的话,结束frps即可

1
pkill frps

重启

那就先停止再启动嘛

加入开机自启

编辑/etc/rc.local文件,将启动那句命令加到exit 0语句之前(如果有)

客户端 - frpc

如需研究完整配置说明请看目录下的frpc_full.ini,以及参考frp中文说明

书写配置

基本配置(必须)

1
2
3
4
5
6
7
8
# 下面这句开头必须要有,表示配置的开始
[common]
# frp 服务端地址,可以填ip或者域名
server_addr = 0.0.0.0
# frp 服务端端口,即填写服务端配置中的 bind_port
server_port = 7000
# 填写 frp 服务端密码
token = token_chenjh_2019

TCP/UDP

这里以转发 ssh 为例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 自定义一个配置名称,格式为“[名称]”,放在开头
[ssh]
# 连接类型,填 tcp 或 udp
type = tcp
# 本地ip,填你需要转发到的目的ip
# 如果是转发到frp客户端所在本机(比如路由器)则填 127.0.0.1
# 否则填对应机器的内网ip
local_ip = 127.0.0.1
# 需要转发到的端口,比如 ssh 端口是 22
local_port = 22
# 是否加密客户端与服务端之间的通信,默认是 false
use_encryption = false
# 是否压缩客户端与服务端之间的通信,默认是 false
# 压缩可以节省流量,但需要消耗 CPU 资源
# 加密自然也会消耗 CPU 资源,但是不大
use_compression = false
# frp 服务端的远程监听端口,即你访问服务端的 remote_port 就相当于访问
# 客户端的 local_port,如果填0则会随机分配一个端口
remote_port = 6001

HTTP(S)

以转发路由器设置页面为例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 自定义一个配置名称,格式为“[名称]”,放在开头
[router-web]
# 连接类型,填 http 或 https
type = http
local_ip = 127.0.0.1
local_port = 80
# http 可以考虑加密和压缩一下
use_encryption = true
use_compression = true
# 自定义访问网站的用户名和密码,如果不定义的话谁都可以访问,会不安全
# 有些路由器如果从内部访问web是不需要用户名密码的,因此需要在这里加一层密码保护
# 如果你发现不加这个密码保护,路由器配置页面原本的用户认证能正常生效的话,可以不加
http_user = admin
http_pwd = admin
# 还记得我们在服务端配置的 subdomain_host = example.com 吗
# 假设这里我们填 web01,那么你将 web01.example.com 解析到服务端ip后
# 你就可以使用 域名:端口 来访问你的 http 了
# 这个域名的作用是用来区分不同的 http,因为你可以配置多个这样的配置
subdomain = web01
# 自定义域名,这个不同于 subdomain,你可以设置与 subdomain_host 无关的其他域名
# subdomain 与 custom_domains 中至少有一个必须要设置
custom_domains = web02.yourdomain.com
# 匹配路径,可以设置多个,用逗号分隔,比如你设置 locations 为以下这个,
# 那么所有 http://xxx/abc 和 http://xxx/def 都会被转发到 http://xxx/
# 如果不需要这个功能可以不写这项,就直接该怎么访问就怎么访问
locations = /abc,/def
# 重写 host header,相当于反向代理中的“发送域名”
# 如果设置了,转发 http 时,请求中的 host 会被替换成这个
# 一般情况下不需要用到这个,可以不写这项
host_header_rewrite = dev.yourdomain.com

TCP/UDP 范围转发

1
2
3
4
5
6
7
8
9
# 自定义一个配置名称,格式为“[range:名称]”,放在开头
[range:multi-port]
type = tcp
local_ip = 127.0.0.1
use_encryption = false
use_compression = false
# 本地端口和远程端口可以指定多个范围,如下格式,且范围之间必须一一对应
local_port = 6010-6020,6022,6024-6028
remote_port = 16010-16020,16022,16024-16028

合并配置

将你决定要使用的配置合起来,然后填到路由器的 frp 配置脚本中。比如将以上示例配置合并之后,看起来应该是这个样子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
[common]
server_addr = 0.0.0.0
server_port = 7000
token = 12345678
[ssh]
type = tcp
local_ip = 127.0.0.1
local_port = 22
use_encryption = false
use_compression = false
remote_port = 6001
[router-web]
type = http
local_ip = 127.0.0.1
local_port = 80
use_encryption = true
use_compression = true
http_user = admin
http_pwd = admin
subdomain = web01
custom_domains = web02.yourdomain.com
locations = /abc,/def
host_header_rewrite = dev.yourdomain.com
[range:multi-port]
type = tcp
local_ip = 127.0.0.1
use_encryption = false
use_compression = false
local_port = 6010-6020,6022,6024-6028
remote_port = 16010-16020,16022,16024-16028

如果你是在 linux 上运行,则写入到frpc.ini中,然后仿照运行服务端的方式来运行客户端

1
./frpc -c frpc.ini

开机自启

创建启动脚本

在文件夹内新建一个txt文本,添加以下内容后,再将该文档重命名为frp.bat。

1
2
3
4
5
@echo off
start "C:\Windows\System32\cmd.exe"
cd "文件所在目录地址,如C:\Software\frp"
frpc -c frpc.ini
exit

双击脚本,弹出命令窗口,如果提示大概如图所示,则说明frp客户端启动成功。
frp内网穿透实现对内网电脑的远程桌面连接.jpg

5.加入开机自动启动服务

网上有教程是新建frpc.vps,然后放进C:\Users\Administrator\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup这个目录,这种方法有个问题,就是必须在你重启电脑并输入管理员账号密码后才会自启动frp。

而我们要实现的是在输入管理员密码进入桌面前就启动frp,方法就是将frp注册为系统服务

(1)下载winsw

下载地址:点击这里
下载完成后,重命名为winsw.exe,并放在frp相同的目录中。

(2)创建winsw.xml

在frp相同目录中创建winsw.xml,并加入以下内容(部分自行修改):

1
2
3
4
5
6
7
8
9
10
<service>
<id>Frp</id>
<name>Frp Server</name><!-- Frp Server 这里是服务的名称,随便写 -->
<description>Frp服务</description><!-- 这里是服务的介绍,随便写 -->
<executable>frpc</executable>
<arguments>-c frpc.ini</arguments>
<onfailure action="restart" delay="60 sec"/>
<onfailure action="restart" delay="120 sec"/>
<logmode>reset</logmode>
</service>
(3)打开CMD命令窗口

以管理员身份创建一个cmd命令窗口,然后cd到frp目录,执行以下两个命令:

1
2
winsw install
winsw start

大功告成!此时,通过任务管理器中,查看是否有frp这个服务呢!
frp内网穿透实现对内网电脑的远程桌面连接1.png

(4)winsw其他命令
1
2
3
4
#停止
winsw stop
#卸载
winsw uninstall

手机远程控制

下载微软的一个远程控制软件 RD Client 手机版 [下载地址](https://apks-1300243549.cos.ap-chengdu.myqcloud.com/CD Client.apk)

  1. 点击软件右上角 +
  2. 点击 Desktop
  3. PC name输入公网IP地址和remote_port,例如,117.73.3.210:33211
  4. User name输入被控制的电脑的登录用户名
  5. 点击右上角save
  6. 点击主页的远程桌面即可进行远程控制

基于FRP实现内网穿透

  • 云主机安装FRP服务器端
    云主机可以是阿里云、腾讯云和京东云等。主要需要一个公网IP
1
2
3
4
wget https://github.com/fatedier/frp/releases/download/v0.33.0/frp_0.33.0_linux_amd64.tar.gz
tar -zxvf frp_0.33.0_linux_amd64.tar.gz
rm -f frpc
rm -f frpc.ini
  • 修改云主机FRP服务端配置frps.ini
1
2
3
4
5
6
7
8
9
10
[common]
bind_addr = 0.0.0.0
bind_port = 7000
vhost_http_port = 80
vhost_https_port = 443

dashboard_user = admin
dashboard_pwd = admin
dashboard_port = 7500
auth_token = 123
  • 运行FRP服务端
1
./frps -c frps.ini
  • 内网NAS安装FRP客户端
1
2
3
4
wget https://github.com/fatedier/frp/releases/download/v0.33.0/frp_0.33.0_linux_amd64.tar.gz
tar -zxvf frp_0.33.0_linux_amd64.tar.gz
rm -f frps
rm -f frps.ini
  • 修改内网NAS主机FRP客户端配置frpc.ini
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[common]
server_addr = 云主机公网IP
server_port = 7000
auth_token = 123

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

[nas-admin]
type = http
local_ip = 内网NAS主机IP
local_port = 80
custom_domains = 自定义域名(可以是花生壳的域名,需要将此域名关联到云主机的公网IP)

[smb]
type = tcp
local_ip = 内网NAS主机IP
local_port = 445
remote_port = 6001
  • 运行FRP客户端
1
./frpc -c frpc.ini

FRP服务端docker镜像制作

  • dockerfile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
FROM ubuntu
MAINTAINER chenjh <chenjh0611@163.com>

ARG FRP_VERSION=0.33.0

RUN apt update \
&& apt install -y wget

WORKDIR /tmp
RUN set -x \
&& wget https://github.com/fatedier/frp/releases/download/v${FRP_VERSION}/frp_${FRP_VERSION}_linux_amd64.tar.gz \
&& tar -zxf frp_${FRP_VERSION}_linux_amd64.tar.gz \
&& mv frp_${FRP_VERSION}_linux_amd64 /var/frp \
&& mkdir -p /var/frp/conf \
&& apt remove -y wget \
&& apt autoremove -y \
&& rm -rf /var/lib/apt/lists/*

COPY conf/frps.ini /var/frp/conf/frps.ini

VOLUME /var/frp/conf

WORKDIR /var/frp
ENTRYPOINT ./frps -c ./conf/frps.ini
  • 配置frps.ini
  • 制作镜像
1
docker build -t frp-server .
  • 启动FRP服务端
1
docker run -d --name frp-server --net=host frp-server

FRP客户端docker镜像制作

  • dockerfile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
FROM ubuntu
MAINTAINER chenjh <chenjh0611@163.com>

ARG FRP_VERSION=0.33.0

RUN apt update \
&& apt install -y wget

WORKDIR /tmp
RUN set -x \
&& wget https://github.com/fatedier/frp/releases/download/v${FRP_VERSION}/frp_${FRP_VERSION}_linux_amd64.tar.gz \
&& tar -zxf frp_${FRP_VERSION}_linux_amd64.tar.gz \
&& mv frp_${FRP_VERSION}_linux_amd64 /var/frp \
&& mkdir -p /var/frp/conf \
&& apt remove -y wget \
&& apt autoremove -y \
&& rm -rf /var/lib/apt/lists/*

COPY conf/frpc.ini /var/frp/conf/frpc.ini

VOLUME /var/frp/conf

WORKDIR /var/frp
ENTRYPOINT ./frpc -c ./conf/frpc.ini
  • 配置frpc.ini
  • 制作镜像
1
docker build -t frp-client .
  • 启动FRP服务端
1
docker run -d --name frp-client --net=host frp-client

结尾

至此,所有步骤都已完成,win+R弹出运行窗口,输入mstsc并确定,输入你绑定的域名,如frp.xxx.com:6900,账户和密码就是你设置的被远程客户端的登录账户和密码。

登录服务端的 dashboard,看看是否连接成功,测试各项转发是否可用

如果出现无法使用的情况,按照基本思路排查问题:

  1. 看服务端和客户端日志是否有报错
  2. 客户端与服务端连接正常,就检查是否是服务端的防火墙或者安全组是否没开放使用到的端口
  3. 如果客户端是在路由器上,想转发至内网设备上的某个端口或服务,请检查目标设备的防火墙是否开放所需端口,且建议为该内网设备分配一个静态ip

参考资料

NAS上使用

帮助

个人微信公众号技术交流QQ群
文章目录
  1. 1. FRP 的作用
  2. 2. 架构原理图
  3. 3. 服务端 - frps
    1. 3.1. 1. 下载程序
    2. 3.2. 配置文件
    3. 3.3. 2. 配置程序
    4. 3.4. 3. 后台运行
      1. 3.4.1. 启动
      2. 3.4.2. 停止
      3. 3.4.3. 重启
      4. 3.4.4. 加入开机自启
  4. 4. 客户端 - frpc
    1. 4.1. 书写配置
      1. 4.1.1. 基本配置(必须)
      2. 4.1.2. TCP/UDP
      3. 4.1.3. HTTP(S)
      4. 4.1.4. TCP/UDP 范围转发
    2. 4.2. 合并配置
    3. 4.3. 开机自启
      1. 4.3.1. 创建启动脚本
      2. 4.3.2. 5.加入开机自动启动服务
        1. 4.3.2.1. (1)下载winsw
        2. 4.3.2.2. (2)创建winsw.xml
        3. 4.3.2.3. (3)打开CMD命令窗口
        4. 4.3.2.4. (4)winsw其他命令
  5. 5. 手机远程控制
  6. 6. 基于FRP实现内网穿透
  7. 7. FRP服务端docker镜像制作
  8. 8. FRP客户端docker镜像制作
  9. 9. 结尾
  10. 10. 参考资料
  11. 11. NAS上使用
  12. 12. 帮助