基于树莓派的家庭内网穿透架构——从 FRP 到智能家居
灿若繁星先生 Lv6

家里有两台树莓派(Pi 3B+ 和 Pi 4B),搭配一台阿里云 ECS,通过 FRP 内网穿透把家里的服务暴露到公网。Pi 4B 上用 Docker 跑了 Dify(AI 应用开发平台)和 Home Assistant(智能家居控制中心),Pi 3B+ 作为 FRP 客户端和 Nginx 反向代理网关,ECS 则是 FRP 服务端和公网入口。本文记录这套架构的设计思路和搭建过程。

为什么需要内网穿透

家庭宽带通常没有固定公网 IP,运营商分配的 IP 随时可能变化,而且大多数家庭路由器处于 NAT 之后,外部无法直接访问内网设备。常见的解决方案有:

  • DDNS + 端口映射:需要路由器支持且运营商不封端口
  • IPv6 直连:依赖运营商和对方网络都支持 IPv6
  • 内网穿透(FRP、ZeroTier、Tailscale 等):最灵活,通过一台有公网 IP 的中转服务器建立隧道

我选择了 FRP(Fast Reverse Proxy),因为它协议简单、性能好、对 TCP/UDP/HTTP/HTTPS 都有良好的支持。

整体架构

核心思路:ECS 做公网入口 → FRP 隧道穿透到 Pi 3B+ → Nginx 反向代理到 Pi 4B 上的各个 Docker 服务

image

设备角色

设备 IP 角色 关键服务
阿里云 ECS <阿里云服务器ip> 公网入口、FRP Server frps、安全组端口转发
Pi 3B+ 192.168.2.65 FRP Client、Nginx 反向代理 frpc、nginx
Pi 4B 192.168.2.64 Docker 应用服务器 Docker、Dify、Home Assistant

端口映射全表

访问入口 ECS 端口 FRP 隧道 Pi3 Nginx 端口 Pi4 后端 应用
http://<阿里云服务器ip>:8889 :8889 TCP :8089 :18080 Dify
http://<阿里云服务器ip>:8890 :8890 TCP :8090 :18081 预留
http://<阿里云服务器ip>:8891 :8891 TCP :8091 :18082 预留
ssh -p 6022 can@<阿里云服务器ip> :6022 TCP SSH 到 Pi3

阿里云 ECS —— FRP 服务端

安装 FRP Server

1
2
3
4
cd /opt
sudo wget https://github.com/fatedier/frp/releases/download/v0.69.0/frp_0.69.0_linux_amd64.tar.gz
sudo tar -xzf frp_0.69.0_linux_amd64.tar.gz
sudo ln -s frp_0.69.0_linux_amd64 frp

配置 frps.toml

1
2
3
4
5
6
7
8
9
bindPort = 7000

auth.token = "你的强随机字符串"

# Web dashboard for monitoring
webServer.addr = "0.0.0.0"
webServer.port = 7500
webServer.user = "admin"
webServer.password = "你的密码"
  • bindPort:FRP 控制通道端口,客户端通过这个端口与服务端建立连接
  • auth.token:认证令牌,客户端和服务端必须一致
  • webServer:可选的 Dashboard,用于监控隧道状态

注册为 systemd 服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
sudo tee /etc/systemd/system/frps.service > /dev/null <<'EOF'
[Unit]
Description=FRP Server Service
After=network.target

[Service]
Type=simple
ExecStart=/opt/frp/frps -c /opt/frp/frps.toml
Restart=on-failure
RestartSec=5s

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now frps

安全组配置

在阿里云控制台开放以下入方向端口:

端口 协议 用途
7000 TCP FRP 控制通道
7500 TCP FRP Dashboard(建议仅内网访问)
8889-8891 TCP 应用端口
6022 TCP SSH 跳板

Pi 3B+ —— FRP 客户端 + Nginx 网关

Pi 3B+ 是整个家庭网络的"交通枢纽",承担两个职责:FRP 客户端(建立到 ECS 的隧道)和 Nginx 反向代理(将请求转发到 Pi 4B)。

