相关介绍
内网穿透
我们在家中、公司的电脑可以正常的访问网页,使用各种网络服务,在同一个局域网下我们能够进行文件共享等操作,但是一旦离开家,离开公司,就不再能访问到你使用的电脑、服务器等设备。为了能够访问到你局域网中的设备,使得你局域网中的设备提供的服务暴露到公网环境下,可以狭义的理解为内网穿透。什么场景下需要用到内网穿透呢?内网穿透应用场景十分广泛,以下列举了常见的一些使用:
- 提供了网络服务并跨网访问,例如搭建了个人博客网站
- 个人网盘,家用NAS
- 程序开发,用于接收回调请求
- 视频监控
FRP
frp 是一个专注于内网穿透的高性能的反向代理应用,采用go语言编写,支持 TCP、UDP、HTTP、HTTPS 等多种协议,且支持 P2P 通信。可以将内网服务以安全、便捷的方式通过具有公网 IP 节点的中转暴露到公网。
NGINX
Nginx是一款轻量级的Web服务器、反向代理服务器,由于它的内存占用少,启动极快,高并发能力强,在互联网项目中广泛应用。
目标
将内网的服务通过FRP进行内网穿透,暴露到公网实现公网访问
FRP内网穿透的基本原理
网络环境介绍
192.168.1.5和192.168.1.7都是局域网内的设备,107.33.45.23是公网服务器,最右的设备是任意一台与局域网隔离的但能正常访问外网的设备。其中在192.168.1.5上安装了frp的客户端,107.33.45.23上安装的是frp的服务端。
frp的工作流程具体如下:
- 在frp客户端启动后,会主动与公网服务器建立连接
- 如果frp服务端认证通过,将会保持与客户端的链接,此时内网服务器和公网服务器是能够正常交换数据的。
- 如果你想在外网直接访问局域网内的设备,那么可以访问公网服务器frp服务端开放的某个指定端口
- frp服务端将会把流量转发给内网设备,看起来就像你内网的设备直接交互。
- 如果你的frp客户端配置是想将请求转发到局域网内的其他设备,那么frp客户端将会请求指定设备
- 如果请求成功,你部署的指定服务将会对此做出响应,回复给frp客户端也就是192.168.1.5
- frp客户端接收到响应后会将响应转发给公网服务器
- 公网服务器最后再将192.168.1.7的响应回复给请求设备。
以上就是frp的一个基本工作原理。如果你的frp客户端和部署的内网服务在同一台设备上的话,frp将会通过本地环回将请求发送给指定服务,和第5步和第六步是一致的。
方案实现
本文将会逐一描述各目标的达成实现,先进行简单的FRP穿透,对FRP的基本有一个基本的了解,然后引入nginx接管80端口,最后再锦上添花说明https的接入。
基本环境准备
- 要使用frp至少需要一个公网地址,如果自己没有公网地址也可以通过某宝购买frp服务租借公网ip,这种方式下无需自己部署frp服务端。
- 需要下载frp的服务端和客户端程序,这个可以从frp的github的官方仓库获取。frp下载页面,请根据实际环境下载不同的压缩包,64位windows下载windows_amd64,64位linux下载linux_amd64的压缩包
- 任意一台可以访问外网的计算机。该设备可以充当内网设备也可以充当外部网络设备,但是在后续的描述中为了清晰,还是会采用两台设备的形式进行描述
ip地址 | 说明 |
---|---|
192.168.1.7 | linux服务器,内网web服务器 |
192.168.1.5 | linux服务器,frp客户端 |
107.45.33.25 | linux服务器,公网服务器,frp服务端 |
目录规划
在本文中所有的程序和数据都放置在/data/software/frp目录下,如果完全沿用本文内容,则请先创建好对应的目录。
mkdir /data/software/frp
第一目标
我们的第一目标将要完成将内网的8080端口暴露到公网的80端口上,这是frp的最基本操作。
部署frp服务端
我们先将下载好的frp压缩包上传到公网服务器,或者在公网服务器上下载指定的压缩包都是可行的。先将压缩包解压到/data/software/frp下
tar -zxvf frp_0.51.3_linux_arm64.tar.gz --strip-components 1 -C /data/software/frp
在tar命令中添加指令--strip-components 1
将会去掉前导目录frp_0.51.3_linux_arm64
然后将所有文件释放到/data/software/frp
目录下。解压完成后会有frps_full.ini文件和frps.ini文件,frps_full.ini文件是frp服务端所有配置的一个样例,我们仅需要frps.ini文件即可。基本的frps.ini文件如下:
[common]
# frp客户端访问的端口
bind_port = 7000
# 服务端允许开放的接口
allow_ports = 8000-9000,80
# 客户端连接秘钥
token = 123qwe
# 服务端日志存放地址
log_file = /var/log/frps.log
# frps的状态面板
dashboard_port = 7500
# 面板用户名
dashboard_user = admin
# 面板密码
dashboard_pwd = 123qwe
对上述的frps.ini文件做一个简单的描述, 我们开放了7000端口用户客户端连接,连接密码是123qwe;允许映射的端口范围是8000到9000,超过这个配置都是不可用的;将日志记录到/var/log/frps.log目录下;开放了访问控制面板,配置端口7500,用户名是admin密码是123qwe
接下来我们启动服务端./frps -c ./frps.ini
,启动完成后我们可以根据公网ip地址访问frp的状态面板,在浏览器输入http://107.45.33.25:7500输入账户密码即可访问,实际情况请替换为你真实的公网ip,面板长这样:
部署frp客户端
在服务端启动完成后,继续进行客户端的配置,我们需要在192.168.1.5这台设备上安装frp的客户端,同样的,参考服务端安装将frp的压缩包进行上传或者下载,然后解压,目录保持统一都是/data/software/frp,解压命令不做赘述。
在客户端我们需要用到的文件是frpc和frpc.ini文件,frpc.ini是客户端的配置文件。我们先进行frpc.ini文件的基本配置,配置如下:
[common]
# 公网服务器地址
server_addr = 107.45.33.25
# 公网服务器配置的bind_port
server_port = 7000
# 公网服务器上配置的token
token = 123qwe
#日志路径
log_file = /var/log/frpc.log
[web1]
type=tcp
local_ip=192.168.1.7
local_port=8080
remote_port=80
在上述的frpc.ini的配置文件中,我们配置了服务端的地址、端口以及认证token,将日志记录在/var/log/frpc.log目录下。然后配置了一个名为web1的穿透规则,该规则类型为tcp连接,本地局域网的ip地址是192.168.1.7, 对应的服务端口是8080,我们将要暴露到公网服务器的80端口上。
接下来通过命令./frpc -c ./frpc.ini
启动客户端,如果启动成功,那么在浏览器输入http://107.45.33.25将能够访问到192.168.1.7上搭建的服务。
配置systemctl和自启动
上述的服务端启动和客户端启动都是通过直接运行命令的,且会一直占用我们的控制台,我们实际上希望程序开机能自启,并在后台运行。为此我们可以通过将命令包装成linux系统的服务来达到这一目的。frps服务端的配置文件如下:
[Unit]
Description=frps Service
After=network.target[Service]
ExecStart=/data/software/frp/frps -c /data/software/frp/frps.ini
ExecReload=/bin/kill -HUP $MAINPID
ExecStop=/bin/kill -TERM $MAINPID
Restart=always[Install]
WantedBy=multi-user.target
我们在/etc/systemd/system
目录下创建文件frps.service,然后将上述内容拷贝至文件中。使用systemctl daemon-reload
刷新配置,然后使用命令systemctl start frps
即可启动frp服务端。如果没有启动成功可以使用systemctl status frps
查看启动状态。如果启动成功,使用systemctl enbale frps
设置开机自启动。
对于客户端与服务端也是基本一致的,客户端的配置文件如下:
[Unit]
Description=frpc Service
After=network.target[Service]
ExecStart=/data/software/frp/frpc -c /data/software/frp/frpc.ini
ExecReload=/bin/kill -HUP $MAINPID
ExecStop=/bin/kill -TERM $MAINPID
Restart=always[Install]
WantedBy=multi-user.target
启动方式和设置开机自启动方式与服务端一致,不再赘述。