由于IP资源数量限制以及防火墙等原因,一般来说,我们的物联网设备和私有服务器都是没有公网IP地址的,因此也无法通过外部网络直接访问,只有公有云服务商或者专线接入的用户,才有有限的独立的公网IP地址可供访问。[使用frp实现内网穿透管理物联网设备]。在这种情况下,如果我们要通过个人电脑、私人服务器提供网络服务,或者需要从公共网络访问并管理我们的物联网设备,就需要有内网穿透的功能,使我们的服务器与物联网设备提供的服务(如文件服务、FTP、网站服务或者SSH远程管理功能等)可以穿过防火墙,能够从公共网络进行访问。
实现跨网络访问的方法较多:
要实现内网穿透,你需要有一台拥有公有IP地址的服务器,在目前云服务器价格持续走低的情况下,拥有一台独立的低配置的云服务器对个人来说并非难事,其成本也远低于其他商用软件如花生壳等。本文以下步骤均以拥有固定IP地址的公网云服务器以及在局域网内的服务器为前提,其中,云服务器安装了Ubuntu18.04版本的linux操作系统,本地私有服务器安装了Windows 10系统,为了充分模拟各种情况,本地服务器还通过WSL运行了Ubuntu18.04系统。拓扑简图如下:
frp的安装与配置很简单,在frp项目官网(或者从我们的frp国内镜像)的release页面下载需要的已经编译好的二进制文件,注意,下载好的frp是包括服务器frps和客户端frpc的,在服务端只需要启动frps而在客户端只需要启动frpc,在我们的服务器和客户端操作分别如下。
由于一般云服务器供应商对服务器端口均进行了限制,为了保证本文后续配置顺利进行,需要在云服务器安全组中开放以下端口,并在后续要提供其他服务时根据情况进行开放,如果服务器自身也启用了防火墙服务,那么下列端口还需要在服务器防火墙配置中再配置一次以予以放行:
本文后续配置中均假设云服务器ip地址为123.123.123.123,实际配置中需要根据真实ip地址修改,同时,本位假设已经拥有一个www.domain.cc域名通过A记录解析至123.123.123.123,因此在配置时均通过域名代替ip地址。这样的好处是如果服务器进行更换,不需要再在每台客户端中配置并更换服务器的ip地址。
通过ssh方式远程连接云服务器后,通过以下命令下载并安装frps。
//下载安装包
wget https://github.com/fatedier/frp/releases/download/v0.34.3/frp_0.34.3_linux_amd64.tar.gz
//解压安装包
tar -xvf frp_0.34.3_linux_amd64.tar.gz
//使用nano或者vim打开解压后的frps.ini文件并做以下最简单的配置以供测试
# frps.ini
[common]
bind_port = 7000
//通过以下命令启动frps
./frps -c ./frps.ini
上述启动方式仅用于调试,在断开ssh连接后服务会自动关闭,服务器与客户端自启动方式见后文详细配置说明。
下载windows版本客户端并解压,打开 frpc.ini 文件进行配置。
# frpc.ini
[common]
server_addr = www.domain.cc
server_port = 7000
[rdp]
type = tcp
local_ip = 127.0.0.1
local_port = 3389
remote_port = 7389
在当前目录下打开 windows powershell 输入以下命令以启动客户端,如果服务器连接成功,会有 start proxy successful 字样提醒:
> .\frpc.exe -c .\frpc.ini
在第三台电脑上,通过快捷键 win+R 启动命令提示框,输入 mstsc ,输入 www.domain.cc:7389 输入用户名和密码(安装了frpc客户端电脑的用户名和密码),即可远程打开windows客户端电脑进行管理。可以看到,在这种条件下,第三方电脑通过公网云服务器的7389端口,访问了windows客户端的3389远程桌面端口,实现了windows电脑端口的内网穿透功能。
在windows10服务器的WSL子系统下(或者独立的Linux系统亦可),安装frp客户端并进行访问。需要注意的是,windows10的Ubuntu子系统,默认没有打开root用户远程ssh权限,需要先进性设置。
//打开ssh配置文件
sudo nano /etc/ssh/sshd_config
//修改以下位置,然后保存:
Port = 22 # 去掉前面的#号,启用22端口
ListenAddress 0.0.0.0 #去掉前面的#号
PasswordAuthentication yes # 将 no 改为 yes 表示使用帐号密码方式登录
PermitRootLogin yes #允许root用户远程登录
//重启sshd服务:
dpkg-reconfigure openssh-server #用于安装RSA_KEY,选择使用现有配置文件keep old...
sudo service ssh restart #重启SSH服务
sudo service ssh status #查看SSH服务状态,应为running
执行以下命令下载并配置运行frp客户端。
//下载安装包
wget https://github.com/fatedier/frp/releases/download/v0.34.3/frp_0.34.3_linux_amd64.tar.gz
//解压安装包
tar -xvf frp_0.34.3_linux_amd64.tar.gz
//使用nano或者vim打开解压后的frpc.ini文件并做以下配置以启用ssh功能
# frpc.ini
[common]
server_addr = www.domain.cc
server_port = 7000
[ssh]
type = tcp
local_ip = 127.0.0.1
local_port = 22
remote_port = 7022
//通过以下命令启动frps
./frps -c ./frps.ini
通过第三方计算机终端访问 ssh -p 7022 root@www.domain.cc ,输入密码后即可通过ssh方式访问linux主机(此处为windows服务器的wsl子系统)。
在下载解压后的文件中,分别有 frpc_full.ini 和 frps_full.ini 两个配置文件示例,包括了大部分功能的配置方法,在frp官网中也提供了大量配置案例。可供参考。
上文所述的frp是不安全的,在没有加密的情况下,任何人都可以使用你的frp服务器进行内网穿透服务。为此,frp提供了token和OpenID加密方式进行加密,要使用token加密,只需要在服务器端的 frps.ini 配置文件和客户端的 frpc.ini 文件中增加同样的token配置项即可。
#frps.ini
[common]
authentication_method = token
token = 12345678
#frpc.ini
[common]
token = 12345678
此外,也可以采用通过环境变量取代配置文件明文密码的方式进行参数配置及加密,参考配置如下:
# frpc.ini
[common]
server_addr = {{ .Envs.FRP_SERVER_ADDR }}
server_port = 7000
[ssh]
type = tcp
local_ip = 127.0.0.1
local_port = 22
remote_port = {{ .Envs.FRP_SSH_REMOTE_PORT }}
服务端配置http服务端口及域名主机。
# frps.ini
[common]
#http端口服务
vhost_http_port = 8000
#配置主机域名后,可以在客户端配置子域名进行访问
subdomain_host = domain.com
如果客户端要配置http子域名,可以采用如下配置,这样可以通过test.domain.com:8000访问客户机的80端口:
# frpc.ini
[web]
type = http
local_port = 80
subdomain = test
如果客户端要配置独立的域名,可以采用如下配置,并把 www.mydomain.com 域名解析到服务器的ip地址上,即可通过如下配置,以 www.mydomain.com:8000 访问客户机80端口:
[web]
type = http
local_port = 80
custom_domains =www.mydomain.com
对于在局域网中搭建的 ftp 服务器,需要通过被动模式,才能穿过防火墙供外部 ftp 客户端访问,以 FileZilla Server 为例,在服务器配置时,需要配置以下被动模式,在本例中, ftp 服务器使用21端口,被动端口定义为7018~7020。
在客户端作如下配置,其中ftp用于配置ftp服务器,ftp1~3用于配置被动端口,配置后可以通过7021端口访问客户端21端口的ftp服务:
[ftp]
type = tcp
local_ip = 127.0.0.1
local_port = 21
remote_port=7021
[ftp1]
type = tcp
local_ip = 127.0.0.1
local_port = 7018
remote_port = 7018
[ftp2]
type = tcp
local_ip = 127.0.0.1
local_port = 7019
remote_port = 7019
[ftp3]
type = tcp
local_ip = 127.0.0.1
local_port = 7020
remote_port = 7020
frp可以通过程序内置的管理页面进行管理,要配置服务端管理页面,需要配置相应的 dashboard 参数。如下配置后,可以访问frp服务器的7500端口,通过设置的用户名和密码管理frps服务器。
//frps.ini
[common]
dashboard_port = 7500
dashboard_user = admin
dashboard_pwd = admin
要管理与配置客户端参数,需要对 frpc.ini 做如下配置,配置后,可以通过在客户端本地7400端口管理并配置frp客户端。
//frpc.ini
[common]
admin_addr = 127.0.0.1
admin_port = 7400
admin_user = admin
admin_pwd = admin
新的Ubuntu系统通过systemd来管理服务以替代传统的init,关于systemd的入门教程,可以参考阮一峰博客的文章要配置frps为系统服务,可以按照如下步骤进行操作.
//1. /usr/frp目录并复制frps 和frps.ini 文件到其中,本步骤仅为后续操作方便。
//2. 在/lib/systemd/system/目录下新建frps.service文件并写入以下内容,这也是service一类文件的标准写法。
[Unit]
Description=Frp Server Service
After=network.target
[Service]
Type=simple
User=root
Restart=on-failure
RestartSec=5s
ExecStart=/usr/frp/frps -c /usr/frp/frps.ini
[Install]
WantedBy=multi-user.target
//以上操作完成后,可以通过Ubuntu系统的systemctl命令操作frps服务
sudo systemctl enable frps.service # 设置开机启动,根据 install 建立软链
sudo systemctl disable frps.service # 取消开机启动,根据 install 移除软链
sudo systemctl daemon-reload # 重新加载配置,修改 systemd 配置执行
systemctl status frps # 查看 frps 服务状态
systemctl cat frps # 查看 frps 服务配置
sudo systemctl start frps # 启动 frps 服务
sudo systemctl stop frps # 停止 frps 服务
利用批处理文件和任务计划来启动程序是windows下常规操作,在 frp 目录下新建一个 start.bat 批处理文件。
@echo off
:home
frpc -c frpc.ini
goto home
上述脚本会在服务中断后自动重启服务(一旦frpc退出,就回到home行重新开始),一个简单的方式是对上述脚本新建一个快捷方式并放置在以下目录中,就可以开机自动启动,但每次开机都会有windows命令行出现。
C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp 因此还是通过配置任务计划更好一些。
搜索任务计划程序,打开windows任务计划程序。新建一个基本任务,“常规”栏名称可以随意填写,在运行时选择不管用户是否登录都运行,并且选择使用最高权限运行和隐藏。在“触发器”栏中选择启动时。在“操作”栏中选择新建操作,程序指向 start.bat 位置,起始位置指向脚本目录。任务配置完成后,系统在开机时即可自动运行。
WINSW 是一个可以把任何(几乎)windows程序注册成windows系统服务的工具软件,[下载WINSW] 并保存在frp目录下,为了方便起见,将WINSW重命名为 myfrpc.ext ,并在同一目录下新建一个 myfrpc.xml 文件,添加内容如下:
<service>
<id>frpc</id>
<name>Frpc</name>
<description>This service runs frp client system with configuration</description>
<env name="JENKINS_HOME" value="%BASE%"/>
<executable>D:\services\frp\frpc.exe</executable>
<arguments>-c frpc.ini</arguments>
<onfailure action="restart" delay="15 sec"/>
<onfailure action="restart" delay="30 sec"/>
<log mode="roll"></log>
</service>
其中, executable 指向 frpc.exe 所在目录, arguments 为运行参数, onfailure 设置了两次重启机会,来保证服务可以正常启动。在命令行中运行 myfrpc.exe(即重命名后的winsw.exe文件) 来管理服务:
./myfrpc.exe install #注册服务,winsw会自动找到同一目录下的xml文件并注册其中的程序
./myfrpc.exe uninstall #取消服务
./myfrpc.exe start #启动服务
./myfrpc.exe stop #停止服务
./myfrpc.exe status #查看服务状态
./myfrpc.exe restart #重启服务
这样就将frpc注册为windows系统服务,在windows任务管理器的服务栏中可以看到该服务。