前言
有小伙伴提醒,
fatedier/frps
才是frp官方的Docker镜像。但我看这个官方镜像都没有详细的使用说明,所以不太想折腾。我下面用的镜像是我以前用过的,以前没有注意它们不是官方,所以不确定是否有潜在安全问题。如果担心安全的话,小伙伴可以看看fatedier/frps
怎么用,比如参考《容器化FRP使用方案》教程。也可通过其它方式使用frp,具体可以看官方Github地址:Repo。
最近有小伙伴问我:如果我有一个VPS,如何给自己家里的设备设置内网穿透服务呢?今天,我这里给一个比较简单且久经考验方案,就是利用Docker搭建frp实现内网穿透!
frp实现内网穿透的大致工作原理如下:
- 在一个有公网ip的VPS中搭建frp server(frps)服务。将域名
test.sample.com
解析到VPS里。 - 给frps开放某些特定的端口,比如
1234
- 在本地电脑安装frp customer(frpc)服务。通过
common
系列参数保证frps-frpc
的通信正常。 - 本地某服务上线,比如
localapp:6534
。 - frpc进行内部连接,比如
frpc:1234
- 穿透路线:test.sample.com→VPS→frps:1234→frpc:1234→localapp:6534
差不多是这样吧,可能实际的情况有些出入。本文不深入探讨frps:1234→frpc:1234
是怎么工作的,有兴趣自己Google一下即可(我也没怎么研究过,这才是重点,哈哈)。你只需要知道,frp是内网穿透的常用方案之一,且frp确实是好用即可。
由于我的本地宽带已经开通公网ip,所以内网穿透对我而言没有太大意义了。但是很多小伙伴家里的宽带没办法申请到公网ip。所以我还是搞一期内网穿透的教程吧,希望对他们有所帮助!
这一期的知识储备和安装一般Docker的基础差不多。所以如果你看我过的Linux基础和Docker系列,这一期十分简单。话不多说,冲!
服务器端
准备工作
# 工作目录。按需修改
work=~/docker/frps
# 创建并进入目录
mkdir -p $work/{conf,log} && cd $work
# 日志文件
touch $work/log/frps.log
# 拉取docker镜像
docker pull ruiny/frps:latest
按需要修改配置文件
vim ./conf/frps.ini
内容如下(有中文标记的项要自己改好):
# [common] is integral section
[common]
# A literal address or host name for IPv6 must be enclosed
# in square brackets, as in "[::1]:80", "[ipv6-host]:http" or "[ipv6-host%zone]:80"
bind_addr = 0.0.0.0
bind_port = 7000
# udp port to help make udp hole to penetrate nat
bind_udp_port = 7001
# udp port used for kcp protocol, it can be same with 'bind_port'
# if not set, kcp is disabled in frps
kcp_bind_port = 7000
# specify which address proxy will listen for, default value is same with bind_addr
# proxy_bind_addr = 127.0.0.1
# if you want to support virtual host, you must set the http port for listening (optional)
# Note: http port and https port can be same with bind_port
vhost_http_port = 80
vhost_https_port = 443
# set dashboard_addr and dashboard_port to view dashboard of frps
# dashboard_addr's default value is same with bind_addr
# dashboard is available only if dashboard_port is set
dashboard_addr = 0.0.0.0
dashboard_port = 7500
# 按需修改,Web管理frps时需要
dashboard_user = superman
dashboard_pwd = test0test
# dashboard assets directory(only for debug mode)
# assets_dir = ./static
# console or real logFile path like ./frps.log
log_file = /var/log/frps.log
# trace, debug, info, warn, error
log_level = info
log_max_days = 3
# 按需修改,在frpc的common系列参数中需要
token = 12345678
# heartbeat configure, it's not recommended to modify the default value
# the default value of heartbeat_timeout is 90
# heartbeat_timeout = 90
# 按需修改,选自己要开放的网段
allow_ports = 3505-3510
# pool_count in each proxy will change to max_pool_count if they exceed the maximum value
max_pool_count = 5
# max ports can be used for each client, default value is 0 means no limit
max_ports_per_client = 0
# authentication_timeout means the timeout interval (seconds) when the frpc connects frps
# if authentication_timeout is zero, the time is not verified, default is 900s
authentication_timeout = 900
# if subdomain_host is not empty, you can set subdomain when type is http or https in frpc's configure file
# when subdomain is test, the host used by routing is test.frps.com
# subdomain_host = frps.imgki.com
# if tcp stream multiplexing is used, default is true
tcp_mux = true
配置yml文件
新建一个docker-compose文件:
vim $work/docker-compose.yml
填入以下内容:
version: '3'
services:
frps:
image: 'ruiny/frps'
container_name: frps1
restart: unless-stopped
ports:
- '6500:7000'
- '6501:7500'
- '6502:7001'
# http端口
- '6503:80'
# https端口
- '6504:443'
# 这里写自己要开放给frpc的端口
- '3505-3510:3505-3510'
volumes:
- ./conf:/var/frp/conf
- ./log/frps.log:/var/log/frps.log
注意:
- 如果你的VPS是专门做内网穿透用的,可以将
- '6503:80'
、- '6504:443'
直接改成- '80:80'
、- '443:443'
。否则,一般你要定义一个其它的端口,以免和Nginx类应用冲突。 - 如果你的VPS安装了宝塔或者ufw等防火墙,你需要开放相应端口!在本示范中,需要开放的端口号为:
6500-6504
和3505-3510
。ufw就不演示了,自己看我以前的Docker文章吧!
上线服务:
cd $work && docker-compose up -d
观察日志(和一般的Docker应用有点不同):
tail -f $work/log/frps.log
(小白请忽视)高级用户可以进入docker内部观察或操作:
docker exec -it frps1 /bin/sh
你可以登陆http://<vps公网ip>:6501
查询frps的工作状态,用户名/密码为superman/test0test
。界面类似于:
到此,frp的服务端就准备好了。下面用Shell登陆自己的本地设备(如NAS或路由器)。
本地端
准备工作
观察一下本地电脑或NAS的ip地址。可以这样找:
ifconfig|less
在里面找enp
字符。比如,我的NAS的信息就类似于:
这个inet后面的192.168.X.X
的地址就是当前设备的局域网ip。下面,我们以192.168.0.125
为例进行示范。
设定工作目录:
# 工作目录。按需改动
work=~/docker/frpc
# 创建并进入工作目录
mkdir -p $work && cd $work
# 拉取docker镜像
docker pull chenhw2/frp:latest
新建frpc.ini
文件:
vim ./frpc.ini
填入以下内容:
[common]
# 填写服务器实际IP或解析该IP的某域名
server_addr = sample.com
# 填写服务器frps的主端口号,本示范中是6500
server_port = 6500
# 与frps.ini中的token要一一对应
token = 12345678
[ssh-3505]
# 将服务端的3505端口连接到本地的22端口进行ssh连接
type = tcp
# 本地ip
local_ip = 192.168.0.125
# 你的ssh端口。默认是22。如果有自定义ssh端口,就写那个自定义端口。
local_port = 22
# frps开放的端口之一。我随便写了个3505。
remote_port = 3505
[http-www.sample.cn]
# 测试http
type = http
# 本地ip
local_ip = 192.168.0.125
# 比如,某个Docker应用的端口号。Emby,jellyfin之类的有Web界面的应用。
local_port = 6533
custom_domains = httptest.sample.com
[https-@.sample.cn]
# 测试https
type = https
# 填写域名
custom_domains = httpstest.sample.com
plugin = https2http
plugin_local_addr = 192.168.0.125:6533
# HTTPS 证书相关的配置
plugin_crt_path = /frp/sample.com.pem
plugin_key_path = /frp/sample.com.key
plugin_host_header_rewrite = 192.168.0.125
plugin_header_X-From-Where = frp
最后,记得将证书通过sftp上传到$work
目录里面。目录内容类似于:
$ ls -hl $work
-rw-r--r-- 1 test_user test 1.1K Jun 13 13:38 frpc.ini
-rw-r--r-- 1 test_user test 1.7K Jun 13 13:42 sample.com.key
-rw-r--r-- 1 test_user test 3.8K Jun 13 13:42 sample.com.pem
我个人建议你申请一个顶级域名的证书,即*.sample.com, sample.com
,这样所有的*.sample.com
都可以用同一个证书,省去了证书维护的麻烦。你如果不想,也可以给每一个子域名单独申请一个证书。全部都上传到$work
文件夹里即可。对于每一条https记录,都定义下面的规则:
# HTTPS 证书相关的配置
plugin_crt_path = /frp/目标域名证书.pem
plugin_key_path = /frp/目标域名证书.key
plugin_host_header_rewrite = 192.168.0.125
plugin_header_X-From-Where = frp
http则比较简单,和tcp类的端口差不多。我强烈建议您使用https远程访问Web界面,这样会比较安全。
细心的小伙伴可能发现,上面的操作与sample.com
、httptest.sample.com
和httpstest.sample.com
这三个域名有关。确实!如果你要使用某域名作为内网穿透所用,你需要将该域名解析到frps所属的VPS的公网ip。以后,你每添加一个新的域名,都要对其进行域名解析。这个道理不难理解吧?
配置yml文件
新建docker-compose文件:
vim $work/docker-compose.yml
将以下内容填入:
version: '3'
services:
frps:
image: 'chenhw2/frp'
container_name: frpc1
restart: unless-stopped
environment:
- ARGS=frpc
volumes:
- .:/frp
上线服务,稍等片刻即可:
cd $work && docker-compose up -d
观察日志输出:
cd $work && docker-compose logs -f
日后想下线服务,只要:
cd $work && docker-compose down
都是常规操作。
测试
SSH
你在自己的Shell终端里测试一下即可:
- 地址:sample.com
- 端口号:3505
- 帐户:<自己的帐户>
- 密码:<自己的密码>
HTTP
访问http://httptest.sample.com:6503
可成功访问应用。
HTTPS
访问https://httpstest.sample.com:6504
可成功访问应用。
小结
FRP内网穿透还是蛮简单的,是吧?根据我过去2年的使用经验来看,FRP内网穿透方案还是十分稳定的,体验不错!不过,我要提醒你一下:内网穿透的流量和带宽受限于frps端,即你的VPS。平时访问一下Web界面管理应用好了,千万不要做类似于用内网穿透地址看高清视频之类的事情,否则VPS的流量很容易耗尽!
参考
- frp 与免费 SSL证书实现内网穿透并支持 HTTPS 访问
- frps配置文件:https://github.com/ruinny/frp-in-docker/blob/master/frps.ini