环境
权限与运行环境
- Server A
- 不作要求
- 不作要求
- Server B
- 不作要求
- 不作要求
- Client C
- 不作要求
- 不作要求
步骤
- 根据A、B的体系结构从FRP发行版中下载下来, A上解压出frpc(客户端),B上解压出frps(服务端)。
- A、B上分别配置frpc.ini和frps.ini。
- A、B上分别编写systemd服务文件,并启用
讨论
相对ssh隧道来说,frp途径更多的是配置文件的问题。所以从步骤上看好像很短很简单的样子, 但写配置文件倒确实是有一点点麻烦的(好用和配置繁琐的trade off)。 接下来就最常见的端口转发与http转发,对相关配置文件简要讨论。
1. frps.ini
http的转发在服务器端的配置主要体现在[common]块中的vhost项,因此http只需要在客户端定义。 对整个连接的保护,则体现在[common]块下的token项。其次dashboard项,正如其名字所示, 浏览器访问指定端口就可以查看服务端运行状态,遗憾的是只能查询。
[common]
bind_port = 7000
kcp_bind_port = 7000
vhost_http_port = 7080
vhost_https_port = 7081
dashboard_port = 7500
dashboard_user = admin
dashboard_pwd = 12345687
token = 12345687
1.5 间章 针对HTTP服务穿透的特别部署姿势
对于内网穿透来说,更多时候会变动的是外网服务器,内网服务器一般是不会变动的。 有的时候发现了更便宜的服务器,考虑迁移的话,这么配置一圈还是有那么点麻烦的 (又是跑到GitHub去下载release,又是建配置文件,又是配置服务的), 对于仅需要HTTP穿透的需求来讲,服务端的配置文件一般是不需要变动的(尽管从FRP开发的历史进程上看, 好像开始倾向于所有的配置交给客户端来设置;服务端往后可能也不负担配置任务了), 于是我们可以利用Dokcer把服务端封装起来,迁移外网服务器的时候只需要在新服务器上启动镜像即可。
本人做了一点微小的工作 (/ω\) 👉kitakami/frp-server
在这个镜像中,只需要通过环境变量配置Dashboard的用户名与密码和验证用的Token即可, 此外切换版本也会相对比较方便。当然如果HTTP服务仅仅只有透过FRP穿透而来的话, 也可以加上nginx镜像组成docker-compose来启动。
2. frpc.ini
客户端的配置,主要是以正确连接上服务器([common]块),与定义具体服务(其他块)。
http的部分相对来说一看就懂,可能需要提一下的就是protocol = kcp
的部分,
传说可以改善客户端与服务端因延迟、丢包而造成的问题。端口转发的部分需要注意,
服务端定义了一个监听端口,客端端上的远程端口就要写那个监听端口。
[common]
server_addr = #远程主机IP
server_port = 7000
auth = qwerty
token = 12345687
[mc]
local_port = 25565
remote_port = 25565
[drive]
type = http
local_ip = 127.0.0.1
local_port = 80
use_encryption = true
use_compression = false
custom_domains = #自定义域名
protocol = kcp
2.5. 间章 http转发
有一些程序(例如gogs、minio)内置http服务器,但有一些程序(主要是php程序,例如nextcloud) 需要借助外部http服务器(例如apache2、nginx)的帮助才能访问。 对于同时有这两类程序的后端,http的转发方法就有两种:
- frp作为反向代理
- frp作为端口转发
个人建议第一个方案,如果要用第二个方案为什么不用ssh-tunnel。如果采纳方案1的话, 比较推荐frp中段采取http协议,进行加密,但不进行压缩。理由是压缩的任务, 理应由http服务器来完成,盲目地对流量进行压缩,潜在地,会造成大量对图片无谓的压缩。
此外,并不是很推荐转发https,除非Server B上连nginx也配置不起。 原则上讲,加证书这种事情应该由最末端的http服务器来做。因为https有一个握手环节, 转发https不过是徒增延迟。
3. frp(s/c).service
为frp注册一个systemd服务,还是比较简单的。例子如下
[Unit]
Description=frps Daemon
After=syslog.target network.target
Wants=network.target
[Service]
Type=simple
# ExecStart=/usr/local/bin/frpc -c /root/frpc.ini
ExecStart=/usr/local/bin/frps -c /root/frps.ini
Restart=always
RestartSec=1min
ExecStop=/usr/bin/killall frps
[Install]
WantedBy=multi-user.target