header image

内网穿透之frp

  • 2018-06-23更新:
    由于新版(0.18.0开始)和之前的版本不兼容,因此针对新版做了一些补充。补充的内容基于0.20.0版本。

  • 2019-05-09更新:
    更改了一些文件的保存位置。

之前讲过ngrok,但是那个需要自己编译,也已经很久很没有更新了(作者开发了ngrok 2,但是变成私有软件了)。所以这次我们换一个大概是中国人编写的frp,作者提供了详细的中文文档,上手十分简单。

frp的GitHub页面,我们可以在Releases页面下载到编译好的版本。提供各种架构的版本:darwin是macOS,linuxwindows就不用多说了,386就是32位平台,amd64就是64位平台,其他还有armmips等多种平台。如果没有还可以自己编译,但不在本文涉及范围。

下载解包之后,会得到几个文件,frps就是服务器端程序,frpc就是客户端程序,后缀ini的就是对应的配置文件,full的就是完整的配置文件。

服务器端配置

基本配置

frpsfrps.ini上传到服务器,让后放到某个目录下(我放到了/opt/frps/目录下)。然后修改frps.ini文件(你也可以先修改了再上传)。

基本上只要一条设置就够了(每条选项一行,=之前是选项名,之后是值,[]内是选项块的名字):

[common]
bind_port = 7000

bind_port就是绑定的端口,设置一个没有被占用的就行了。值为端口号的整数。
如果服务器有多个IP地址,我们还可以设置bind_addr来绑定特定的IP地址。值为点分十进制的IPv4地址(如1.2.3.4)。

2018-06-23更新:新版增加了IPv6支持,因此值还可以设置为IPv6地址(必须用方括号[],如[2400::1:23:456:7890])。

PS:由于Go语言的特点,0.0.0.0[::]是一样的效果,会同时监听IPv4和IPv6地址,但在用netstat里只能看到IPv6被监听,实际上是通过了IPv4-Mapped IPv6 Address同时兼听了IPv4地址的。

如果要开启kcp,我们还可以设置kcp_bind_port选项。值为端口号。
为了增加安全性,我们可以加上密码privilege_token选项。值为字符串。

2018-06-23更新:从0.17.0版开始,privilege_token不再支持,请改为token

其他更多选项及相关说明请参见frps_full.ini文件。

然后我们只要运行如下命令就可以了:

/opt/frps/frps -c /opt/frps/frps.ini

开机自动运行

当然,我们要让它开机自动运行,如果系统使用的是systemd来进行初始化,我们只需要编写一个service文件(保存为/lib/systemd/system/frps.service)就行了:

2019-05-09更新:
请将文件保存到/etc/systemd/system/frps.service

[Unit]
Description=frp server
After=network.target

[Service]
Type=simple
ExecStart=/opt/frps/frps -c /opt/frps/frps.ini
Restart=on-failure

[Install]
WantedBy=multi-user.target

然后照例启用和启动服务就行(逐条执行):

sudo systemctl enable frps
sudo systemctl start frps
sudo systemctl status frps

上面最后一条命令是查看服务状态的,如果是active就是成功运行了。

客户端配置

服务器端配置很简单,客户端配置就要复杂一点了。客户端里的配置文件一样是上面介绍的格式,下面我们以[]包含的不同块来分开介绍。注意,所有选项都在一个配置文件里。

如果是运行在NAS上的,同样上传到NAS之后使用(我上传到了/opt/frpc/目录)。

[common]

如同名字所说,这里都是一些公共配置,基本上如下:

[common]
server_addr = 1.2.3.4
server_port = 7000
admin_addr = 127.0.0.1
admin_port = 7400

server_addr就是我们的服务器IP地址,你也可以用域名,但是不推荐。
server_port就是我们在上面bind_port设置的端口号。
admin_addradmin_port是为了能够热加载配置而设置的,监听本机(127.0.0.1)的7400端口。
如果启用了密码,设置privilege_token和上面服务器设置的一样就行了。

2018-06-23更新:从0.17.0版开始,privilege_token不再支持,请改为token

如果上面设置了kcp_bind_port,我们还可以用protocol = kcp来启用kcp协议。
其他更多选项及相关说明请参见frps_full.ini文件。

公共设置就这些了,基本上这样就能用了。下面我们来设置具体的端口映射。

最基本的映射

基本的映射只要设置一个唯一的块名,然后下面做对应的设置就行了。比如我们设置SSH访问:

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

[ssh]就是一个名称,我们自己设置就行了,用[]包上即可,下面的选项都是对应在这个块下的。一个ini可以包含多个设置。
type就是类型,大多数服务都是tcp的。除此之外还支持udphttp服务(当然,http也是tcp的一种,有这个只是为了方便虚拟主机的设置,详见GitHub上的说明),还有一个stcp我们下面会提到。
local_ip就是我们想转发到外网的本地主机的IP,127.0.0.1代表的就是本机。
local_port就是服务的端口了,22是ssh的默认端口。
remote_port就是我们想在服务器上打开的端口,比如我这里设置23333
如果需要加密,我们可以在每个映射下设置use_encryption = true
如果需要压缩,我们可以设置use_compression = true
其他更多选项及相关说明请参见frps_full.ini文件。

