frp 是一个可用于内网穿透的高性能的反向代理应用,支持 tcp, udp, http, https 协议。利用免费frp内网穿透服务实现处于内网或防火墙后的机器,对外网环境提供http
或https
服务。对于 http 服务支持基于域名的虚拟主机,支持自定义域名绑定,使多个域名可以共用一个80端口,支持80端口穿透。利用处于内网或防火墙后的机器,对外网环境提供 tcp/udp 服务,例如在家里通过 ssh 访问处于公司内网环境内的主机,支持 Web 服务根据域名进行路由转发,支持kcp协议和点对点穿透。
FRP 的作用
利用处于内网或防火墙后的机器,对外网环境提供 HTTP 或 HTTPS 服务。
对于 HTTP, HTTPS 服务支持基于域名的虚拟主机,支持自定义域名绑定,使多个域名可以共用一个 80 端口。
利用处于内网或防火墙后的机器,对外网环境提供 TCP 和 UDP 服务,例如在家里通过 SSH 访问处于公司内网环境内的主机。
架构原理图
服务端 - frps
1. 下载程序
首先到 frp 的 releases 页面下载最新版的对应 VPS 的处理器架构的压缩包、地址:https://github.com/fatedier/frp/releases
如何知道 VPS 的处理器架构?在 VPS 上运行这个命令:
如果输出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
mv frp_0.27.0_linux_amd64 frp cd frp
chmod +x frps
|
然后试着运行一下frps
,看看是否能正常运行
正常情况下会输出如下一串帮助信息,那么就说明你下载了正确架构的版本
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
即可
重启
那就先停止再启动嘛
加入开机自启
编辑/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: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
中,然后仿照运行服务端的方式来运行客户端
开机自启
创建启动脚本
在文件夹内新建一个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客户端启动成功。
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> <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这个服务呢!
(4)winsw其他命令
1 2 3 4
| #停止 winsw stop #卸载 winsw uninstall
|
手机远程控制
下载微软的一个远程控制软件 RD Client 手机版 [下载地址](https://apks-1300243549.cos.ap-chengdu.myqcloud.com/CD Client.apk)
- 点击软件右上角
+
号
- 点击
Desktop
- PC name输入公网IP地址和remote_port,例如,117.73.3.210:33211
- User name输入被控制的电脑的登录用户名
- 点击右上角save
- 点击主页的远程桌面即可进行远程控制
基于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
|
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
|
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服务端docker镜像制作
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
|
1
| docker build -t frp-server .
|
1
| docker run -d --name frp-server --net=host frp-server
|
FRP客户端docker镜像制作
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
|
1
| docker build -t frp-client .
|
1
| docker run -d --name frp-client --net=host frp-client
|
结尾
至此,所有步骤都已完成,win+R弹出运行窗口,输入mstsc并确定,输入你绑定的域名,如frp.xxx.com:6900,账户和密码就是你设置的被远程客户端的登录账户和密码。
登录服务端的 dashboard,看看是否连接成功,测试各项转发是否可用
如果出现无法使用的情况,按照基本思路排查问题:
- 看服务端和客户端日志是否有报错
- 客户端与服务端连接正常,就检查是否是服务端的防火墙或者安全组是否没开放使用到的端口
- 如果客户端是在路由器上,想转发至内网设备上的某个端口或服务,请检查目标设备的防火墙是否开放所需端口,且建议为该内网设备分配一个静态ip
参考资料
NAS上使用
帮助