树莓派折腾记:使用FRP穿透内网

  文章更新:
  20170525 初次成文

  问题提出:
  在实际网络环境中,树莓派常常处于内网环境下,由于内外网相互隔离的原因,我们无法在外网访问处于内网中的树莓派。为了解决这个问题,"内网穿透"技术应运而生。

  FRP是一个可用于内网穿透的高性能的反向代理应用,支持 tcp, udp, http, https协议。在这篇文章中,小苏将为大家介绍FRP服务端和客户端的配置,通过FRP,让树莓派穿透内网,使大家在外网环境下也能轻松访问处于内网中的树莓派~

  本篇文章只做抛砖引玉目的,请大家在看完文章之后再仔细阅读一下FRP官方文档以了解详情~

  解决方案:
  FRP是一个免费开源的项目,其代码托管在Github上:
  
  FRP项目:
  https://github.com/fatedier/frp/
  FRP官方中文说明文档:
  https://github.com/fatedier/frp/blob/master/README_zh.md
  Release页面:
  https://github.com/fatedier/frp/releases

  FRP分为客户端程序和服务端程序两部分,其中,我们需要一台拥有公网IP的机器作为服务端。在Release页面,我们可以下载到已经编译好的适用于不同架构/平台的程序压缩包,每个程序压缩包中包含此架构/平台下的客户端和服务端。

  截至本文发稿前,FRP的最近版本为0.10.0,这是一个包含了很多改动的版本,如果你使用的是旧版的frp程序,需要将客户端和服务端同时升级并重新配置。

  由于树莓派的CPU是arm架构,所以我们需要下载frp_0.10.0_linux_arm.tar.gz,解压此文件后将得到:

  frp_0.10.0_linux_arm
   ├─ LICENSE  #版权许可
   ├─ frpc  #arm架构的frp客户端程序
   ├─ frpc.ini  #frp客户端配置说明文件
   ├─ frpc_min.ini  #frp客户端最小化配置文件
   ├─ frps  #arm架构的frp服务端程序
   ├─ frps.ini  #frp服务端配置说明文件
   └─ frps_min.ini  #frp客户端最小化配置文件

  由于我们只需要arm架构的客户端程序,所以我们只需要其中的frpc这个文件,至于客户端配置文件,之后小苏会提供。

  相似的,我们还需要获取FRP服务端程序,在此次配置过程中,小苏使用一台Debian系统,64位CPU的vps作为服务端载体,所以小苏需要在Release页面下载frp_0.10.0_linux_amd64.tar.gz,解压文件后得到:

  frp_0.10.0_linux_amd64
   ├─ LICENSE  #版权许可
   ├─ frpc  #amd64架构的frp客户端程序
   ├─ frpc.ini  #frp客户端配置说明文件
   ├─ frpc_min.ini  #frp客户端最小化配置文件
   ├─ frps  #amd64架构的frp服务端程序
   ├─ frps.ini  #frp服务端配置说明文件
   └─ frps_min.ini  #frp客户端最小化配置文件

  相应的,frps这个文件是我们所需要的,其配置文件小苏之后会提供。

  客户端(frpc)配置:

  得到所需文件后,我们开始配置frp的客户端程序:

  使用SFTP连接到树莓派,将frpc传到树莓派的/bin目录,并且登入SSH,执行以下命令:

sudo chmod +x /bin/frpc
sudo touch /bin/frpc.ini
sudo vim /bin/frpc.ini

  将以下内容粘贴进frpc.ini中,依实际情况修改后并保存(文末也提供单独的ini配置文件供大家使用):

[common]
server_addr = 123.123.123.123    #服务器公网IP
server_port = 7000    #frp服务端口,需与frps.ini相同
privilege_token = 123456      #特权模式密钥,需与frps.ini相同

log_file = /bin/frpc.log    #日志文件存储路径
log_level = info    #日志记录级别
log_max_days = 3    #日志最大存储天数
pool_count = 5
tcp_mux = true