为什么需要 Nginx 中间层?

FRP 虽然可以直接转发 TCP 流量到 Pi 4B,但加入 Nginx 有几个好处:

  1. 统一入口管理:所有流量经过 Nginx,方便集中管理日志、限流、访问控制
  2. 灵活路由:未来可以在 Nginx 层添加认证、负载均衡、HTTPS 终结等
  3. 解耦:Pi 4B 上的应用端口变化时,只需改 Nginx 配置,无需动 FRP

FRP 客户端配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# frpc.toml
serverAddr = "<阿里云服务器ip>"
serverPort = 7000
auth.token = "与服务端相同的随机字符串"

# Dify: ECS:8889 -> Pi3:8089
[[proxies]]
name = "dify"
type = "tcp"
localIP = "127.0.0.1"
localPort = 8089
remotePort = 8889

# App xxx: ECS:8890 -> Pi3:8090
[[proxies]]
name = "app-xxx"
type = "tcp"
localIP = "127.0.0.1"
localPort = 8090
remotePort = 8890

# SSH: ECS:6022 -> Pi3:22
[[proxies]]
name = "pi3-ssh"
type = "tcp"
localIP = "127.0.0.1"
localPort = 22
remotePort = 6022

每个 [[proxies]] 定义一条 TCP 隧道:remotePort 是 ECS 上监听的公网端口,localPort 是 Pi 3B+ 本地端口。FRP 会把到达 ECS remotePort 的流量原封不动转发到 Pi 3B+ 的 localPort

Nginx 反向代理

每个应用一个 server 块,各自监听独立端口:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# Dify - port 8089
server {
listen 8089;
server_name _;

location / {
proxy_pass http://192.168.2.64:18080;

proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

# WebSocket support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";

proxy_connect_timeout 60s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
proxy_buffering off;
proxy_request_buffering off;
}
}

关键配置说明:

  • WebSocket 支持UpgradeConnection 头确保 WebSocket 连接正确代理(Dify 的 SSE 流式输出依赖此配置)
  • 长超时proxy_read_timeout 300s 防止 AI 流式响应被 Nginx 断开
  • 关闭缓冲proxy_buffering off 让响应数据即时透传,避免流式输出被缓存

注册 systemd 服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
sudo tee /etc/systemd/system/frpc.service > /dev/null <<'EOF'
[Unit]
Description=FRP Client Service
After=network.target

[Service]
Type=simple
ExecStart=/opt/frp/frpc -c /opt/frp/frpc.toml
Restart=on-failure
RestartSec=5s

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now frpc

Pi 4B —— Docker 应用服务器

Pi 4B 是家庭服务的计算核心,所有应用通过 Docker 部署,方便管理和隔离。

安装 Docker

1
2
3
curl -fsSL https://get.docker.com | sudo sh
sudo usermod -aG docker yuda
newgrp docker

国内网络环境需要配置镜像加速:

1
2
3
4
5
6
7
8
9
10
11
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<'EOF'
{
"registry-mirrors": [
"https://docker.m.daocloud.io",
"https://docker.1panel.live",
"https://hub.rat.dev"
]
}
EOF
sudo systemctl restart docker

部署 Dify(AI 应用开发平台)

Dify 是一个开源的 LLM 应用开发平台,支持可视化的 Prompt 编排、RAG 管道、Agent 框架等功能。

1
2
3
4
5
6
cd /opt
sudo git clone https://github.com/langgenius/dify.git
sudo chown -R yuda:yuda dify

cd dify/docker
cp .env.example .env

修改 .env 中的端口配置:

1
2
EXPOSE_NGINX_PORT=18080
EXPOSE_NGINX_SSL_PORT=18443

启动:

1
docker compose up -d

首次启动后访问 http://192.168.2.64:18080 设置管理员账号。Dify 会启动多个容器(API、Web、Worker、数据库、Redis、Nginx 等),Pi 4B 的 4GB 内存基本够用。

