最近想到还有块树莓派在吃灰,今天使用frp折腾了一下内网穿透,把放在家里的树莓派也可以通过外网访问。
前置需求:
- 具有公网IP的机器一台(具有公网IP的宽带或者VPS均可)
- 域名一个(非必需)
环境介绍
首先我们需要在具有公网IP的机器上配置和启动frp的服务端,我使用的我是自己的VPS,以下涉及frp服务端的操作均在我的VPS上执行,系统环境如下:
1 | root@visionsmile:~# lsb_release -a |
下载frp
然后下载frp,frp项目提供了很多平台的二进制程序,可以在这里按需下载。
我这里需要下载的是amd64版本的:
1 | $ wget https://github.com/fatedier/frp/releases/download/v0.20.0/frp_0.20.0_linux_amd64.tar.gz |
下载完之后解压:
1 | $ tar -xvzf frp_0.20.0_linux_amd64.tar.gz |
frp配置和启动
此时目录下具有这样的目录结构:
1 | root:~/downloads/frp_0.20.0_linux_amd64# ls |
frps是frp的服务端程序,frps.ini是服务端的配置。frps.ini的全部配置选项可以看这里:frps_full.ini.
当前的frp版本的frps.ini的默认配置如下:
1 | $ cat frps.ini |
这里的bind_port
既是后面我们使用frpc(frp客户端)连接到服务端的端口,请保证该端口被防火墙(iptables)放行。
注意:如果是阿里云的服务器,需要在网页的安全组里设置放行端口,直接在服务器上使用ufw或者iptables是没有效果的。
在这里我不写太复杂的东西,保持默认即可,更多功能可以去读项目的frp/README
然后就可以启动frp了:
1 | $ ./frps -c frps.ini |
执行之后如下图:
配置frps在服务器上开机启动
Linux上设置开机启动有两种方法,一种是把启动命令添加到/etc/ec.local
中,另一种则是使用systemd
创建服务。这里我两种都会介绍一下,但是我推荐使用systemd.
首先先在服务器上将frp拷贝到/etc
目录下:
1 | $ sudo mkdir /etc/frp |
使用systemd
然后新建开机启动的服务,我使用的是systemd来启动frps服务:
1 | $ sudo cd /etc/systemd/system |
将下面内容填入其中:
1 | [Unit] |
保存退出,然后修改权限:
1 | $ sudo chmod 755 frps.service |
现在就可以启动了:
1 | $ sudo systemctl start frps |
使用/etc/rc.local
因为服务端是被动接收不需要依赖其他的服务启动顺序也可以直接写到了/etc/rc.local
中,客户端有点不一样,后面详说。
添加开机启动命令(已经执行过移动frp的目录到/etc/frp
):
1 | $ sudo nano /etc/rc.local |
使用域名解析服务端地址(可选)
之所以要使用域名是因为如果我们的服务端出现了问题,客户端直接也没用了,但是我又想如果这台服务器挂掉,我可以在不修改客户端的情况下连接到另一台服务器。
如果在frpc中直接填死服务端的IP地址是没办法做到这一点的,所以我想到的是使用一个域名解析到我想要连接到的服务器地址。
所以,我们使用一个域名(或者二级域名)解析到我们想要连接的服务器地址:比如我在dnspod上将frp.imzlp.com
解析A到了服务器XXX.XXX.XXX.XXX
。改完之后记得ping
一下看是否连通。
与上面下载frp服务端的方式相同,下载frp的客户端。注意下面的命令在客户端机器(raspberry pi)上执行。
frp客户端的默认配置如下:
1 | $ cat frpc.ini |
暂时需要修改的是server_addr
和server_port
,因为上面我使用了默认的端口,所以在这里只需要修改server_addr
就可以了。
改为我的自定义域名(如果没有域名则也可以直接指定服务端的IP地址),如下:
1 | $ cat frpc.ini |
在[ssh]
lable下的local_port
的客户端的端口转发到服务端的remote_port
端口。也要保证在服务端remote_port
被防火墙放行,不然也是连接不上的。
然后就可以在客户机上启动frpc
了:
1 | $ ./frpc -c frpc.ini |
尝试连接内网SSH
通过上面的操作,frps和frpc均已启动,我们可以尝试一下通过互联网连接树莓派的ssh,因为我上面使用了域名的解析,所以我可以直接使用域名:
1 | $ ssh -oPort=6000 pi@frp.imzlp.com |
注意:要指定ssh连接的服务端端口(即在frpc.ini)中的remote_port
参数。不出意外连接成功,如下:
配置frpc在客户端上开机启动
注意:这里是Linux的介绍,Windows的脚本在后面。
1 | # 执行在frp_0.20.0_linux_arm的目录(配置文件均已更改) |
在客户端开机启动我使用的是systemd
的服务:
1 | $ sudo cd /etc/systemd/system |
将下面内容填入其中:
1 | [Unit] |
请特别注意上面脚本中的这两行:
1 | Type=idle |
这两条语句的目的是等待系统初始化完成,如果frp直接在开机时启动会因为链接不上网络(如果是使用域名的可能会因为DNS解析不到)而错误中止。
注意:如果不希望等待,则可以把ExecStartPre
去掉,但是要求在frpc的配置中把login_fail_exit
设置为false
。
启动frpc并设置为开机启动:
1 | $ systemctl start frpc |
使用kcp协议
使用过kcp来加速ss肯定会知道,kcp加速会带来更高的传输效率和降低延迟。
frp现在的版本(>v0.12.0)的底层通信协议支持kcp,可以在配置文件中手动启用:
服务端:
在服务端的frps.ini中启用 kcp 协议支持,指定一个 udp 端口用于接收客户端请求:
1 | # frps.ini |
客户端:
在 frpc.ini 指定需要使用的协议类型,目前只支持 tcp 和 kcp。其他代理配置不需要变更:
1 | # frpc.ini |
开启加密和流量压缩
有些局域网会做流量的特征识别进行拦截,frp也提供了流量加密和压缩(在frpc.ini中添加):
1 | use_encryption = true |
使用Mstsc远程连接
在我之前的文章将树莓派打造成便携的Linux编译环境中写到过可以在树莓派上安装xrdp
使其可以被windows的mstsc连接。
1 | # 安装xrdp 使其可以使用mstsc连接 |
通过局域网连接时这样的:
因为mstsc默认访问的端口时3389,所以在我们想要通过互联网访问时,需要将树莓派(客户端)的3389端口映射到服务器端的端口。
具体操作如下:
编辑客户端frpc.ini,添加一个lable:
1 | [xvnc] |
代表着就是,将本地的3389端口映射为服务器端的6001端口,保存后重启frpc服务即可。
1 | $ systemctl restart frpc |
注意:与上面提到的相同,要保证服务器端的6001端口没有被防火墙禁用。
操作完毕之后就可以使用Mstsc在外网链接了(同样我使用域名):
连接上之后就和局域网连接一样了:
登陆进去之后:
同样的方法也可以使用在windows作为客户端的远程连接上,比anydesk或者teamviewer强多了。
十分酸爽,太流畅了,就像操作本地的电脑一样。
还可以使用rdpwrap,使远程连接访问其他账户时不会把本地账户踢出(等同于WindowsServer的功能)。
重新加载配置
frp提供了一种方法从修改的配置文件读取变动并应用代理的更新(这样就不用中止再重新启动了)。
将下面的参数添加到frpc.ini
:
1 | # frpc.ini |
重新加载的命令:
1 | frpc reload -c ./frpc.ini |
注意:当前的frp版本(v0.20.0)只有start
里的内容才会被重新加载,比如server_addr
等,所以如果frpc.ini
中server_addr
有变动,使用reload
也并不会重新连接到新的服务器。
我的frp配置文件
1 | #frps.ini |
1 | #frpc.ini |
我写了一个py脚本来检测我域名的DNS更新,如果有更新就重启客户端的frpc服务:
1 | # 注意,此脚本不能在windows上用。 |
同样地我把它加入到了systemctl
的启动服务里面:
1 | # /etc/systemd/system/syncfrpcdns.service |
也同样开启开机启动:
1 | $ sudo systemctl enable syncfrpcdns.service |
上上面的脚本是只能在Linux下跑的,我也写了一个功能相同的可以在Win下跑的:
1 | # SyncFrpServerHost.py |
注意:该脚本可以作为Frpc的开机启动程序,不用再单独设置Frpc的开机的开机启动。最好把frpc.ini
中的login_fail_exit
设置为false
。
开机启动且隐藏窗口可以写一个简单的vbs来实现(其实也可以使用pythonw
):
1 | DIM objShell |
将其快捷方式放在C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp
下即可。
这样当我切换frp.imzlpe.me
的服务器时,客户端检测到DNS变化也会更新连接到新的服务器的。
结语
操作时最重要的一点是要检查端口是否被防火墙放行,因为连接不上很有可能是端口被禁止了而不是frp配置的问题。
frp的更多使用方法可以看这里:frp/README。
Update
2018.11.10 16:19
- 增加服务端上使用systemd来启动frps.
- 修改部分措辞
- 增加阿里云的安全组介绍