[ssh]    #服务名称,可自定义
type = tcp    #协议类型(tcp)
local_ip = 127.0.0.1
local_port = 22    #本地SSH服务端口
remote_port = 2200    #穿透后SSH服务访问端口

[web]    #服务名称,可自定义
type = http    #协议类型(http)
local_ip = 127.0.0.1
local_port = 80    #本地web服务端口
use_encryption = false
use_compression = true
subdomain = web    #二级域名,建议与此项的服务名称"web"设置为相同
custom_domains = web.frp.com    #自定义域名

  
  服务端(frps)配置:

  相似的,将frps文件上传到服务器的/bin目录下,登陆SSH,执行以下命令(命令基本相同,只不过上面是frpc这里是frps):

sudo chmod +x /bin/frpc
sudo touch /bin/frps.ini
sudo vim /bin/frps.ini

  将以下内容粘贴到frps.ini中,依实际情况修改后保存(文末提供单独的ini配置文件供大家使用):

[common]
bind_addr = 0.0.0.0
bind_port = 7000    #frp服务端口,需与frpc.ini相同
vhost_http_port = 80    #http服务端口
vhost_https_port = 443    #https服务端口
dashboard_port = 7500    #控制台端口
privilege_token = 123456    #特权模式密钥,需与frpc.ini相同

log_file = /bin/frps.log    #日志文件存储路径
log_level = info    #日志记录级别
log_max_days = 3    #日志最大存储天数
max_pool_count = 5
authentication_timeout = 900