部署 Home Assistant(智能家居控制中心)

Home Assistant 是目前最流行的开源智能家居平台,支持 2000+ 品牌设备的接入和自动化编排。树莓派是其官方推荐硬件之一。

使用 Docker 部署非常简单:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
mkdir -p /opt/homeassistant
cd /opt/homeassistant

# Create docker-compose.yml
tee docker-compose.yml <<'EOF'
version: '3'
services:
homeassistant:
container_name: homeassistant
image: ghcr.io/home-assistant/home-assistant:stable
volumes:
- ./config:/config
- /etc/localtime:/etc/localtime:ro
restart: unless-stopped
network_mode: host
EOF

docker compose up -d

几点说明:

  • network_mode: host:Home Assistant 需要发现局域网内的智能设备(如通过 mDNS、SSDP 等协议),使用 host 网络模式可以让容器直接访问宿主机网络,避免设备发现失败
  • 数据持久化:配置文件挂载到 ./config 目录,升级镜像不会丢失配置
  • 默认监听 8123 端口,启动后访问 http://192.168.2.64:8123 进行初始设置

如果需要从公网访问 Home Assistant,按照同样的流程:Pi 3B+ 的 frpc.toml 新增一条 TCP proxy,nginx-proxy.conf 新增一个 server 块代理到 Pi 4B 的 8123 端口,ECS 安全组开放对应端口即可。

常用运维命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# View all containers
docker ps

# View Dify logs
cd /opt/dify/docker && docker compose logs -f

# Update Dify
cd /opt/dify && git pull origin main
cd docker && docker compose down && docker compose pull && docker compose up -d

# Update Home Assistant
cd /opt/homeassistant && docker compose pull && docker compose up -d

# Clean up unused images
docker system prune -f

SSH 访问

通过 FRP 的 SSH 隧道,可以在任何网络环境下 SSH 到家里的树莓派:

1
2
3
4
5
# SSH to Pi 3B+
ssh -p 6022 can@<阿里云服务器ip>

# SSH to Pi 4B (via Pi 3B+ jump host)
ssh -J can@<阿里云服务器ip>:6022 yuda@192.168.2.64

Pi 3B+ 充当跳板机,所有 SSH 流量经过 ECS → FRP → Pi 3B+ → Pi 4B 的链路。

新增应用的标准流程

当需要部署新应用时,按以下步骤操作:

1
2
3
4
5
1. Pi 4B: Docker 部署应用,映射到新端口(如 18083)
2. Pi 3B+: frpc.toml 添加 TCP proxy(localPort=8093, remotePort=8893)
3. Pi 3B+: nginx-proxy.conf 添加 server 块(listen 8093, proxy_pass Pi4:18083)
4. ECS: 安全组开放 8893 端口
5. 验证: curl http://<阿里云服务器ip>:8893

请求链路追踪

以访问 Dify 为例,一个完整的请求路径:

1
2
3
4
5
用户浏览器 → http://<阿里云服务器ip>:8889
→ 阿里云 ECS :8889 (FRP Server 接收)
→ FRP 隧道转发到 Pi 3B+ :8089
→ Pi 3B+ Nginx proxy_pass 到 Pi 4B :18080
→ Pi 4B Dify 容器处理请求并返回

总结

这套架构的核心设计思路:

  • 分层解耦:ECS(公网入口)→ Pi 3B+(流量分发)→ Pi 4B(业务计算),每层职责清晰
  • FRP 穿透:通过一台有公网 IP 的 ECS 搭建反向代理隧道,解决家庭网络没有公网 IP 的问题
  • Nginx 网关:在 FRP 和应用之间加一层反向代理,获得日志、认证、路由等灵活性
  • Docker 容器化:所有应用容器化部署,升级和维护简单
  • 可扩展:新增应用只需四步操作(Docker 部署 → FRP 配置 → Nginx 配置 → 安全组放行)

整套方案成本低(两台树莓派 + 一台最低配 ECS)、维护简单、扩展灵活,适合有类似需求的个人开发者参考。