本来树莓派是用的动态dns解析移动宽带的ip,但是合同到期后宽带就没了,如果还想让树莓派能通过公网访问,就只有做内网穿透。

下载frp

可以去github上下来对应的版本:https://github.com/fatedier/frp/releases

我已经提前下载好了v0.36.1版本的frp:

amd64位版:http://io.claws.top/tool/frp_64.tar.gz

amd32位版:http://io.claws.top/tool/frp_32.tar.gz

以64位版为例,下载解压:

wget http://io.claws.top/tool/frp_64.tar.gz
tar -zxvf frp_64.tar.gz

进入目录中,可以看到有可执行的 frps 和 frpc。frp 分为两部分,frps 需要部署在有公网IP的服务器上,负责转发;frpc 部署在需要做内网穿透的内网服务器上。两边同时运行就可以内网穿透了。

配置frp

公网服务器

作者已经写好了一份简单的配置以及systemd服务文件,把他们拷贝到对应的位置就可以了。

sudo cp frps /usr/bin/
sudo mkdir /etc/frp
sudo cp frps.ini /etc/frp
sudo cp systemd/frps.service /etc/systemd/system

接下来可以对配置文件 /etc/frp/frps.ini 进行修改。服务端的文件不需要特别配置。

[common]
bind_port = 7000 # 管理端口
token = iQYIPZdTTWRF4TBerB0or76zpbaFBLkh # token(需要保持客户端和服务端一致)

之后通过 systemctl 启动服务:

systemctl start frps.service

内网服务器

sudo cp frpc /usr/bin/
sudo mkdir /etc/frp
sudo cp frpc.ini /etc/frp
sudo cp systemd/frpc.service /etc/systemd/system

然后可以对 frpc 配置文件进行一定的修改,例如希望转发 80 端口:

[common]
server_addr = 1.1.1.1 # 换成你的公网服务器ip
server_port = 7000 # 公网服务器管理端口
token = iQYIPZdTTWRF4TBerB0or76zpbaFBLkh #token需与公网服务器frps中的保持一致

[ssh]
type = tcp 
local_ip = 127.0.0.1
local_port = 22
remote_port = 7100

[web] 
type = tcp # 单纯的tcp转发
local_ip = 127.0.0.1
local_port = 80
remote_port = 7200

虽然frp也提供了一些方便的 http,https转发类型,但是考虑到希望在内网服务器80端口部署多个网站,单纯转发tcp就够了,剩余的工作交给nginx处理。

remote_port 表示公网服务器上的端口,只要经过这个端口就可以被frp转发到内网服务器上。

Nginx配置示例

我现在的情况是,公网服务器上有网站,同时还希望能将一些域名对应的请求转发给内网服务器。需要在公网服务器的nginx上配置一个代理:

server{
    listen 80;
    #server_name flood.claws.top tv.claws.top tvcontent.claws.top;
    proxy_set_header Host $host:$server_port;
    location / {
        proxy_pass http://127.0.0.1:7200;
    }
}

server_name 可以配置一些希望被转发的域名。如果不写,则需要把这个server放在所有监听80端口的server的最前面。这样一来,如果请求中的域名不匹配任何一个监听80端口server,那么就会走默认第一个server,转发给frp负责的端口。

值得注意的是,proxy_pass 转发的请求中host字段会被换成127.0.0.1。因此,如果想在内网服务器上根据server_name进一步区分网站,需要写proxy_set_header Host $host:$server_port;这一句。

内网服务器的Nginx配置示例:

server{
    listen 80;
    server_name flood.claws.top;
    location / {
        proxy_pass http://127.0.0.1:3000;
    }
}
server{
    listen 80;
    server_name tv.claws.top;
    set $name 'http://tvcontent.claws.top';
    location ~\.mp4$ {
        default_type text/html;
        add_header Content-Type 'text/html; charset=utf-8';
        return 200 '<video controls><source src=\"$name$request_uri\"></video>';
    }
    location / {
        root /home/pi/cdn;
        autoindex on;
        autoindex_exact_size off;
        autoindex_format html;
        charset utf-8,gbk;
    }
}
server{
    listen 80;
    server_name tvcontent.claws.top;
    location / {
        root /home/pi/cdn;
    }
}

同时监听80端口的三个server可以通过server_name进行区分。