前言

有小伙伴提醒,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.comVPSfrps:1234frpc:1234localapp: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-65043505-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。界面类似于:

docker搭建frp客户端 docker frp_服务器

到此,frp的服务端就准备好了。下面用Shell登陆自己的本地设备(如NAS或路由器)。

本地端

准备工作

观察一下本地电脑或NAS的ip地址。可以这样找:

ifconfig|less

在里面找enp字符。比如,我的NAS的信息就类似于:

docker搭建frp客户端 docker frp_内网穿透_02

这个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.comhttptest.sample.comhttpstest.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的流量很容易耗尽!

参考