subdomain_host = frp.com    #服务端绑定域名
tcp_mux = true

  
  值得说明的是,frps.ini中subdomain_host的域名需要泛解析到服务器的公网IP(比如*.frp.com),这个时候,如果客户端frpc.ini文件中的subdomain属性有定义(如web),则此服务绑定的域名为web.frp.com。

  如果frpc.ini中定义了custom_domains属性,那么可以将custom_domains中提到的自定义域名解析到服务器所在的公网IP,方可正常使用该自定义域名访问此项服务。

  在frps.ini中,vhost_http_port的值一旦被指定(如80),那么所有客户端中web服务映射到服务器中的端口都相同(都为80,比如http://web.frp.com:80)vhost_https_port同理。

  dashboard_port属性指定了服务器的控制台端口(以7500为例),访问服务器ip:该端口(如http://123.123.123.123:7500),即可进入控制面板来查看frp服务的状态信息(默认用户名和密码都为admin)。

  frpc.ini和frps.ini中注释未提到的内容可以在官方文档或压缩包中自带的配置说明文件frpc.ini/frps.ini中找到,未提到的内容大多为官方推荐配置,可直接应用。为节省篇幅,这里不再赘述。
  
  
  测试frps服务(服务端):

  配置文件配置完毕后,我们可以尝试在服务器端执行以下命令以启动frps服务:

(sudo) /bin/frps -c /bin/frps.ini

  执行完毕后,frps服务将会在前台启动,且终端应该不会有输出(若终端有输出,可能在启动过程中出现了某些错误)。这时候我们使用Ctrl+C终止程序,执行cat命令查看日志文件:

(sudo) cat /bin/frps.log

  如果日志文件中没有错误信息,那么说明frps服务端配置且启动正常。
Screenshot_20170525-215330~01.png
  
  测试frpc服务(客户端):

  类似的,在客户端(树莓派)中我们需要执行以下命令启动frpc服务:

sudo /bin/frpc -c /bin/frpc.ini

  同理,执行完毕后,终端应该不会有输出,使用Ctrl+C终止程序,执行cat命令查看日志文件:

sudo cat /bin/frpc.log

  若未出现错误信息,则说明frpc客户端配置且启动正常。
Screenshot_20170525-215015~01.png
  
  启动FRP服务:

  将启动脚本(文末提供)startfrpc.sh传到客户端(树莓派)的/bin中,将启动脚本startfrps.sh传到服务端的/bin中,并且使用以下命令赋予这两个脚本可执行权限。

  值得注意的是,在启动脚本中需要用到curl程序,若客户端/服务端中未安装curl,则应先安装curl

sudo chmod +x /bin/startfrpc.sh #在客户端中执行
sudo chmod +x /bin/startfrps.sh #在服务端中执行

  赋予可执行权限之后,在终端执行以下命令即可启动FRP:

sudo startfrpc.sh #客户端启动脚本
(sudo) startfrps.sh #服务端启动脚本

  
  开机自启FRP服务:

  接下来,我们将让frps/frpc服务开机启动:

  编辑客户端(树莓派)/etc/rc.local文件,在exit 0之前添加以下代码行:

# Start Frpc
/bin/startfrpc.sh >> /dev/null 2>&1

  
  编辑服务端/etc/rc.local,在文件末尾添加以下代码行(如果文件末行为exit 0,则应该将以下内容添加到exit 0之前):

# Start Frps
/bin/startfrps.sh >> /dev/null 2>&1

  
  这时,关机并重新启动客户端和服务端,待开机后,在客户端或者服务端中执行以下命令:

ps -A | grep frp

  若返回类似结果则证明frps/frpc服务启动成功:

  客户端:

1920 ?        00:00:00 startfrpc.sh
1925 ?        00:00:15 frpc

  
  服务端:

1920 ?        00:00:00 startfrps.sh
1925 ?        00:00:15 frps

  
  停止FRP服务:

  我们可以使用相同的命令查看FRP服务的PID,比如在服务端中执行:

ps -A | grep frp

  例如终端返回:

1920 ?        00:00:00 startfrps.sh
1925 ?        00:00:15 frps

  
  可以得到这两个进程的PID为1920和1925,我们可以使用kill命令杀掉这两个进程来停止FRP服务:

(sudo) kill 1920 1925

  
  客户端停止流程同理。
  
  
  资源下载:

  FRP.zip

  解压此压缩包将会得到以下文件,对文件按需修改后按文章内容操作即可:

  FRP
  ├─ frpc
  │ ├── frpc.ini  #未添加注释的示例frpc.ini
  │ ├── frpc_note.ini  #添加注释的示例frpc.ini
  │ └── startfrpc.sh  #frpc启动脚本
  └─ frps
    ├── frps.ini  #未添加注释的示例frps.ini
    ├── frps_note.ini  #添加注释的示例frps.ini
    └── startfrps.sh  #frps启动脚本
  

已有 9 条评论
  1. 好长好棒!立即实践(并不)#滑稽

    1. 调皮的Pandaria大佬...
      (・ω< )★

  2. 萌新

    如果没有公网ip的设备要怎么办........

    1. 如果能从家用宽带商那里申请到公网IP,那么也可以在Windows上搭建Frp服务器。
      如果申请不到的话,可以选择公共的Ngork或者Frp服务,
      不过速度一般都很慢,延迟也很高...

    2. 如果没有公网ip,可以买一个域名,腾讯云做活动很便宜,然后在服务端用dnspod实现ddns
      https://zhuanlan.zhihu.com/p/21501138

    3. 如果没有公网ip,可以买一个域名,腾讯云做活动很便宜,然后在服务端用dnspod实现ddns
      https://zhuanlan.zhihu.com/p/21501138

  3. 萌新

    好吧.......看起来只能使用ngrok了.....
    路由器里面的花生壳也用不了....

    话说,在打开这个网站的时候,第一次打开总会出现以下内容:
    {"msg":"connection timeout","code":"50403202","id":"74ce204f5745f25e77e7354d96df7ed5"}
    刷新了又正常了.....不知道这是什么问题......

    1. 现在某些地方的CDN节点可能有些问题...待会儿应该就好了~

    2. 萌新

      原来如此~

添加新评论