这样,当我们启动客户端之后,就可以通过访问服务器的23333端口来访问实际运行在本地主机的22端口上的SSH服务了。下面是一个Transmission远程访问的配置示例:

[transmission]
type = tcp
local_ip = 127.0.0.1
local_port = 9091
remote_port = 9091

当然,有时我们觉得这样直接把服务暴露给公网太不安全,那怎么办呢,上面提到过的stcp就是一个解决方案。

安全的映射

安全的映射我们需要两个客户端,一个运行在提供服务的主机上(简称A),一个运行在访问服务的主机上(简称B),通过服务器中转访问,服务器并不直接开放端口。

在提供服务的主机(A)上设置

我们还是以ssh服务为例:

[secret_ssh]
type = stcp
local_ip = 127.0.0.1
local_port = 22
sk = abcdef

前三项配置和前面的基本一样,就是type设置成了stcp。但最后我们不再设置remote_port,而是设置了一个sk,这是安全访问的密码,只有密码一致才能访问。

运行客户端之后,我们就可以通过另一个客户端来访问了。

在访问服务的主机(B)上设置

我们在另一台主机(B)上同样设置frpc.ini[common]部分是一样的,但是我们设置的并不是为了提供服务,而是访问服务,所以有所不同

[common]
server_addr = 1.2.3.4
server_port = 7000

[secret_ssh_vistor]
type = stcp
role = vistor
server_name = secret_ssh
sk = abcdef
bind_addr = 127.0.0.1
bind_port = 23333

type一样是stcp
多了个role = vistor表示我们是访客而不是提供服务的(吐个槽,作者这里错成vistor了,怎么想都是visitor才对嘛)。
2018-06-23更新:作者已经修正为了,请使用visitor作为正确的值。
然后server_name要和我们上面在主机A上设置的[]内的名字一样。
sk也要和上面一样。
bind_addr表示绑定在本机(B)上的IP地址,你可以绑定0.0.0.0或者具体的IP地址来再向局域网内提供访问。
bing_port就是绑定本机的端口了。

运行客户端之后,我们就可以访问本机(B)的23333端口,来访问主机A上的22端口的SSH服务了。

点对点映射

2018-06-23新增此节

新版增加了点对点映射,设置方法和安全映射差不多,仅type的值设置为xtcp

点对点映射时,连接不通过服务器,而是直接在两个主机(A和B)之间建立,但并不能支持所有网络环境,如果不能正常工作,还是需要使用安全映射。

自动运行客户端

我们可以先运行一下看看有没有什么错误。

/opt/frpc/frpc -c /opt/frpc/frpc.ini

因为我是运行在NAS上的,所以还是要自动运行。设置起来和服务器基本是一摸一样的,只不过把frps改成了frpc

如果系统使用的是systemd来进行初始化,我们只需要编写一个service文件(保存为/lib/systemd/system/frpc.service)就行了:

2019-05-09更新:
请将文件保存到/etc/systemd/system/frpc.service

[Unit]
Description=frp client
After=network.target

[Service]
Type=simple
ExecStart=/opt/frpc/frpc -c /opt/frpc/frpc.ini
ExecReload=/opt/frpc/frpc -c /opt/frpc/frpc.ini --reload
Restart=on-failure

[Install]
WantedBy=multi-user.target

多了一个ExecReload选项是为了可以热加载配置,因为我们主要都是修改客户端配置,这样可以方便修改之后立即生效。

然后照例启用和启动服务就行(逐条执行):

sudo systemctl enable frpc
sudo systemctl start frpc
sudo systemctl status frpc

上面最后一条命令是查看服务状态的,如果是active就是成功运行了。如果我们需要热加载配置,只需要用命令sudo systemctl reload frpc就可以了。

补充

如果是运行在Windows上的,网上有很多资料如何自动运行,就不细说了。如果只是临时使用(比如是作为上面提到的安全映射里的主机B),那么只需要在命令行执行代码就行了(打开命令行的方式:在文件管理器的frpc.exe所在文件夹里按住Shift点右键,然后选择在此处打开命令行提示符/Powershell窗口)。

frpc -c frpc.ini

2018-06-23更新:新版可以直接用命令行参数启动,不需要建立ini文件。如:

frpc tcp -s "127.0.0.1:7000" -n ssh -l 22 -r 6000

具体参数含义和用法请使用frpc -h命令查看。

最后

感谢frp作者fatedier的工作,大家如果有问题咨询作者或者想捐款给作者,可以在GitHub上的说明的最后找到相关的联系方式。

打赏

微信支付宝

  1. 请问大神知道怎样用 frp让Transmission的51413端口打开吗,不然没有上传。我用的是移动大内网,路由器LEDE用frp已经可以在外面访问路由器的aria2-web正常下载,现在还有Transmission没搞好。

    1. 这个没有办法,因为51413并不实际传输数据,实际传输数据还要打开别的端口,别的客户端和你的服务器的51413端口交流了,就会试图连接你的服务器的IP地址来传输数据。
      目前没有更好的解决办法,毕竟IPv4地址资源稀缺是无法逆转的,只能等IPv6普及了。正好最近中央发出了指示了,希望能快点普及就好。

回复

your email will keep secret. (* required).

你可以使用这些HTML标签和属性:<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> .

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据